diff --git a/docs/module-graph.md b/docs/module-graph.md index 2f115877fe..48d3fc6f51 100644 --- a/docs/module-graph.md +++ b/docs/module-graph.md @@ -935,19 +935,9 @@ flowchart TD pkg_experimental_browser_use_stagehand_native --> pkg_browser_use pkg_experimental_browser_use_stagehand_native --> pkg_system_prompt pkg_experimental_browser_use_stagehand_native --> pkg_tools - pkg_experimental_client_ui_forge --> pkg_agent - pkg_experimental_client_ui_forge --> pkg_agent_controller - pkg_experimental_client_ui_forge --> pkg_experimental_forge - pkg_experimental_client_ui_forge --> pkg_experimental_forge_session pkg_experimental_client_ui_forge --> pkg_experimental_worktree - pkg_experimental_client_ui_forge --> pkg_fs - pkg_experimental_client_ui_forge --> pkg_sandbox - pkg_experimental_client_ui_forge --> pkg_sandbox_policy pkg_experimental_client_ui_forge --> pkg_session - pkg_experimental_client_ui_forge --> pkg_session_projection - pkg_experimental_client_ui_forge --> pkg_subprocess - pkg_experimental_client_ui_forge --> pkg_typert_protocol - pkg_experimental_client_ui_forge --> pkg_working_directory + pkg_experimental_client_ui_forge --> pkg_timeout pkg_experimental_computer_use_cua_driver_native --> pkg_computer_use pkg_experimental_computer_use_cua_driver_native --> pkg_system_prompt pkg_experimental_computer_use_cua_driver_native --> pkg_tools @@ -1735,7 +1725,7 @@ flowchart TD | [`experimental-browser-use-chrome-devtools-mcp`](../packages/experimental/browser-use-chrome-devtools-mcp) | `experimental` | [`agent`](../packages/core/agent), [`browser-use`](../packages/browser-use/browser-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) | | [`experimental-browser-use-playwright-mcp`](../packages/experimental/browser-use-playwright-mcp) | `experimental` | [`agent`](../packages/core/agent), [`browser-use`](../packages/browser-use/browser-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) | | [`experimental-browser-use-stagehand-native`](../packages/experimental/browser-use-stagehand-native) | `experimental` | [`agent`](../packages/core/agent), [`browser-use`](../packages/browser-use/browser-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) | -| [`experimental-client-ui-forge`](../packages/experimental/client-ui-forge) | `experimental` | [`agent`](../packages/core/agent), [`agent-controller`](../packages/core/agent-controller), [`experimental-forge`](../packages/experimental/forge), [`experimental-forge-session`](../packages/experimental/forge-session), [`experimental-worktree`](../packages/experimental/worktree), [`fs`](../packages/fs/fs), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`subprocess`](../packages/subprocess/subprocess), [`typert-protocol`](../packages/typert/protocol), [`working-directory`](../packages/session/working-directory) | +| [`experimental-client-ui-forge`](../packages/experimental/client-ui-forge) | `experimental` | [`experimental-worktree`](../packages/experimental/worktree), [`session`](../packages/core/session), [`timeout`](../packages/util/timeout) | | [`experimental-computer-use-cua-driver-native`](../packages/experimental/computer-use-cua-driver-native) | `experimental` | [`computer-use`](../packages/computer-use/computer-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) | | [`experimental-cua-macos`](../packages/experimental/cua-macos) | `experimental` | [`agent`](../packages/core/agent), [`computer-use`](../packages/computer-use/computer-use), [`subprocess`](../packages/subprocess/subprocess), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-questions`](../packages/interaction/user-questions) | | [`experimental-tool-worktree`](../packages/experimental/tool-worktree) | `experimental` | [`experimental-worktree`](../packages/experimental/worktree), [`tools`](../packages/core/tools) | diff --git a/docs/module-graph.zh.md b/docs/module-graph.zh.md index e569e3df31..70aacc9384 100644 --- a/docs/module-graph.zh.md +++ b/docs/module-graph.zh.md @@ -937,19 +937,9 @@ flowchart TD pkg_experimental_browser_use_stagehand_native --> pkg_browser_use pkg_experimental_browser_use_stagehand_native --> pkg_system_prompt pkg_experimental_browser_use_stagehand_native --> pkg_tools - pkg_experimental_client_ui_forge --> pkg_agent - pkg_experimental_client_ui_forge --> pkg_agent_controller - pkg_experimental_client_ui_forge --> pkg_experimental_forge - pkg_experimental_client_ui_forge --> pkg_experimental_forge_session pkg_experimental_client_ui_forge --> pkg_experimental_worktree - pkg_experimental_client_ui_forge --> pkg_fs - pkg_experimental_client_ui_forge --> pkg_sandbox - pkg_experimental_client_ui_forge --> pkg_sandbox_policy pkg_experimental_client_ui_forge --> pkg_session - pkg_experimental_client_ui_forge --> pkg_session_projection - pkg_experimental_client_ui_forge --> pkg_subprocess - pkg_experimental_client_ui_forge --> pkg_typert_protocol - pkg_experimental_client_ui_forge --> pkg_working_directory + pkg_experimental_client_ui_forge --> pkg_timeout pkg_experimental_computer_use_cua_driver_native --> pkg_computer_use pkg_experimental_computer_use_cua_driver_native --> pkg_system_prompt pkg_experimental_computer_use_cua_driver_native --> pkg_tools @@ -1737,7 +1727,7 @@ flowchart TD | [`experimental-browser-use-chrome-devtools-mcp`](../packages/experimental/browser-use-chrome-devtools-mcp) | `experimental` | [`agent`](../packages/core/agent), [`browser-use`](../packages/browser-use/browser-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) | | [`experimental-browser-use-playwright-mcp`](../packages/experimental/browser-use-playwright-mcp) | `experimental` | [`agent`](../packages/core/agent), [`browser-use`](../packages/browser-use/browser-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) | | [`experimental-browser-use-stagehand-native`](../packages/experimental/browser-use-stagehand-native) | `experimental` | [`agent`](../packages/core/agent), [`browser-use`](../packages/browser-use/browser-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) | -| [`experimental-client-ui-forge`](../packages/experimental/client-ui-forge) | `experimental` | [`agent`](../packages/core/agent), [`agent-controller`](../packages/core/agent-controller), [`experimental-forge`](../packages/experimental/forge), [`experimental-forge-session`](../packages/experimental/forge-session), [`experimental-worktree`](../packages/experimental/worktree), [`fs`](../packages/fs/fs), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`subprocess`](../packages/subprocess/subprocess), [`typert-protocol`](../packages/typert/protocol), [`working-directory`](../packages/session/working-directory) | +| [`experimental-client-ui-forge`](../packages/experimental/client-ui-forge) | `experimental` | [`experimental-worktree`](../packages/experimental/worktree), [`session`](../packages/core/session), [`timeout`](../packages/util/timeout) | | [`experimental-computer-use-cua-driver-native`](../packages/experimental/computer-use-cua-driver-native) | `experimental` | [`computer-use`](../packages/computer-use/computer-use), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) | | [`experimental-cua-macos`](../packages/experimental/cua-macos) | `experimental` | [`agent`](../packages/core/agent), [`computer-use`](../packages/computer-use/computer-use), [`subprocess`](../packages/subprocess/subprocess), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-questions`](../packages/interaction/user-questions) | | [`experimental-tool-worktree`](../packages/experimental/tool-worktree) | `experimental` | [`experimental-worktree`](../packages/experimental/worktree), [`tools`](../packages/core/tools) | diff --git a/packages/experimental/client-ui-forge/package.json b/packages/experimental/client-ui-forge/package.json index 538de45229..748fd71eca 100644 --- a/packages/experimental/client-ui-forge/package.json +++ b/packages/experimental/client-ui-forge/package.json @@ -57,25 +57,15 @@ "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "workspace:~", - "@deepseek-ai/dsh-agent": "workspace:*", - "@deepseek-ai/dsh-agent-controller": "workspace:*", - "@deepseek-ai/dsh-experimental-forge": "workspace:*", - "@deepseek-ai/dsh-experimental-forge-session": "workspace:*", "@deepseek-ai/dsh-experimental-worktree": "workspace:*", - "@deepseek-ai/dsh-fs": "workspace:*", - "@deepseek-ai/dsh-sandbox": "workspace:*", - "@deepseek-ai/dsh-sandbox-policy": "workspace:*", "@deepseek-ai/dsh-session": "workspace:*", - "@deepseek-ai/dsh-session-projection": "workspace:*", - "@deepseek-ai/dsh-subprocess": "workspace:*", - "@deepseek-ai/dsh-typert-protocol": "workspace:*", - "@deepseek-ai/dsh-working-directory": "workspace:*" + "@deepseek-ai/dsh-timeout": "workspace:*" }, "dependencies": { "@deepseek-ai/schemastery": "workspace:~", - "@deepseek-ai/dsh-timeout": "workspace:*", "@deepseek-ai/dsh-util-values": "workspace:*", - "zod": "^4.4.3" + "zod": "^4.4.3", + "@deepseek-ai/dsh-typert-protocol": "workspace:*" }, "devDependencies": { "@deepseek-ai/cordis": "workspace:~", @@ -109,13 +99,13 @@ "@deepseek-ai/dsh-subprocess": "workspace:*", "@deepseek-ai/dsh-subprocess-local": "workspace:*", "@deepseek-ai/dsh-system-prompt": "workspace:*", - "@deepseek-ai/dsh-typert-protocol": "workspace:*", "@deepseek-ai/dsh-util-workspace-path": "workspace:*", "@deepseek-ai/dsh-working-directory": "workspace:*", "@testing-library/react": "^16.3.3", "clsx": "^2.1.1", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "@deepseek-ai/dsh-timeout": "workspace:*" }, "files": [ "locale/*.json", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 96cede3702..9447e7a799 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8400,9 +8400,9 @@ importers: packages/experimental/client-ui-forge: dependencies: - '@deepseek-ai/dsh-timeout': + '@deepseek-ai/dsh-typert-protocol': specifier: workspace:* - version: link:../../util/timeout + version: link:../../typert/protocol '@deepseek-ai/dsh-util-values': specifier: workspace:* version: link:../../util/values @@ -8506,9 +8506,9 @@ importers: '@deepseek-ai/dsh-system-prompt': specifier: workspace:* version: link:../../core/system-prompt - '@deepseek-ai/dsh-typert-protocol': + '@deepseek-ai/dsh-timeout': specifier: workspace:* - version: link:../../typert/protocol + version: link:../../util/timeout '@deepseek-ai/dsh-util-workspace-path': specifier: workspace:* version: link:../../util/workspace-path diff --git a/scripts/package-dependency-policy.ts b/scripts/package-dependency-policy.ts index 95e498cdfc..5281c4db4c 100644 --- a/scripts/package-dependency-policy.ts +++ b/scripts/package-dependency-policy.ts @@ -68,9 +68,14 @@ const PEER_REQUIRED_HOST_EXPORTS = { '@deepseek-ai/dsh-user-questions': ['UserQuestionError'], // `instanceof` checks need the translator's own class instance. '@deepseek-ai/dsh-experimental-translator': ['TranslationError'], + // Stateless; a safe classification would turn the forge panel's worktree peer into a dependency. + '@deepseek-ai/dsh-experimental-worktree': ['generatedWorktreeName'], '@deepseek-ai/dsh-scope': ['carrierKeyOf', 'createScope', 'scopeOf', 'scopeTarget'], - '@deepseek-ai/dsh-session': ['SESSION_FORMAT_VERSION'], + // appendPluginRecord writes through the Session class's private log; pluginRecordOf is stateless. + '@deepseek-ai/dsh-session': ['SESSION_FORMAT_VERSION', 'appendPluginRecord', 'pluginRecordOf'], '@deepseek-ai/dsh-session-persistence': ['SessionPersistenceNotFoundError'], + // Readers recognize a deadline's TimeoutReason only by `instanceof` against their own copy. + '@deepseek-ai/dsh-timeout': ['deadline'], } as const satisfies HostDependencyExports /** Exact import specifier to reviewed runtime exports. */ diff --git a/scripts/verify-package-dependencies.spec.ts b/scripts/verify-package-dependencies.spec.ts index ca5f646337..4736079d59 100644 --- a/scripts/verify-package-dependencies.spec.ts +++ b/scripts/verify-package-dependencies.spec.ts @@ -247,6 +247,11 @@ describe('package dependency scope', () => { expect(PACKAGE_DEPENDENCY_POLICY.peerRequiredHostExports['@deepseek-ai/dsh-typert-protocol']).toBeUndefined() expect(PACKAGE_DEPENDENCY_POLICY.peerRequiredHostExports['@deepseek-ai/dsh-experimental-translator']) .toEqual(['TranslationError']) + expect(PACKAGE_DEPENDENCY_POLICY.peerRequiredHostExports['@deepseek-ai/dsh-experimental-worktree']) + .toEqual(['generatedWorktreeName']) + expect(PACKAGE_DEPENDENCY_POLICY.peerRequiredHostExports['@deepseek-ai/dsh-session']) + .toEqual(['SESSION_FORMAT_VERSION', 'appendPluginRecord', 'pluginRecordOf']) + expect(PACKAGE_DEPENDENCY_POLICY.peerRequiredHostExports['@deepseek-ai/dsh-timeout']).toEqual(['deadline']) }) it('discovers the Client directory, dsh.client declarations, and configured Host packages', () => { diff --git a/scripts/verify-plugin-record-callers.spec.ts b/scripts/verify-plugin-record-callers.spec.ts index c1ceedf82f..70b45a4963 100644 --- a/scripts/verify-plugin-record-callers.spec.ts +++ b/scripts/verify-plugin-record-callers.spec.ts @@ -6,6 +6,7 @@ import { afterEach, describe, expect, it } from 'vitest' import { checkDeclaredPluginRecordWrites, checkPluginRecordCallers, + DEPENDENCY_POLICY_FILE, findPluginRecordReferences, isAdmittedCaller, OWNER_FILE, @@ -132,10 +133,11 @@ describe('verify-plugin-record-callers', () => { expect(checkPluginRecordCallers(corpus(source))).toEqual([]) }) - it('admits experimental source, the owner, tests, and this gate', () => { + it('admits experimental source, the owner, tests, this gate, and the dependency policy', () => { for (const file of [ EXPERIMENTAL, OWNER_FILE, + DEPENDENCY_POLICY_FILE, 'packages/session/session-persistence/tests/live-write-contract.ts', 'apps/web/tests/session.e2e.ts', 'examples/demo/tests/demo.spec.ts', diff --git a/scripts/verify-plugin-record-callers.ts b/scripts/verify-plugin-record-callers.ts index 742096ab9c..e1a1b55e39 100644 --- a/scripts/verify-plugin-record-callers.ts +++ b/scripts/verify-plugin-record-callers.ts @@ -4,7 +4,8 @@ * `appendPluginRecord` in `@deepseek-ai/dsh-session` appends an ignorable `plugin:` record that the * experimental persistence catalogue lists and that a Session format migration keeps only on a best-effort * basis. Experimental packages may rely on that; a release package must declare its events instead. - * The owning module and test files, which exercise the operation, are exempt. + * The owning module and test files, which exercise the operation, are exempt, as is the published + * dependency policy, which names the function to classify the export without calling it. * * Discovery is syntax-aware: every identifier spelled `appendPluginRecord` counts — an import, a * named re-export, a call, a namespace member, a destructured binding, or an alias source — and so @@ -42,6 +43,9 @@ const GATE_FILES: ReadonlySet = new Set([ 'scripts/verify-plugin-record-callers.spec.ts', ]) +/** The published dependency policy names the restricted function to classify the export's package edge. */ +export const DEPENDENCY_POLICY_FILE = 'scripts/package-dependency-policy.ts' + const SOURCE_EXTENSION = /\.(?:[cm]?[jt]s|[jt]sx)$/u /** A line continuation, which a string or template literal drops from its value. */ @@ -99,10 +103,11 @@ export function isTestFile(file: string): boolean { /** * Whether a file may reference the restricted function. * @param file - repository-relative path, in POSIX separators. - * @returns whether the file is experimental source, the owner, a test, or this gate. + * @returns whether the file is experimental source, the owner, a test, this gate, or the dependency policy. */ export function isAdmittedCaller(file: string): boolean { return file.startsWith(EXPERIMENTAL_PREFIX) || file === OWNER_FILE || isTestFile(file) || GATE_FILES.has(file) + || file === DEPENDENCY_POLICY_FILE } function scriptKind(file: string): ts.ScriptKind {