@opengsd/gsd-pi 1.2.0-dev.84c56d87 → 1.2.0-dev.9ad8ae33
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/headless-events.js +7 -5
- package/dist/mcp-server.js +2 -1
- package/dist/resource-loader.d.ts +10 -5
- package/dist/resource-loader.js +121 -6
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +5 -4
- 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/gsd/auto/custom-verify-retry-store.js +17 -2
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
- package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
- package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
- package/dist/resources/extensions/gsd/auto/loop.js +4 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +89 -54
- package/dist/resources/extensions/gsd/auto/phases.js +49 -6
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
- package/dist/resources/extensions/gsd/auto-dispatch.js +50 -58
- package/dist/resources/extensions/gsd/auto-model-selection.js +36 -13
- package/dist/resources/extensions/gsd/auto-post-unit.js +30 -12
- package/dist/resources/extensions/gsd/auto-prompts.js +78 -19
- package/dist/resources/extensions/gsd/auto-start.js +35 -15
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +5 -4
- package/dist/resources/extensions/gsd/auto-verification.js +23 -30
- package/dist/resources/extensions/gsd/auto-worktree.js +14 -1
- package/dist/resources/extensions/gsd/auto.js +37 -1
- package/dist/resources/extensions/gsd/blocked-models.js +28 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +26 -6
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +23 -6
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +145 -50
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +302 -80
- package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
- package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
- package/dist/resources/extensions/gsd/commands/context.js +16 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
- package/dist/resources/extensions/gsd/consent-question.js +353 -0
- package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
- package/dist/resources/extensions/gsd/constants.js +0 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
- package/dist/resources/extensions/gsd/db/queries.js +26 -0
- package/dist/resources/extensions/gsd/db-writer.js +8 -17
- package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
- package/dist/resources/extensions/gsd/doctor-git-checks.js +2 -18
- package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
- package/dist/resources/extensions/gsd/files.js +33 -19
- package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
- package/dist/resources/extensions/gsd/gsd-db.js +2 -1
- package/dist/resources/extensions/gsd/guidance.js +60 -0
- package/dist/resources/extensions/gsd/guided-flow.js +6 -3
- package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
- package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
- package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
- package/dist/resources/extensions/gsd/preferences-models.js +2 -2
- package/dist/resources/extensions/gsd/projection-flush.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.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/research-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +7 -5
- package/dist/resources/extensions/gsd/prompts/system.md +5 -2
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
- package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
- package/dist/resources/extensions/gsd/session-lock.js +1 -1
- package/dist/resources/extensions/gsd/state.js +5 -0
- package/dist/resources/extensions/gsd/tool-contract.js +14 -3
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +22 -12
- package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
- package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
- package/dist/resources/extensions/gsd/uat-policy.js +40 -15
- package/dist/resources/extensions/gsd/unit-context-composer.js +65 -0
- package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
- package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
- package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
- package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
- package/dist/resources/extensions/gsd/workflow-events.js +6 -18
- package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
- package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
- package/dist/resources/extensions/gsd/worktree.js +8 -1
- package/dist/resources/extensions/shared/gsd-browser-cli.js +45 -3
- package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
- package/dist/resources/shared/package-manager-detection.js +1 -1
- package/dist/resources/shared/package.json +3 -0
- package/dist/resources/skills/create-skill/SKILL.md +3 -0
- package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/update-check.d.ts +2 -0
- package/dist/update-check.js +24 -1
- package/dist/update-cmd.js +20 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
- 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 +6 -6
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- 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 +26 -18
- package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
- 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 +54 -29
- package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
- package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
- package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
- package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
- package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
- package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
- package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
- 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 +69 -28
- package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
- package/dist/web/standalone/node_modules/postcss/package.json +48 -48
- package/package.json +2 -2
- 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/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 +10 -5
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +4 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +18 -18
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +99 -38
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -4
- 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/README.md +1 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
- package/packages/pi-ai/dist/image-models.generated.js +6 -6
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/index.d.ts +2 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +2 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +419 -221
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +460 -261
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +12 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
- package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.js +12 -3
- package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/package.json +3 -2
- 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/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +5 -4
- 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/browser-tools/tests/gsd-browser-launch-config.test.mjs +40 -1
- package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
- package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
- package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
- package/src/resources/extensions/gsd/auto/loop.ts +4 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +98 -56
- package/src/resources/extensions/gsd/auto/phases.ts +65 -26
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
- package/src/resources/extensions/gsd/auto-dispatch.ts +48 -61
- package/src/resources/extensions/gsd/auto-model-selection.ts +41 -12
- package/src/resources/extensions/gsd/auto-post-unit.ts +33 -12
- package/src/resources/extensions/gsd/auto-prompts.ts +115 -35
- package/src/resources/extensions/gsd/auto-start.ts +36 -18
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +4 -4
- package/src/resources/extensions/gsd/auto-verification.ts +26 -28
- package/src/resources/extensions/gsd/auto-worktree.ts +14 -1
- package/src/resources/extensions/gsd/auto.ts +44 -1
- package/src/resources/extensions/gsd/blocked-models.ts +49 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -5
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +23 -6
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +163 -55
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +350 -86
- package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
- package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
- package/src/resources/extensions/gsd/commands/context.ts +16 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
- package/src/resources/extensions/gsd/consent-question.ts +431 -0
- package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
- package/src/resources/extensions/gsd/constants.ts +0 -3
- package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
- package/src/resources/extensions/gsd/db/queries.ts +37 -0
- package/src/resources/extensions/gsd/db-writer.ts +11 -19
- package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
- package/src/resources/extensions/gsd/doctor-git-checks.ts +2 -19
- package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
- package/src/resources/extensions/gsd/files.ts +33 -12
- package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
- package/src/resources/extensions/gsd/gsd-db.ts +4 -3
- package/src/resources/extensions/gsd/guidance.ts +78 -0
- package/src/resources/extensions/gsd/guided-flow.ts +21 -26
- package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
- package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
- package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
- package/src/resources/extensions/gsd/preferences-models.ts +2 -1
- package/src/resources/extensions/gsd/projection-flush.ts +20 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.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/research-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +7 -5
- package/src/resources/extensions/gsd/prompts/system.md +5 -2
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
- package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
- package/src/resources/extensions/gsd/session-lock.ts +1 -1
- package/src/resources/extensions/gsd/state.ts +5 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +97 -1
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +198 -26
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
- package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
- package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
- package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
- package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -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/gsd-command-home.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/guidance.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +2 -6
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +19 -1
- package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +273 -38
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
- package/src/resources/extensions/gsd/tool-contract.ts +38 -3
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +22 -12
- package/src/resources/extensions/gsd/tools/complete-task.ts +3 -2
- package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
- package/src/resources/extensions/gsd/uat-policy.ts +60 -15
- package/src/resources/extensions/gsd/unit-context-composer.ts +99 -0
- package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
- package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
- package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
- package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
- package/src/resources/extensions/gsd/workflow-events.ts +12 -20
- package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
- package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
- package/src/resources/extensions/gsd/worktree.ts +7 -1
- package/src/resources/extensions/shared/gsd-browser-cli.ts +54 -3
- package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
- package/src/resources/shared/package-manager-detection.ts +1 -1
- package/src/resources/shared/package.json +3 -0
- package/src/resources/skills/create-skill/SKILL.md +3 -0
- package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
- package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
- package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
- package/src/resources/skills/gsd-browser/SKILL.md +0 -41
- /package/dist/web/standalone/.next/static/{AOpDeK_gJHU8OZjRo31gQ → FBNo5cT_chy7YNoAQsU3o}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{AOpDeK_gJHU8OZjRo31gQ → FBNo5cT_chy7YNoAQsU3o}/_ssgManifest.js +0 -0
|
@@ -186,6 +186,7 @@ export function writeLock(basePath, unitType, unitId, sessionFile) {
|
|
|
186
186
|
* stale session-file pointer.
|
|
187
187
|
*/
|
|
188
188
|
export function clearLock(basePath) {
|
|
189
|
+
const legacyLock = readLegacyLock(basePath);
|
|
189
190
|
clearLegacyLockFile(basePath);
|
|
190
191
|
if (!isDbAvailable())
|
|
191
192
|
return;
|
|
@@ -198,9 +199,13 @@ export function clearLock(basePath) {
|
|
|
198
199
|
deleteRuntimeKv("worker", staleWorker.worker_id, SESSION_FILE_KV_KEY);
|
|
199
200
|
return;
|
|
200
201
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
if (legacyLock?.pid) {
|
|
203
|
+
markWorkerStoppingByPid(projectRoot, legacyLock.pid);
|
|
204
|
+
const workerByLegacyPid = getAllAutoWorkers().find((w) => w.pid === legacyLock.pid
|
|
205
|
+
&& normalizeRealPath(w.project_root_realpath) === projectRoot);
|
|
206
|
+
if (workerByLegacyPid)
|
|
207
|
+
forceReleaseLeasesForWorker(workerByLegacyPid.worker_id);
|
|
208
|
+
}
|
|
204
209
|
const worker = findActiveWorkerForCurrentProcess(projectRoot);
|
|
205
210
|
if (worker)
|
|
206
211
|
deleteRuntimeKv("worker", worker.worker_id, SESSION_FILE_KV_KEY);
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// Read-only callers (forensics, dashboard, doctor) depend on this seam, not on
|
|
6
6
|
// the single-writer surface.
|
|
7
7
|
import { getDbOrNull } from "./engine.js";
|
|
8
|
+
import { isClosedStatus } from "../status-guards.js";
|
|
8
9
|
import { getGateIdsForTurn } from "../gate-registry.js";
|
|
9
10
|
import { emptyTaskStatusCounts, rowToActiveTaskSummary, rowToIdStatusSummary, rowToTaskStatusCounts, rowsToStringColumn, } from "../db-lightweight-query-rows.js";
|
|
10
11
|
import { rowToActiveDecision, rowToActiveRequirement, rowToDecision, rowToRequirement, rowsToRequirementCounts, } from "../db-decision-requirement-rows.js";
|
|
@@ -217,6 +218,31 @@ export function getMilestoneSlices(milestoneId) {
|
|
|
217
218
|
const rows = getDbOrNull().prepare("SELECT * FROM slices WHERE milestone_id = :mid ORDER BY sequence, id").all({ ":mid": milestoneId });
|
|
218
219
|
return rows.map(rowToSlice);
|
|
219
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* Consolidated DB read for dispatch/gate/completion decisions (ADR-017).
|
|
223
|
+
* `done` uses the canonical closed-status predicate (`isClosedStatus`) — the
|
|
224
|
+
* same vocabulary the SQL terminal-status fragment derives from. Decision
|
|
225
|
+
* paths must consume this instead of parsing `.gsd/*.md` projections.
|
|
226
|
+
* Rows keep `getMilestoneSlices` ordering (sequence, then id).
|
|
227
|
+
*/
|
|
228
|
+
export function getMilestoneSliceSummaries(milestoneId) {
|
|
229
|
+
return getMilestoneSlices(milestoneId).map((s) => ({
|
|
230
|
+
id: s.id,
|
|
231
|
+
title: s.title,
|
|
232
|
+
done: isClosedStatus(s.status),
|
|
233
|
+
depends: s.depends ?? [],
|
|
234
|
+
}));
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Ids of slices closed per the canonical status vocabulary (ADR-017), in
|
|
238
|
+
* milestone order. Thin wrapper over `getMilestoneSliceSummaries` for the
|
|
239
|
+
* common "which slices are done?" decision-path read.
|
|
240
|
+
*/
|
|
241
|
+
export function getClosedSliceIds(milestoneId) {
|
|
242
|
+
return getMilestoneSliceSummaries(milestoneId)
|
|
243
|
+
.filter((s) => s.done)
|
|
244
|
+
.map((s) => s.id);
|
|
245
|
+
}
|
|
220
246
|
export function getArtifact(path) {
|
|
221
247
|
if (!getDbOrNull())
|
|
222
248
|
return null;
|
|
@@ -620,27 +620,18 @@ async function mirrorDecisionToMemory(id, normalizedFields) {
|
|
|
620
620
|
/**
|
|
621
621
|
* Extract a milestone/slice reference from a deferral decision.
|
|
622
622
|
*
|
|
623
|
-
* Detects deferrals
|
|
624
|
-
* - scope contains "defer" (e.g., "deferral", "defer")
|
|
625
|
-
* - choice or decision contains "defer" + an M###/S## pattern
|
|
623
|
+
* Detects deferrals when the slice reference is part of the deferral phrase.
|
|
626
624
|
*
|
|
627
625
|
* Returns { milestoneId, sliceId } if found, null otherwise.
|
|
628
626
|
*/
|
|
629
627
|
export function extractDeferredSliceRef(fields) {
|
|
630
|
-
const
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
const choiceMatch = fields.choice.match(slicePattern);
|
|
638
|
-
if (choiceMatch) {
|
|
639
|
-
return { milestoneId: choiceMatch[1], sliceId: choiceMatch[2] };
|
|
640
|
-
}
|
|
641
|
-
const decisionMatch = fields.decision.match(slicePattern);
|
|
642
|
-
if (decisionMatch) {
|
|
643
|
-
return { milestoneId: decisionMatch[1], sliceId: decisionMatch[2] };
|
|
628
|
+
const defersSlicePattern = /\bdefer(?:ral|red|ring|s)?\b\s+(?:(?:of|the)\s+)*(?:slice\s+)?\b(M\d{3,4})\/(S\d{2,3})\b/i;
|
|
629
|
+
const sliceIsDeferredPattern = /\b(M\d{3,4})\/(S\d{2,3})\b\s+(?:is|was|will be|should be|can be)\s+defer(?:red|ring)?\b/i;
|
|
630
|
+
for (const text of [fields.choice, fields.decision, fields.scope]) {
|
|
631
|
+
const match = text.match(defersSlicePattern) ?? text.match(sliceIsDeferredPattern);
|
|
632
|
+
if (match) {
|
|
633
|
+
return { milestoneId: match[1], sliceId: match[2] };
|
|
634
|
+
}
|
|
644
635
|
}
|
|
645
636
|
return null;
|
|
646
637
|
}
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
import { resolveMilestoneFile } from "./paths.js";
|
|
3
3
|
import { findMilestoneIds } from "./guided-flow.js";
|
|
4
4
|
import { parseUnitId } from "./unit-id.js";
|
|
5
|
-
import { isDbAvailable,
|
|
6
|
-
import {
|
|
7
|
-
import { isClosedStatus, isSkippedForDispatch } from "./status-guards.js";
|
|
5
|
+
import { isDbAvailable, getMilestoneSliceSummaries, getMilestone } from "./gsd-db.js";
|
|
6
|
+
import { isSkippedForDispatch } from "./status-guards.js";
|
|
8
7
|
import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
|
|
9
8
|
import { readFileSync } from "node:fs";
|
|
10
9
|
const SLICE_DISPATCH_TYPES = new Set([
|
|
@@ -97,38 +96,14 @@ export function getPriorSliceCompletionBlocker(base, _mainBranch, unitType, unit
|
|
|
97
96
|
continue;
|
|
98
97
|
}
|
|
99
98
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}));
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
if (!slices) {
|
|
112
|
-
// File-based fallback: parse roadmap checkboxes
|
|
113
|
-
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
114
|
-
if (!roadmapPath)
|
|
115
|
-
continue;
|
|
116
|
-
let roadmapContent;
|
|
117
|
-
try {
|
|
118
|
-
roadmapContent = readFileSync(roadmapPath, "utf-8");
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
const parsed = parseRoadmap(roadmapContent);
|
|
124
|
-
if (parsed.slices.length === 0)
|
|
125
|
-
continue;
|
|
126
|
-
slices = parsed.slices.map((s) => ({
|
|
127
|
-
id: s.id,
|
|
128
|
-
done: s.done,
|
|
129
|
-
depends: s.depends ?? [],
|
|
130
|
-
}));
|
|
131
|
-
}
|
|
99
|
+
// DB-authoritative eligibility list (ADR-017) — markdown projections are
|
|
100
|
+
// never parsed for dispatch decisions. No DB / no rows → skip this
|
|
101
|
+
// milestone's check (unknown is not a blocker).
|
|
102
|
+
if (!isDbAvailable())
|
|
103
|
+
continue;
|
|
104
|
+
const slices = getMilestoneSliceSummaries(mid);
|
|
105
|
+
if (slices.length === 0)
|
|
106
|
+
continue;
|
|
132
107
|
if (mid !== targetMid) {
|
|
133
108
|
const incomplete = slices.find((slice) => !slice.done);
|
|
134
109
|
if (incomplete) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { existsSync, statSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
2
|
import { isDbAvailable, _getAdapter } from "./gsd-db.js";
|
|
4
3
|
import { isAfter, latestExplicitReopenAt } from "./milestone-reopen-events.js";
|
|
5
4
|
import { resolveGsdPathContract, resolveMilestoneFile } from "./paths.js";
|
|
6
5
|
import { deriveState } from "./state.js";
|
|
6
|
+
import { workflowEventLogPath } from "./workflow-event-ledger.js";
|
|
7
7
|
import { readEvents } from "./workflow-events.js";
|
|
8
|
-
import {
|
|
8
|
+
import { flushWorkflowProjections } from "./projection-flush.js";
|
|
9
9
|
export async function checkEngineHealth(basePath, issues, fixesApplied) {
|
|
10
10
|
const dbPath = resolveGsdPathContract(basePath).projectDb;
|
|
11
11
|
if (!isDbAvailable() && existsSync(dbPath)) {
|
|
@@ -228,7 +228,7 @@ export async function checkEngineHealth(basePath, issues, fixesApplied) {
|
|
|
228
228
|
// relative to the event log and re-render them.
|
|
229
229
|
try {
|
|
230
230
|
if (isDbAvailable()) {
|
|
231
|
-
const eventLogPath =
|
|
231
|
+
const eventLogPath = workflowEventLogPath(basePath);
|
|
232
232
|
const events = readEvents(eventLogPath);
|
|
233
233
|
if (events.length > 0) {
|
|
234
234
|
const lastEventTs = new Date(events[events.length - 1].ts).getTime();
|
|
@@ -239,7 +239,7 @@ export async function checkEngineHealth(basePath, issues, fixesApplied) {
|
|
|
239
239
|
const roadmapPath = resolveMilestoneFile(basePath, milestone.id, "ROADMAP");
|
|
240
240
|
if (!roadmapPath || !existsSync(roadmapPath)) {
|
|
241
241
|
try {
|
|
242
|
-
await
|
|
242
|
+
await flushWorkflowProjections(basePath, { milestoneId: milestone.id });
|
|
243
243
|
fixesApplied.push(`re-rendered missing projections for ${milestone.id}`);
|
|
244
244
|
}
|
|
245
245
|
catch {
|
|
@@ -250,7 +250,7 @@ export async function checkEngineHealth(basePath, issues, fixesApplied) {
|
|
|
250
250
|
const projectionMtime = statSync(roadmapPath).mtimeMs;
|
|
251
251
|
if (lastEventTs > projectionMtime) {
|
|
252
252
|
try {
|
|
253
|
-
await
|
|
253
|
+
await flushWorkflowProjections(basePath, { milestoneId: milestone.id });
|
|
254
254
|
fixesApplied.push(`re-rendered stale projections for ${milestone.id}`);
|
|
255
255
|
}
|
|
256
256
|
catch {
|
|
@@ -3,10 +3,9 @@ import { spawnSync } from "node:child_process";
|
|
|
3
3
|
import { cpSync, existsSync, mkdirSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { loadFile } from "./files.js";
|
|
6
|
-
import { parseRoadmap as parseLegacyRoadmap } from "./parsers-legacy.js";
|
|
7
|
-
import { isDbAvailable, getMilestone } from "./gsd-db.js";
|
|
8
6
|
import { resolveMilestoneFile } from "./paths.js";
|
|
9
|
-
import {
|
|
7
|
+
import { isCompletedMilestoneTerminal } from "./milestone-closeout.js";
|
|
8
|
+
import { deriveState } from "./state.js";
|
|
10
9
|
import { allWorktreesDirs, createWorktree, listWorktrees, resolveGitDir } from "./worktree-manager.js";
|
|
11
10
|
import { abortAndReset } from "./git-self-heal.js";
|
|
12
11
|
import { RUNTIME_EXCLUSION_PATHS, resolveMilestoneIntegrationBranch, writeIntegrationBranch } from "./git-service.js";
|
|
@@ -141,21 +140,6 @@ function getSnapshotDiffCheckFailure(basePath) {
|
|
|
141
140
|
}
|
|
142
141
|
return failures.length > 0 ? failures.join("\n") : null;
|
|
143
142
|
}
|
|
144
|
-
async function isCompletedMilestoneTerminal(basePath, milestoneId) {
|
|
145
|
-
const summaryPath = resolveMilestoneFile(basePath, milestoneId, "SUMMARY");
|
|
146
|
-
if (!summaryPath)
|
|
147
|
-
return false;
|
|
148
|
-
if (isDbAvailable()) {
|
|
149
|
-
const milestone = getMilestone(milestoneId);
|
|
150
|
-
return !!milestone && milestone.status === "complete";
|
|
151
|
-
}
|
|
152
|
-
const roadmapPath = resolveMilestoneFile(basePath, milestoneId, "ROADMAP");
|
|
153
|
-
const roadmapContent = roadmapPath ? await loadFile(roadmapPath) : null;
|
|
154
|
-
if (!roadmapContent)
|
|
155
|
-
return false;
|
|
156
|
-
const roadmap = parseLegacyRoadmap(roadmapContent);
|
|
157
|
-
return isMilestoneComplete(roadmap);
|
|
158
|
-
}
|
|
159
143
|
export async function checkGitHealth(basePath, issues, fixesApplied, shouldFix, isolationMode = "none") {
|
|
160
144
|
// Degrade gracefully if not a git repo
|
|
161
145
|
if (!nativeIsRepo(basePath)) {
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Typed contract for which tool lifecycle hooks fire under which
|
|
3
|
+
// engine, plus the single seam for tool-name normalization.
|
|
4
|
+
//
|
|
5
|
+
// ── Why this contract exists ────────────────────────────────────────────────
|
|
6
|
+
// External engines (claude-code-cli) pre-execute tools inside the vendor CLI
|
|
7
|
+
// and hand the agent loop a `toolCall.externalResult`. The loop short-circuits
|
|
8
|
+
// before `beforeToolCall`/`afterToolCall` ever run for those calls
|
|
9
|
+
// (packages/pi-agent-core/src/agent-loop.ts, prepareToolCall: the
|
|
10
|
+
// externalResult branch returns an "immediate" outcome before the
|
|
11
|
+
// config.beforeToolCall invocation, and "immediate" outcomes skip
|
|
12
|
+
// finalizeExecutedToolCall where config.afterToolCall lives).
|
|
13
|
+
// `beforeToolCall`/`afterToolCall` are exactly what the extension runner maps
|
|
14
|
+
// to the `tool_call`/`tool_result` extension events
|
|
15
|
+
// (packages/gsd-agent-core/src/session/agent-session-extensions.ts,
|
|
16
|
+
// installAgentToolHooks).
|
|
17
|
+
//
|
|
18
|
+
// `tool_execution_start` is emitted unconditionally before prepareToolCall
|
|
19
|
+
// and `tool_execution_end` after every finalized outcome — immediate or
|
|
20
|
+
// executed — so those two are the ONLY tool lifecycle hooks that fire for
|
|
21
|
+
// every tool call on every engine.
|
|
22
|
+
//
|
|
23
|
+
// Consequence: any enforcement attached only to `tool_call` (blocking) or
|
|
24
|
+
// `tool_result` (rewriting) is silently dead under external engines. Safety
|
|
25
|
+
// enforcement must ride `tool_execution_start`/`tool_execution_end`, or
|
|
26
|
+
// mirror across both with toolCallId dedup. See the per-registration contract
|
|
27
|
+
// comments in bootstrap/register-hooks.ts for how each registered hook
|
|
28
|
+
// honors (or knowingly violates) this contract.
|
|
29
|
+
import { stripMcpToolPrefix } from "./mcp-tool-name.js";
|
|
30
|
+
import { canonicalWorkflowSurfaceToolName } from "./workflow-tool-surface.js";
|
|
31
|
+
/**
|
|
32
|
+
* Tool lifecycle hooks that fire for EVERY tool call on EVERY engine,
|
|
33
|
+
* including external engines (claude-code-cli) that pre-execute tools.
|
|
34
|
+
* Attach safety-critical enforcement and evidence collection here.
|
|
35
|
+
*/
|
|
36
|
+
export const UNIVERSAL_TOOL_HOOKS = ["tool_execution_start", "tool_execution_end"];
|
|
37
|
+
/**
|
|
38
|
+
* Tool lifecycle hooks that fire ONLY for natively executed tools. External
|
|
39
|
+
* engines pre-execute tools (externalResult), short-circuiting the agent
|
|
40
|
+
* loop's beforeToolCall/afterToolCall — so handlers on these events never run
|
|
41
|
+
* for those calls. Blocking guards attached only here are dead under external
|
|
42
|
+
* engines; they need a tool_execution_start mirror to be universal.
|
|
43
|
+
*/
|
|
44
|
+
export const NATIVE_ONLY_TOOL_HOOKS = ["tool_call", "tool_result"];
|
|
45
|
+
// Non-tool lifecycle events (session_start, agent_end, message_update, ...)
|
|
46
|
+
// are intentionally NOT classified here: they are emitted by the session
|
|
47
|
+
// host / extension runner independent of tool execution, so the external
|
|
48
|
+
// engine short-circuit above does not apply to them. Only classify events
|
|
49
|
+
// whose engine behavior has been verified against the agent loop.
|
|
50
|
+
/**
|
|
51
|
+
* Canonical tool name: strips the `mcp__<server>__` prefix when present,
|
|
52
|
+
* nothing else. Use for identity checks against host/native tool names and
|
|
53
|
+
* for any guard that must NOT conflate workflow aliases with their canonical
|
|
54
|
+
* tools (e.g. write gates, evidence keys).
|
|
55
|
+
*
|
|
56
|
+
* Malformed MCP names (empty server or empty tool segment, e.g.
|
|
57
|
+
* `mcp____tool` or `mcp__server__`) are returned unchanged.
|
|
58
|
+
*/
|
|
59
|
+
export function canonicalToolName(toolName) {
|
|
60
|
+
return stripMcpToolPrefix(toolName);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Workflow-aware canonical tool name: strips the MCP prefix AND resolves
|
|
64
|
+
* workflow tool aliases to their canonical contract names. Use whenever the
|
|
65
|
+
* name is compared against the workflow tool surface (scoping, presentation,
|
|
66
|
+
* dispatch) — plain {@link canonicalToolName} would miss alias spellings.
|
|
67
|
+
*/
|
|
68
|
+
export function canonicalWorkflowToolName(toolName) {
|
|
69
|
+
return canonicalWorkflowSurfaceToolName(toolName);
|
|
70
|
+
}
|
|
@@ -11,7 +11,11 @@ import { spawn } from "node:child_process";
|
|
|
11
11
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
12
12
|
import { randomUUID } from "node:crypto";
|
|
13
13
|
import { resolve } from "node:path";
|
|
14
|
+
import { killProcessTree, SIGKILL_GRACE_MS, HARD_DEADLINE_MS } from "@gsd/pi-coding-agent";
|
|
14
15
|
const ALWAYS_FORWARD_ENV = ["PATH", "HOME"];
|
|
16
|
+
// SIGKILL_GRACE_MS / HARD_DEADLINE_MS are imported from @gsd/pi-coding-agent
|
|
17
|
+
// (shell.ts) — the single source of truth for the graceful-kill timing ladder —
|
|
18
|
+
// so this sandbox can never drift from the canonical kill path it delegates to.
|
|
15
19
|
export const EXEC_DEFAULTS = {
|
|
16
20
|
clampTimeoutMs: 600_000,
|
|
17
21
|
defaultTimeoutMs: 30_000,
|
|
@@ -120,6 +124,7 @@ export function runExecSandbox(request, opts) {
|
|
|
120
124
|
exit_code: null,
|
|
121
125
|
signal: null,
|
|
122
126
|
timed_out: false,
|
|
127
|
+
force_resolved: false,
|
|
123
128
|
duration_ms: duration,
|
|
124
129
|
stdout_bytes: 0,
|
|
125
130
|
stderr_bytes: Buffer.byteLength(`spawn error: ${message}\n`),
|
|
@@ -172,24 +177,38 @@ export function runExecSandbox(request, opts) {
|
|
|
172
177
|
stderrTruncated = true;
|
|
173
178
|
}
|
|
174
179
|
});
|
|
180
|
+
const effectiveGraceMs = opts.kill_grace_ms ?? SIGKILL_GRACE_MS;
|
|
181
|
+
const effectiveForceResolveDelay = opts.force_resolve_delay_ms ?? (effectiveGraceMs + HARD_DEADLINE_MS);
|
|
175
182
|
let timedOut = false;
|
|
183
|
+
let settled = false;
|
|
184
|
+
let forceResolveTimer;
|
|
176
185
|
const timer = setTimeout(() => {
|
|
177
186
|
timedOut = true;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
187
|
+
// killProcessTree handles both platforms and kills the whole tree: on Unix
|
|
188
|
+
// it signals the process group (SIGTERM -> grace -> SIGKILL); on Windows it
|
|
189
|
+
// force-kills the tree via taskkill /F /T. Using child.kill("SIGTERM") here
|
|
190
|
+
// would only terminate the direct child on Windows, orphaning grandchildren.
|
|
191
|
+
if (child.pid != null) {
|
|
192
|
+
killProcessTree(child.pid, { graceMs: effectiveGraceMs });
|
|
185
193
|
}
|
|
186
194
|
else {
|
|
187
|
-
child.kill("
|
|
195
|
+
child.kill("SIGTERM");
|
|
188
196
|
}
|
|
197
|
+
// Arm hard-deadline force-resolve in case child never closes (D-state).
|
|
198
|
+
// The "SIGKILL" here is a synthetic marker (the process may not have actually
|
|
199
|
+
// received it); force_resolved=true records that this was a deadline, not an exit.
|
|
200
|
+
forceResolveTimer = setTimeout(() => {
|
|
201
|
+
finalize(null, "SIGKILL", true);
|
|
202
|
+
}, effectiveForceResolveDelay);
|
|
203
|
+
forceResolveTimer.unref?.();
|
|
189
204
|
}, timeoutMs);
|
|
190
205
|
timer.unref?.();
|
|
191
|
-
const finalize = (exitCode, signal) => {
|
|
206
|
+
const finalize = (exitCode, signal, forceResolved = false) => {
|
|
207
|
+
if (settled)
|
|
208
|
+
return;
|
|
209
|
+
settled = true;
|
|
192
210
|
clearTimeout(timer);
|
|
211
|
+
clearTimeout(forceResolveTimer);
|
|
193
212
|
const duration = Date.now() - started;
|
|
194
213
|
const stdoutBuf = Buffer.concat(stdoutChunks);
|
|
195
214
|
const stderrBuf = Buffer.concat(stderrChunks);
|
|
@@ -211,6 +230,7 @@ export function runExecSandbox(request, opts) {
|
|
|
211
230
|
exit_code: exitCode,
|
|
212
231
|
signal,
|
|
213
232
|
timed_out: timedOut,
|
|
233
|
+
force_resolved: forceResolved,
|
|
214
234
|
duration_ms: duration,
|
|
215
235
|
stdout_bytes: stdoutBytes,
|
|
216
236
|
stderr_bytes: stderrBytes,
|
|
@@ -254,6 +274,7 @@ function writeMeta(path, result, request, now) {
|
|
|
254
274
|
exit_code: result.exit_code,
|
|
255
275
|
signal: result.signal,
|
|
256
276
|
timed_out: result.timed_out,
|
|
277
|
+
force_resolved: result.force_resolved,
|
|
257
278
|
duration_ms: result.duration_ms,
|
|
258
279
|
stdout_bytes: result.stdout_bytes,
|
|
259
280
|
stderr_bytes: result.stderr_bytes,
|
|
@@ -261,7 +282,6 @@ function writeMeta(path, result, request, now) {
|
|
|
261
282
|
stderr_truncated: result.stderr_truncated,
|
|
262
283
|
stdout_path: result.stdout_path,
|
|
263
284
|
stderr_path: result.stderr_path,
|
|
264
|
-
...(request.metadata ? { metadata: request.metadata } : {}),
|
|
265
285
|
};
|
|
266
286
|
writeFileSync(path, `${JSON.stringify(meta, null, 2)}\n`);
|
|
267
287
|
}
|
|
@@ -576,38 +576,52 @@ export function parseTaskPlanIO(content) {
|
|
|
576
576
|
outputFiles: extractPaths(outputSection),
|
|
577
577
|
};
|
|
578
578
|
}
|
|
579
|
+
/** Canonical list of recognised UAT types — uat-policy.ts re-exports this as UAT_TYPES. */
|
|
580
|
+
export const UAT_TYPE_KEYWORDS = [
|
|
581
|
+
'artifact-driven',
|
|
582
|
+
'browser-executable',
|
|
583
|
+
'runtime-executable',
|
|
584
|
+
'live-runtime',
|
|
585
|
+
'mixed',
|
|
586
|
+
'human-experience',
|
|
587
|
+
];
|
|
588
|
+
/** Match a value against the recognised UAT type keywords (leading-keyword-only). */
|
|
589
|
+
function matchUatTypeKeyword(value) {
|
|
590
|
+
const normalized = value.trim().toLowerCase();
|
|
591
|
+
return UAT_TYPE_KEYWORDS.find(keyword => normalized.startsWith(keyword));
|
|
592
|
+
}
|
|
579
593
|
/**
|
|
580
594
|
* Extract the UAT type from a UAT file's raw content.
|
|
581
595
|
*
|
|
582
596
|
* UAT files have no YAML frontmatter - pass raw file content directly.
|
|
583
597
|
* Classification is leading-keyword-only: e.g. `mixed (artifact-driven + live-runtime)` → `'mixed'`.
|
|
584
598
|
*
|
|
599
|
+
* The canonical form is a `- UAT mode: <type>` bullet under `## UAT Type`
|
|
600
|
+
* (case-insensitive prefix, `**bold**` tolerated). When no such line exists,
|
|
601
|
+
* a line that itself starts with a recognised keyword — e.g. a bare
|
|
602
|
+
* `browser-executable` under the heading — is accepted, so agent-authored
|
|
603
|
+
* format drift does not silently fall back to artifact-driven.
|
|
604
|
+
*
|
|
585
605
|
* Returns `undefined` when:
|
|
586
606
|
* - the `## UAT Type` section is absent
|
|
587
|
-
* -
|
|
588
|
-
* -
|
|
607
|
+
* - a `UAT mode:` line exists but its value starts with no recognised keyword
|
|
608
|
+
* - no line in the section starts with `UAT mode:` or a recognised keyword
|
|
589
609
|
*/
|
|
590
610
|
export function extractUatType(content) {
|
|
591
611
|
const sectionText = extractSection(content, 'UAT Type');
|
|
592
612
|
if (!sectionText)
|
|
593
613
|
return undefined;
|
|
594
|
-
const
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
if (rawValue.startsWith('live-runtime'))
|
|
606
|
-
return 'live-runtime';
|
|
607
|
-
if (rawValue.startsWith('human-experience'))
|
|
608
|
-
return 'human-experience';
|
|
609
|
-
if (rawValue.startsWith('mixed'))
|
|
610
|
-
return 'mixed';
|
|
614
|
+
const lines = parseBullets(sectionText).map(line => line.replace(/\*\*/g, ''));
|
|
615
|
+
for (const line of lines) {
|
|
616
|
+
const declared = /^uat mode:\s*(.*)$/i.exec(line);
|
|
617
|
+
if (declared)
|
|
618
|
+
return matchUatTypeKeyword(declared[1]);
|
|
619
|
+
}
|
|
620
|
+
for (const line of lines) {
|
|
621
|
+
const matched = matchUatTypeKeyword(line);
|
|
622
|
+
if (matched)
|
|
623
|
+
return matched;
|
|
624
|
+
}
|
|
611
625
|
return undefined;
|
|
612
626
|
}
|
|
613
627
|
/**
|
|
@@ -28,13 +28,17 @@ export function buildGsdHomeModel(state, closeout) {
|
|
|
28
28
|
const workLabel = activeWorkLabel(state);
|
|
29
29
|
const strandedQuick = closeout?.strandedQuick ?? null;
|
|
30
30
|
const unmergedMilestone = closeout?.unmergedMilestones?.[0];
|
|
31
|
+
const idleResidueHint = closeout?.idleResidueHint ?? null;
|
|
32
|
+
const hasIdleResidue = Boolean(idleResidueHint);
|
|
31
33
|
const nextReason = complete
|
|
32
34
|
? "all milestones are complete"
|
|
33
35
|
: blocked
|
|
34
36
|
? "the active milestone is blocked"
|
|
35
|
-
:
|
|
36
|
-
? "
|
|
37
|
-
:
|
|
37
|
+
: hasIdleResidue
|
|
38
|
+
? "milestone git residue needs recovery"
|
|
39
|
+
: !hasActiveWork
|
|
40
|
+
? "there is no active milestone"
|
|
41
|
+
: "";
|
|
38
42
|
const canAdvance = hasActiveWork && !blocked && !complete;
|
|
39
43
|
const unmappedActive = complete ? countUnmappedActiveRequirements() : 0;
|
|
40
44
|
const recommended = strandedQuick
|
|
@@ -43,11 +47,13 @@ export function buildGsdHomeModel(state, closeout) {
|
|
|
43
47
|
? "finish_milestone"
|
|
44
48
|
: blocked
|
|
45
49
|
? "fix_recover"
|
|
46
|
-
:
|
|
47
|
-
? "
|
|
48
|
-
:
|
|
49
|
-
? "
|
|
50
|
-
:
|
|
50
|
+
: hasIdleResidue
|
|
51
|
+
? "fix_recover"
|
|
52
|
+
: canAdvance
|
|
53
|
+
? "continue_step"
|
|
54
|
+
: complete && unmappedActive > 0
|
|
55
|
+
? "review_requirements_backlog"
|
|
56
|
+
: "start_configure";
|
|
51
57
|
const completionSummary = complete
|
|
52
58
|
? appendRequirementsBacklogToSummary(state, [
|
|
53
59
|
`All milestones complete${state.lastCompletedMilestone ? ` after ${state.lastCompletedMilestone.id}: ${state.lastCompletedMilestone.title}` : ""}.`,
|
|
@@ -57,7 +63,9 @@ export function buildGsdHomeModel(state, closeout) {
|
|
|
57
63
|
? [`Quick task Q${strandedQuick.taskNum} finished on ${strandedQuick.quickBranch} but is not merged to ${strandedQuick.originalBranch}.`]
|
|
58
64
|
: unmergedMilestone
|
|
59
65
|
? [`${unmergedMilestone.milestoneId} is complete but not merged into ${unmergedMilestone.integrationBranch}.`]
|
|
60
|
-
:
|
|
66
|
+
: idleResidueHint
|
|
67
|
+
? [idleResidueHint.message]
|
|
68
|
+
: completionSummary;
|
|
61
69
|
return {
|
|
62
70
|
title: "GSD — What now?",
|
|
63
71
|
summary: [
|
|
@@ -130,10 +138,12 @@ export function buildGsdHomeModel(state, closeout) {
|
|
|
130
138
|
label: "Fix or recover",
|
|
131
139
|
description: blocked
|
|
132
140
|
? "Review the blocker and recovery commands for the active milestone."
|
|
133
|
-
:
|
|
134
|
-
|
|
141
|
+
: hasIdleResidue
|
|
142
|
+
? "Review stranded milestone worktrees/branches and run the suggested recovery command."
|
|
143
|
+
: disabled("This becomes active when closeout, validation, or state recovery is needed.", "no blocker is active"),
|
|
144
|
+
enabled: blocked || hasIdleResidue,
|
|
135
145
|
recommended: recommended === "fix_recover",
|
|
136
|
-
disabledReason: blocked ? undefined : "no blocker is active",
|
|
146
|
+
disabledReason: blocked || hasIdleResidue ? undefined : "no blocker is active",
|
|
137
147
|
},
|
|
138
148
|
{
|
|
139
149
|
id: "start_configure",
|
|
@@ -169,7 +169,7 @@ export function insertArtifact(a) {
|
|
|
169
169
|
export function insertMilestone(m) {
|
|
170
170
|
if (!getDbOrNull())
|
|
171
171
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
172
|
-
getDbOrNull().prepare(`INSERT OR IGNORE INTO milestones (
|
|
172
|
+
const result = getDbOrNull().prepare(`INSERT OR IGNORE INTO milestones (
|
|
173
173
|
id, title, status, depends_on, created_at,
|
|
174
174
|
vision, success_criteria, key_risks, proof_strategy,
|
|
175
175
|
verification_contract, verification_integration, verification_operational, verification_uat,
|
|
@@ -199,6 +199,7 @@ export function insertMilestone(m) {
|
|
|
199
199
|
":requirement_coverage": m.planning?.requirementCoverage ?? "",
|
|
200
200
|
":boundary_map_markdown": m.planning?.boundaryMapMarkdown ?? "",
|
|
201
201
|
});
|
|
202
|
+
return (result.changes ?? 0) > 0;
|
|
202
203
|
}
|
|
203
204
|
export function upsertMilestonePlanning(milestoneId, planning) {
|
|
204
205
|
if (!getDbOrNull())
|
|
@@ -55,6 +55,66 @@ export function needsRemediationBlockerGuidance(milestoneId) {
|
|
|
55
55
|
`3. If this should wait, defer it explicitly: \`/gsd park ${milestoneId}\``,
|
|
56
56
|
].join("\n");
|
|
57
57
|
}
|
|
58
|
+
// ─── Milestone closeout UAT sign-off blockers ───────────────────────────
|
|
59
|
+
// The first sentence is the blocker finding; the numbered steps are the
|
|
60
|
+
// resolution path. `verdict` is the recorded non-PASS verdict, or undefined
|
|
61
|
+
// when no verdict has been recorded at all.
|
|
62
|
+
export function uatSignoffBlockerGuidance(milestoneId, sliceId, verdict) {
|
|
63
|
+
const finding = verdict === undefined
|
|
64
|
+
? `missing UAT PASS verdict for ${sliceId}`
|
|
65
|
+
: `UAT verdict for ${sliceId} is "${verdict}"`;
|
|
66
|
+
const sliceSpecificRerunStep = `If ${sliceId} is not the most recently completed slice, type a chat request to re-run UAT for ${sliceId}; run-uat will record the verdict through \`gsd_uat_result_save\`.`;
|
|
67
|
+
const steps = verdict === undefined
|
|
68
|
+
? [
|
|
69
|
+
`1. Run UAT for the most recently completed slice to record a verdict: \`/gsd dispatch uat\``,
|
|
70
|
+
`2. ${sliceSpecificRerunStep}`,
|
|
71
|
+
`3. Review the UAT criteria and progress: \`/gsd status\``,
|
|
72
|
+
`4. After UAT records PASS, run \`/gsd auto\` to complete the milestone.`,
|
|
73
|
+
]
|
|
74
|
+
: [
|
|
75
|
+
`1. Review the failing UAT findings: \`/gsd status\` (the ${sliceId} ASSESSMENT records what failed)`,
|
|
76
|
+
`2. Fix the issue, then re-run UAT for the most recently completed slice to record a fresh verdict: \`/gsd dispatch uat\``,
|
|
77
|
+
`3. ${sliceSpecificRerunStep}`,
|
|
78
|
+
`4. If the fix needs new implementation work, add remediation slices: \`/gsd dispatch reassess\``,
|
|
79
|
+
`5. After UAT records PASS, run \`/gsd auto\` to complete the milestone.`,
|
|
80
|
+
];
|
|
81
|
+
return [
|
|
82
|
+
`Cannot complete milestone ${milestoneId}: ${finding}. Manual UAT sign-off (PASS) is required before milestone closure.`,
|
|
83
|
+
`Fix options:`,
|
|
84
|
+
...steps,
|
|
85
|
+
].join("\n");
|
|
86
|
+
}
|
|
87
|
+
// ─── Worktree isolation degradation ─────────────────────────────────────
|
|
88
|
+
// The first sentence of each notice is load-bearing for log matching and
|
|
89
|
+
// tests — keep it intact and append guidance after it.
|
|
90
|
+
function restoreIsolationHint(milestoneId) {
|
|
91
|
+
return `To restore isolation: close any processes using the old worktree, merge salvageable work with \`/gsd worktree merge ${milestoneId}\` or remove the stale worktree with \`/gsd worktree remove ${milestoneId}\`, then run \`/gsd doctor fix\`.`;
|
|
92
|
+
}
|
|
93
|
+
export function worktreeCreationFailedGuidance(milestoneId, error) {
|
|
94
|
+
return [
|
|
95
|
+
`Auto-worktree creation for ${milestoneId} failed: ${error}. Continuing in project root.`,
|
|
96
|
+
`Worktree isolation is degraded for this session.`,
|
|
97
|
+
restoreIsolationHint(milestoneId),
|
|
98
|
+
].join("\n");
|
|
99
|
+
}
|
|
100
|
+
export function isolationDegradedFallbackGuidance(milestoneId) {
|
|
101
|
+
return [
|
|
102
|
+
`Worktree isolation is degraded. Fell back to branch milestone/${milestoneId}.`,
|
|
103
|
+
`Work continues safely on the milestone branch in the project root.`,
|
|
104
|
+
restoreIsolationHint(milestoneId),
|
|
105
|
+
].join("\n");
|
|
106
|
+
}
|
|
107
|
+
/** Hard entry blockers from auto-start: bootstrap stopped, user must act. */
|
|
108
|
+
export function milestoneEntryBlockedGuidance(milestoneId, reason) {
|
|
109
|
+
const finding = reason === "creation-failed"
|
|
110
|
+
? `worktree/branch creation failed. Isolation is degraded.`
|
|
111
|
+
: `isolation is degraded from a prior worktree failure.`;
|
|
112
|
+
return [
|
|
113
|
+
`Cannot enter milestone ${milestoneId}: ${finding}`,
|
|
114
|
+
restoreIsolationHint(milestoneId),
|
|
115
|
+
`Then run \`/gsd auto\` to retry.`,
|
|
116
|
+
].join("\n");
|
|
117
|
+
}
|
|
58
118
|
// ─── Crash recovery resume hints ────────────────────────────────────────
|
|
59
119
|
/** Resume hint for an interrupted auto-mode unit, by unit class. */
|
|
60
120
|
export function crashResumeHint(unitType, unitId) {
|