@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
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* @see https://github.com/open-gsd/gsd-pi/issues/2577
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { TOOL_SURFACE_NOT_READY } from "./tool-surface-readiness.js";
|
|
14
|
+
|
|
13
15
|
// ── ErrorClass discriminated union ──────────────────────────────────────────
|
|
14
16
|
|
|
15
17
|
export type ErrorClass =
|
|
@@ -70,6 +72,10 @@ const CONNECTION_RE = /terminated|connection.?(?:refused|error)|other side close
|
|
|
70
72
|
const STREAM_RE = /in JSON at position \d+|Unexpected end of JSON|SyntaxError.*JSON/i;
|
|
71
73
|
const RESET_DELAY_RE = /reset in (\d+)s/i;
|
|
72
74
|
const TOOL_SCHEMA_RE = /schema overload|consecutive tool validation failures/i;
|
|
75
|
+
// GSD tool-surface readiness abort (claude-code stream adapter): the workflow
|
|
76
|
+
// MCP server had not registered the Unit's required tools at SDK init. The
|
|
77
|
+
// server typically finishes connecting within seconds — same-model retry.
|
|
78
|
+
const TOOL_SURFACE_NOT_READY_RE = new RegExp(TOOL_SURFACE_NOT_READY, "i");
|
|
73
79
|
// Provider rejected the request shape for the selected model (400 bad request,
|
|
74
80
|
// grammar limits, etc.). Not transient — try a different model/fallback.
|
|
75
81
|
// Context-window 400s stay in SERVER_RE (checked earlier).
|
|
@@ -108,6 +114,11 @@ export function classifyError(errorMsg: string, retryAfterMs?: number): ErrorCla
|
|
|
108
114
|
return { kind: "tool-schema", retryAfterMs: 0 };
|
|
109
115
|
}
|
|
110
116
|
|
|
117
|
+
// Tool-surface readiness abort — transient; retry the same model shortly.
|
|
118
|
+
if (TOOL_SURFACE_NOT_READY_RE.test(errorMsg)) {
|
|
119
|
+
return { kind: "network", retryAfterMs: retryAfterMs ?? 3_000 };
|
|
120
|
+
}
|
|
121
|
+
|
|
111
122
|
const isPermanent = PERMANENT_RE.test(errorMsg);
|
|
112
123
|
const isRateLimit = RATE_LIMIT_RE.test(errorMsg) || AFFORDABILITY_RE.test(errorMsg);
|
|
113
124
|
const isUnsupportedModel =
|
|
@@ -12,6 +12,7 @@ import { spawn } from "node:child_process";
|
|
|
12
12
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
13
13
|
import { randomUUID } from "node:crypto";
|
|
14
14
|
import { resolve } from "node:path";
|
|
15
|
+
import { killProcessTree, SIGKILL_GRACE_MS, HARD_DEADLINE_MS } from "@gsd/pi-coding-agent";
|
|
15
16
|
|
|
16
17
|
export interface ExecSandboxRequest {
|
|
17
18
|
/** Interpreter to use. */
|
|
@@ -47,6 +48,17 @@ export interface ExecSandboxOptions {
|
|
|
47
48
|
now?: () => Date;
|
|
48
49
|
/** Optional override for id generation (tests). */
|
|
49
50
|
generateId?: () => string;
|
|
51
|
+
/**
|
|
52
|
+
* Grace period (ms) between SIGTERM and SIGKILL on timeout.
|
|
53
|
+
* Defaults to SIGKILL_GRACE_MS. Exposed as a test seam.
|
|
54
|
+
*/
|
|
55
|
+
kill_grace_ms?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Delay (ms) after a kill is initiated before the hard-deadline force-resolves
|
|
58
|
+
* the promise (handles D-state / non-closing children).
|
|
59
|
+
* Defaults to SIGKILL_GRACE_MS + HARD_DEADLINE_MS. Exposed as a test seam.
|
|
60
|
+
*/
|
|
61
|
+
force_resolve_delay_ms?: number;
|
|
50
62
|
}
|
|
51
63
|
|
|
52
64
|
export interface ExecSandboxResult {
|
|
@@ -55,6 +67,12 @@ export interface ExecSandboxResult {
|
|
|
55
67
|
exit_code: number | null;
|
|
56
68
|
signal: NodeJS.Signals | null;
|
|
57
69
|
timed_out: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* True when the result came from the hard-deadline force-resolve (a non-closing
|
|
72
|
+
* D-state child that never emitted 'close') rather than an observed process exit.
|
|
73
|
+
* In that case `signal` is the synthetic "SIGKILL" marker, not a delivered signal.
|
|
74
|
+
*/
|
|
75
|
+
force_resolved: boolean;
|
|
58
76
|
duration_ms: number;
|
|
59
77
|
stdout_bytes: number;
|
|
60
78
|
stderr_bytes: number;
|
|
@@ -68,6 +86,10 @@ export interface ExecSandboxResult {
|
|
|
68
86
|
|
|
69
87
|
const ALWAYS_FORWARD_ENV = ["PATH", "HOME"] as const;
|
|
70
88
|
|
|
89
|
+
// SIGKILL_GRACE_MS / HARD_DEADLINE_MS are imported from @gsd/pi-coding-agent
|
|
90
|
+
// (shell.ts) — the single source of truth for the graceful-kill timing ladder —
|
|
91
|
+
// so this sandbox can never drift from the canonical kill path it delegates to.
|
|
92
|
+
|
|
71
93
|
export const EXEC_DEFAULTS = {
|
|
72
94
|
clampTimeoutMs: 600_000,
|
|
73
95
|
defaultTimeoutMs: 30_000,
|
|
@@ -180,6 +202,7 @@ export function runExecSandbox(
|
|
|
180
202
|
exit_code: null,
|
|
181
203
|
signal: null,
|
|
182
204
|
timed_out: false,
|
|
205
|
+
force_resolved: false,
|
|
183
206
|
duration_ms: duration,
|
|
184
207
|
stdout_bytes: 0,
|
|
185
208
|
stderr_bytes: Buffer.byteLength(`spawn error: ${message}\n`),
|
|
@@ -233,23 +256,39 @@ export function runExecSandbox(
|
|
|
233
256
|
}
|
|
234
257
|
});
|
|
235
258
|
|
|
259
|
+
const effectiveGraceMs = opts.kill_grace_ms ?? SIGKILL_GRACE_MS;
|
|
260
|
+
const effectiveForceResolveDelay = opts.force_resolve_delay_ms ?? (effectiveGraceMs + HARD_DEADLINE_MS);
|
|
261
|
+
|
|
236
262
|
let timedOut = false;
|
|
263
|
+
let settled = false;
|
|
264
|
+
let forceResolveTimer: NodeJS.Timeout | undefined;
|
|
265
|
+
|
|
237
266
|
const timer = setTimeout(() => {
|
|
238
267
|
timedOut = true;
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
268
|
+
// killProcessTree handles both platforms and kills the whole tree: on Unix
|
|
269
|
+
// it signals the process group (SIGTERM -> grace -> SIGKILL); on Windows it
|
|
270
|
+
// force-kills the tree via taskkill /F /T. Using child.kill("SIGTERM") here
|
|
271
|
+
// would only terminate the direct child on Windows, orphaning grandchildren.
|
|
272
|
+
if (child.pid != null) {
|
|
273
|
+
killProcessTree(child.pid, { graceMs: effectiveGraceMs });
|
|
245
274
|
} else {
|
|
246
|
-
child.kill("
|
|
275
|
+
child.kill("SIGTERM");
|
|
247
276
|
}
|
|
277
|
+
// Arm hard-deadline force-resolve in case child never closes (D-state).
|
|
278
|
+
// The "SIGKILL" here is a synthetic marker (the process may not have actually
|
|
279
|
+
// received it); force_resolved=true records that this was a deadline, not an exit.
|
|
280
|
+
forceResolveTimer = setTimeout(() => {
|
|
281
|
+
finalize(null, "SIGKILL", true);
|
|
282
|
+
}, effectiveForceResolveDelay);
|
|
283
|
+
forceResolveTimer.unref?.();
|
|
248
284
|
}, timeoutMs);
|
|
249
285
|
timer.unref?.();
|
|
250
286
|
|
|
251
|
-
const finalize = (exitCode: number | null, signal: NodeJS.Signals | null) => {
|
|
287
|
+
const finalize = (exitCode: number | null, signal: NodeJS.Signals | null, forceResolved = false) => {
|
|
288
|
+
if (settled) return;
|
|
289
|
+
settled = true;
|
|
252
290
|
clearTimeout(timer);
|
|
291
|
+
clearTimeout(forceResolveTimer);
|
|
253
292
|
const duration = Date.now() - started;
|
|
254
293
|
const stdoutBuf = Buffer.concat(stdoutChunks);
|
|
255
294
|
const stderrBuf = Buffer.concat(stderrChunks);
|
|
@@ -274,6 +313,7 @@ export function runExecSandbox(
|
|
|
274
313
|
exit_code: exitCode,
|
|
275
314
|
signal,
|
|
276
315
|
timed_out: timedOut,
|
|
316
|
+
force_resolved: forceResolved,
|
|
277
317
|
duration_ms: duration,
|
|
278
318
|
stdout_bytes: stdoutBytes,
|
|
279
319
|
stderr_bytes: stderrBytes,
|
|
@@ -324,6 +364,7 @@ function writeMeta(
|
|
|
324
364
|
exit_code: result.exit_code,
|
|
325
365
|
signal: result.signal,
|
|
326
366
|
timed_out: result.timed_out,
|
|
367
|
+
force_resolved: result.force_resolved,
|
|
327
368
|
duration_ms: result.duration_ms,
|
|
328
369
|
stdout_bytes: result.stdout_bytes,
|
|
329
370
|
stderr_bytes: result.stderr_bytes,
|
|
@@ -331,7 +372,6 @@ function writeMeta(
|
|
|
331
372
|
stderr_truncated: result.stderr_truncated,
|
|
332
373
|
stdout_path: result.stdout_path,
|
|
333
374
|
stderr_path: result.stderr_path,
|
|
334
|
-
...(request.metadata ? { metadata: request.metadata } : {}),
|
|
335
375
|
};
|
|
336
376
|
writeFileSync(path, `${JSON.stringify(meta, null, 2)}\n`);
|
|
337
377
|
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Guidance module — the single catalog mapping typed findings
|
|
3
|
+
// (Recovery kinds, milestone blocker kinds, doctor issue codes, crash unit
|
|
4
|
+
// classes) to user-facing remediation: what happened and what to do next.
|
|
5
|
+
//
|
|
6
|
+
// Emit sites pass the typed finding; phrasing, command names, and step
|
|
7
|
+
// ordering live here. A missing catalog row is a visible gap, not a silent
|
|
8
|
+
// omission scattered across call sites.
|
|
9
|
+
|
|
10
|
+
import type { RecoveryFailureKind } from "./recovery-classification.js";
|
|
11
|
+
import type { DoctorIssueCode } from "./doctor-types.js";
|
|
12
|
+
|
|
13
|
+
// ─── Shape ──────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
export interface Guidance {
|
|
16
|
+
summary: string;
|
|
17
|
+
steps: string[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Flatten guidance into a notification / pause-banner string. */
|
|
21
|
+
export function formatGuidance(guidance: Guidance): string {
|
|
22
|
+
if (guidance.steps.length === 0) return guidance.summary;
|
|
23
|
+
const numbered = guidance.steps.map((step, index) => `${index + 1}. ${step}`).join("\n");
|
|
24
|
+
return `${guidance.summary}\n\n${numbered}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ─── Recovery Classification remediation ────────────────────────────────
|
|
28
|
+
// Keyed by RecoveryFailureKind. The provider kind is split by transience,
|
|
29
|
+
// which Recovery Classification resolves before looking up guidance.
|
|
30
|
+
|
|
31
|
+
export type RecoveryGuidanceKey =
|
|
32
|
+
| Exclude<RecoveryFailureKind, "provider">
|
|
33
|
+
| "provider-transient"
|
|
34
|
+
| "provider-permanent";
|
|
35
|
+
|
|
36
|
+
const RECOVERY_REMEDIATION: Record<RecoveryGuidanceKey, string> = {
|
|
37
|
+
"tool-schema": "Fix the Unit Tool Contract or tool schema before retrying.",
|
|
38
|
+
"tool-contract":
|
|
39
|
+
"Fix the Unit Tool Contract or prompt so the Unit is only asked to use tools owned by its phase.",
|
|
40
|
+
"tool-unavailable":
|
|
41
|
+
"The tool surface had not finished registering when the Unit called it (workflow MCP startup race). Retry after the surface is ready; escalate if the tool never appears.",
|
|
42
|
+
"deterministic-policy": "Resolve the policy blocker; retrying the same Unit will repeat the failure.",
|
|
43
|
+
"lifecycle-progression":
|
|
44
|
+
"Route to the required owning Unit or restore the missing artifact before advancing lifecycle state.",
|
|
45
|
+
"stale-worker":
|
|
46
|
+
"Run `/gsd doctor` to detect and clear the stale worker or lock, then run `/gsd auto` to resume.",
|
|
47
|
+
"worktree-invalid":
|
|
48
|
+
"Run `/gsd doctor` to diagnose the milestone worktree (`gsd worktree list` shows its state). Repair it, or merge salvageable work with `gsd worktree merge <name>` before recreating — recreating discards uncommitted work.",
|
|
49
|
+
"verification-drift":
|
|
50
|
+
"Run `/gsd status` to see the verification finding, fix or re-run the verification, then run `/gsd auto` to resume. `/gsd doctor` can repair stale state files.",
|
|
51
|
+
"reconciliation-drift":
|
|
52
|
+
"Run `/gsd doctor` to surface the persistent or repair-failed drift kinds, apply its fixes, then run `/gsd auto` to resume.",
|
|
53
|
+
"illegal-transition":
|
|
54
|
+
"A derived Phase edge rejected by the Phase Transition Invariant survived reconciliation; inspect deriveState and the State Reconciliation Module before resuming.",
|
|
55
|
+
"runtime-unknown": "Inspect the runtime error and add a dedicated classification if it is repeatable.",
|
|
56
|
+
"provider-transient": "Retry after the provider/network condition clears.",
|
|
57
|
+
"provider-permanent": "Inspect provider credentials, model entitlement, or request shape.",
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export function recoveryRemediation(key: RecoveryGuidanceKey): string {
|
|
61
|
+
return RECOVERY_REMEDIATION[key];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ─── Milestone validation blockers ──────────────────────────────────────
|
|
65
|
+
// NOTE: the first line of each blocker is load-bearing — validation-block-guard
|
|
66
|
+
// matches /milestone validation returned needs-(?:attention|remediation)/i.
|
|
67
|
+
// Keep that phrase intact when editing.
|
|
68
|
+
|
|
69
|
+
export function needsAttentionBlockerGuidance(milestoneId: string): string {
|
|
70
|
+
return [
|
|
71
|
+
`Milestone ${milestoneId} is blocked because milestone validation returned needs-attention.`,
|
|
72
|
+
`Fix options:`,
|
|
73
|
+
`1. Review the validation details: \`/gsd status\``,
|
|
74
|
+
`2. If you fixed the missing evidence or issue, re-run milestone validation: \`/gsd validate-milestone\``,
|
|
75
|
+
`3. If the finding is acceptable, override it: \`/gsd verdict pass --rationale "why this is okay"\``,
|
|
76
|
+
`4. If this should wait, defer it explicitly: \`/gsd park ${milestoneId}\``,
|
|
77
|
+
`After validation or override passes, run \`/gsd auto\` to complete and merge the milestone.`,
|
|
78
|
+
].join("\n");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function needsRemediationBlockerGuidance(milestoneId: string): string {
|
|
82
|
+
return [
|
|
83
|
+
`Milestone ${milestoneId} is blocked because milestone validation returned needs-remediation, but all slices are complete.`,
|
|
84
|
+
`Fix options:`,
|
|
85
|
+
`1. Run \`/gsd dispatch reassess\` to add remediation slices, then run \`/gsd auto\``,
|
|
86
|
+
`2. If the finding is acceptable, override it: \`/gsd verdict pass --rationale "why this is okay"\``,
|
|
87
|
+
`3. If this should wait, defer it explicitly: \`/gsd park ${milestoneId}\``,
|
|
88
|
+
].join("\n");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ─── Crash recovery resume hints ────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
/** Resume hint for an interrupted auto-mode unit, by unit class. */
|
|
94
|
+
export function crashResumeHint(unitType: string, unitId: string): string | undefined {
|
|
95
|
+
if (unitType === "starting" && unitId === "bootstrap") {
|
|
96
|
+
return `No work was lost. Run /gsd auto to restart.`;
|
|
97
|
+
}
|
|
98
|
+
if (unitType.includes("research") || unitType.includes("plan")) {
|
|
99
|
+
return `The ${unitType} unit may be incomplete. Run /gsd auto to re-run it.`;
|
|
100
|
+
}
|
|
101
|
+
if (unitType.includes("execute")) {
|
|
102
|
+
return `Task execution was interrupted. Run /gsd auto to resume — completed work is preserved.`;
|
|
103
|
+
}
|
|
104
|
+
if (unitType.includes("complete")) {
|
|
105
|
+
return `Slice/milestone completion was interrupted. Run /gsd auto to finish.`;
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ─── Doctor issue fix hints ─────────────────────────────────────────────
|
|
111
|
+
// Partial by design: codes without a row render no hint. Add rows here as
|
|
112
|
+
// guidance is authored — the gap is visible in one place.
|
|
113
|
+
|
|
114
|
+
const DOCTOR_FIX_HINTS: Partial<Record<DoctorIssueCode, string>> = {
|
|
115
|
+
db_unavailable:
|
|
116
|
+
"The workflow database could not be opened — state derivation is degraded. Restart the session; if it persists, run `/gsd doctor` from the project root.",
|
|
117
|
+
stale_crash_lock: "Run `/gsd doctor` to clear the stale lock, then `/gsd auto` to resume.",
|
|
118
|
+
stale_parallel_session: "Run `/gsd doctor` to clear the stale session registration.",
|
|
119
|
+
unresolved_git_conflicts:
|
|
120
|
+
"Resolve the conflict markers, commit, then re-run `/gsd auto`.",
|
|
121
|
+
conflict_markers_in_tracked_files:
|
|
122
|
+
"Search the listed files for `<<<<<<<` markers, resolve, and commit.",
|
|
123
|
+
worktree_dirty:
|
|
124
|
+
"Commit or merge the worktree's changes (`gsd worktree merge <name>`) before removing it.",
|
|
125
|
+
worktree_branch_merged: "The branch is merged — remove the worktree to reclaim space.",
|
|
126
|
+
orphaned_auto_worktree: "Run `/gsd doctor` to fix, or merge salvageable work with `gsd worktree merge <name>`.",
|
|
127
|
+
gitignore_missing_patterns: "Run `/gsd doctor` to append the missing .gitignore patterns.",
|
|
128
|
+
invalid_preferences: "Edit .gsd/PREFERENCES.md to fix the invalid field, then re-run the command.",
|
|
129
|
+
provider_key_missing: "Add the provider API key to your environment or provider config, then retry.",
|
|
130
|
+
provider_key_backedoff: "The key is cooling down after repeated failures — wait, or switch the phase model in .gsd/PREFERENCES.md.",
|
|
131
|
+
state_file_stale: "Run `/gsd doctor` to rebuild the projection from the database.",
|
|
132
|
+
state_file_missing: "Run `/gsd doctor` to rebuild the projection from the database.",
|
|
133
|
+
projection_drift: "Run `/gsd doctor` to rebuild markdown projections from the database (DB is the source of truth).",
|
|
134
|
+
uat_retry_exhausted: "Review the failing UAT criteria via `/gsd status`, fix the issue, then re-run `/gsd auto`.",
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export function doctorFixHint(code: DoctorIssueCode): string | undefined {
|
|
138
|
+
return DOCTOR_FIX_HINTS[code];
|
|
139
|
+
}
|
|
@@ -90,7 +90,7 @@ import {
|
|
|
90
90
|
} from "./preparation.js";
|
|
91
91
|
import { verifyExpectedArtifact } from "./auto-recovery.js";
|
|
92
92
|
import type { MilestoneScope } from "./workspace.js";
|
|
93
|
-
import { getPendingGate } from "./bootstrap/write-gate.js";
|
|
93
|
+
import { clearPendingGate, extractDepthVerificationMilestoneId, getPendingGate } from "./bootstrap/write-gate.js";
|
|
94
94
|
import {
|
|
95
95
|
_getPendingAutoStart,
|
|
96
96
|
clearPendingAutoStart,
|
|
@@ -100,7 +100,7 @@ import {
|
|
|
100
100
|
setPendingAutoStart,
|
|
101
101
|
} from "./pending-auto-start.js";
|
|
102
102
|
import { clearGuidedUnitContext, setGuidedUnitContext } from "./guided-unit-context.js";
|
|
103
|
-
import { scheduleAutoStartAfterIdle } from "./discussion-handoff.js";
|
|
103
|
+
import { checkAutoStartAfterDiscuss, scheduleAutoStartAfterIdle } from "./discussion-handoff.js";
|
|
104
104
|
export {
|
|
105
105
|
maybeHandleEmptyIntentTurn,
|
|
106
106
|
maybeHandleReadyPhraseWithoutFiles,
|
|
@@ -1959,6 +1959,20 @@ export async function showSmartEntry(
|
|
|
1959
1959
|
// Stale entry from an interrupted discussion — clear and continue
|
|
1960
1960
|
deletePendingAutoStart(basePath);
|
|
1961
1961
|
} else {
|
|
1962
|
+
if (milestoneHasContext && !isAgentTurnInFlight(ctx)) {
|
|
1963
|
+
// The discussion already produced CONTEXT but the agent_end handoff
|
|
1964
|
+
// never consumed the entry — e.g. an external-engine post-hoc gate
|
|
1965
|
+
// re-arm wiped the depth verification after the save (write-gate
|
|
1966
|
+
// two-process sync). CONTEXT can only be written through a verified
|
|
1967
|
+
// depth gate, so a gate still pending for this milestone is stale:
|
|
1968
|
+
// clear it and re-run the handoff instead of dead-ending.
|
|
1969
|
+
const gateBasePath = entry.scope.workspace.projectRoot;
|
|
1970
|
+
const pendingGateId = getPendingGate(gateBasePath);
|
|
1971
|
+
if (pendingGateId && extractDepthVerificationMilestoneId(pendingGateId) === entry.milestoneId) {
|
|
1972
|
+
clearPendingGate(gateBasePath);
|
|
1973
|
+
}
|
|
1974
|
+
if (checkAutoStartAfterDiscuss(basePath)) return;
|
|
1975
|
+
}
|
|
1962
1976
|
ctx.ui.notify("Discussion already in progress — answer the question above to continue.", "info");
|
|
1963
1977
|
return;
|
|
1964
1978
|
}
|
|
@@ -3,6 +3,7 @@ import { homedir } from "node:os";
|
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
|
|
5
5
|
import type { ClaudeCodeMcpConfig } from "./preferences-types.js";
|
|
6
|
+
import { isGsdBrowserMcpServerConfig } from "../shared/gsd-browser-cli.js";
|
|
6
7
|
import { toMcpWildcardToolName } from "./mcp-tool-name.js";
|
|
7
8
|
import { resolveModelMcpConfig } from "./preferences-mcp.js";
|
|
8
9
|
|
|
@@ -83,34 +84,12 @@ function isWorkflowMcpServerConfig(config: unknown): boolean {
|
|
|
83
84
|
return args.some((arg) => arg.includes("gsd-mcp-server") || arg.includes("packages/mcp-server"));
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
function isBrowserMcpServerConfig(config: unknown): boolean {
|
|
87
|
-
if (!isRecord(config)) return false;
|
|
88
|
-
const command = typeof config.command === "string" ? config.command : "";
|
|
89
|
-
if (command.includes("gsd-browser") || command.includes("@opengsd/gsd-browser")) {
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const env = config.env;
|
|
94
|
-
if (isRecord(env)) {
|
|
95
|
-
if (
|
|
96
|
-
typeof env.GSD_BROWSER_CLI_PATH === "string"
|
|
97
|
-
|| typeof env.GSD_BROWSER_BIN_PATH === "string"
|
|
98
|
-
|| typeof env.GSD_BROWSER_MCP_COMMAND === "string"
|
|
99
|
-
) {
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const args = Array.isArray(config.args) ? config.args.filter((arg): arg is string => typeof arg === "string") : [];
|
|
105
|
-
return args.some((arg) => arg.includes("gsd-browser") || arg.includes("@opengsd/gsd-browser"));
|
|
106
|
-
}
|
|
107
|
-
|
|
108
87
|
export function discoverWorkflowMcpServerName(projectDir: string): string | undefined {
|
|
109
88
|
return discoverMcpServers(projectDir).find((server) => isWorkflowMcpServerConfig(server.config))?.name;
|
|
110
89
|
}
|
|
111
90
|
|
|
112
91
|
export function discoverBrowserMcpServerName(projectDir: string): string | undefined {
|
|
113
|
-
return discoverMcpServers(projectDir).find((server) =>
|
|
92
|
+
return discoverMcpServers(projectDir).find((server) => isGsdBrowserMcpServerConfig(server.config))?.name;
|
|
114
93
|
}
|
|
115
94
|
|
|
116
95
|
export function discoverMcpServerNames(projectDir: string): string[] {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
|
-
// File Purpose:
|
|
2
|
+
// File Purpose: GSD-facing face over the shared @gsd/pi-ai MCP tool-name helpers.
|
|
3
|
+
|
|
4
|
+
import { parseMcpToolName as parsePiAiMcpToolName, stripMcpToolPrefix } from "@gsd/pi-ai";
|
|
3
5
|
|
|
4
6
|
const MCP_TOOL_PREFIX = "mcp__";
|
|
5
7
|
|
|
@@ -9,18 +11,11 @@ export interface ParsedMcpToolName {
|
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
export function parseMcpToolName(toolName: string): ParsedMcpToolName | null {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
if (toolSeparator < 0) return null;
|
|
15
|
-
return {
|
|
16
|
-
serverName: toolName.slice(MCP_TOOL_PREFIX.length, toolSeparator),
|
|
17
|
-
toolName: toolName.slice(toolSeparator + 2),
|
|
18
|
-
};
|
|
14
|
+
const parsed = parsePiAiMcpToolName(toolName);
|
|
15
|
+
return parsed ? { serverName: parsed.server, toolName: parsed.tool } : null;
|
|
19
16
|
}
|
|
20
17
|
|
|
21
|
-
export
|
|
22
|
-
return parseMcpToolName(toolName)?.toolName ?? toolName;
|
|
23
|
-
}
|
|
18
|
+
export { stripMcpToolPrefix };
|
|
24
19
|
|
|
25
20
|
export function toMcpToolName(serverName: string, toolName: string): string {
|
|
26
21
|
return `${MCP_TOOL_PREFIX}${serverName}__${toolName}`;
|
|
@@ -264,7 +264,7 @@ export function reportConsolidationGaps(basePath: string): ConsolidationGapRepor
|
|
|
264
264
|
try {
|
|
265
265
|
const report = scanConsolidationGaps(basePath);
|
|
266
266
|
if (report.totalGaps === 0) return report;
|
|
267
|
-
appendNotification(report.summary, "warning", "workflow-logger");
|
|
267
|
+
appendNotification(report.summary, "warning", "workflow-logger", { kind: "memory-consolidation" });
|
|
268
268
|
logWarning("memory-consolidation", report.summary);
|
|
269
269
|
return report;
|
|
270
270
|
} catch (e) {
|
|
@@ -10,6 +10,7 @@ import { readCrashLock, isLockProcessAlive } from "../crash-recovery.js";
|
|
|
10
10
|
import { closeWorkflowDatabase } from "../db-workspace.js";
|
|
11
11
|
import { readPausedSessionMetadata } from "../interrupted-session.js";
|
|
12
12
|
import { gsdRoot } from "../paths.js";
|
|
13
|
+
import { canonicalWorktreesDir } from "../worktree-placement.js";
|
|
13
14
|
import type { MigrationPreview } from "./writer.js";
|
|
14
15
|
|
|
15
16
|
export interface MigrationPaths {
|
|
@@ -106,8 +107,10 @@ export function assertMigrationHasSlices(preview: MigrationPreview): void {
|
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
function hasWorktreeState(targetRoot: string): boolean {
|
|
110
|
+
// Legacy container is probed via gsdRoot() (symlink-resolved) on purpose —
|
|
111
|
+
// migration targets may have .gsd in the external-state layout.
|
|
109
112
|
const containers = [
|
|
110
|
-
|
|
113
|
+
canonicalWorktreesDir(targetRoot),
|
|
111
114
|
join(gsdRoot(targetRoot), "worktrees"),
|
|
112
115
|
];
|
|
113
116
|
for (const worktreesDir of containers) {
|
|
@@ -12,6 +12,17 @@ import { randomUUID } from "node:crypto";
|
|
|
12
12
|
export type NotifySeverity = "info" | "success" | "warning" | "error";
|
|
13
13
|
export type NotificationSource = "notify" | "workflow-logger";
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Optional structured identity for a notification. When present, `kind`
|
|
17
|
+
* (a stable machine name like "auto-stop" or "provider-error-pause") plus
|
|
18
|
+
* `scope` (e.g. a milestone/slice id) — not the prose — key deduplication,
|
|
19
|
+
* and consumers can filter without parsing message text.
|
|
20
|
+
*/
|
|
21
|
+
export interface NotificationMeta {
|
|
22
|
+
kind?: string;
|
|
23
|
+
scope?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
15
26
|
export interface NotificationEntry {
|
|
16
27
|
id: string;
|
|
17
28
|
ts: string;
|
|
@@ -19,6 +30,8 @@ export interface NotificationEntry {
|
|
|
19
30
|
message: string;
|
|
20
31
|
source: NotificationSource;
|
|
21
32
|
read: boolean;
|
|
33
|
+
kind?: string;
|
|
34
|
+
scope?: string;
|
|
22
35
|
}
|
|
23
36
|
|
|
24
37
|
// ─── Constants ──────────────────────────────────────────────────────────
|
|
@@ -60,11 +73,15 @@ export function appendNotification(
|
|
|
60
73
|
message: string,
|
|
61
74
|
severity: NotifySeverity,
|
|
62
75
|
source: NotificationSource = "notify",
|
|
76
|
+
meta?: NotificationMeta,
|
|
63
77
|
): void {
|
|
64
78
|
if (!_basePath) return;
|
|
65
79
|
if (_suppressCount > 0) return;
|
|
66
80
|
const persistedMessage = message.length > 500 ? message.slice(0, 500) + "…" : message;
|
|
67
|
-
|
|
81
|
+
// Structured identity (kind + scope) keys dedup when present, so a rephrased
|
|
82
|
+
// message of the same event still dedups; otherwise fall back to the prose.
|
|
83
|
+
const identity = meta?.kind ? `${meta.kind}:${meta.scope ?? ""}` : persistedMessage;
|
|
84
|
+
const dedupKey = `${_basePath}:${severity}:${source}:${identity}`;
|
|
68
85
|
const now = Date.now();
|
|
69
86
|
const lastSeen = _recentMessageTimestamps.get(dedupKey);
|
|
70
87
|
if (lastSeen !== undefined && now - lastSeen < DEDUP_WINDOW_MS) return;
|
|
@@ -82,6 +99,8 @@ export function appendNotification(
|
|
|
82
99
|
message: persistedMessage,
|
|
83
100
|
source,
|
|
84
101
|
read: false,
|
|
102
|
+
...(meta?.kind ? { kind: meta.kind } : {}),
|
|
103
|
+
...(meta?.scope ? { scope: meta.scope } : {}),
|
|
85
104
|
};
|
|
86
105
|
|
|
87
106
|
try {
|
|
@@ -102,11 +121,15 @@ export function appendNotification(
|
|
|
102
121
|
|
|
103
122
|
/**
|
|
104
123
|
* Read all notification entries from disk. Returns newest-first.
|
|
124
|
+
* An optional filter narrows by structured identity (kind and/or scope).
|
|
105
125
|
*/
|
|
106
|
-
export function readNotifications(basePath?: string): NotificationEntry[] {
|
|
126
|
+
export function readNotifications(basePath?: string, filter?: NotificationMeta): NotificationEntry[] {
|
|
107
127
|
const bp = basePath ?? _basePath;
|
|
108
128
|
if (!bp) return [];
|
|
109
|
-
|
|
129
|
+
const entries = _readEntriesFromDisk(bp).filter(
|
|
130
|
+
(e) => (!filter?.kind || e.kind === filter.kind) && (!filter?.scope || e.scope === filter.scope),
|
|
131
|
+
);
|
|
132
|
+
return entries.reverse();
|
|
110
133
|
}
|
|
111
134
|
|
|
112
135
|
/**
|
|
@@ -128,8 +128,7 @@ function discoverWorkers(basePath: string): string[] {
|
|
|
128
128
|
return [...mids].sort();
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
function querySliceProgress(basePath: string, mid: string): SliceProgress[] {
|
|
132
|
-
const workRoot = worktreePathFor(basePath, mid);
|
|
131
|
+
function querySliceProgress(basePath: string, mid: string, workRoot: string = worktreePathFor(basePath, mid)): SliceProgress[] {
|
|
133
132
|
const dbPath = resolveGsdPathContract(workRoot, basePath).projectDb;
|
|
134
133
|
if (!existsSync(dbPath)) return [];
|
|
135
134
|
|
|
@@ -193,9 +192,12 @@ function collectWorkerData(basePath: string): WorkerView[] {
|
|
|
193
192
|
const workers: WorkerView[] = [];
|
|
194
193
|
|
|
195
194
|
for (const mid of mids) {
|
|
195
|
+
// Resolve the worktree path once per worker per tick — this runs on a
|
|
196
|
+
// 5-second refresh interval and worktreePathFor probes the filesystem.
|
|
197
|
+
const workRoot = worktreePathFor(basePath, mid);
|
|
196
198
|
const status = readJsonSafe<StatusJson>(join(parallelDir, `${mid}.status.json`));
|
|
197
|
-
const lock = readJsonSafe<AutoLock>(join(
|
|
198
|
-
const slices = querySliceProgress(basePath, mid);
|
|
199
|
+
const lock = readJsonSafe<AutoLock>(join(workRoot, ".gsd", "auto.lock"));
|
|
200
|
+
const slices = querySliceProgress(basePath, mid, workRoot);
|
|
199
201
|
|
|
200
202
|
const pid = lock?.pid || status?.pid || 0;
|
|
201
203
|
const alive = pid ? isPidAlive(pid) : false;
|
|
@@ -148,6 +148,39 @@ export function clearPathCache(): void {
|
|
|
148
148
|
|
|
149
149
|
// ─── Name Builders ─────────────────────────────────────────────────────────
|
|
150
150
|
|
|
151
|
+
/** Directories owned by the GSD framework — metadata, never project source. */
|
|
152
|
+
export const FRAMEWORK_METADATA_DIRS: readonly string[] = [".gsd", ".planning", ".audits"];
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Every artifact suffix used with the name builders below — the single source
|
|
156
|
+
* for the `<ID>-<SUFFIX>.md` naming vocabulary. Extend this list when a new
|
|
157
|
+
* artifact type is introduced; consumers (md-importer walking, pre-execution
|
|
158
|
+
* artifact detection) pick it up from here.
|
|
159
|
+
*/
|
|
160
|
+
export const PLANNING_ARTIFACT_SUFFIXES: readonly string[] = [
|
|
161
|
+
"CONTEXT",
|
|
162
|
+
"CONTEXT-DRAFT",
|
|
163
|
+
"ROADMAP",
|
|
164
|
+
"PLAN",
|
|
165
|
+
"REPLAN",
|
|
166
|
+
"SUMMARY",
|
|
167
|
+
"RESEARCH",
|
|
168
|
+
"VALIDATION",
|
|
169
|
+
"ASSESSMENT",
|
|
170
|
+
"UAT",
|
|
171
|
+
"DISCUSSION",
|
|
172
|
+
"EVAL-REVIEW",
|
|
173
|
+
"PARKED",
|
|
174
|
+
"VERIFICATION-FAILED",
|
|
175
|
+
"CONTINUE",
|
|
176
|
+
];
|
|
177
|
+
|
|
178
|
+
/** Matches a bare planning-artifact file name, e.g. "M001-CONTEXT.md", "S01-PLAN.md". */
|
|
179
|
+
export const PLANNING_ARTIFACT_NAME_RE = new RegExp(
|
|
180
|
+
`^[MST]\\d+-(${PLANNING_ARTIFACT_SUFFIXES.join("|")})\\.md$`,
|
|
181
|
+
"i",
|
|
182
|
+
);
|
|
183
|
+
|
|
151
184
|
/**
|
|
152
185
|
* Build a milestone-level file name.
|
|
153
186
|
* ("M001", "CONTEXT") → "M001-CONTEXT.md"
|