@opengsd/gsd-pi 1.2.0-dev.955e4da0 → 1.2.0-dev.fb12b103
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.
- package/dist/cli-style.d.ts +17 -0
- package/dist/cli-style.js +28 -0
- package/dist/cli.js +1 -1
- package/dist/headless-events.d.ts +4 -2
- package/dist/headless-events.js +7 -29
- package/dist/models-resolver.d.ts +3 -13
- package/dist/models-resolver.js +3 -22
- package/dist/resource-loader.js +2 -14
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
- package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
- package/dist/resources/extensions/async-jobs/index.js +65 -0
- package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
- package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
- package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
- package/dist/resources/extensions/bg-shell/overlay.js +9 -6
- package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
- package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
- package/dist/resources/extensions/bg-shell/utilities.js +3 -0
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
- package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
- package/dist/resources/extensions/browser-tools/index.js +69 -12
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +30 -4
- package/dist/resources/extensions/gsd/auto/orchestrator.js +7 -5
- package/dist/resources/extensions/gsd/auto-dispatch.js +12 -1
- package/dist/resources/extensions/gsd/auto-model-selection.js +25 -6
- package/dist/resources/extensions/gsd/auto-post-unit.js +11 -2
- package/dist/resources/extensions/gsd/auto-prompts.js +15 -10
- package/dist/resources/extensions/gsd/auto-start.js +15 -10
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +7 -16
- package/dist/resources/extensions/gsd/auto-worktree.js +30 -90
- package/dist/resources/extensions/gsd/auto.js +4 -13
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +23 -6
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +122 -20
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +6 -2
- package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
- package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
- package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
- package/dist/resources/extensions/gsd/captures.js +4 -6
- package/dist/resources/extensions/gsd/constants.js +0 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +4 -12
- package/dist/resources/extensions/gsd/doctor-environment.js +2 -6
- package/dist/resources/extensions/gsd/doctor-format.js +9 -6
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +13 -15
- package/dist/resources/extensions/gsd/error-classifier.js +9 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
- package/dist/resources/extensions/gsd/guidance.js +98 -0
- package/dist/resources/extensions/gsd/guided-flow.js +17 -2
- package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
- package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
- package/dist/resources/extensions/gsd/migrate/safety.js +4 -1
- package/dist/resources/extensions/gsd/notification-store.js +11 -4
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +6 -4
- package/dist/resources/extensions/gsd/paths.js +27 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
- package/dist/resources/extensions/gsd/preferences-models.js +14 -48
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +1 -1
- package/dist/resources/extensions/gsd/prompts/system.md +5 -2
- package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
- package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
- package/dist/resources/extensions/gsd/publication.js +87 -0
- package/dist/resources/extensions/gsd/recovery-classification.js +37 -94
- package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
- package/dist/resources/extensions/gsd/state.js +1 -20
- package/dist/resources/extensions/gsd/stop-notice.js +57 -0
- package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +9 -7
- package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
- package/dist/resources/extensions/gsd/uat-policy.js +2 -1
- package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
- package/dist/resources/extensions/gsd/unit-context-composer.js +74 -1
- package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
- package/dist/resources/extensions/gsd/unit-registry.js +337 -0
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
- package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
- package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
- package/dist/resources/extensions/gsd/worktree-git-recovery.js +15 -9
- package/dist/resources/extensions/gsd/worktree-root.js +11 -0
- package/dist/resources/extensions/gsd/worktree-session-state.js +4 -5
- package/dist/resources/extensions/search-the-web/native-search.js +5 -3
- package/dist/resources/extensions/shared/browser-contract.js +59 -0
- package/dist/resources/extensions/shared/gsd-browser-cli.js +96 -5
- package/dist/resources/shared/package.json +3 -0
- package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
- package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/container.js +18 -26
- package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +14 -47
- package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
- package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
- package/dist/web/standalone/node_modules/postcss/lib/input.js +29 -54
- package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +37 -47
- package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +9 -26
- package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +55 -57
- package/dist/web/standalone/node_modules/postcss/lib/node.js +31 -99
- package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/parser.js +9 -10
- package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
- package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +11 -30
- package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
- package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
- package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
- package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +28 -69
- package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +2 -6
- package/dist/web/standalone/node_modules/postcss/package.json +48 -48
- package/dist/web/standalone/package.json +1 -1
- package/dist/worktree-cli.js +3 -6
- package/dist/worktree-status-banner.js +7 -15
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/rpc.d.ts +1 -0
- package/packages/contracts/dist/rpc.d.ts.map +1 -1
- package/packages/contracts/dist/rpc.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +4 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/cli.js +6 -3
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +8 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +17 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
- package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
- package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
- package/packages/pi-agent-core/dist/index.d.ts +1 -0
- package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/index.js +3 -0
- package/packages/pi-agent-core/dist/index.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +94 -382
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +149 -422
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
- package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
- package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
- package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +9 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
- package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
- package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
- package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
- package/src/resources/extensions/async-jobs/index.ts +79 -0
- package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
- package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
- package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
- package/src/resources/extensions/bg-shell/overlay.ts +9 -5
- package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
- package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
- package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
- package/src/resources/extensions/bg-shell/utilities.ts +3 -0
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
- package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
- package/src/resources/extensions/browser-tools/index.ts +71 -13
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +29 -1
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +34 -4
- package/src/resources/extensions/gsd/auto/orchestrator.ts +7 -5
- package/src/resources/extensions/gsd/auto-dispatch.ts +12 -0
- package/src/resources/extensions/gsd/auto-model-selection.ts +25 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +13 -2
- package/src/resources/extensions/gsd/auto-prompts.ts +40 -26
- package/src/resources/extensions/gsd/auto-start.ts +15 -10
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +10 -17
- package/src/resources/extensions/gsd/auto-worktree.ts +30 -93
- package/src/resources/extensions/gsd/auto.ts +8 -15
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +23 -6
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +151 -15
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +6 -2
- package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
- package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
- package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
- package/src/resources/extensions/gsd/captures.ts +4 -6
- package/src/resources/extensions/gsd/constants.ts +0 -3
- package/src/resources/extensions/gsd/crash-recovery.ts +3 -9
- package/src/resources/extensions/gsd/doctor-environment.ts +2 -7
- package/src/resources/extensions/gsd/doctor-format.ts +12 -7
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +13 -15
- package/src/resources/extensions/gsd/error-classifier.ts +11 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
- package/src/resources/extensions/gsd/guidance.ts +139 -0
- package/src/resources/extensions/gsd/guided-flow.ts +16 -2
- package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
- package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
- package/src/resources/extensions/gsd/migrate/safety.ts +4 -1
- package/src/resources/extensions/gsd/notification-store.ts +26 -3
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +6 -4
- package/src/resources/extensions/gsd/paths.ts +33 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
- package/src/resources/extensions/gsd/preferences-models.ts +12 -47
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +1 -1
- package/src/resources/extensions/gsd/prompts/system.md +5 -2
- package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
- package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
- package/src/resources/extensions/gsd/publication.ts +122 -0
- package/src/resources/extensions/gsd/recovery-classification.ts +42 -96
- package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
- package/src/resources/extensions/gsd/state.ts +4 -21
- package/src/resources/extensions/gsd/stop-notice.ts +75 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +16 -19
- package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
- package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
- package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
- package/src/resources/extensions/gsd/tests/guidance.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +53 -11
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +73 -58
- package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
- package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +24 -29
- package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +67 -2
- package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
- package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +2 -2
- package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +8 -7
- package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
- package/src/resources/extensions/gsd/uat-policy.ts +2 -1
- package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
- package/src/resources/extensions/gsd/unit-context-composer.ts +111 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
- package/src/resources/extensions/gsd/unit-registry.ts +412 -0
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
- package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
- package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
- package/src/resources/extensions/gsd/worktree-git-recovery.ts +15 -9
- package/src/resources/extensions/gsd/worktree-root.ts +12 -0
- package/src/resources/extensions/gsd/worktree-session-state.ts +3 -5
- package/src/resources/extensions/search-the-web/native-search.ts +5 -3
- package/src/resources/extensions/shared/browser-contract.ts +66 -0
- package/src/resources/extensions/shared/gsd-browser-cli.ts +119 -5
- package/src/resources/shared/package.json +3 -0
- package/src/resources/skills/create-skill/references/executable-code.md +1 -1
- package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
- /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → mU4QIDlpVHDdjDpeEKh5W}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → mU4QIDlpVHDdjDpeEKh5W}/_ssgManifest.js +0 -0
|
@@ -11,6 +11,11 @@ import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, realpathSync
|
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
import { tmpdir } from "node:os";
|
|
13
13
|
import { execSync } from "node:child_process";
|
|
14
|
+
import {
|
|
15
|
+
commitAll,
|
|
16
|
+
createGsdIntegrationProject,
|
|
17
|
+
writeGsdMilestoneContext,
|
|
18
|
+
} from "./gsd-integration-fixture.ts";
|
|
14
19
|
|
|
15
20
|
import {
|
|
16
21
|
createAutoWorktree,
|
|
@@ -32,17 +37,12 @@ function run(command: string, cwd: string): string {
|
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
function createTempRepo(): string {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
run("git add .", dir);
|
|
42
|
-
run("git commit -m init", dir);
|
|
43
|
-
// Ensure branch is called main
|
|
44
|
-
run("git branch -M main", dir);
|
|
45
|
-
return dir;
|
|
40
|
+
return createGsdIntegrationProject("auto-wt-test-").root;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function commitMilestoneContext(repo: string, milestoneId: string): void {
|
|
44
|
+
writeGsdMilestoneContext(repo, milestoneId);
|
|
45
|
+
commitAll(repo, "add milestone");
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
describe("auto-worktree lifecycle", () => {
|
|
@@ -59,13 +59,7 @@ describe("auto-worktree lifecycle", () => {
|
|
|
59
59
|
|
|
60
60
|
test("create → detect → teardown", () => {
|
|
61
61
|
tempDir = createTempRepo();
|
|
62
|
-
|
|
63
|
-
// Create .gsd/milestones/M003 with a dummy file (simulates planning artifacts)
|
|
64
|
-
const msDir = join(tempDir, ".gsd", "milestones", "M003");
|
|
65
|
-
mkdirSync(msDir, { recursive: true });
|
|
66
|
-
writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
|
|
67
|
-
run("git add .", tempDir);
|
|
68
|
-
run("git commit -m \"add milestone\"", tempDir);
|
|
62
|
+
commitMilestoneContext(tempDir, "M003");
|
|
69
63
|
|
|
70
64
|
// ─── createAutoWorktree ──────────────────────────────────────────
|
|
71
65
|
const wtPath = createAutoWorktree(tempDir, "M003");
|
|
@@ -112,11 +106,7 @@ describe("auto-worktree lifecycle", () => {
|
|
|
112
106
|
|
|
113
107
|
test("re-entry: create again, exit without teardown, re-enter", () => {
|
|
114
108
|
tempDir = createTempRepo();
|
|
115
|
-
|
|
116
|
-
mkdirSync(msDir, { recursive: true });
|
|
117
|
-
writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
|
|
118
|
-
run("git add .", tempDir);
|
|
119
|
-
run("git commit -m \"add milestone\"", tempDir);
|
|
109
|
+
commitMilestoneContext(tempDir, "M003");
|
|
120
110
|
|
|
121
111
|
const wtPath2 = createAutoWorktree(tempDir, "M003");
|
|
122
112
|
assert.ok(existsSync(wtPath2), "worktree re-created");
|
|
@@ -192,13 +182,62 @@ describe("auto-worktree lifecycle", () => {
|
|
|
192
182
|
}
|
|
193
183
|
});
|
|
194
184
|
|
|
185
|
+
test("legacy symlink-resolved auto worktree is detected after module state reset", () => {
|
|
186
|
+
tempDir = createTempRepo();
|
|
187
|
+
const savedGsdHome = process.env.GSD_HOME;
|
|
188
|
+
const fakeHome = realpathSync(mkdtempSync(join(tmpdir(), "auto-wt-home-legacy-")));
|
|
189
|
+
const storage = join(fakeHome, ".gsd", "projects", "abc123def456");
|
|
190
|
+
mkdirSync(join(storage, "milestones", "M001"), { recursive: true });
|
|
191
|
+
writeFileSync(join(storage, "milestones", "M001", "CONTEXT.md"), "# M001\n");
|
|
192
|
+
symlinkSync(storage, join(tempDir, ".gsd"));
|
|
193
|
+
process.env.GSD_HOME = join(fakeHome, ".gsd");
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
// Worktrees created by older versions live at .gsd/worktrees/<MID>;
|
|
197
|
+
// git resolves the symlink and registers them under external state.
|
|
198
|
+
// Detection must keep working for them — canonical .gsd-worktrees/
|
|
199
|
+
// creation never crosses the symlink, so create the legacy worktree
|
|
200
|
+
// explicitly.
|
|
201
|
+
const wtPath = join(tempDir, ".gsd", "worktrees", "M001");
|
|
202
|
+
run(`git worktree add -b milestone/M001 "${wtPath}"`, tempDir);
|
|
203
|
+
const realWtPath = realpathSync(wtPath);
|
|
204
|
+
assert.ok(realWtPath.startsWith(storage), "git registered the symlink-resolved worktree path");
|
|
205
|
+
|
|
206
|
+
_resetAutoWorktreeOriginalBaseForTests();
|
|
207
|
+
process.chdir(realWtPath);
|
|
208
|
+
|
|
209
|
+
assert.ok(isInAutoWorktree(tempDir), "structural detection works without module originalBase");
|
|
210
|
+
const resolved = getAutoWorktreePath(realWtPath, "M001");
|
|
211
|
+
assert.ok(resolved, "existing legacy worktree is found when basePath is the worktree path");
|
|
212
|
+
assert.equal(realpathSync(resolved!), realWtPath);
|
|
213
|
+
|
|
214
|
+
enterAutoWorktree(tempDir, "M001");
|
|
215
|
+
process.chdir(realWtPath);
|
|
216
|
+
assert.deepStrictEqual(
|
|
217
|
+
getActiveAutoWorktreeContext(),
|
|
218
|
+
{
|
|
219
|
+
originalBase: tempDir,
|
|
220
|
+
worktreeName: "M001",
|
|
221
|
+
branch: "milestone/M001",
|
|
222
|
+
},
|
|
223
|
+
"active context is detected from a symlink-resolved legacy worktree cwd",
|
|
224
|
+
);
|
|
225
|
+
} finally {
|
|
226
|
+
process.chdir(tempDir);
|
|
227
|
+
try {
|
|
228
|
+
teardownAutoWorktree(tempDir, "M001");
|
|
229
|
+
} catch {
|
|
230
|
+
// Best-effort cleanup for partially-created temp worktrees.
|
|
231
|
+
}
|
|
232
|
+
if (savedGsdHome === undefined) delete process.env.GSD_HOME;
|
|
233
|
+
else process.env.GSD_HOME = savedGsdHome;
|
|
234
|
+
rmSync(fakeHome, { recursive: true, force: true });
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
|
|
195
238
|
test("coexistence with manual worktree", async () => {
|
|
196
239
|
tempDir = createTempRepo();
|
|
197
|
-
|
|
198
|
-
mkdirSync(msDir, { recursive: true });
|
|
199
|
-
writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
|
|
200
|
-
run("git add .", tempDir);
|
|
201
|
-
run("git commit -m \"add milestone\"", tempDir);
|
|
240
|
+
commitMilestoneContext(tempDir, "M003");
|
|
202
241
|
|
|
203
242
|
// Import createWorktree directly for manual worktree
|
|
204
243
|
const { createWorktree } = await import("../../worktree-manager.ts");
|
|
@@ -221,11 +260,7 @@ describe("auto-worktree lifecycle", () => {
|
|
|
221
260
|
|
|
222
261
|
test("split-brain prevention: originalBase cleared after teardown", () => {
|
|
223
262
|
tempDir = createTempRepo();
|
|
224
|
-
|
|
225
|
-
mkdirSync(msDir, { recursive: true });
|
|
226
|
-
writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
|
|
227
|
-
run("git add .", tempDir);
|
|
228
|
-
run("git commit -m \"add milestone\"", tempDir);
|
|
263
|
+
commitMilestoneContext(tempDir, "M003");
|
|
229
264
|
|
|
230
265
|
createAutoWorktree(tempDir, "M003");
|
|
231
266
|
teardownAutoWorktree(tempDir, "M003");
|
|
@@ -235,11 +270,7 @@ describe("auto-worktree lifecycle", () => {
|
|
|
235
270
|
|
|
236
271
|
test("#1526: getMainBranch returns milestone/<MID> in auto-worktree", async () => {
|
|
237
272
|
tempDir = createTempRepo();
|
|
238
|
-
|
|
239
|
-
mkdirSync(msDir, { recursive: true });
|
|
240
|
-
writeFileSync(join(msDir, "CONTEXT.md"), "# M005 Context\n");
|
|
241
|
-
run("git add .", tempDir);
|
|
242
|
-
run("git commit -m \"add milestone\"", tempDir);
|
|
273
|
+
commitMilestoneContext(tempDir, "M005");
|
|
243
274
|
|
|
244
275
|
const { GitServiceImpl } = await import("../../git-service.ts");
|
|
245
276
|
|
|
@@ -259,11 +290,7 @@ describe("auto-worktree lifecycle", () => {
|
|
|
259
290
|
|
|
260
291
|
test("#1713: stale worktree directory without .git file", async () => {
|
|
261
292
|
tempDir = createTempRepo();
|
|
262
|
-
|
|
263
|
-
mkdirSync(msDir, { recursive: true });
|
|
264
|
-
writeFileSync(join(msDir, "CONTEXT.md"), "# M010 Context\n");
|
|
265
|
-
run("git add .", tempDir);
|
|
266
|
-
run("git commit -m \"add milestone\"", tempDir);
|
|
293
|
+
commitMilestoneContext(tempDir, "M010");
|
|
267
294
|
|
|
268
295
|
// Simulate a crash leaving a stale directory with no .git file.
|
|
269
296
|
const { worktreePath } = await import("../../worktree-manager.ts");
|
|
@@ -284,11 +311,7 @@ describe("auto-worktree lifecycle", () => {
|
|
|
284
311
|
|
|
285
312
|
test("#778: re-attach does not reconcile plan checkboxes into a worktree-local .gsd projection", async () => {
|
|
286
313
|
tempDir = createTempRepo();
|
|
287
|
-
|
|
288
|
-
mkdirSync(msDir, { recursive: true });
|
|
289
|
-
writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
|
|
290
|
-
run("git add .", tempDir);
|
|
291
|
-
run("git commit -m \"add milestone\"", tempDir);
|
|
314
|
+
commitMilestoneContext(tempDir, "M003");
|
|
292
315
|
|
|
293
316
|
const planRelPath = join(".gsd", "milestones", "M004", "slices", "S01", "S01-PLAN.md");
|
|
294
317
|
const planDir = join(tempDir, ".gsd", "milestones", "M004", "slices", "S01");
|
|
@@ -348,11 +371,7 @@ describe("auto-worktree lifecycle", () => {
|
|
|
348
371
|
|
|
349
372
|
test("#2791: mcp.json is not copied into worktree on creation after copyPlanningArtifacts removal", () => {
|
|
350
373
|
tempDir = createTempRepo();
|
|
351
|
-
|
|
352
|
-
mkdirSync(msDir, { recursive: true });
|
|
353
|
-
writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
|
|
354
|
-
run("git add .", tempDir);
|
|
355
|
-
run("git commit -m \"add milestone\"", tempDir);
|
|
374
|
+
commitMilestoneContext(tempDir, "M003");
|
|
356
375
|
|
|
357
376
|
// Create mcp.json in .gsd/ AFTER the commit (untracked, like real usage).
|
|
358
377
|
// Phase C removed copyPlanningArtifacts, so creation should not seed a
|
|
@@ -377,11 +396,7 @@ describe("auto-worktree lifecycle", () => {
|
|
|
377
396
|
|
|
378
397
|
test("#2791: mcp.json synced via syncGsdStateToWorktree (ROOT_STATE_FILES)", () => {
|
|
379
398
|
tempDir = createTempRepo();
|
|
380
|
-
|
|
381
|
-
mkdirSync(msDir, { recursive: true });
|
|
382
|
-
writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
|
|
383
|
-
run("git add .", tempDir);
|
|
384
|
-
run("git commit -m \"add milestone\"", tempDir);
|
|
399
|
+
commitMilestoneContext(tempDir, "M003");
|
|
385
400
|
|
|
386
401
|
// Create worktree first (no mcp.json yet)
|
|
387
402
|
const wtPath = createAutoWorktree(tempDir, "M003");
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
|
|
6
|
+
export type GsdIntegrationProject = {
|
|
7
|
+
root: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type CreateGsdIntegrationProjectOptions = {
|
|
11
|
+
prefix?: string;
|
|
12
|
+
initialFiles?: Record<string, string>;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function projectRoot(project: GsdIntegrationProject | string): string {
|
|
16
|
+
return typeof project === "string" ? project : project.root;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function git(project: GsdIntegrationProject | string, ...args: string[]): string {
|
|
20
|
+
return execFileSync("git", args, {
|
|
21
|
+
cwd: projectRoot(project),
|
|
22
|
+
encoding: "utf-8",
|
|
23
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
24
|
+
}).trim();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function createGsdIntegrationProject(
|
|
28
|
+
options: CreateGsdIntegrationProjectOptions | string = {},
|
|
29
|
+
): GsdIntegrationProject {
|
|
30
|
+
const resolvedOptions = typeof options === "string" ? { prefix: options } : options;
|
|
31
|
+
const prefix = resolvedOptions.prefix ?? "gsd-integration-";
|
|
32
|
+
const root = realpathSync(mkdtempSync(join(tmpdir(), prefix)));
|
|
33
|
+
|
|
34
|
+
git(root, "init");
|
|
35
|
+
git(root, "config", "user.email", "test@test.com");
|
|
36
|
+
git(root, "config", "user.name", "Test");
|
|
37
|
+
git(root, "config", "core.autocrlf", "false");
|
|
38
|
+
|
|
39
|
+
writeProjectFile(root, "README.md", "# test\n");
|
|
40
|
+
for (const [relativePath, content] of Object.entries(resolvedOptions.initialFiles ?? {})) {
|
|
41
|
+
writeProjectFile(root, relativePath, content);
|
|
42
|
+
}
|
|
43
|
+
git(root, "add", ".");
|
|
44
|
+
git(root, "commit", "-m", "init");
|
|
45
|
+
git(root, "branch", "-M", "main");
|
|
46
|
+
|
|
47
|
+
return { root };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function writeProjectFile(
|
|
51
|
+
project: GsdIntegrationProject | string,
|
|
52
|
+
relativePath: string,
|
|
53
|
+
content: string,
|
|
54
|
+
): string {
|
|
55
|
+
const filePath = join(projectRoot(project), relativePath);
|
|
56
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
57
|
+
writeFileSync(filePath, content, "utf-8");
|
|
58
|
+
return filePath;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function writeGsdMilestoneContext(
|
|
62
|
+
project: GsdIntegrationProject | string,
|
|
63
|
+
milestoneId: string,
|
|
64
|
+
content = `# ${milestoneId} Context\n`,
|
|
65
|
+
): string {
|
|
66
|
+
return writeProjectFile(
|
|
67
|
+
project,
|
|
68
|
+
join(".gsd", "milestones", milestoneId, "CONTEXT.md"),
|
|
69
|
+
content,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function commitAll(project: GsdIntegrationProject | string, message: string): void {
|
|
74
|
+
git(project, "add", ".");
|
|
75
|
+
git(project, "commit", "-m", message);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function cleanupGsdIntegrationProject(project: GsdIntegrationProject | string): void {
|
|
79
|
+
rmSync(projectRoot(project), { recursive: true, force: true });
|
|
80
|
+
}
|
|
@@ -60,7 +60,9 @@ test("ensureProjectWorkflowMcpConfig creates .mcp.json with workflow and browser
|
|
|
60
60
|
assert.equal(typeof browserArgs[mcpArgIndex + 6], "string");
|
|
61
61
|
assert.ok((browserArgs[mcpArgIndex + 6] ?? "").length > 0, "identity-key must be non-empty");
|
|
62
62
|
assert.equal(browserArgs[mcpArgIndex + 7], "--identity-project");
|
|
63
|
-
assert.equal(browserArgs[mcpArgIndex + 8],
|
|
63
|
+
assert.equal(typeof browserArgs[mcpArgIndex + 8], "string");
|
|
64
|
+
assert.ok((browserArgs[mcpArgIndex + 8] ?? "").length > 0, "identity-project must be non-empty");
|
|
65
|
+
assert.doesNotMatch(browserArgs[mcpArgIndex + 8] ?? "", /[\\/]/, "identity-project must not be a filesystem path");
|
|
64
66
|
assert.equal((browserServer as { cwd?: string })?.cwd, projectRoot);
|
|
65
67
|
|
|
66
68
|
const settings = JSON.parse(readFileSync(join(projectRoot, ".claude", "settings.local.json"), "utf-8")) as {
|
|
@@ -14,7 +14,7 @@ import { tmpdir } from "node:os";
|
|
|
14
14
|
import { resolveExpectedArtifactPath } from "../auto-artifact-paths.ts";
|
|
15
15
|
import { unitPhaseLabel, unitVerb } from "../auto-dashboard.ts";
|
|
16
16
|
import { classifyUnitPhase } from "../metrics.ts";
|
|
17
|
-
import { resolveModelWithFallbacksForUnit } from "../preferences-models.ts";
|
|
17
|
+
import { resolveDefaultSessionModel, resolveModelWithFallbacksForUnit } from "../preferences-models.ts";
|
|
18
18
|
import { KNOWN_UNIT_LABELS } from "../preferences-types.ts";
|
|
19
19
|
|
|
20
20
|
function withModelPreferences<T>(fn: () => T): T {
|
|
@@ -92,6 +92,37 @@ test("run-uat falls back to completion when uat bucket is not configured", () =>
|
|
|
92
92
|
}
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
+
test("default session model resolves from the explicit project base path", () => {
|
|
96
|
+
const oldHome = process.env.GSD_HOME;
|
|
97
|
+
const originalCwd = process.cwd();
|
|
98
|
+
const home = mkdtempSync(join(tmpdir(), "gsd-model-map-home-"));
|
|
99
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-model-map-project-"));
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
process.env.GSD_HOME = home;
|
|
103
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
104
|
+
writeFileSync(join(base, ".gsd", "PREFERENCES.md"), [
|
|
105
|
+
"---",
|
|
106
|
+
"models:",
|
|
107
|
+
" execution: gpt-5.5",
|
|
108
|
+
"---",
|
|
109
|
+
"",
|
|
110
|
+
].join("\n"));
|
|
111
|
+
process.chdir(home);
|
|
112
|
+
|
|
113
|
+
assert.deepEqual(resolveDefaultSessionModel("openai-codex", base), {
|
|
114
|
+
provider: "openai-codex",
|
|
115
|
+
id: "gpt-5.5",
|
|
116
|
+
});
|
|
117
|
+
} finally {
|
|
118
|
+
process.chdir(originalCwd);
|
|
119
|
+
if (oldHome === undefined) delete process.env.GSD_HOME;
|
|
120
|
+
else process.env.GSD_HOME = oldHome;
|
|
121
|
+
rmSync(home, { recursive: true, force: true });
|
|
122
|
+
rmSync(base, { recursive: true, force: true });
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
95
126
|
test("every known unit label with a dispatch phase resolves when all model buckets are configured", () => {
|
|
96
127
|
withModelPreferences(() => {
|
|
97
128
|
const missing = KNOWN_UNIT_LABELS.filter((unitType) => !resolveModelWithFallbacksForUnit(unitType));
|
|
@@ -306,6 +306,38 @@ describe("notification-store", () => {
|
|
|
306
306
|
rmSync(lockPath, { force: true });
|
|
307
307
|
});
|
|
308
308
|
|
|
309
|
+
test("structured meta persists kind and scope on the entry", () => {
|
|
310
|
+
initNotificationStore(tmp);
|
|
311
|
+
appendNotification("Auto-mode blocked — validation gate", "warning", "notify", { kind: "auto-stop", scope: "M005" });
|
|
312
|
+
|
|
313
|
+
const entries = readNotifications();
|
|
314
|
+
assert.equal(entries.length, 1);
|
|
315
|
+
assert.equal(entries[0].kind, "auto-stop");
|
|
316
|
+
assert.equal(entries[0].scope, "M005");
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
test("dedup keys on kind+scope when present, not on prose", () => {
|
|
320
|
+
initNotificationStore(tmp);
|
|
321
|
+
appendNotification("Auto-mode blocked — validation gate", "warning", "notify", { kind: "auto-stop", scope: "M005" });
|
|
322
|
+
// Rephrased message, same structured identity → deduped within the window
|
|
323
|
+
appendNotification("Auto-mode blocked — gate rejected", "warning", "notify", { kind: "auto-stop", scope: "M005" });
|
|
324
|
+
// Same kind, different scope → distinct
|
|
325
|
+
appendNotification("Auto-mode blocked — validation gate", "warning", "notify", { kind: "auto-stop", scope: "M006" });
|
|
326
|
+
|
|
327
|
+
assert.equal(readNotifications().length, 2);
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
test("readNotifications filters by kind and scope", () => {
|
|
331
|
+
initNotificationStore(tmp);
|
|
332
|
+
appendNotification("a", "info", "notify", { kind: "auto-stop", scope: "M005" });
|
|
333
|
+
appendNotification("b", "info", "notify", { kind: "provider-error-pause", scope: "M005" });
|
|
334
|
+
appendNotification("c", "info");
|
|
335
|
+
|
|
336
|
+
assert.equal(readNotifications(tmp, { kind: "auto-stop" }).length, 1);
|
|
337
|
+
assert.equal(readNotifications(tmp, { scope: "M005" }).length, 2);
|
|
338
|
+
assert.equal(readNotifications(tmp, { kind: "provider-error-pause", scope: "M005" })[0].message, "b");
|
|
339
|
+
});
|
|
340
|
+
|
|
309
341
|
test("listeners are notified on append, markAllRead, and clear", () => {
|
|
310
342
|
initNotificationStore(tmp);
|
|
311
343
|
let calls = 0;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth/subscription vs pay-per-token API routing for bare model IDs.
|
|
3
|
+
*
|
|
4
|
+
* When the same model ID (e.g. gpt-5.5) exists on multiple providers, resolveModelId
|
|
5
|
+
* must prefer subscription/OAuth routes over platform API keys.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import test from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import { MODELS } from "../../../../../packages/pi-ai/dist/models.generated.js";
|
|
11
|
+
import {
|
|
12
|
+
BARE_ID_SUBSCRIPTION_PROVIDER_PRECEDENCE,
|
|
13
|
+
resolveModelId,
|
|
14
|
+
} from "../auto-model-selection.js";
|
|
15
|
+
|
|
16
|
+
type ModelRef = { id: string; provider: string };
|
|
17
|
+
|
|
18
|
+
function modelsForProviders(modelId: string, providers: string[]): ModelRef[] {
|
|
19
|
+
return providers.map((provider) => ({ id: modelId, provider }));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Table-driven precedence cases — one row per conflict shape, not per model ID. */
|
|
23
|
+
const PRECEDENCE_CASES: Array<{
|
|
24
|
+
label: string;
|
|
25
|
+
modelId: string;
|
|
26
|
+
providers: string[];
|
|
27
|
+
expected: string;
|
|
28
|
+
currentProvider?: string;
|
|
29
|
+
}> = [
|
|
30
|
+
{
|
|
31
|
+
label: "ChatGPT OAuth beats OpenAI API (gpt-5.5)",
|
|
32
|
+
modelId: "gpt-5.5",
|
|
33
|
+
providers: ["openai", "openai-codex"],
|
|
34
|
+
expected: "openai-codex",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
label: "Codex beats Copilot beats OpenAI API (gpt-5.5 triple)",
|
|
38
|
+
modelId: "gpt-5.5",
|
|
39
|
+
providers: ["openai", "github-copilot", "openai-codex"],
|
|
40
|
+
expected: "openai-codex",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
label: "Copilot OAuth beats OpenAI API when no Codex (gpt-5.5)",
|
|
44
|
+
modelId: "gpt-5.5",
|
|
45
|
+
providers: ["openai", "github-copilot"],
|
|
46
|
+
expected: "github-copilot",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
label: "Copilot OAuth beats OpenAI API (gpt-5-mini)",
|
|
50
|
+
modelId: "gpt-5-mini",
|
|
51
|
+
providers: ["openai", "github-copilot"],
|
|
52
|
+
expected: "github-copilot",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
label: "Anthropic beats Copilot for Claude (claude-sonnet-4-6)",
|
|
56
|
+
modelId: "claude-sonnet-4-6",
|
|
57
|
+
providers: ["anthropic", "github-copilot"],
|
|
58
|
+
expected: "anthropic",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
label: "Copilot beats Google API for Gemini (gemini-2.5-pro)",
|
|
62
|
+
modelId: "gemini-2.5-pro",
|
|
63
|
+
providers: ["google", "github-copilot"],
|
|
64
|
+
expected: "github-copilot",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
label: "Gemini CLI beats Google API (gemini-2.5-pro)",
|
|
68
|
+
modelId: "gemini-2.5-pro",
|
|
69
|
+
providers: ["google", "google-gemini-cli"],
|
|
70
|
+
expected: "google-gemini-cli",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
label: "Gemini CLI beats Copilot beats Google API",
|
|
74
|
+
modelId: "gemini-2.5-pro",
|
|
75
|
+
providers: ["google", "github-copilot", "google-gemini-cli"],
|
|
76
|
+
expected: "google-gemini-cli",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
label: "Session provider still wins (openai-codex explicit)",
|
|
80
|
+
modelId: "gpt-5.5",
|
|
81
|
+
providers: ["openai", "openai-codex", "github-copilot"],
|
|
82
|
+
expected: "github-copilot",
|
|
83
|
+
currentProvider: "github-copilot",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
label: "claude-code session beats anthropic (#3772)",
|
|
87
|
+
modelId: "claude-sonnet-4-6",
|
|
88
|
+
providers: ["anthropic", "claude-code"],
|
|
89
|
+
expected: "claude-code",
|
|
90
|
+
currentProvider: "claude-code",
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
for (const row of PRECEDENCE_CASES) {
|
|
95
|
+
test(`resolveModelId precedence: ${row.label}`, () => {
|
|
96
|
+
const available = modelsForProviders(row.modelId, row.providers);
|
|
97
|
+
const result = resolveModelId(row.modelId, available, row.currentProvider);
|
|
98
|
+
assert.ok(result, `expected a match for ${row.modelId}`);
|
|
99
|
+
assert.equal(result.provider, row.expected);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
test("BARE_ID_SUBSCRIPTION_PROVIDER_PRECEDENCE covers known OAuth/subscription providers", () => {
|
|
104
|
+
const expected = [
|
|
105
|
+
"openai-codex",
|
|
106
|
+
"google-gemini-cli",
|
|
107
|
+
"anthropic",
|
|
108
|
+
"github-copilot",
|
|
109
|
+
"google-antigravity",
|
|
110
|
+
];
|
|
111
|
+
assert.deepEqual([...BARE_ID_SUBSCRIPTION_PROVIDER_PRECEDENCE], expected);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("every catalog overlap with OAuth/subscription + API resolves to subscription route", () => {
|
|
115
|
+
const oauthProviders = new Set(["anthropic", "github-copilot", "openai-codex"]);
|
|
116
|
+
const subscriptionCli = new Set(["google-gemini-cli", "google-antigravity", "claude-code"]);
|
|
117
|
+
const apiPayPerToken = new Set(["openai", "google", "azure-openai-responses"]);
|
|
118
|
+
|
|
119
|
+
const byId = new Map<string, Set<string>>();
|
|
120
|
+
for (const [provider, models] of Object.entries(MODELS)) {
|
|
121
|
+
for (const id of Object.keys(models)) {
|
|
122
|
+
if (!byId.has(id)) byId.set(id, new Set());
|
|
123
|
+
byId.get(id)!.add(provider);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const failures: string[] = [];
|
|
128
|
+
|
|
129
|
+
for (const [modelId, providers] of byId) {
|
|
130
|
+
if (providers.size < 2) continue;
|
|
131
|
+
|
|
132
|
+
const hasApi = [...providers].some((p) => apiPayPerToken.has(p));
|
|
133
|
+
const subscriptionCandidates = [...providers].filter(
|
|
134
|
+
(p) => oauthProviders.has(p) || subscriptionCli.has(p),
|
|
135
|
+
);
|
|
136
|
+
if (!hasApi || subscriptionCandidates.length === 0) continue;
|
|
137
|
+
|
|
138
|
+
const testProviders = new Set<string>(subscriptionCandidates);
|
|
139
|
+
for (const p of providers) {
|
|
140
|
+
if (apiPayPerToken.has(p)) testProviders.add(p);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const available = modelsForProviders(modelId, [...testProviders]);
|
|
144
|
+
const result = resolveModelId(modelId, available, undefined);
|
|
145
|
+
if (!result) {
|
|
146
|
+
failures.push(`${modelId}: no resolution among ${[...testProviders].join(", ")}`);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const winnerIsSubscription =
|
|
151
|
+
oauthProviders.has(result.provider) ||
|
|
152
|
+
subscriptionCli.has(result.provider) ||
|
|
153
|
+
result.provider === "anthropic";
|
|
154
|
+
|
|
155
|
+
if (!winnerIsSubscription) {
|
|
156
|
+
failures.push(
|
|
157
|
+
`${modelId}: got ${result.provider}, expected subscription route among ${[...testProviders].join(", ")}`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
assert.equal(
|
|
163
|
+
failures.length,
|
|
164
|
+
0,
|
|
165
|
+
`catalog overlap routing failures:\n${failures.join("\n")}`,
|
|
166
|
+
);
|
|
167
|
+
});
|