@chengxianglibra/dsh-data-analysis 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.en.md +138 -0
  2. package/README.md +55 -82
  3. package/lib/client/credentials/install.js +3 -3
  4. package/lib/client/i18n/copy.js +4 -1
  5. package/lib/client/i18n/host.js +1 -0
  6. package/lib/client/i18n/settings.js +30 -0
  7. package/lib/client/input-context.js +1 -1
  8. package/lib/client/python-tool/card.js +2 -2
  9. package/lib/client/python-tool/model.js +1 -1
  10. package/lib/client/right-tabs/install.js +10 -7
  11. package/lib/client/settings/card.js +90 -0
  12. package/lib/client/settings/install.js +14 -0
  13. package/lib/client.js +104 -70
  14. package/lib/datasource/changes-contract.js +6 -2
  15. package/lib/datasource/configure.js +1 -1
  16. package/lib/datasource/python-options.js +1 -7
  17. package/lib/datasource/python.js +12 -7
  18. package/lib/datasource/test.js +1 -1
  19. package/lib/disclosure/execution-guidance.js +5 -8
  20. package/lib/plugin-agents.js +2 -2
  21. package/lib/plugin.js +14 -4
  22. package/lib/presentation/assets/portable.js +1 -1
  23. package/lib/presentation/assets/static.js +47 -47
  24. package/lib/presentation/execution-policy.js +5 -0
  25. package/lib/presentation/projection/index.js +27 -10
  26. package/lib/presentation/tool.js +2 -1
  27. package/lib/settings.js +17 -0
  28. package/lib/types/client/i18n/copy.d.ts +15 -0
  29. package/lib/types/client/i18n/host.d.ts +1 -0
  30. package/lib/types/client/i18n/settings.d.ts +16 -0
  31. package/lib/types/client/settings/card.d.ts +9 -0
  32. package/lib/types/client/settings/install.d.ts +2 -0
  33. package/lib/types/client.d.ts +2 -2
  34. package/lib/types/datasource/python-options.d.ts +1 -2
  35. package/lib/types/datasource/python.d.ts +2 -2
  36. package/lib/types/disclosure/execution-guidance.d.ts +8 -0
  37. package/lib/types/plugin-agents.d.ts +2 -0
  38. package/lib/types/plugin.d.ts +23 -3
  39. package/lib/types/presentation/execution-policy.d.ts +5 -0
  40. package/lib/types/rpc.d.ts +2 -2
  41. package/lib/types/semantic-reference/rpc.d.ts +2 -2
  42. package/lib/types/settings.d.ts +14 -0
  43. package/package.json +85 -65
  44. package/python/presentation-kit/dist/dsh_data_analysis_presentation_kit-1.1.0-py3-none-any.whl +0 -0
  45. package/skills/dsh-data-analysis-files/SKILL.md +22 -10
  46. package/skills/dsh-data-analysis-files/references/delivery.md +15 -0
  47. package/skills/dsh-data-analysis-presentation/SKILL.md +15 -19
  48. package/skills/dsh-data-analysis-presentation/references/schema.md +4 -1
@@ -0,0 +1,5 @@
1
+ /** Report-specific wall-clock budgets; leave time after source reads for publication. */
2
+ export const PRESENTATION_EXECUTION_BUDGETS = Object.freeze({
3
+ sourceReadTimeoutMs: 120_000,
4
+ toolTimeoutMs: 180_000,
5
+ });
@@ -1,6 +1,7 @@
1
1
  import { MarivoEnvironmentError } from "../../environment/errors.js";
2
2
  import { readPythonExecution } from "../../python-execution.js";
3
3
  import { PRESENTATION_BUDGETS, PresentationContractError, parsePresentationDocument, parsePresentationDraft, parseTypedDataset, } from "../contracts/index.js";
4
+ import { PRESENTATION_EXECUTION_BUDGETS } from "../execution-policy.js";
4
5
  import { readWorkspaceJson } from "./files.js";
5
6
  import { MARIVO_PRESENTATION_READ_PROGRAM } from "./program.js";
6
7
  export { readWorkspaceJson } from "./files.js";
@@ -60,16 +61,32 @@ export class MarivoPresentationProjection {
60
61
  let diagnostics = [];
61
62
  const artifactData = new Map();
62
63
  if (draft.sources.length > 0) {
63
- const result = await this.#runner.runChecked({
64
- program: MARIVO_PRESENTATION_READ_PROGRAM,
65
- args: [JSON.stringify({ sources: draft.sources, datasets: artifactSelections })],
66
- limits: {
67
- timeoutMs: 30_000,
68
- stdoutMaxBytes: PRESENTATION_BUDGETS.documentBytes,
69
- stderrMaxBytes: 65_536,
70
- },
71
- signal: options.signal,
72
- });
64
+ const startedAt = performance.now();
65
+ let result;
66
+ try {
67
+ result = await this.#runner.runChecked({
68
+ program: MARIVO_PRESENTATION_READ_PROGRAM,
69
+ args: [JSON.stringify({ sources: draft.sources, datasets: artifactSelections })],
70
+ limits: {
71
+ timeoutMs: PRESENTATION_EXECUTION_BUDGETS.sourceReadTimeoutMs,
72
+ stdoutMaxBytes: PRESENTATION_BUDGETS.documentBytes,
73
+ stderrMaxBytes: 65_536,
74
+ },
75
+ signal: options.signal,
76
+ });
77
+ }
78
+ catch (error) {
79
+ if (!(error instanceof MarivoEnvironmentError) || error.code !== 'subprocess-timeout')
80
+ throw error;
81
+ // Construct only safe operation metadata; upstream messages/details may contain secrets.
82
+ throw new MarivoEnvironmentError('subprocess-timeout', 'Presentation source reading timed out. Source projection did not complete; report submission has not started. Keep the draft and source declarations for retry; do not remove sources or rerun analysis to repair presentation.', {
83
+ phase: 'presentation-source-read',
84
+ timeoutMs: PRESENTATION_EXECUTION_BUDGETS.sourceReadTimeoutMs,
85
+ durationMs: Math.max(0, Math.round(performance.now() - startedAt)),
86
+ sourceCount: draft.sources.length,
87
+ sessionCount: new Set(draft.sources.map((source) => source.ref.sessionId)).size,
88
+ });
89
+ }
73
90
  this.#assertReady(options.signal);
74
91
  if (result.exitCode !== 0)
75
92
  throw new MarivoEnvironmentError('subprocess-failed', 'The bound Marivo presentation read failed.', { exitCode: result.exitCode });
@@ -2,6 +2,7 @@ import { randomUUID } from 'node:crypto';
2
2
  import { defineTool } from '@deepseek-ai/dsh-tools';
3
3
  import { registerMarivoTool } from "../tool-lifecycle.js";
4
4
  import { parsePresentationBuildId } from "./contracts/index.js";
5
+ import { PRESENTATION_EXECUTION_BUDGETS } from "./execution-policy.js";
5
6
  import { MARIVO_PRESENT_TOOL_NAME, MARIVO_PRESENTATION_DELIVERY_KIND, parsePresentationDelivery, presentationReceiptText, } from "./receipt.js";
6
7
  import { publishPresentation, resolvePresentation } from "./reports.js";
7
8
  /** One call projects a draft, builds the document, commits them, then emits the receipt. */
@@ -38,7 +39,7 @@ export function createMarivoPresentTool(source, session, lifecycleSignal) {
38
39
  ],
39
40
  presentationMeta: (_args, value) => JSON.parse(value.deliveryJson),
40
41
  },
41
- timeoutMs: 120_000,
42
+ timeoutMs: PRESENTATION_EXECUTION_BUDGETS.toolTimeoutMs,
42
43
  async execute(args, exec) {
43
44
  const signal = lifecycleSignal ? AbortSignal.any([exec.signal, lifecycleSignal]) : exec.signal;
44
45
  if (typeof args.draft_path !== 'string' ||
@@ -0,0 +1,17 @@
1
+ import { resolvePythonOptions } from "./datasource/python-options.js";
2
+ export const PYTHON_SETTINGS_NAMESPACE = 'dsh-data-analysis';
3
+ export function currentPythonOptions(options) {
4
+ const value = options.pythonTimeoutMs;
5
+ return resolvePythonOptions({
6
+ pythonTimeoutMs: value !== null && typeof value === 'object' && typeof value.get === 'function'
7
+ ? value.get()
8
+ : value,
9
+ });
10
+ }
11
+ /** Config is projected by the Host settings service; a headless composition reads its live entry. */
12
+ export function installPythonSettings(ctx, options) {
13
+ const dispose = ctx.inject(['settings'], (settingsCtx) => {
14
+ settingsCtx.effect(() => settingsCtx.settings.configure({ auto: false }, ctx.fiber));
15
+ });
16
+ return { get: () => currentPythonOptions(options), dispose: () => dispose.dispose() };
17
+ }
@@ -4,14 +4,29 @@ import * as navigation from './navigation.ts';
4
4
  import * as presentation from './presentation.ts';
5
5
  import * as python from './python.ts';
6
6
  import * as semantic from './semantic.ts';
7
+ import * as settings from './settings.ts';
7
8
  export declare const dictionaries: {
8
9
  credentials: typeof credentials;
9
10
  navigation: typeof navigation;
10
11
  presentation: typeof presentation;
11
12
  semantic: typeof semantic;
12
13
  python: typeof python;
14
+ settings: typeof settings;
13
15
  };
14
16
  export declare const zh: {
17
+ 'marivo.settings.title': "数据分析";
18
+ 'marivo.settings.timeout': "Python 默认执行超时(秒)";
19
+ 'marivo.settings.hint': "默认 120 秒。保存后对所有 Workspace 的下一次 Python 调用生效,不改变已开始调用的时限。单次调用可指定其他时限;仍受 Harness 执行限制约束。";
20
+ 'marivo.settings.description': "Python 执行设置。";
21
+ 'marivo.settings.expand': "展开设置";
22
+ 'marivo.settings.collapse': "收起设置";
23
+ 'marivo.settings.save': "保存";
24
+ 'marivo.settings.saving': "保存中…";
25
+ 'marivo.settings.discard': "放弃修改";
26
+ 'marivo.settings.unsaved': "未保存";
27
+ 'marivo.settings.invalid': "请输入 0.001 至 2147483.647 秒,最多三位小数。";
28
+ 'marivo.settings.read-only': "当前连接的设置只读。";
29
+ 'marivo.settings.failed': "保存失败或设置已被其他页面修改。草稿已保留;可放弃修改以读取最新值,再重试。";
15
30
  'marivo.python.input': "输入";
16
31
  'marivo.python.output': "输出";
17
32
  'marivo.python.raw': "原始输入/输出";
@@ -8,6 +8,7 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
8
8
  'marivo.presentation': keyof typeof dictionaries.presentation.zh;
9
9
  'marivo.semantic': keyof typeof dictionaries.semantic.zh;
10
10
  'marivo.python': keyof typeof dictionaries.python.zh;
11
+ 'marivo.settings': keyof typeof dictionaries.settings.zh;
11
12
  }
12
13
  }
13
14
  export declare function installCopy(ctx: Context): void;
@@ -0,0 +1,16 @@
1
+ export declare const zh: {
2
+ readonly 'marivo.settings.title': "数据分析";
3
+ readonly 'marivo.settings.timeout': "Python 默认执行超时(秒)";
4
+ readonly 'marivo.settings.hint': "默认 120 秒。保存后对所有 Workspace 的下一次 Python 调用生效,不改变已开始调用的时限。单次调用可指定其他时限;仍受 Harness 执行限制约束。";
5
+ readonly 'marivo.settings.description': "Python 执行设置。";
6
+ readonly 'marivo.settings.expand': "展开设置";
7
+ readonly 'marivo.settings.collapse': "收起设置";
8
+ readonly 'marivo.settings.save': "保存";
9
+ readonly 'marivo.settings.saving': "保存中…";
10
+ readonly 'marivo.settings.discard': "放弃修改";
11
+ readonly 'marivo.settings.unsaved': "未保存";
12
+ readonly 'marivo.settings.invalid': "请输入 0.001 至 2147483.647 秒,最多三位小数。";
13
+ readonly 'marivo.settings.read-only': "当前连接的设置只读。";
14
+ readonly 'marivo.settings.failed': "保存失败或设置已被其他页面修改。草稿已保留;可放弃修改以读取最新值,再重试。";
15
+ };
16
+ export declare const en: Record<keyof typeof zh, string>;
@@ -0,0 +1,9 @@
1
+ import type { ConfigForm } from '@deepseek-ai/dsh-client-ui-settings/client';
2
+ export interface PythonSettingsValue {
3
+ pythonTimeoutMs: number;
4
+ }
5
+ /** Seconds in the form, exact integer milliseconds at the Host boundary. */
6
+ export declare function timeoutMilliseconds(text: string): number | undefined;
7
+ export declare function PythonSettingsCard({ scope }: {
8
+ scope: ConfigForm<PythonSettingsValue>;
9
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,2 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ export declare function installSettings(ctx: Context): void;
@@ -1,9 +1,9 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
- import { inject, installRightTabs } from './client/right-tabs/install.tsx';
2
+ import { installRightTabs } from './client/right-tabs/install.tsx';
3
3
  export { marivoPresentationDeliveryDefinition, parsePresentationDurableContent, presentationDeliveryFromEvent, presentationsForNode, } from './client/presentation/delivery.ts';
4
4
  export { PresentationDeliveryModel } from './client/presentation/delivery-model.ts';
5
5
  export { HostPresentationReader } from './client/presentation/host-entry.tsx';
6
- export { inject };
6
+ export declare const inject: string[];
7
7
  export declare function apply(ctx: Context, options?: {
8
8
  diagnostics?: boolean;
9
9
  onInstalled?: (controller: ReturnType<typeof installRightTabs>) => void;
@@ -1,9 +1,8 @@
1
1
  export declare const DEFAULT_PYTHON_TIMEOUT_MS = 120000;
2
- export declare const DEFAULT_PYTHON_MAX_TIMEOUT_MS = 600000;
3
2
  export interface MarivoPythonOptions {
4
3
  pythonTimeoutMs?: number;
5
- pythonMaxTimeoutMs?: number;
6
4
  }
5
+ export type MarivoPythonOptionsSource = MarivoPythonOptions | (() => MarivoPythonOptions);
7
6
  /** Do not echo rejected inputs: tool arguments and configuration are not trusted diagnostics. */
8
7
  export declare function pythonTimeout(value: unknown, name: string): number;
9
8
  export declare function resolvePythonOptions(options: MarivoPythonOptions): Required<MarivoPythonOptions>;
@@ -1,6 +1,6 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
2
  import { type MarivoDatasourceBridgeSource } from './bridge.ts';
3
- import { type MarivoPythonOptions } from './python-options.ts';
3
+ import { type MarivoPythonOptionsSource } from './python-options.ts';
4
4
  import { type MarivoCredentialService } from './service.ts';
5
5
  export interface MarivoPythonExecutionSummary {
6
6
  phase: 'preparing' | 'executing' | 'capturing-code';
@@ -16,4 +16,4 @@ export declare class MarivoPythonExecutionError extends Error {
16
16
  readonly execution: MarivoPythonExecutionSummary;
17
17
  constructor(message: string, execution: MarivoPythonExecutionSummary);
18
18
  }
19
- export declare function registerMarivoPythonTool(ctx: Context, source: MarivoDatasourceBridgeSource, service: MarivoCredentialService, options?: MarivoPythonOptions): () => Promise<void>;
19
+ export declare function registerMarivoPythonTool(ctx: Context, source: MarivoDatasourceBridgeSource, service: MarivoCredentialService, options?: MarivoPythonOptionsSource): () => Promise<void>;
@@ -1,5 +1,13 @@
1
1
  import type { Agent } from '@deepseek-ai/dsh-agent';
2
2
  import type { MarivoDisclosureController } from './activation.ts';
3
+ declare module '@deepseek-ai/dsh-llm' {
4
+ interface MessageSourceMap {
5
+ plugin: {
6
+ kind: 'plugin';
7
+ plugin: string;
8
+ };
9
+ }
10
+ }
3
11
  export declare const MARIVO_DATASOURCE_CREDENTIAL_PROMPT: string;
4
12
  export declare const MARIVO_ANALYSIS_CLOSEOUT_PROMPT: string;
5
13
  /** Full-plugin seam: requires its execution tools, credentials service and system sections. */
@@ -17,6 +17,8 @@ export declare function createMarivoAgentInstallation(ctx: Context, environmentO
17
17
  credentials?: CredentialStore;
18
18
  credentialService?: MarivoCredentialService;
19
19
  credentialInteraction?: 'web' | 'none';
20
+ /** Read once at call admission so saved settings affect existing Agents. */
21
+ pythonOptionsSource?: () => MarivoPythonOptions;
20
22
  /** Runtime-scoped Help source; normal plugin installation never binds Help to a Workspace. */
21
23
  helpBridgeSource?: MarivoHelpBridgeSource;
22
24
  }): {
@@ -1,17 +1,17 @@
1
1
  import { type ReportPublishingConfig } from './report-publishing/config.ts';
2
+ import { type PythonTimeoutConfig } from './settings.ts';
2
3
  export { installMarivoPlugin, type MarivoPluginEnvironmentResolver } from './plugin-agents.ts';
3
4
  export { resolvePresentationWorkspace } from './workspace-identity.ts';
4
5
  import type { Context } from '@deepseek-ai/cordis';
5
6
  import z from '@deepseek-ai/schemastery';
6
7
  import type { DatasourceDefaults } from './datasource/defaults.ts';
7
- import { type MarivoPythonOptions } from './datasource/python-options.ts';
8
8
  export { MARIVO_DATASOURCE_CREDENTIAL_PROMPT } from './disclosure/execution-guidance.ts';
9
9
  /** Cordis plugin name used by loader diagnostics and lifecycle logs. */
10
10
  export declare const name = "dsh-data-analysis";
11
11
  /** Services that must exist before the plugin binds and watches Agent scopes. */
12
12
  export declare const inject: string[];
13
13
  /** Loader-safe configuration for the shared Runtime and per-Workspace bindings. */
14
- export interface Config extends MarivoPythonOptions {
14
+ export interface Config extends PythonTimeoutConfig {
15
15
  readonly reportPublishing?: ReportPublishingConfig;
16
16
  /** Non-secret creation defaults by backend; checked against each live Runtime schema. */
17
17
  readonly datasourceDefaults?: DatasourceDefaults;
@@ -28,6 +28,26 @@ export interface Config extends MarivoPythonOptions {
28
28
  readonly installTimeoutMs?: number;
29
29
  }
30
30
  /** Cordis loader schema. Runtime defaults are resolved in {@link apply}. */
31
- export declare const Config: z<Config>;
31
+ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
32
+ datasourceDefaults: z<any, any, "plain">;
33
+ reportPublishing: z<any, any, "plain">;
34
+ pythonTimeoutMs: z<number, number, "volatile-defined">;
35
+ credentialInteraction: z<"none" | "web", "none" | "web", "defined">;
36
+ projectRoot: z<string, string, "plain">;
37
+ pythonExecutable: z<string, string, "plain">;
38
+ runtimeRoot: z<string, string, "plain">;
39
+ bootstrapPythonExecutable: z<string, string, "plain">;
40
+ installTimeoutMs: z<number, number, "defined">;
41
+ }>>, Schemastery.ObjectT<NoInfer<{
42
+ datasourceDefaults: z<any, any, "plain">;
43
+ reportPublishing: z<any, any, "plain">;
44
+ pythonTimeoutMs: z<number, number, "volatile-defined">;
45
+ credentialInteraction: z<"none" | "web", "none" | "web", "defined">;
46
+ projectRoot: z<string, string, "plain">;
47
+ pythonExecutable: z<string, string, "plain">;
48
+ runtimeRoot: z<string, string, "plain">;
49
+ bootstrapPythonExecutable: z<string, string, "plain">;
50
+ installTimeoutMs: z<number, number, "defined">;
51
+ }>>, "plain">;
32
52
  /** Ensure the shared Runtime once, mount its skills, then bind each Workspace lazily. */
33
53
  export declare function apply(ctx: Context, config?: Config): Promise<() => Promise<void>>;
@@ -0,0 +1,5 @@
1
+ /** Report-specific wall-clock budgets; leave time after source reads for publication. */
2
+ export declare const PRESENTATION_EXECUTION_BUDGETS: Readonly<{
3
+ sourceReadTimeoutMs: 120000;
4
+ toolTimeoutMs: 180000;
5
+ }>;
@@ -1,3 +1,3 @@
1
1
  /** Dedicated plugin RPC envelopes over Harness-owned authenticated exact Fetch routes. */
2
- import { type ConnectionRpcHandler, type HostConnectionHandle } from '@deepseek-ai/dsh-client-connection';
3
- export declare function registerPluginRpc(connection: Pick<HostConnectionHandle, 'fetch'>, channel: string, endpoints: readonly string[], handler: ConnectionRpcHandler): () => Promise<void>;
2
+ import { type ConnectionRpcHandlerResult, type HostConnectionHandle } from '@deepseek-ai/dsh-client-connection';
3
+ export declare function registerPluginRpc(connection: Pick<HostConnectionHandle, 'fetch'>, channel: string, endpoints: readonly string[], handler: (endpoint: string, payload: unknown, signal: AbortSignal) => Promise<ConnectionRpcHandlerResult>): () => Promise<void>;
@@ -1,4 +1,4 @@
1
- import type { ConnectionRpcHandler, HostConnectionHandle } from '@deepseek-ai/dsh-client-connection';
1
+ import type { ConnectionRpcHandlerResult, HostConnectionHandle } from '@deepseek-ai/dsh-client-connection';
2
2
  import type { MarivoCheckedRunner } from '../environment/types.ts';
3
3
  import { SemanticReferenceBridge } from './bridge.ts';
4
4
  import { type SemanticReferenceUsage } from './usage.ts';
@@ -12,4 +12,4 @@ export declare class SemanticReferenceService {
12
12
  stop(): void;
13
13
  close(): Promise<void>;
14
14
  }
15
- export declare function registerSemanticReferenceRpc(connection: HostConnectionHandle, service: SemanticReferenceService, browser?: ConnectionRpcHandler): () => Promise<void>;
15
+ export declare function registerSemanticReferenceRpc(connection: HostConnectionHandle, service: SemanticReferenceService, browser?: (endpoint: string, payload: unknown, signal: AbortSignal) => Promise<ConnectionRpcHandlerResult>): () => Promise<void>;
@@ -0,0 +1,14 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import { type MarivoPythonOptions } from './datasource/python-options.ts';
3
+ export declare const PYTHON_SETTINGS_NAMESPACE = "dsh-data-analysis";
4
+ export interface PythonTimeoutConfig {
5
+ pythonTimeoutMs?: number | {
6
+ get(): number;
7
+ };
8
+ }
9
+ export declare function currentPythonOptions(options: PythonTimeoutConfig): Required<MarivoPythonOptions>;
10
+ /** Config is projected by the Host settings service; a headless composition reads its live entry. */
11
+ export declare function installPythonSettings(ctx: Context, options: PythonTimeoutConfig): {
12
+ get: () => Required<MarivoPythonOptions>;
13
+ dispose: () => Promise<void>;
14
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@chengxianglibra/dsh-data-analysis",
3
3
  "description": "Marivo runtime, live Help, secure datasource execution and presentation delivery for DeepSeek Harness",
4
- "version": "0.2.0",
4
+ "version": "0.2.2",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/chengxianglibra/dsh-data-analysis.git",
@@ -57,7 +57,8 @@
57
57
  "skills/dsh-data-analysis-files/**",
58
58
  "python/presentation-kit/dist/dsh_data_analysis_presentation_kit-1.1.0-py3-none-any.whl",
59
59
  "cordis.patch.yml",
60
- "README.md"
60
+ "README.md",
61
+ "README.en.md"
61
62
  ],
62
63
  "scripts": {
63
64
  "build": "npm run clean && tsc -p tsconfig.build.json && node scripts/finalize-build.mjs",
@@ -73,7 +74,7 @@
73
74
  "schema": "dsh-data-analysis-compatibility/v2",
74
75
  "dsh": {
75
76
  "distribution": "@deepseek-ai/dsh",
76
- "peerRange": ">=0.1.5-rc.1"
77
+ "peerRange": ">=0.1.7-rc.1"
77
78
  },
78
79
  "marivo": {
79
80
  "version": "0.5.5",
@@ -98,7 +99,11 @@
98
99
  "@deepseek-ai/dsh-client-ui-input-trigger",
99
100
  "@deepseek-ai/dsh-client-ui-sidebar",
100
101
  "@deepseek-ai/dsh-client-ui-layout",
101
- "@deepseek-ai/dsh-client-ui-sidebar-right"
102
+ "@deepseek-ai/dsh-client-ui-sidebar-right",
103
+ "@deepseek-ai/dsh-client-ui-settings",
104
+ "@deepseek-ai/dsh-client-ui-settings-plugins",
105
+ "@deepseek-ai/dsh-client-ui-plugin-manager",
106
+ "@deepseek-ai/dsh-client-ui-workspace"
102
107
  ],
103
108
  "platform": "web"
104
109
  },
@@ -109,37 +114,42 @@
109
114
  "dependencies": {
110
115
  "@aws-sdk/client-s3": "^3.1129.0",
111
116
  "@deepseek-ai/schemastery": "^3.18.1",
117
+ "@noble/hashes": "2.4.0",
112
118
  "zod": "^4.4.3"
113
119
  },
114
120
  "devDependencies": {
115
- "@deepseek-ai/dsh-agent-loop": "0.1.5-rc.1",
116
- "@deepseek-ai/dsh-anonymous-user-id": "0.1.5-rc.1",
117
- "@deepseek-ai/dsh-bash-local": "0.1.5-rc.1",
118
- "@deepseek-ai/dsh-client-store": "0.1.5-rc.1",
119
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.5-rc.1",
120
- "@deepseek-ai/dsh-client-ui-renderer": "0.1.5-rc.1",
121
- "@deepseek-ai/dsh-client-ui-sidebar-right": "0.1.5-rc.1",
122
- "@deepseek-ai/dsh-client-ui-slots": "0.1.5-rc.1",
123
- "@deepseek-ai/dsh-code-runtime": "0.1.5-rc.1",
124
- "@deepseek-ai/dsh-code-runtime-worker-thread": "0.1.5-rc.1",
125
- "@deepseek-ai/dsh-credentials-local": "0.1.5-rc.1",
126
- "@deepseek-ai/dsh-fs-local": "0.1.5-rc.1",
127
- "@deepseek-ai/dsh-fs-observation-policy": "0.1.5-rc.1",
128
- "@deepseek-ai/dsh-launch-environment": "0.1.5-rc.1",
129
- "@deepseek-ai/dsh-llm-deepseek": "0.1.5-rc.1",
130
- "@deepseek-ai/dsh-scope": "0.1.5-rc.1",
131
- "@deepseek-ai/dsh-session-persistence": "0.1.5-rc.1",
132
- "@deepseek-ai/dsh-session-persistence-jsonl": "0.1.5-rc.1",
133
- "@deepseek-ai/dsh-session-projection": "0.1.5-rc.1",
134
- "@deepseek-ai/dsh-skill": "0.1.5-rc.1",
135
- "@deepseek-ai/dsh-storage": "0.1.5-rc.1",
136
- "@deepseek-ai/dsh-storage-json": "0.1.5-rc.1",
137
- "@deepseek-ai/dsh-subprocess-local": "0.1.5-rc.1",
138
- "@deepseek-ai/dsh-tool-bash": "0.1.5-rc.1",
139
- "@deepseek-ai/dsh-tool-fs": "0.1.5-rc.1",
140
- "@deepseek-ai/dsh-tool-present": "0.1.5-rc.1",
141
- "@deepseek-ai/dsh-tool-skill": "0.1.5-rc.1",
142
- "@deepseek-ai/dsh-util-workspace-path": "0.1.5-rc.1",
121
+ "@deepseek-ai/dsh-app-boot": "0.1.7-rc.1",
122
+ "@deepseek-ai/dsh-config-editor": "0.1.7-rc.1",
123
+ "@deepseek-ai/dsh-agent-loop": "0.1.7-rc.1",
124
+ "@deepseek-ai/dsh-anonymous-user-id": "0.1.7-rc.1",
125
+ "@deepseek-ai/dsh-bash-local": "0.1.7-rc.1",
126
+ "@deepseek-ai/dsh-client-store": "0.1.7-rc.1",
127
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.1",
128
+ "@deepseek-ai/dsh-client-ui-plugin-manager": "0.1.7-rc.1",
129
+ "@deepseek-ai/dsh-client-ui-workspace": "0.1.7-rc.1",
130
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.1",
131
+ "@deepseek-ai/dsh-client-ui-sidebar-right": "0.1.7-rc.1",
132
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.1",
133
+ "@deepseek-ai/dsh-credentials-local": "0.1.7-rc.1",
134
+ "@deepseek-ai/dsh-fs-local": "0.1.7-rc.1",
135
+ "@deepseek-ai/dsh-sandbox-local": "0.1.7-rc.1",
136
+ "@deepseek-ai/dsh-sandbox-policy": "0.1.7-rc.1",
137
+ "@deepseek-ai/dsh-fs-observation-policy": "0.1.7-rc.1",
138
+ "@deepseek-ai/dsh-launch-environment": "0.1.7-rc.1",
139
+ "@deepseek-ai/dsh-llm-deepseek": "0.1.7-rc.1",
140
+ "@deepseek-ai/dsh-scope": "0.1.7-rc.1",
141
+ "@deepseek-ai/dsh-session-persistence": "0.1.7-rc.1",
142
+ "@deepseek-ai/dsh-session-persistence-jsonl": "0.1.7-rc.1",
143
+ "@deepseek-ai/dsh-session-projection": "0.1.7-rc.1",
144
+ "@deepseek-ai/dsh-skill": "0.1.7-rc.1",
145
+ "@deepseek-ai/dsh-storage": "0.1.7-rc.1",
146
+ "@deepseek-ai/dsh-storage-json": "0.1.7-rc.1",
147
+ "@deepseek-ai/dsh-subprocess-local": "0.1.7-rc.1",
148
+ "@deepseek-ai/dsh-tool-bash": "0.1.7-rc.1",
149
+ "@deepseek-ai/dsh-tool-fs": "0.1.7-rc.1",
150
+ "@deepseek-ai/dsh-tool-present": "0.1.7-rc.1",
151
+ "@deepseek-ai/dsh-tool-skill": "0.1.7-rc.1",
152
+ "@deepseek-ai/dsh-util-workspace-path": "0.1.7-rc.1",
143
153
  "@shikijs/core": "4.4.3",
144
154
  "@shikijs/engine-javascript": "4.4.3",
145
155
  "@shikijs/langs": "4.4.3",
@@ -155,41 +165,51 @@
155
165
  "recharts": "3.8.1",
156
166
  "sql-formatter": "15.8.2",
157
167
  "typescript": "^6.0.3",
158
- "zustand": "4.4.7"
168
+ "zustand": "4.4.7",
169
+ "@deepseek-ai/dsh-settings": "0.1.7-rc.1",
170
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.7-rc.1",
171
+ "@deepseek-ai/dsh-client-ui-settings-plugins": "0.1.7-rc.1",
172
+ "@deepseek-ai/dsh-ptc-runtime-node": "0.1.7-rc.1",
173
+ "@deepseek-ai/dsh-ptc-runtime": "0.1.7-rc.1"
159
174
  },
160
175
  "peerDependencies": {
161
176
  "@deepseek-ai/cordis": "^4.0.1",
162
- "@deepseek-ai/dsh-agent": ">=0.1.5-rc.1",
163
- "@deepseek-ai/dsh-api-gateway": ">=0.1.5-rc.1",
164
- "@deepseek-ai/dsh-api-session-controller": ">=0.1.5-rc.1",
165
- "@deepseek-ai/dsh-api-workspace-controller": ">=0.1.5-rc.1",
166
- "@deepseek-ai/dsh-atomic-write": ">=0.1.5-rc.1",
167
- "@deepseek-ai/dsh-client-connection": ">=0.1.5-rc.1",
168
- "@deepseek-ai/dsh-client-locale": ">=0.1.5-rc.1",
169
- "@deepseek-ai/dsh-client-ui-chat": ">=0.1.5-rc.1",
170
- "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.5-rc.1",
171
- "@deepseek-ai/dsh-client-ui-input-trigger": ">=0.1.5-rc.1",
172
- "@deepseek-ai/dsh-client-ui-layout": ">=0.1.5-rc.1",
173
- "@deepseek-ai/dsh-client-ui-primitives": ">=0.1.5-rc.1",
174
- "@deepseek-ai/dsh-client-ui-sidebar": ">=0.1.5-rc.1",
175
- "@deepseek-ai/dsh-client-ui-sidebar-right": ">=0.1.5-rc.1",
176
- "@deepseek-ai/dsh-client-ui-tool": ">=0.1.5-rc.1",
177
- "@deepseek-ai/dsh-credentials": ">=0.1.5-rc.1",
178
- "@deepseek-ai/dsh-home-paths": ">=0.1.5-rc.1",
179
- "@deepseek-ai/dsh-llm": ">=0.1.5-rc.1",
180
- "@deepseek-ai/dsh-sandbox": ">=0.1.5-rc.1",
181
- "@deepseek-ai/dsh-scope": ">=0.1.5-rc.1",
182
- "@deepseek-ai/dsh-session": ">=0.1.5-rc.1",
183
- "@deepseek-ai/dsh-shell": ">=0.1.5-rc.1",
184
- "@deepseek-ai/dsh-shell-env": ">=0.1.5-rc.1",
185
- "@deepseek-ai/dsh-skill-filesystem": ">=0.1.5-rc.1",
186
- "@deepseek-ai/dsh-storage-domain": ">=0.1.5-rc.1",
187
- "@deepseek-ai/dsh-system-prompt": ">=0.1.5-rc.1",
188
- "@deepseek-ai/dsh-tools": ">=0.1.5-rc.1",
189
- "@deepseek-ai/dsh-typert-protocol": ">=0.1.5-rc.1",
190
- "@deepseek-ai/dsh-typert-registry": ">=0.1.5-rc.1",
191
- "@deepseek-ai/dsh-util-values": ">=0.1.5-rc.1",
192
- "@deepseek-ai/dsh-workspace": ">=0.1.5-rc.1",
193
- "react": "^18.3.1"
177
+ "@deepseek-ai/dsh-agent": ">=0.1.7-rc.1",
178
+ "@deepseek-ai/dsh-api-gateway": ">=0.1.7-rc.1",
179
+ "@deepseek-ai/dsh-api-session-controller": ">=0.1.7-rc.1",
180
+ "@deepseek-ai/dsh-api-workspace-controller": ">=0.1.7-rc.1",
181
+ "@deepseek-ai/dsh-atomic-write": ">=0.1.7-rc.1",
182
+ "@deepseek-ai/dsh-client-connection": ">=0.1.7-rc.1",
183
+ "@deepseek-ai/dsh-client-locale": ">=0.1.7-rc.1",
184
+ "@deepseek-ai/dsh-client-ui-chat": ">=0.1.7-rc.1",
185
+ "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.7-rc.1",
186
+ "@deepseek-ai/dsh-client-ui-input-trigger": ">=0.1.7-rc.1",
187
+ "@deepseek-ai/dsh-client-ui-layout": ">=0.1.7-rc.1",
188
+ "@deepseek-ai/dsh-client-ui-primitives": ">=0.1.7-rc.1",
189
+ "@deepseek-ai/dsh-client-ui-plugin-manager": ">=0.1.7-rc.1",
190
+ "@deepseek-ai/dsh-client-ui-workspace": ">=0.1.7-rc.1",
191
+ "@deepseek-ai/dsh-client-ui-sidebar": ">=0.1.7-rc.1",
192
+ "@deepseek-ai/dsh-client-ui-sidebar-right": ">=0.1.7-rc.1",
193
+ "@deepseek-ai/dsh-client-ui-tool": ">=0.1.7-rc.1",
194
+ "@deepseek-ai/dsh-credentials": ">=0.1.7-rc.1",
195
+ "@deepseek-ai/dsh-home-paths": ">=0.1.7-rc.1",
196
+ "@deepseek-ai/dsh-llm": ">=0.1.7-rc.1",
197
+ "@deepseek-ai/dsh-sandbox": ">=0.1.7-rc.1",
198
+ "@deepseek-ai/dsh-scope": ">=0.1.7-rc.1",
199
+ "@deepseek-ai/dsh-session": ">=0.1.7-rc.1",
200
+ "@deepseek-ai/dsh-shell": ">=0.1.7-rc.1",
201
+ "@deepseek-ai/dsh-shell-env": ">=0.1.7-rc.1",
202
+ "@deepseek-ai/dsh-skill-filesystem": ">=0.1.7-rc.1",
203
+ "@deepseek-ai/dsh-storage-domain": ">=0.1.7-rc.1",
204
+ "@deepseek-ai/dsh-system-prompt": ">=0.1.7-rc.1",
205
+ "@deepseek-ai/dsh-tools": ">=0.1.7-rc.1",
206
+ "@deepseek-ai/dsh-typert-protocol": ">=0.1.7-rc.1",
207
+ "@deepseek-ai/dsh-typert-registry": ">=0.1.7-rc.1",
208
+ "@deepseek-ai/dsh-util-values": ">=0.1.7-rc.1",
209
+ "@deepseek-ai/dsh-workspace": ">=0.1.7-rc.1",
210
+ "react": "^18.3.1",
211
+ "@deepseek-ai/dsh-settings": ">=0.1.7-rc.1",
212
+ "@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-rc.1",
213
+ "@deepseek-ai/dsh-client-ui-settings-plugins": ">=0.1.7-rc.1"
194
214
  }
195
215
  }
@@ -1,32 +1,44 @@
1
1
  ---
2
2
  name: dsh-data-analysis-files
3
- description: 分析已上传或 Workspace 中的 CSV、JSON、Parquet、Excel 文件,使用 pandas 或 DuckDB 计算,按需导出 CSV、JSON、PNG 等普通文件或接入报告。无需先建立 Marivo datasource 或语义模型。
3
+ description: 分析附件或 Workspace 中的 CSV、JSON、Parquet、Excel 数据,回答问题或交付 CSV、TSV、XLSX、JSON、PNG 文件并使用原生表格预览。可接续报告展示,无需先建立 Marivo datasource 或语义模型。
4
4
  ---
5
5
 
6
6
  # 文件分析
7
7
 
8
+ 本 Skill 负责文件读取、计算、分析核对与普通文件交付。按用户问题选择方法;需要保存报告或交互展示时,完成分析后交给 `dsh-data-analysis-presentation`。
9
+
10
+ ## 确认输入与执行
11
+
8
12
  使用 Harness 提供的当前附件可读路径,或用户指定的 Workspace 文件;同名附件按消息和完整路径区分。路径不可读时报告实际问题,不猜测 Host 缓存位置。
13
+ 在实际读取代码中使用该完整路径,使执行记录保留输入身份;不为缩短路径而复制成 Workspace 同名文件,以免覆盖或在后续追问中读到旧副本。
9
14
 
10
- 文件读取、计算和最终文件生成(包括 CSV、JSON、PNG)均通过 `marivo_python` 在绑定 Runtime 中执行,不改走 Bash 的 `python`/`python3` 或其他解释器。纯本地文件分析可直接使用 pandas 或原生 `duckdb`,传 `datasources: []`;按任务选择或组合使用,无需 `md.raw_sql`、Marivo 分析 Skill、live Help 或语义建模。只有实际访问 Marivo datasource 时才声明其精确名称并查询相关契约。
15
+ 文件读取、计算和最终文件生成均通过 `marivo_python` 在绑定 Runtime 中执行,不改走 Bash 的 `python`/`python3` 或其他解释器。纯本地文件分析可直接使用 pandas 或原生 `duckdb`,传 `datasources: []`;无需 `md.raw_sql`、Marivo 分析 Skill、live Help 或语义建模。只有实际访问 Marivo datasource 时才声明其精确名称并查询相关契约。
11
16
 
12
17
  使用现有 reader,保留回答所需的 sheet、字段和解析范围;区分样本与全量。Excel `.xlsx` 可用 DuckDB `read_xlsx`,首次使用可能联网获取官方扩展;不承诺旧 `.xls` 或冷缓存离线读取,不临时安装 Python 依赖。
13
18
 
14
19
  每次 `marivo_python` 都是独立进程。原生 DuckDB 连接可在本次调用内复用、创建临时表,并及时关闭;后续追问重新读取原文件或已有结果,不依赖上次内存状态。按问题控制读取和输出规模,SQL `LIMIT` 不代表仅扫描这些行。
15
20
 
16
- ## 按用户目标交付
21
+ ## 计算与核对
22
+
23
+ 按问题确认粒度、单位、时间范围与比较基准;检查会影响计算的解析类型、缺失值、重复记录及连接基数。合并同名文件、筛选或去重时说明实际规则,不把缺失值当零,不把样本当全量。
17
24
 
18
- 普通答案直接用文字,不为结论额外创建文件。用户要求 CSV、JSON、PNG 等实际文件时,先通过 `marivo_python` 生成最终文件,优先写入当前绑定 Workspace;确认执行成功、文件存在后,调用当前实际可用的 Harness 原生 `present`,再回复用户。回复前分别核对文件生成与原生声明状态:生成文件、回复路径或展示代码块均不能替代原生交付。缺少 `present` 时,最终回复必须说明“文件已生成,原生交付能力不可用”,并提供准确路径;不能只说文件已生成。不猜测附件缓存或 Shell 私有临时目录。
25
+ 完成文字答案或生成交付物前,逐项核对用户问题及各比较分支。保留比较两侧、变化方向和比例分母,从原值核对差值、比例与合计;Top N 或子集不能替代全量结论。观测和数值贡献不自动证明原因;结论措辞应体现实际证据强度。
26
+ 最后核对解释文字中的比较名称与涨跌方向是否和表中同一项一致;基准不同可以解释比率差异,本身不能证明业务变化的原因。
19
27
 
20
- 需要交互图表、表格、报告或看板时加载 `dsh-data-analysis-presentation`,将 DataFrame 交给现有 writer,并关联实际返回的 `codeRef`,使用 `marivo_present` 保存固定 Build。在正文说明文件名与分析范围,不将文件结果冒充 Marivo Artifact 或 Evidence。普通 `present` 不赋予文件 Report/Build 或 Evidence 身份。
28
+ 某个基准或分支缺数据时,交付已有支持的答案,并明确缺失范围及影响,不用另一项成功比较替代。所需答案已有支持或已明确阻塞时结束,不为完善展示额外扩展分析。
21
29
 
22
- 报告内部的 `presentation.json`、computed 数据和 receipt 不作为默认附件;只有用户另行要求实际文件且文件已经存在于 Session 文件系统可访问位置时,才调用 `present`。阅读器下载/发布 HTML 沿用现有流程,浏览器内生成的下载不伪装成 Session 文件。
30
+ ## 可复用语义与停止条件
23
31
 
24
- ## 能力与失败
32
+ 分析中发现可供后续任务复用的业务定义或语义缺口时,先区分共享口径与本次结果:指标定义、维度含义或业务关系可作为语义候选;观测数值、临时筛选与未验证假设保留在当前分析中,不自动成为共享定义。
25
33
 
26
- 遵循 Harness [present 契约](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.5-rc.1/packages/fs/tool-present/README.md),由工具验证路径和文件类型。当前工具集中缺少 `present` 时,明确说明“文件已生成,原生交付能力不可用”,提供实际准确路径供手动使用,不虚构卡片,不安装工具或改写 profile。
34
+ 仅当当前问题需要该共享定义,或用户已授权语义沉淀时,加载 `marivo-semantic`,携带复用用途、已有依据、适用范围和未决含义,按其 Skill 与实时 Help 检查并优先复用已有对象。需要新增或修正时只处理最小必要缺口;业务含义与授权已明确则继续,实质歧义按语义 Skill 澄清,不自行猜测定义,也不重复请求已有授权。
35
+
36
+ 收到经验证的对象引用后继续原问题;必要对象已完成且原问题已回答,或阻塞已明确时停止。不递归扩展相邻指标、实体或业务域。顺带发现的范围外机会只在答复中简要说明用途与依据,不自动建模、另建记录文件或继续探索。普通文件计算仍无需语义建模;展示流程不承担语义沉淀。
37
+
38
+ ## 按用户目标交付
27
39
 
28
- 生成失败不声明成功;声明失败区分“文件已生成”和“交付未完成”,修复路径或可见性后只重试交付,不为补卡片重跑分析。响应不确定时先核对已有调用结果和事件,不盲目重复声明。原生打开失败时使用 Host 的预览或错误反馈,不绕过权限。
40
+ 普通答案和简短比较表格直接在聊天中回答,不额外创建文件。用户要查看或交付已有的 CSV、TSV、XLSX 表格文件时,确认当前 Session 可访问该文件后,按[文件交付](references/delivery.md)调用实际可用的 Harness 原生 `present`;交付卡片由 Harness 在右侧打开只读表格预览。用户要求生成 CSV、TSV、JSON、PNG 等实际文件时,通过 `marivo_python` 生成最终文件,优先写入当前绑定 Workspace;确认执行成功、文件存在后再调用 `present`。文件生成和原生声明分别核对,路径或代码块不能替代交付。不承诺插件能写入 XLSX,也不把 Harness 对旧 `.xls` 的预览当作插件可分析 `.xls`。
29
41
 
30
- 卡片打开当前源文件,不保存内容版本;修改、移动或删除会影响后续读取。成功声明的持久事件属于 Harness,即使 PTC 外层程序随后失败,也不撤销已成功的声明。子代理产物属于其调用 Session;父 Agent 如需交付,先确认自己能访问文件,再在父 Session 显式调用 `present`,不自动跨 Session 转投递。
42
+ 需要在报告中筛选或联动分析结果的图表、表格、报告或看板时加载 `dsh-data-analysis-presentation`,将 DataFrame 交给现有 writer,关联实际返回的 `codeRef`,用 `marivo_present` 保存固定 Build。在正文说明文件名与分析范围,不将文件结果冒充 Marivo Artifact 或 Evidence。普通 `present` 不赋予文件 Report/Build 或 Evidence 身份。
31
43
 
32
44
  需要起步代码时读[简短示例](references/examples.md);其中提供无需额外依赖的 PNG 写入代码,也通过 `marivo_python` 执行。
@@ -0,0 +1,15 @@
1
+ # 文件交付与恢复
2
+
3
+ 用户要求查看或交付 CSV、TSV、XLSX、JSON、PNG 等实际文件时读取本页。生成或确认文件后,按当前 Harness 原生 `present` 工具契约交付;不猜测附件缓存或 Shell 私有临时目录。工具拥有路径与类型校验,契约见 Harness `dsh-v0.1.7-rc.1/packages/deliverables/tool-present/README.zh.md`。
4
+
5
+ ## 生成与声明
6
+
7
+ 只交付用户要求的最终文件。报告内部的 `presentation.json`、computed 数据和 receipt 不作为默认附件;用户另行要求时,先确认实际文件已经存在且当前 Session 可访问。浏览器内生成的下载不伪装成 Session 文件;报告 HTML 交给展示 Skill 的导出或发布流程。
8
+
9
+ 文件生成成功,或用户要求预览且已有文件确认可访问后,调用 `present`,分别核对生成与声明结果。CSV、TSV、XLSX 由 Harness 原生表格预览读取文件,契约见 `dsh-v0.1.7-rc.1/packages/client/ui-sidebar-documentpreview/README.zh.md`;这是只读文件视图,不是 Marivo Report/Build,也不代表插件支持写入 XLSX 或分析旧 `.xls`。当前缺少 `present` 时,说明文件实际状态和原生交付能力不可用,并提供准确路径;不虚构卡片,不安装工具或改写 profile。
10
+
11
+ ## 失败与再次交付
12
+
13
+ 生成失败不声明成功;声明失败区分“文件已生成”和“交付未完成”。修复路径或可见性后只重试交付,不为补卡片重跑分析。响应不确定时先核对已有调用结果和事件,不盲目重复声明。原生打开失败时使用 Host 的预览或错误反馈,不绕过权限。
14
+
15
+ 卡片读取当前源文件,不保存内容版本;修改、移动或删除会影响后续读取。成功声明的持久事件属于 Harness,即使 PTC 外层程序随后失败,也不撤销已成功的声明。子代理产物属于其调用 Session;父 Agent 如需交付,先确认自己能访问文件,再在父 Session 显式调用 `present`,不自动跨 Session 转投递。