@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
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Deterministic timing tests for the exec-sandbox graceful-kill
|
|
3
|
+
// ladder + hard-deadline force-resolve (S04/T02).
|
|
4
|
+
//
|
|
5
|
+
// T01 extended runExecSandbox's timeout path to a graceful
|
|
6
|
+
// SIGTERM -> grace -> SIGKILL ladder (via killProcessTree) plus a caller-side
|
|
7
|
+
// force-resolve hard deadline so a non-closing ("D-state") child can never hang
|
|
8
|
+
// the awaiting promise. A true D-state child is non-portable, so we simulate the
|
|
9
|
+
// exact symptom deterministically:
|
|
10
|
+
// 1. A SIGTERM-cooperative child (trap 'exit 0' TERM) closes promptly on the
|
|
11
|
+
// first SIGTERM — proving the ladder resolves via `close` well before the
|
|
12
|
+
// force-resolve deadline.
|
|
13
|
+
// 2. A SIGTERM-ignoring (trap '' TERM) child combined with a LARGE
|
|
14
|
+
// kill_grace_ms (so SIGKILL never fires in-window) and a SHORT
|
|
15
|
+
// force_resolve_delay_ms — the only way the promise can settle is the
|
|
16
|
+
// hard deadline, proving the no-hang guarantee.
|
|
17
|
+
//
|
|
18
|
+
// Unlike the sync bash path (which throws on force-resolve), runExecSandbox
|
|
19
|
+
// always RESOLVES; force-resolve calls finalize(null, "SIGKILL") and preserves
|
|
20
|
+
// timed_out === true so the agent can still distinguish a graceful timeout exit
|
|
21
|
+
// from a forced kill.
|
|
22
|
+
|
|
23
|
+
import { test } from 'node:test';
|
|
24
|
+
import assert from 'node:assert/strict';
|
|
25
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
26
|
+
import { tmpdir } from 'node:os';
|
|
27
|
+
import { join } from 'node:path';
|
|
28
|
+
|
|
29
|
+
import { EXEC_DEFAULTS, runExecSandbox, type ExecSandboxOptions } from '../exec-sandbox.ts';
|
|
30
|
+
|
|
31
|
+
const isWin = process.platform === 'win32';
|
|
32
|
+
|
|
33
|
+
function freshBase(): string {
|
|
34
|
+
return mkdtempSync(join(tmpdir(), 'gsd-exec-gracekill-'));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function cleanup(dir: string): void {
|
|
38
|
+
rmSync(dir, { recursive: true, force: true });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function baseOpts(base: string, overrides: Partial<ExecSandboxOptions> = {}): ExecSandboxOptions {
|
|
42
|
+
return {
|
|
43
|
+
baseDir: base,
|
|
44
|
+
clamp_timeout_ms: EXEC_DEFAULTS.clampTimeoutMs,
|
|
45
|
+
default_timeout_ms: 10_000,
|
|
46
|
+
stdout_cap_bytes: 1_024,
|
|
47
|
+
stderr_cap_bytes: 1_024,
|
|
48
|
+
digest_chars: 120,
|
|
49
|
+
env_allowlist: EXEC_DEFAULTS.envAllowlist,
|
|
50
|
+
...overrides,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Wall-clock guard: reject if the call has not settled by `ms`. Proves no-hang
|
|
55
|
+
// independently of the assertions on timing/markers.
|
|
56
|
+
function wallClockGuard<T>(promise: Promise<T>, ms: number): Promise<T> {
|
|
57
|
+
return Promise.race([
|
|
58
|
+
promise,
|
|
59
|
+
new Promise<never>((_, reject) => {
|
|
60
|
+
const t = setTimeout(() => reject(new Error(`Call did not settle within ${ms}ms (hang)`)), ms);
|
|
61
|
+
if (typeof t === 'object' && 'unref' in t) t.unref();
|
|
62
|
+
}),
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Clean up a detached child (and its process group) that a large kill_grace_ms
|
|
67
|
+
// intentionally leaves alive past the force-resolve deadline.
|
|
68
|
+
function cleanupByPidFile(pidFile: string): void {
|
|
69
|
+
if (!existsSync(pidFile)) return;
|
|
70
|
+
const pid = Number.parseInt(readFileSync(pidFile, 'utf-8').trim(), 10);
|
|
71
|
+
if (!Number.isFinite(pid) || pid <= 0) return;
|
|
72
|
+
if (isWin) return; // best-effort; test is skipped on win32
|
|
73
|
+
try {
|
|
74
|
+
process.kill(-pid, 'SIGKILL');
|
|
75
|
+
} catch {
|
|
76
|
+
try {
|
|
77
|
+
process.kill(pid, 'SIGKILL');
|
|
78
|
+
} catch {
|
|
79
|
+
// already gone
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
test(
|
|
85
|
+
'runExecSandbox: SIGTERM-cooperative child exits promptly within grace on timeout',
|
|
86
|
+
{ skip: isWin ? 'Unix-primary graceful semantics' : false, timeout: 20_000 },
|
|
87
|
+
async (t) => {
|
|
88
|
+
const base = freshBase();
|
|
89
|
+
t.after(() => cleanup(base));
|
|
90
|
+
|
|
91
|
+
const KILL_GRACE_MS = 5_000;
|
|
92
|
+
const FORCE_RESOLVE_DELAY_MS = 8_000; // grace + hard-deadline; must NOT be reached
|
|
93
|
+
const TIMEOUT_MS = 300;
|
|
94
|
+
|
|
95
|
+
// Child traps SIGTERM and exits 0, then sleeps long. The first SIGTERM from
|
|
96
|
+
// the ladder ends it immediately -> `close` fires -> finalize via close,
|
|
97
|
+
// well before the force-resolve deadline.
|
|
98
|
+
const script = `trap 'exit 0' TERM; sleep 30`;
|
|
99
|
+
|
|
100
|
+
const result = await wallClockGuard(
|
|
101
|
+
runExecSandbox(
|
|
102
|
+
{ runtime: 'bash', script, timeout_ms: TIMEOUT_MS },
|
|
103
|
+
baseOpts(base, {
|
|
104
|
+
kill_grace_ms: KILL_GRACE_MS,
|
|
105
|
+
force_resolve_delay_ms: FORCE_RESOLVE_DELAY_MS,
|
|
106
|
+
}),
|
|
107
|
+
),
|
|
108
|
+
15_000,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
// timed_out is preserved even though the child exited cooperatively.
|
|
112
|
+
assert.equal(result.timed_out, true, 'timeout fired so timed_out must be true');
|
|
113
|
+
// Proves SIGTERM (close) resolved it, NOT the force-resolve deadline:
|
|
114
|
+
// a force-resolve would land at ~TIMEOUT_MS + FORCE_RESOLVE_DELAY_MS (~8.3s).
|
|
115
|
+
assert.ok(
|
|
116
|
+
result.duration_ms < KILL_GRACE_MS,
|
|
117
|
+
`expected prompt close well under grace (${KILL_GRACE_MS}ms), got ${result.duration_ms}ms`,
|
|
118
|
+
);
|
|
119
|
+
// A clean SIGTERM-trapped exit resolves via `close` with an exit code,
|
|
120
|
+
// not the force-resolve sentinel (exit_code null / signal SIGKILL).
|
|
121
|
+
assert.notEqual(
|
|
122
|
+
result.signal,
|
|
123
|
+
'SIGKILL',
|
|
124
|
+
'cooperative child must not be force-resolved as SIGKILL',
|
|
125
|
+
);
|
|
126
|
+
assert.equal(result.force_resolved, false, 'a cooperative close must not be flagged as force-resolved');
|
|
127
|
+
},
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
test(
|
|
131
|
+
'runExecSandbox: SIGTERM-ignoring (non-closing) child force-resolves via hard deadline without hanging',
|
|
132
|
+
{ skip: isWin ? 'Unix-primary graceful semantics; force-resolve covered on POSIX' : false, timeout: 20_000 },
|
|
133
|
+
async (t) => {
|
|
134
|
+
const base = freshBase();
|
|
135
|
+
const pidFile = join(base, 'child.pid');
|
|
136
|
+
t.after(() => {
|
|
137
|
+
cleanupByPidFile(pidFile);
|
|
138
|
+
cleanup(base);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Timing seams: SIGKILL never fires in-window (grace huge), so the only way
|
|
142
|
+
// the promise can settle is the hard deadline -> proves the caller-side
|
|
143
|
+
// force-resolve.
|
|
144
|
+
const KILL_GRACE_MS = 30_000;
|
|
145
|
+
const FORCE_RESOLVE_DELAY_MS = 800;
|
|
146
|
+
// Generous timeout so the SIGTERM trap is reliably installed before the kill
|
|
147
|
+
// fires, even under heavy parallel test load. A too-tight timeout can race
|
|
148
|
+
// the shell's startup: the kill lands before `trap '' TERM` runs, SIGTERM
|
|
149
|
+
// takes its default action, the child closes on SIGTERM, and the
|
|
150
|
+
// force-resolve path never runs (flaky 'SIGTERM' instead of 'SIGKILL').
|
|
151
|
+
const TIMEOUT_MS = 1_500;
|
|
152
|
+
|
|
153
|
+
// Install the SIGTERM trap FIRST (before any other command) so the shell is
|
|
154
|
+
// already immune by the time the kill fires; then record the detached
|
|
155
|
+
// shell's PID (process-group leader) for cleanup. The shell loops forever
|
|
156
|
+
// holding its stdout pipe open -> `close` never fires in-window -> the
|
|
157
|
+
// caller's hard deadline must force-resolve.
|
|
158
|
+
const script = `trap '' TERM; echo $$ > '${pidFile}'; while true; do sleep 1; done`;
|
|
159
|
+
|
|
160
|
+
const start = Date.now();
|
|
161
|
+
const result = await wallClockGuard(
|
|
162
|
+
runExecSandbox(
|
|
163
|
+
{ runtime: 'bash', script, timeout_ms: TIMEOUT_MS },
|
|
164
|
+
baseOpts(base, {
|
|
165
|
+
kill_grace_ms: KILL_GRACE_MS,
|
|
166
|
+
force_resolve_delay_ms: FORCE_RESOLVE_DELAY_MS,
|
|
167
|
+
}),
|
|
168
|
+
),
|
|
169
|
+
8_000,
|
|
170
|
+
);
|
|
171
|
+
const elapsed = Date.now() - start;
|
|
172
|
+
|
|
173
|
+
// (a) Did not hang and settled well before the SIGKILL grace would fire.
|
|
174
|
+
assert.ok(
|
|
175
|
+
elapsed < KILL_GRACE_MS,
|
|
176
|
+
`expected force-resolve before SIGKILL grace (${KILL_GRACE_MS}ms), took ${elapsed}ms`,
|
|
177
|
+
);
|
|
178
|
+
// (b) Settled in the force-resolve band: >= timeout (kill initiated) and
|
|
179
|
+
// roughly timeout + force_resolve_delay (generous CI slack, but kept below
|
|
180
|
+
// the 8000ms wallClockGuard so the upper bound is actually reachable).
|
|
181
|
+
assert.ok(
|
|
182
|
+
elapsed >= TIMEOUT_MS && elapsed <= TIMEOUT_MS + FORCE_RESOLVE_DELAY_MS + 4_000,
|
|
183
|
+
`expected settle near ${TIMEOUT_MS + FORCE_RESOLVE_DELAY_MS}ms, took ${elapsed}ms`,
|
|
184
|
+
);
|
|
185
|
+
// (c) Force-resolve preserves timed_out and surfaces the SIGKILL sentinel
|
|
186
|
+
// (exit_code null) plus the explicit force_resolved flag, so the agent can
|
|
187
|
+
// tell a forced kill (D-state hard deadline) from a clean SIGKILL exit.
|
|
188
|
+
assert.equal(result.timed_out, true, 'force-resolve must preserve timed_out');
|
|
189
|
+
assert.equal(result.exit_code, null, 'force-resolve exit_code must be null');
|
|
190
|
+
assert.equal(result.signal, 'SIGKILL', 'force-resolve must mark signal SIGKILL');
|
|
191
|
+
assert.equal(result.force_resolved, true, 'force-resolve must set force_resolved=true');
|
|
192
|
+
},
|
|
193
|
+
);
|
|
@@ -2,7 +2,7 @@ import test from "node:test";
|
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
3
|
|
|
4
4
|
import { registerExecTools } from "../bootstrap/exec-tools.ts";
|
|
5
|
-
import { executeUatExec } from "../tools/exec-tool.ts";
|
|
5
|
+
import { executeGsdExec, executeUatExec } from "../tools/exec-tool.ts";
|
|
6
6
|
import type { ExecSandboxRequest, ExecSandboxResult } from "../exec-sandbox.ts";
|
|
7
7
|
|
|
8
8
|
function makeExecResult(request: ExecSandboxRequest): ExecSandboxResult {
|
|
@@ -12,6 +12,7 @@ function makeExecResult(request: ExecSandboxRequest): ExecSandboxResult {
|
|
|
12
12
|
exit_code: 0,
|
|
13
13
|
signal: null,
|
|
14
14
|
timed_out: false,
|
|
15
|
+
force_resolved: false,
|
|
15
16
|
duration_ms: 1,
|
|
16
17
|
stdout_bytes: 12,
|
|
17
18
|
stderr_bytes: 0,
|
|
@@ -51,6 +52,33 @@ test("executeUatExec accepts evidence-mode aliases for intent", async () => {
|
|
|
51
52
|
assert.equal(requests[0]?.metadata?.intent, "uat-artifact-check");
|
|
52
53
|
});
|
|
53
54
|
|
|
55
|
+
test("gsd_exec surfaces a force-resolved (D-state) kill distinctly from a clean exit", async () => {
|
|
56
|
+
// A hard-deadline force-resolve sets force_resolved=true with a synthetic SIGKILL
|
|
57
|
+
// signal and null exit code. The tool result must carry that flag in details and
|
|
58
|
+
// render it as exit=timeout(force-killed) so the agent can tell it apart from a
|
|
59
|
+
// normally-exited or cleanly-timed-out command.
|
|
60
|
+
const result = await executeGsdExec(
|
|
61
|
+
{ runtime: "bash", script: "sleep 60" },
|
|
62
|
+
{
|
|
63
|
+
baseDir: "/tmp/gsd-exec-force-resolved-test",
|
|
64
|
+
preferences: null,
|
|
65
|
+
run: async (request) => ({
|
|
66
|
+
...makeExecResult(request),
|
|
67
|
+
exit_code: null,
|
|
68
|
+
signal: "SIGKILL",
|
|
69
|
+
timed_out: true,
|
|
70
|
+
force_resolved: true,
|
|
71
|
+
digest: "[no stdout \u2014 timed out]",
|
|
72
|
+
}),
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
assert.equal(result.isError, true, "a force-resolved kill is an error result");
|
|
77
|
+
assert.equal(result.details?.force_resolved, true, "details must expose force_resolved");
|
|
78
|
+
const text = result.content.map((c) => c.text ?? "").join("\n");
|
|
79
|
+
assert.match(text, /exit=timeout\(force-killed\)/, "summary must distinguish a force-killed result");
|
|
80
|
+
});
|
|
81
|
+
|
|
54
82
|
test("registerExecTools exposes gsd_uat_exec intent as recoverable string schema", () => {
|
|
55
83
|
const tools: Array<{ name: string; parameters: any }> = [];
|
|
56
84
|
registerExecTools({
|
|
@@ -117,7 +117,8 @@ describe("extension bootstrap isolation (#4168, #4172)", () => {
|
|
|
117
117
|
// registration is wrapped in its own try/catch so one failure does not
|
|
118
118
|
// prevent siblings from loading.
|
|
119
119
|
|
|
120
|
-
import { registerGsdExtension } from "../bootstrap/register-extension.ts";
|
|
120
|
+
import { CRITICAL_GSD_WORKFLOW_TOOL_NAMES, registerGsdExtension } from "../bootstrap/register-extension.ts";
|
|
121
|
+
import { drainLogs } from "../workflow-logger.ts";
|
|
121
122
|
|
|
122
123
|
describe("registerGsdExtension defensive registration", () => {
|
|
123
124
|
test("a failing shortcut registration does not prevent kill command registration", async () => {
|
|
@@ -161,4 +162,37 @@ describe("registerGsdExtension defensive registration", () => {
|
|
|
161
162
|
`registerGsdExtension must NOT register 'gsd' (it is registered separately by index.ts), got ${JSON.stringify(registered)}`,
|
|
162
163
|
);
|
|
163
164
|
});
|
|
165
|
+
|
|
166
|
+
test("critical workflow tool list includes lifecycle planning and completion tools", () => {
|
|
167
|
+
assert.ok(CRITICAL_GSD_WORKFLOW_TOOL_NAMES.includes("gsd_plan_slice"));
|
|
168
|
+
assert.ok(CRITICAL_GSD_WORKFLOW_TOOL_NAMES.includes("gsd_slice_complete"));
|
|
169
|
+
assert.ok(CRITICAL_GSD_WORKFLOW_TOOL_NAMES.includes("gsd_validate_milestone"));
|
|
170
|
+
assert.ok(CRITICAL_GSD_WORKFLOW_TOOL_NAMES.includes("gsd_complete_milestone"));
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test("partial db-tools registration fails visibly when critical tools are missing", () => {
|
|
174
|
+
drainLogs();
|
|
175
|
+
const registeredTools: string[] = [];
|
|
176
|
+
const pi = {
|
|
177
|
+
registerCommand: () => {},
|
|
178
|
+
registerTool: (tool: { name: string }) => {
|
|
179
|
+
if (tool.name === "gsd_plan_slice") {
|
|
180
|
+
throw new Error("simulated db-tools partial registration failure");
|
|
181
|
+
}
|
|
182
|
+
registeredTools.push(tool.name);
|
|
183
|
+
},
|
|
184
|
+
registerHook: () => {},
|
|
185
|
+
registerShortcut: () => {},
|
|
186
|
+
events: { on: () => {}, off: () => {}, emit: () => {} },
|
|
187
|
+
getAllTools: () => registeredTools.map((name) => ({ name })),
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
assert.throws(
|
|
191
|
+
() => registerGsdExtension(pi as any),
|
|
192
|
+
/Critical GSD workflow tool registration failed; missing required tool\(s\): .*gsd_plan_slice/,
|
|
193
|
+
);
|
|
194
|
+
assert.ok(registeredTools.includes("gsd_plan_milestone"));
|
|
195
|
+
assert.ok(!registeredTools.includes("gsd_plan_slice"));
|
|
196
|
+
drainLogs();
|
|
197
|
+
});
|
|
164
198
|
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// GSD Extension — Guidance module tests
|
|
2
|
+
// The catalog is the test surface: every typed finding must resolve to
|
|
3
|
+
// non-empty remediation, and load-bearing phrases must survive edits.
|
|
4
|
+
|
|
5
|
+
import { describe, test } from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
formatGuidance,
|
|
10
|
+
recoveryRemediation,
|
|
11
|
+
needsAttentionBlockerGuidance,
|
|
12
|
+
needsRemediationBlockerGuidance,
|
|
13
|
+
crashResumeHint,
|
|
14
|
+
doctorFixHint,
|
|
15
|
+
type RecoveryGuidanceKey,
|
|
16
|
+
} from "../guidance.js";
|
|
17
|
+
import { classifyFailure, type RecoveryFailureKind } from "../recovery-classification.js";
|
|
18
|
+
import { isValidationBlockedState } from "../validation-block-guard.js";
|
|
19
|
+
import type { GSDState } from "../types.js";
|
|
20
|
+
|
|
21
|
+
const RECOVERY_KEYS: RecoveryGuidanceKey[] = [
|
|
22
|
+
"tool-schema",
|
|
23
|
+
"tool-contract",
|
|
24
|
+
"tool-unavailable",
|
|
25
|
+
"deterministic-policy",
|
|
26
|
+
"lifecycle-progression",
|
|
27
|
+
"stale-worker",
|
|
28
|
+
"worktree-invalid",
|
|
29
|
+
"verification-drift",
|
|
30
|
+
"reconciliation-drift",
|
|
31
|
+
"illegal-transition",
|
|
32
|
+
"runtime-unknown",
|
|
33
|
+
"provider-transient",
|
|
34
|
+
"provider-permanent",
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
describe("guidance catalog", () => {
|
|
38
|
+
test("every recovery guidance key resolves to non-empty remediation", () => {
|
|
39
|
+
for (const key of RECOVERY_KEYS) {
|
|
40
|
+
const remediation = recoveryRemediation(key);
|
|
41
|
+
assert.ok(remediation.length > 0, `empty remediation for ${key}`);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("classifyFailure carries catalog remediation for every failure kind", () => {
|
|
46
|
+
const kinds: RecoveryFailureKind[] = [
|
|
47
|
+
"tool-schema",
|
|
48
|
+
"tool-contract",
|
|
49
|
+
"deterministic-policy",
|
|
50
|
+
"lifecycle-progression",
|
|
51
|
+
"stale-worker",
|
|
52
|
+
"worktree-invalid",
|
|
53
|
+
"verification-drift",
|
|
54
|
+
"reconciliation-drift",
|
|
55
|
+
"runtime-unknown",
|
|
56
|
+
];
|
|
57
|
+
for (const kind of kinds) {
|
|
58
|
+
const result = classifyFailure({ error: new Error("boom"), failureKind: kind });
|
|
59
|
+
assert.equal(result.failureKind, kind);
|
|
60
|
+
assert.equal(result.exitReason, kind);
|
|
61
|
+
assert.ok(result.remediation.length > 0, `empty remediation for ${kind}`);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("escalation kinds with weak guidance now name a concrete command", () => {
|
|
66
|
+
for (const key of ["stale-worker", "worktree-invalid", "verification-drift", "reconciliation-drift"] as const) {
|
|
67
|
+
assert.match(recoveryRemediation(key), /\/gsd /, `no command in remediation for ${key}`);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("formatGuidance numbers steps under the summary", () => {
|
|
72
|
+
const text = formatGuidance({ summary: "It broke.", steps: ["Fix it.", "Retry."] });
|
|
73
|
+
assert.equal(text, "It broke.\n\n1. Fix it.\n2. Retry.");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("formatGuidance with no steps is just the summary", () => {
|
|
77
|
+
assert.equal(formatGuidance({ summary: "All good.", steps: [] }), "All good.");
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe("milestone blocker guidance", () => {
|
|
82
|
+
test("needs-attention blocker keeps the phrase the validation-block guard matches", () => {
|
|
83
|
+
const state = { phase: "blocked", blockers: [needsAttentionBlockerGuidance("M005")] } as unknown as GSDState;
|
|
84
|
+
assert.ok(isValidationBlockedState(state));
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("needs-remediation blocker keeps the phrase the validation-block guard matches", () => {
|
|
88
|
+
const state = { phase: "blocked", blockers: [needsRemediationBlockerGuidance("M005")] } as unknown as GSDState;
|
|
89
|
+
assert.ok(isValidationBlockedState(state));
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test("blockers carry the milestone id and concrete fix commands", () => {
|
|
93
|
+
const text = needsAttentionBlockerGuidance("M007");
|
|
94
|
+
assert.match(text, /M007/);
|
|
95
|
+
assert.match(text, /\/gsd status/);
|
|
96
|
+
assert.match(text, /\/gsd validate-milestone/);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe("crash resume hints", () => {
|
|
101
|
+
test("bootstrap crash reports no work lost", () => {
|
|
102
|
+
assert.match(crashResumeHint("starting", "bootstrap") ?? "", /No work was lost/);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test("unit classes map to their resume hints", () => {
|
|
106
|
+
assert.match(crashResumeHint("research-milestone", "M001") ?? "", /may be incomplete/);
|
|
107
|
+
assert.match(crashResumeHint("execute-task", "T001") ?? "", /completed work is preserved/);
|
|
108
|
+
assert.match(crashResumeHint("complete-slice", "S001") ?? "", /interrupted/);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test("unknown unit types yield no hint", () => {
|
|
112
|
+
assert.equal(crashResumeHint("triage-captures", "X"), undefined);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe("doctor fix hints", () => {
|
|
117
|
+
test("known codes resolve to a hint", () => {
|
|
118
|
+
assert.ok(doctorFixHint("stale_crash_lock"));
|
|
119
|
+
assert.ok(doctorFixHint("db_unavailable"));
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test("codes without authored guidance resolve to undefined", () => {
|
|
123
|
+
assert.equal(doctorFixHint("delimiter_in_title"), undefined);
|
|
124
|
+
});
|
|
125
|
+
});
|
package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts
CHANGED
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
insertTask,
|
|
36
36
|
openDatabase,
|
|
37
37
|
} from "../../gsd-db.ts";
|
|
38
|
+
import { createGsdIntegrationProject } from "./gsd-integration-fixture.ts";
|
|
38
39
|
|
|
39
40
|
function run(cmd: string, cwd: string): string {
|
|
40
41
|
// Safe: all inputs are hardcoded test strings, not user input
|
|
@@ -42,17 +43,12 @@ function run(cmd: string, cwd: string): string {
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
function createTempRepo(): string {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
writeFileSync(join(dir, ".gsd", "STATE.md"), "# State\n");
|
|
52
|
-
run("git add .", dir);
|
|
53
|
-
run("git commit -m init", dir);
|
|
54
|
-
run("git branch -M main", dir);
|
|
55
|
-
return dir;
|
|
46
|
+
return createGsdIntegrationProject({
|
|
47
|
+
prefix: "wt-ms-merge-test-",
|
|
48
|
+
initialFiles: {
|
|
49
|
+
".gsd/STATE.md": "# State\n",
|
|
50
|
+
},
|
|
51
|
+
}).root;
|
|
56
52
|
}
|
|
57
53
|
|
|
58
54
|
function createTempRepoWithExternalGsd(): { repo: string; externalState: string } {
|
|
@@ -784,6 +780,52 @@ describe("auto-worktree-milestone-merge", { timeout: 300_000 }, () => {
|
|
|
784
780
|
);
|
|
785
781
|
});
|
|
786
782
|
|
|
783
|
+
test("#2156 (legacy): mergeMilestoneToMain removes external-state worktrees created under .gsd/worktrees/", () => {
|
|
784
|
+
const { repo, externalState } = freshRepoWithExternalGsd();
|
|
785
|
+
// Worktrees created by older versions live at .gsd/worktrees/<MID>; git
|
|
786
|
+
// resolves the symlink and registers them under external state. Canonical
|
|
787
|
+
// .gsd-worktrees/ creation never crosses the symlink, so this coverage
|
|
788
|
+
// creates the legacy worktree explicitly. createAutoWorktree chdirs into
|
|
789
|
+
// the new worktree and mergeMilestoneToMain reads process.cwd() as the
|
|
790
|
+
// worktree cwd, so mirror that here.
|
|
791
|
+
const wtPath = join(repo, ".gsd", "worktrees", "M216");
|
|
792
|
+
run(`git worktree add -b milestone/M216 "${wtPath}"`, repo);
|
|
793
|
+
process.chdir(wtPath);
|
|
794
|
+
|
|
795
|
+
addSliceToMilestone(repo, wtPath, "M216", "S01", "Legacy external cleanup", [
|
|
796
|
+
{ file: "legacy-external-cleanup.ts", content: "export const legacyExternalCleanup = true;\n", message: "add legacy external cleanup" },
|
|
797
|
+
]);
|
|
798
|
+
|
|
799
|
+
const realWtPath = realpathSync(wtPath);
|
|
800
|
+
assert.ok(
|
|
801
|
+
realWtPath.startsWith(externalState),
|
|
802
|
+
`legacy worktree should be registered under external .gsd state, got ${realWtPath}`,
|
|
803
|
+
);
|
|
804
|
+
|
|
805
|
+
// Recreate the exact divergence from #1852: local .gsd/ is replaced with a
|
|
806
|
+
// stale real directory, so the computed path no longer matches git's record.
|
|
807
|
+
unlinkSync(join(repo, ".gsd"));
|
|
808
|
+
mkdirSync(join(repo, ".gsd", "worktrees", "M216"), { recursive: true });
|
|
809
|
+
writeFileSync(join(repo, ".gsd", "STATE.md"), "# Local stale state\n");
|
|
810
|
+
writeFileSync(join(repo, ".gsd", "worktrees", "M216", "stale.txt"), "stale local artifact\n");
|
|
811
|
+
|
|
812
|
+
const roadmap = makeRoadmap("M216", "Legacy external cleanup", [
|
|
813
|
+
{ id: "S01", title: "Legacy external cleanup" },
|
|
814
|
+
]);
|
|
815
|
+
|
|
816
|
+
mergeMilestoneToMain(repo, "M216", roadmap);
|
|
817
|
+
|
|
818
|
+
assert.ok(
|
|
819
|
+
!run("git worktree list", repo).includes("M216"),
|
|
820
|
+
"merged legacy milestone worktree should be removed from git worktree list",
|
|
821
|
+
);
|
|
822
|
+
assert.ok(!existsSync(realWtPath), "real external worktree directory should be removed");
|
|
823
|
+
assert.ok(
|
|
824
|
+
!run("git branch", repo).includes("milestone/M216"),
|
|
825
|
+
"milestone branch should be deleted after merge cleanup",
|
|
826
|
+
);
|
|
827
|
+
});
|
|
828
|
+
|
|
787
829
|
test("#2912: MERGE_HEAD cleaned up after squash-merge conflict", () => {
|
|
788
830
|
const repo = freshRepo();
|
|
789
831
|
const wtPath = createAutoWorktree(repo, "M291");
|