gsd-pi 2.82.0-dev.2841a1e44 → 2.82.0-dev.3709f22a5
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/README.md +2 -2
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +7 -0
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
- package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
- package/dist/resources/extensions/gsd/auto/loop.js +5 -5
- package/dist/resources/extensions/gsd/auto/orchestrator.js +11 -0
- package/dist/resources/extensions/gsd/auto/phases.js +28 -2
- package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +13 -6
- package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +70 -9
- package/dist/resources/extensions/gsd/auto-recovery.js +31 -1
- package/dist/resources/extensions/gsd/auto-start.js +85 -12
- package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
- package/dist/resources/extensions/gsd/auto.js +37 -4
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +25 -6
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +9 -8
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +4 -2
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +5 -2
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +13 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +17 -1
- package/dist/resources/extensions/gsd/crash-recovery.js +31 -5
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
- package/dist/resources/extensions/gsd/doctor-git-checks.js +46 -1
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
- package/dist/resources/extensions/gsd/doctor.js +2 -28
- package/dist/resources/extensions/gsd/export-html.js +27 -425
- package/dist/resources/extensions/gsd/git-service.js +39 -1
- package/dist/resources/extensions/gsd/gsd-db.js +1 -0
- package/dist/resources/extensions/gsd/guided-flow.js +93 -111
- package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
- package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
- package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
- package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
- package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
- package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
- package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
- package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
- package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
- package/dist/resources/extensions/gsd/status-guards.js +4 -0
- package/dist/resources/extensions/gsd/templates/plan.md +8 -5
- package/dist/resources/extensions/gsd/templates/task-plan.md +4 -2
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
- package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
- package/dist/resources/extensions/gsd/tools/plan-slice.js +89 -14
- package/dist/resources/extensions/gsd/unit-context-manifest.js +7 -8
- package/dist/resources/extensions/gsd/validation.js +23 -1
- package/dist/resources/extensions/gsd/verification-gate.js +68 -7
- package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +33 -8
- package/dist/resources/extensions/shared/html-shell.js +388 -0
- package/dist/resources/extensions/visual-brief/page-contract.js +2 -0
- package/dist/resources/extensions/visual-brief/prompts.js +29 -0
- 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 +15 -15
- 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/server/app/_global-error/page_client-reference-manifest.js +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/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
- 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 +4 -5
- 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 +2 -5
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -7
- 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 +4 -7
- 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 +4 -5
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
- package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +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/app/layout-8c10ec293ae0f1d5.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-6a95bc41e0f7ec89.js → webpack-9a4db269f9ed63ad.js} +1 -1
- package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
- package/package.json +2 -2
- package/packages/mcp-server/src/workflow-tools.test.ts +1 -1
- package/packages/native/tsconfig.json +2 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +5 -6
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
- package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
- package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
- package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
- package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
- package/packages/pi-ai/src/providers/simple-options.ts +5 -6
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/src/resources/GSD-WORKFLOW.md +7 -0
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
- package/src/resources/extensions/gsd/auto/contracts.ts +14 -6
- package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
- package/src/resources/extensions/gsd/auto/loop.ts +8 -5
- package/src/resources/extensions/gsd/auto/orchestrator.ts +11 -0
- package/src/resources/extensions/gsd/auto/phases.ts +30 -2
- package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +14 -6
- package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +77 -7
- package/src/resources/extensions/gsd/auto-recovery.ts +29 -0
- package/src/resources/extensions/gsd/auto-start.ts +92 -9
- package/src/resources/extensions/gsd/auto-worktree.ts +119 -1
- package/src/resources/extensions/gsd/auto.ts +40 -4
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +33 -6
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +9 -8
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +4 -2
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +3 -1
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +16 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +17 -1
- package/src/resources/extensions/gsd/crash-recovery.ts +30 -4
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
- package/src/resources/extensions/gsd/doctor-git-checks.ts +45 -1
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
- package/src/resources/extensions/gsd/doctor-types.ts +1 -0
- package/src/resources/extensions/gsd/doctor.ts +2 -27
- package/src/resources/extensions/gsd/export-html.ts +27 -427
- package/src/resources/extensions/gsd/git-service.ts +45 -1
- package/src/resources/extensions/gsd/gsd-db.ts +3 -0
- package/src/resources/extensions/gsd/guided-flow.ts +126 -128
- package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
- package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
- package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
- package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
- package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
- package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
- package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/src/resources/extensions/gsd/prompts/queue.md +4 -4
- package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
- package/src/resources/extensions/gsd/status-guards.ts +5 -0
- package/src/resources/extensions/gsd/templates/plan.md +8 -5
- package/src/resources/extensions/gsd/templates/task-plan.md +4 -2
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +80 -1
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +12 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +11 -2
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +43 -2
- package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
- package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +103 -1
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
- package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +225 -1
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
- package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +20 -1
- package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +46 -2
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -2
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
- package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +65 -7
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +38 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
- package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
- package/src/resources/extensions/gsd/tools/plan-slice.ts +98 -12
- package/src/resources/extensions/gsd/types.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +12 -9
- package/src/resources/extensions/gsd/validation.ts +23 -1
- package/src/resources/extensions/gsd/verification-gate.ts +78 -6
- package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +41 -8
- package/src/resources/extensions/shared/html-shell.ts +412 -0
- package/src/resources/extensions/visual-brief/page-contract.ts +2 -0
- package/src/resources/extensions/visual-brief/prompts.ts +37 -1
- package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +40 -0
- package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
- package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
- package/dist/web/standalone/.next/static/css/0262768ec1b89d34.css +0 -1
- package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
- package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
- /package/dist/web/standalone/.next/static/{Qgr2B_MRhPxC0z8fwv4vT → kkGf3_VaPFkiDNV_D7Dtl}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Qgr2B_MRhPxC0z8fwv4vT → kkGf3_VaPFkiDNV_D7Dtl}/_ssgManifest.js +0 -0
package/README.md
CHANGED
|
@@ -376,7 +376,7 @@ The database is authoritative for milestones, slices, tasks, requirements, summa
|
|
|
376
376
|
|
|
377
377
|
10. **Adaptive replanning** — After each slice completes, the roadmap is reassessed. If the work revealed new information that changes the plan, slices are reordered, added, or removed before continuing.
|
|
378
378
|
|
|
379
|
-
11. **Verification enforcement** — Configure
|
|
379
|
+
11. **Verification enforcement** — Configure simple executable commands (`npm run lint`, `npm run test`, etc.) that run automatically after task execution. Verification commands must not use shell composition or control syntax such as pipes, redirects, semicolons, backticks, or command substitution. Failures trigger auto-fix retries before advancing. Execute-task commits and snapshots are deferred until verification passes; failed or incomplete verification blocks closeout instead of publishing changes. Auto-discovered checks from `package.json` and Python pytest project markers (`python-project`) run in advisory mode — they log warnings but don't block on pre-existing errors. Configurable via `verification_commands`, `verification_auto_fix`, and `verification_max_retries` preferences.
|
|
380
380
|
|
|
381
381
|
12. **Milestone validation** — After all slices complete, a `validate-milestone` gate compares roadmap success criteria against actual results before sealing the milestone.
|
|
382
382
|
|
|
@@ -670,7 +670,7 @@ auto_report: true
|
|
|
670
670
|
| `context_mode.exec_stdout_cap_bytes` | Persisted stdout cap for `gsd_exec` output (default: 1048576) |
|
|
671
671
|
| `context_mode.exec_digest_chars` | Trailing stdout characters returned to the agent context (default: 300) |
|
|
672
672
|
| `context_mode.exec_env_allowlist` | Environment variables forwarded to sandboxed `gsd_exec` runs in addition to `PATH` and `HOME` |
|
|
673
|
-
| `verification_commands` | Array of
|
|
673
|
+
| `verification_commands` | Array of simple executable commands to run after task execution (e.g., `["npm run lint", "npm run test"]`); avoid pipes, redirects, semicolons, backticks, and command substitution |
|
|
674
674
|
| `verification_auto_fix` | Auto-retry on verification failures (default: true) |
|
|
675
675
|
| `verification_max_retries` | Max retries for verification failures (default: 2) |
|
|
676
676
|
| `phases.require_slice_discussion` | Pause auto-mode before each slice for human discussion review |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
d2173e15ccf5aedf
|
|
@@ -448,6 +448,13 @@ What differed from the plan and why (or "None").
|
|
|
448
448
|
|
|
449
449
|
The one-liner must be substantive: "JWT auth with refresh rotation using jose" not "Authentication implemented."
|
|
450
450
|
|
|
451
|
+
When `key_files` or `key_decisions` are empty, render them as empty YAML lists:
|
|
452
|
+
|
|
453
|
+
```yaml
|
|
454
|
+
key_files: []
|
|
455
|
+
key_decisions: []
|
|
456
|
+
```
|
|
457
|
+
|
|
451
458
|
**Slice summary:** Written when all tasks in a slice complete. Compresses all task summaries. Includes `drill_down_paths` to each task summary. During slice completion, review task summaries for `key_decisions` and ensure any significant ones are captured in `.gsd/DECISIONS.md`.
|
|
452
459
|
|
|
453
460
|
**Milestone summary:** Updated each time a slice completes. Compresses all slice summaries. This is what gets injected into later slice planning instead of loading many individual summaries.
|
|
@@ -105,9 +105,10 @@ export function mapUsage(sdkUsage, totalCostUsd) {
|
|
|
105
105
|
output: sdkUsage.output_tokens,
|
|
106
106
|
cacheRead: sdkUsage.cache_read_input_tokens,
|
|
107
107
|
cacheWrite: sdkUsage.cache_creation_input_tokens,
|
|
108
|
+
// Claude Agent SDK result usage is cumulative across its internal loop;
|
|
109
|
+
// repeated cache reads do not represent additional live context.
|
|
108
110
|
totalTokens: sdkUsage.input_tokens +
|
|
109
111
|
sdkUsage.output_tokens +
|
|
110
|
-
sdkUsage.cache_read_input_tokens +
|
|
111
112
|
sdkUsage.cache_creation_input_tokens,
|
|
112
113
|
cost: {
|
|
113
114
|
input: 0,
|
|
@@ -6,9 +6,14 @@
|
|
|
6
6
|
* failures that merit retry.
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
|
-
* Error codes indicating infrastructure failures
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* Error codes indicating infrastructure-level failures from the OS,
|
|
10
|
+
* filesystem, or network. This set includes permanent resource failures
|
|
11
|
+
* (ENOSPC, ENOMEM, EROFS), transient resource exhaustion (EAGAIN, ENOBUFS),
|
|
12
|
+
* and network/offline errors (ECONNREFUSED, ENOTFOUND, ENETUNREACH).
|
|
13
|
+
*
|
|
14
|
+
* Transient git failures are retried separately through
|
|
15
|
+
* TRANSIENT_GIT_RETRY_CODES in native-git-bridge.ts before escalating to the
|
|
16
|
+
* auto-loop.
|
|
12
17
|
*/
|
|
13
18
|
export const INFRA_ERROR_CODES = new Set([
|
|
14
19
|
"ENOSPC", // disk full
|
|
@@ -18,6 +23,7 @@ export const INFRA_ERROR_CODES = new Set([
|
|
|
18
23
|
"EMFILE", // too many open files (process)
|
|
19
24
|
"ENFILE", // too many open files (system)
|
|
20
25
|
"EAGAIN", // resource temporarily unavailable (resource exhaustion)
|
|
26
|
+
"ENOBUFS", // no buffer space available (transient pipe exhaustion)
|
|
21
27
|
"ECONNREFUSED", // connection refused (offline / local server down)
|
|
22
28
|
"ENOTFOUND", // DNS lookup failed (offline / no network)
|
|
23
29
|
"ENETUNREACH", // network unreachable (offline / no route)
|
|
@@ -35,7 +35,7 @@ import { createWorkflowTurnReporter } from "./workflow-turn-reporter.js";
|
|
|
35
35
|
import { validateWorkflowSessionLock } from "./workflow-session-lock.js";
|
|
36
36
|
import { dequeueSidecarItem } from "./workflow-sidecar-queue.js";
|
|
37
37
|
import { maintainWorkerHeartbeat } from "./workflow-worker-heartbeat.js";
|
|
38
|
-
import { measureMemoryPressure } from "./workflow-memory-pressure.js";
|
|
38
|
+
import { measureMemoryPressure, shouldCheckMemoryPressure, } from "./workflow-memory-pressure.js";
|
|
39
39
|
import { buildSidecarIterationData } from "./workflow-sidecar-iteration.js";
|
|
40
40
|
import { createExecutionGraphUnitDispatchDeps, runUnitPhaseViaContract, } from "./workflow-unit-dispatch.js";
|
|
41
41
|
import { handleCustomEngineDispatchOutcome } from "./workflow-custom-engine-dispatch-outcome.js";
|
|
@@ -130,9 +130,9 @@ function logCustomVerifyRetrySaveFailure(err) {
|
|
|
130
130
|
});
|
|
131
131
|
}
|
|
132
132
|
// ── Memory pressure monitoring (#3331) ──────────────────────────────────
|
|
133
|
-
// Check heap usage every N iterations and trigger
|
|
134
|
-
// the OS OOM killer sends SIGKILL. The threshold is
|
|
135
|
-
// limit (--max-old-space-size or default ~1.5-4GB depending on platform).
|
|
133
|
+
// Check heap usage on session startup, then every N iterations, and trigger
|
|
134
|
+
// graceful shutdown before the OS OOM killer sends SIGKILL. The threshold is
|
|
135
|
+
// 90% of the V8 heap limit (--max-old-space-size or default ~1.5-4GB depending on platform).
|
|
136
136
|
const MEMORY_CHECK_INTERVAL = 5; // check every 5 iterations
|
|
137
137
|
const MAX_CUSTOM_ENGINE_VERIFY_RETRIES = 3;
|
|
138
138
|
async function enforceMinRequestInterval(s, prefs) {
|
|
@@ -262,7 +262,7 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
262
262
|
}
|
|
263
263
|
// ── Memory pressure check (#3331) ──
|
|
264
264
|
// Graceful shutdown before OOM killer sends SIGKILL.
|
|
265
|
-
if (iteration
|
|
265
|
+
if (shouldCheckMemoryPressure(iteration, MEMORY_CHECK_INTERVAL)) {
|
|
266
266
|
const mem = measureMemoryPressure();
|
|
267
267
|
debugLog("autoLoop", { phase: "memory-check", ...mem });
|
|
268
268
|
const memoryDecision = decideMemoryPressure({ ...mem, iteration });
|
|
@@ -117,6 +117,17 @@ export class AutoOrchestrator {
|
|
|
117
117
|
await this.deps.health.postAdvanceRecord(stopped);
|
|
118
118
|
return stopped;
|
|
119
119
|
}
|
|
120
|
+
if (!("unitType" in decision)) {
|
|
121
|
+
const blocked = {
|
|
122
|
+
kind: "blocked",
|
|
123
|
+
reason: decision.reason,
|
|
124
|
+
action: decision.action,
|
|
125
|
+
stateSnapshot: reconciliation.stateSnapshot,
|
|
126
|
+
};
|
|
127
|
+
await this.deps.runtime.journalTransition({ name: "advance-blocked", reason: blocked.reason });
|
|
128
|
+
await this.deps.health.postAdvanceRecord(blocked);
|
|
129
|
+
return blocked;
|
|
130
|
+
}
|
|
120
131
|
const nextKey = `${decision.unitType}:${decision.unitId}`;
|
|
121
132
|
// Record every dispatch decision in the ring buffer before pre-flight
|
|
122
133
|
// checks so the stuck-loop detector observes the full decision history
|
|
@@ -44,6 +44,7 @@ import { resolveManifest } from "../unit-context-manifest.js";
|
|
|
44
44
|
import { createWorktreeSafetyModule } from "../worktree-safety.js";
|
|
45
45
|
import { isSuspiciousGhostCompletion } from "../auto-unit-closeout.js";
|
|
46
46
|
import { decideVerificationRetry, verificationRetryKey } from "./verification-retry-policy.js";
|
|
47
|
+
import { buildPhaseHandoffOutcome, setAutoOutcomeWidget } from "../auto-dashboard.js";
|
|
47
48
|
// ─── Path Comparison Helper ───────────────────────────────────────────────
|
|
48
49
|
/** Compare two paths for physical identity, tolerating trailing slashes and symlinks. */
|
|
49
50
|
function isSamePathLocal(a, b) {
|
|
@@ -103,6 +104,12 @@ function unitWritesSource(unitType) {
|
|
|
103
104
|
function formatWorktreeSafetyFailure(result) {
|
|
104
105
|
return `Worktree Safety failed (${result.kind}): ${result.reason} ${result.remediation}`;
|
|
105
106
|
}
|
|
107
|
+
function formatWorktreeSafetyStopReason(result) {
|
|
108
|
+
if (result.kind === "empty-worktree-with-project-content") {
|
|
109
|
+
return `Worktree Safety failed (${result.kind}). Run /gsd doctor fix, then /gsd auto.`;
|
|
110
|
+
}
|
|
111
|
+
return `Worktree Safety failed (${result.kind}).`;
|
|
112
|
+
}
|
|
106
113
|
function resolveEmptyWorktreeWithProjectContent(unitRoot, projectRoot) {
|
|
107
114
|
if (isSamePathLocal(unitRoot, projectRoot))
|
|
108
115
|
return false;
|
|
@@ -176,7 +183,7 @@ async function validateSourceWriteWorktreeSafety(ic, unitType, unitId, milestone
|
|
|
176
183
|
projectRoot,
|
|
177
184
|
});
|
|
178
185
|
ctx.ui.notify(msg, "error");
|
|
179
|
-
await deps.stopAuto(ctx, pi,
|
|
186
|
+
await deps.stopAuto(ctx, pi, formatWorktreeSafetyStopReason(result));
|
|
180
187
|
return { action: "break", reason: result.kind };
|
|
181
188
|
}
|
|
182
189
|
// ─── Session timeout auto-resume state ────────────────────────────────────────
|
|
@@ -968,7 +975,14 @@ export async function runDispatch(ic, preData, loopState) {
|
|
|
968
975
|
prompt = preDispatchResult.prompt;
|
|
969
976
|
}
|
|
970
977
|
const guardBasePath = _resolveDispatchGuardBasePath(s);
|
|
971
|
-
|
|
978
|
+
let mainBranch = "main";
|
|
979
|
+
try {
|
|
980
|
+
mainBranch = deps.getMainBranch(guardBasePath);
|
|
981
|
+
}
|
|
982
|
+
catch (err) {
|
|
983
|
+
debugLog("autoLoop", { phase: "getMainBranch-failed", error: String(err) });
|
|
984
|
+
}
|
|
985
|
+
const priorSliceBlocker = deps.getPriorSliceCompletionBlocker(guardBasePath, mainBranch, unitType, unitId);
|
|
972
986
|
if (priorSliceBlocker) {
|
|
973
987
|
await deps.stopAuto(ctx, pi, priorSliceBlocker);
|
|
974
988
|
debugLog("autoLoop", { phase: "exit", reason: "prior-slice-blocker" });
|
|
@@ -1923,6 +1937,18 @@ export async function runFinalize(ic, iterData, loopState, sidecarItem) {
|
|
|
1923
1937
|
lastProgressAt: Date.now(),
|
|
1924
1938
|
lastProgressKind: "finalize-success",
|
|
1925
1939
|
});
|
|
1940
|
+
if (!preUnitSnapshot.type.startsWith("hook/") &&
|
|
1941
|
+
preUnitSnapshot.type !== "custom-step" &&
|
|
1942
|
+
preUnitSnapshot.type !== "complete-milestone") {
|
|
1943
|
+
setAutoOutcomeWidget(ctx, {
|
|
1944
|
+
...buildPhaseHandoffOutcome({
|
|
1945
|
+
unitType: preUnitSnapshot.type,
|
|
1946
|
+
unitId: preUnitSnapshot.id,
|
|
1947
|
+
agentEndMessages: s.lastUnitAgentEndMessages,
|
|
1948
|
+
}),
|
|
1949
|
+
startedAt: s.autoStartTime,
|
|
1950
|
+
});
|
|
1951
|
+
}
|
|
1926
1952
|
}
|
|
1927
1953
|
s.currentUnit = null;
|
|
1928
1954
|
clearCurrentPhase();
|
|
@@ -4,6 +4,18 @@ import { createRequire } from "node:module";
|
|
|
4
4
|
const require = createRequire(import.meta.url);
|
|
5
5
|
const DEFAULT_MEMORY_PRESSURE_THRESHOLD = 0.85;
|
|
6
6
|
const DEFAULT_HEAP_LIMIT_MB = 4096;
|
|
7
|
+
/**
|
|
8
|
+
* Returns true on auto-mode startup, then every configured interval.
|
|
9
|
+
*
|
|
10
|
+
* Iteration 1 is checked explicitly so early session memory pressure cannot
|
|
11
|
+
* bypass the periodic interval guard.
|
|
12
|
+
*/
|
|
13
|
+
export function shouldCheckMemoryPressure(iteration, interval) {
|
|
14
|
+
if (!Number.isInteger(interval) || interval <= 0) {
|
|
15
|
+
throw new Error("Memory pressure check interval must be a positive integer");
|
|
16
|
+
}
|
|
17
|
+
return iteration === 1 || iteration % interval === 0;
|
|
18
|
+
}
|
|
7
19
|
function defaultHeapLimitBytes() {
|
|
8
20
|
const v8 = require("node:v8");
|
|
9
21
|
const limit = v8.getHeapStatistics?.().heap_size_limit;
|
|
@@ -27,6 +27,19 @@ export function extractUatSliceId(unitId) {
|
|
|
27
27
|
return slice;
|
|
28
28
|
return null;
|
|
29
29
|
}
|
|
30
|
+
export function buildPhaseHandoffOutcome(input) {
|
|
31
|
+
const phase = unitPhaseLabel(input.unitType);
|
|
32
|
+
const detail = extractLastAssistantSummary(input.agentEndMessages) ??
|
|
33
|
+
`Completed ${unitVerb(input.unitType)} ${input.unitId}.`;
|
|
34
|
+
return {
|
|
35
|
+
status: "complete",
|
|
36
|
+
title: `${phase} complete`,
|
|
37
|
+
detail,
|
|
38
|
+
unitLabel: `${unitVerb(input.unitType)} ${input.unitId}`,
|
|
39
|
+
nextAction: "Preparing the next phase. Review this handoff while the next session starts.",
|
|
40
|
+
commands: ["/gsd status for overview", "/gsd visualize to inspect", "/gsd notifications for history"],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
30
43
|
// ─── Unit Description Helpers ─────────────────────────────────────────────────
|
|
31
44
|
export function unitVerb(unitType) {
|
|
32
45
|
if (unitType.startsWith("hook/"))
|
|
@@ -464,7 +477,6 @@ export function _resetWidgetModeForTests() {
|
|
|
464
477
|
export function updateProgressWidget(ctx, unitType, unitId, state, accessors, tierBadge) {
|
|
465
478
|
if (!ctx.hasUI)
|
|
466
479
|
return;
|
|
467
|
-
ctx.ui.setWidget("gsd-outcome", undefined);
|
|
468
480
|
// Welcome header is a startup-only banner — permanently suppress it once
|
|
469
481
|
// auto-mode activates. The dashboard widget owns all status from here.
|
|
470
482
|
// Note: setHeader(undefined) restores the built-in header (logo +
|
|
@@ -927,3 +939,56 @@ function normalizeRollupText(value) {
|
|
|
927
939
|
return null;
|
|
928
940
|
return clean;
|
|
929
941
|
}
|
|
942
|
+
function isAssistantMessage(value) {
|
|
943
|
+
if (!value || typeof value !== "object")
|
|
944
|
+
return false;
|
|
945
|
+
const record = value;
|
|
946
|
+
if (record.role === "assistant")
|
|
947
|
+
return true;
|
|
948
|
+
const message = record.message;
|
|
949
|
+
if (message && typeof message === "object") {
|
|
950
|
+
return message.role === "assistant";
|
|
951
|
+
}
|
|
952
|
+
return false;
|
|
953
|
+
}
|
|
954
|
+
function extractLastAssistantSummary(messages) {
|
|
955
|
+
if (!messages || messages.length === 0)
|
|
956
|
+
return null;
|
|
957
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
958
|
+
if (!isAssistantMessage(messages[i]))
|
|
959
|
+
continue;
|
|
960
|
+
const text = extractMessageText(messages[i]);
|
|
961
|
+
const clean = normalizeRollupText(text);
|
|
962
|
+
if (clean)
|
|
963
|
+
return truncateToWidth(clean, 220, "…");
|
|
964
|
+
}
|
|
965
|
+
return null;
|
|
966
|
+
}
|
|
967
|
+
function extractMessageText(value) {
|
|
968
|
+
if (typeof value === "string")
|
|
969
|
+
return value;
|
|
970
|
+
if (!value || typeof value !== "object")
|
|
971
|
+
return null;
|
|
972
|
+
const record = value;
|
|
973
|
+
if (typeof record.content === "string")
|
|
974
|
+
return record.content;
|
|
975
|
+
const message = record.message;
|
|
976
|
+
if (message && typeof message === "object") {
|
|
977
|
+
return extractMessageText(message);
|
|
978
|
+
}
|
|
979
|
+
const content = record.content;
|
|
980
|
+
if (Array.isArray(content)) {
|
|
981
|
+
const parts = content
|
|
982
|
+
.map((part) => {
|
|
983
|
+
if (typeof part === "string")
|
|
984
|
+
return part;
|
|
985
|
+
if (!part || typeof part !== "object")
|
|
986
|
+
return "";
|
|
987
|
+
const partRecord = part;
|
|
988
|
+
return typeof partRecord.text === "string" ? partRecord.text : "";
|
|
989
|
+
})
|
|
990
|
+
.filter(Boolean);
|
|
991
|
+
return parts.length > 0 ? parts.join(" ") : null;
|
|
992
|
+
}
|
|
993
|
+
return null;
|
|
994
|
+
}
|
|
@@ -102,6 +102,9 @@ function missingSliceStop(mid, phase) {
|
|
|
102
102
|
level: "error",
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
|
+
function isRegistryMilestoneComplete(state, mid) {
|
|
106
|
+
return state.registry.some((milestone) => milestone.id === mid && milestone.status === "complete");
|
|
107
|
+
}
|
|
105
108
|
/**
|
|
106
109
|
* Check for milestone slices missing SUMMARY files.
|
|
107
110
|
* Returns array of missing slice IDs, or empty array if all present or DB unavailable.
|
|
@@ -247,6 +250,8 @@ export const DISPATCH_RULES = [
|
|
|
247
250
|
return null;
|
|
248
251
|
if (!MILESTONE_ID_RE.test(mid))
|
|
249
252
|
return null;
|
|
253
|
+
if (isRegistryMilestoneComplete(state, mid))
|
|
254
|
+
return null;
|
|
250
255
|
// Align with the plan-v2 gate's lookup semantics: whitespace-only counts
|
|
251
256
|
// as missing, and an auto worktree may fall back to GSD_PROJECT_ROOT.
|
|
252
257
|
if (hasFinalizedMilestoneContext(basePath, mid))
|
|
@@ -557,6 +562,8 @@ export const DISPATCH_RULES = [
|
|
|
557
562
|
match: async ({ state, mid, midTitle, basePath, prefs, structuredQuestionsAvailable }) => {
|
|
558
563
|
if (state.phase !== "pre-planning")
|
|
559
564
|
return null;
|
|
565
|
+
if (isRegistryMilestoneComplete(state, mid))
|
|
566
|
+
return null;
|
|
560
567
|
const contextFile = resolveMilestoneFile(basePath, mid, "CONTEXT");
|
|
561
568
|
const hasContext = !!(contextFile && (await loadFile(contextFile)));
|
|
562
569
|
if (hasContext)
|
|
@@ -1091,19 +1098,19 @@ export const DISPATCH_RULES = [
|
|
|
1091
1098
|
return { action: "skip" };
|
|
1092
1099
|
}
|
|
1093
1100
|
}
|
|
1094
|
-
// Safety guard (#2675): block completion when VALIDATION
|
|
1095
|
-
//
|
|
1096
|
-
// terminal
|
|
1097
|
-
//
|
|
1101
|
+
// Safety guard (#2675, #5747): block completion when VALIDATION
|
|
1102
|
+
// verdict is non-passing. The state machine treats these verdicts as
|
|
1103
|
+
// terminal, but completing-milestone should NOT proceed — remediation
|
|
1104
|
+
// or human attention is needed.
|
|
1098
1105
|
const validationFile = resolveMilestoneFile(basePath, mid, "VALIDATION");
|
|
1099
1106
|
if (validationFile) {
|
|
1100
1107
|
const validationContent = await loadFile(validationFile);
|
|
1101
1108
|
if (validationContent) {
|
|
1102
1109
|
const verdict = extractVerdict(validationContent);
|
|
1103
|
-
if (verdict === "needs-remediation") {
|
|
1110
|
+
if (verdict === "needs-remediation" || verdict === "needs-attention") {
|
|
1104
1111
|
return {
|
|
1105
1112
|
action: "stop",
|
|
1106
|
-
reason: `Cannot complete milestone ${mid}: VALIDATION verdict is "
|
|
1113
|
+
reason: `Cannot complete milestone ${mid}: VALIDATION verdict is "${verdict}". Address the validation findings and re-run validation, or update the verdict manually.`,
|
|
1107
1114
|
level: "warning",
|
|
1108
1115
|
};
|
|
1109
1116
|
}
|
|
@@ -494,6 +494,8 @@ autoModeStartThinkingLevel) {
|
|
|
494
494
|
* Handles formats: "provider/model", "bare-id", "org/model-name" (OpenRouter).
|
|
495
495
|
*/
|
|
496
496
|
export function resolveModelId(modelId, availableModels, currentProvider) {
|
|
497
|
+
if (!modelId)
|
|
498
|
+
return undefined;
|
|
497
499
|
const slashIdx = modelId.indexOf("/");
|
|
498
500
|
if (slashIdx !== -1) {
|
|
499
501
|
const maybeProvider = modelId.substring(0, slashIdx);
|
|
@@ -23,7 +23,7 @@ import { rebuildState } from "./doctor.js";
|
|
|
23
23
|
import { parseUnitId } from "./unit-id.js";
|
|
24
24
|
import { closeoutUnit } from "./auto-unit-closeout.js";
|
|
25
25
|
import { runTurnGitAction, } from "./git-service.js";
|
|
26
|
-
import { verifyExpectedArtifact, resolveExpectedArtifactPath, writeBlockerPlaceholder, diagnoseExpectedArtifact, } from "./auto-recovery.js";
|
|
26
|
+
import { verifyExpectedArtifact, resolveExpectedArtifactPath, writeBlockerPlaceholder, diagnoseExpectedArtifact, diagnoseWorktreeIntegrityFailure, } from "./auto-recovery.js";
|
|
27
27
|
import { regenerateIfMissing } from "./workflow-projections.js";
|
|
28
28
|
import { WorktreeStateProjection } from "./worktree-state-projection.js";
|
|
29
29
|
import { createWorkspace, scopeMilestone } from "./workspace.js";
|
|
@@ -125,7 +125,7 @@ async function buildTaskCommitContextForUnit(basePath, unitId) {
|
|
|
125
125
|
sliceId: sid,
|
|
126
126
|
sliceTitle: stripKnownIdPrefix(slice?.title, sid),
|
|
127
127
|
oneLiner: summary?.oneLiner || task?.one_liner || undefined,
|
|
128
|
-
keyFiles: summary?.frontmatter.key_files?.filter(f => !f.includes("{{")) ??
|
|
128
|
+
keyFiles: summary?.frontmatter.key_files?.filter(f => !f.includes("{{") && f.trim() !== "(none)") ??
|
|
129
129
|
task?.key_files ??
|
|
130
130
|
undefined,
|
|
131
131
|
issueNumber: ghIssueNumber,
|
|
@@ -303,6 +303,19 @@ export function buildStepCompleteMessage(nextState) {
|
|
|
303
303
|
return `Step complete. Next: ${next.label}\n`
|
|
304
304
|
+ `Run /clear, then /gsd to continue (or /gsd auto to run continuously).`;
|
|
305
305
|
}
|
|
306
|
+
/**
|
|
307
|
+
* Decide whether step mode should stop at the step wizard after a unit finishes.
|
|
308
|
+
*
|
|
309
|
+
* @param currentUnitType The just-finished unit type, such as "execute-task" or
|
|
310
|
+
* "complete-milestone"; may be null/undefined when no current unit is known.
|
|
311
|
+
* @param phaseAfterUnit The freshly derived next phase, such as "executing" or
|
|
312
|
+
* "complete"; may be null/undefined if state derivation failed.
|
|
313
|
+
* @returns true to show the step wizard; false to keep the loop running so
|
|
314
|
+
* terminal milestone completion can reach the merge/finalization path.
|
|
315
|
+
*/
|
|
316
|
+
export function shouldReturnStepWizardAfterUnit(currentUnitType, phaseAfterUnit) {
|
|
317
|
+
return currentUnitType !== "complete-milestone" && phaseAfterUnit !== "complete";
|
|
318
|
+
}
|
|
306
319
|
export const USER_DRIVEN_DEEP_UNITS = new Set([
|
|
307
320
|
"discuss-project",
|
|
308
321
|
"discuss-requirements",
|
|
@@ -318,6 +331,10 @@ function artifactValidationKind(unitType) {
|
|
|
318
331
|
return null;
|
|
319
332
|
}
|
|
320
333
|
function describeArtifactVerificationFailure(unitType, unitId, basePath) {
|
|
334
|
+
const worktreeFailure = diagnoseWorktreeIntegrityFailure(basePath);
|
|
335
|
+
if (worktreeFailure) {
|
|
336
|
+
return `${worktreeFailure} Unit: ${unitType} ${unitId}.`;
|
|
337
|
+
}
|
|
321
338
|
const artifactPath = resolveExpectedArtifactPath(unitType, unitId, basePath);
|
|
322
339
|
if (!artifactPath) {
|
|
323
340
|
return `Artifact verification failed: ${unitType} "${unitId}" has no resolvable artifact path.`;
|
|
@@ -362,7 +379,14 @@ export async function autoCommitUnit(basePath, unitType, unitId, ctx) {
|
|
|
362
379
|
return null;
|
|
363
380
|
}
|
|
364
381
|
}
|
|
365
|
-
|
|
382
|
+
/**
|
|
383
|
+
* Execute the turn-level git action (commit, snapshot, or status-only).
|
|
384
|
+
*
|
|
385
|
+
* @param opts.softFailure - Defaults to false. When true, retry git failures,
|
|
386
|
+
* warn, and continue without pausing auto-mode; use for best-effort deferred
|
|
387
|
+
* closeout work where a git failure should not block the run.
|
|
388
|
+
*/
|
|
389
|
+
async function runCloseoutGitAction(pctx, unit, opts) {
|
|
366
390
|
const { s, ctx, pi, pauseAuto } = pctx;
|
|
367
391
|
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
368
392
|
const uokFlags = resolveUokFlags(prefs);
|
|
@@ -390,13 +414,24 @@ async function runCloseoutGitAction(pctx, unit) {
|
|
|
390
414
|
});
|
|
391
415
|
}
|
|
392
416
|
else {
|
|
393
|
-
const
|
|
417
|
+
const maxAttempts = opts?.softFailure ? 3 : 1;
|
|
418
|
+
let gitResult = runTurnGitAction({
|
|
394
419
|
basePath: s.basePath,
|
|
395
420
|
action: turnAction,
|
|
396
421
|
unitType: unit.type,
|
|
397
422
|
unitId: unit.id,
|
|
398
423
|
taskContext,
|
|
399
424
|
});
|
|
425
|
+
for (let attempt = 1; gitResult.status === "failed" && attempt < maxAttempts; attempt++) {
|
|
426
|
+
await new Promise((resolve) => setTimeout(resolve, 250 * attempt));
|
|
427
|
+
gitResult = runTurnGitAction({
|
|
428
|
+
basePath: s.basePath,
|
|
429
|
+
action: turnAction,
|
|
430
|
+
unitType: unit.type,
|
|
431
|
+
unitId: unit.id,
|
|
432
|
+
taskContext,
|
|
433
|
+
});
|
|
434
|
+
}
|
|
400
435
|
if (uokFlags.gitops) {
|
|
401
436
|
writeTurnGitTransaction({
|
|
402
437
|
basePath: s.basePath,
|
|
@@ -444,12 +479,15 @@ async function runCloseoutGitAction(pctx, unit) {
|
|
|
444
479
|
});
|
|
445
480
|
}
|
|
446
481
|
const failureMsg = `Git ${turnAction} failed: ${(gitResult.error ?? "unknown error").split("\n")[0]}`;
|
|
447
|
-
ctx.ui.notify(failureMsg, "error");
|
|
482
|
+
ctx.ui.notify(failureMsg, opts?.softFailure ? "warning" : "error");
|
|
448
483
|
debugLog("postUnit", {
|
|
449
|
-
phase: "git-action-failed-blocking",
|
|
484
|
+
phase: opts?.softFailure ? "git-action-failed-soft" : "git-action-failed-blocking",
|
|
450
485
|
action: turnAction,
|
|
451
486
|
error: gitResult.error ?? "unknown error",
|
|
452
487
|
});
|
|
488
|
+
if (opts?.softFailure) {
|
|
489
|
+
return "continue";
|
|
490
|
+
}
|
|
453
491
|
await pauseAuto(ctx, pi);
|
|
454
492
|
return "dispatched";
|
|
455
493
|
}
|
|
@@ -467,7 +505,10 @@ async function runCloseoutGitAction(pctx, unit) {
|
|
|
467
505
|
s.lastGitActionFailure = message;
|
|
468
506
|
s.lastGitActionStatus = "failed";
|
|
469
507
|
debugLog("postUnit", { phase: "git-action", error: message, action: turnAction });
|
|
470
|
-
ctx.ui.notify(`Git ${turnAction} failed: ${message.split("\n")[0]}`,
|
|
508
|
+
ctx.ui.notify(`Git ${turnAction} failed: ${message.split("\n")[0]}`, opts?.softFailure ? "warning" : "error");
|
|
509
|
+
if (opts?.softFailure) {
|
|
510
|
+
return "continue";
|
|
511
|
+
}
|
|
471
512
|
if (uokFlags.gitops) {
|
|
472
513
|
await pauseAuto(ctx, pi);
|
|
473
514
|
return "dispatched";
|
|
@@ -961,6 +1002,22 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
961
1002
|
ctx.ui.notify(`${s.currentUnit.type} ${s.currentUnit.id} — deterministic policy rejection, wrote blocker placeholder (no retries) (#4973)`, "warning");
|
|
962
1003
|
// Fall through to "continue" — do NOT enter the retry or db-unavailable paths.
|
|
963
1004
|
}
|
|
1005
|
+
else if (!triggerArtifactVerified && diagnoseWorktreeIntegrityFailure(s.basePath)) {
|
|
1006
|
+
const retryKey = `${s.currentUnit.type}:${s.currentUnit.id}`;
|
|
1007
|
+
const worktreeFailure = diagnoseWorktreeIntegrityFailure(s.basePath);
|
|
1008
|
+
s.pendingVerificationRetry = null;
|
|
1009
|
+
s.verificationRetryCount.delete(retryKey);
|
|
1010
|
+
s.verificationRetryFailureHashes.delete(retryKey);
|
|
1011
|
+
debugLog("postUnit", {
|
|
1012
|
+
phase: "worktree-integrity-failure",
|
|
1013
|
+
unitType: s.currentUnit.type,
|
|
1014
|
+
unitId: s.currentUnit.id,
|
|
1015
|
+
basePath: s.basePath,
|
|
1016
|
+
});
|
|
1017
|
+
ctx.ui.notify(`${worktreeFailure} Retry ${s.currentUnit.id} after repair.`, "error");
|
|
1018
|
+
await pauseAuto(ctx, pi);
|
|
1019
|
+
return "dispatched";
|
|
1020
|
+
}
|
|
964
1021
|
else if (!triggerArtifactVerified && !isDbAvailable()) {
|
|
965
1022
|
debugLog("postUnit", { phase: "artifact-verify-skip-db-unavailable", unitType: s.currentUnit.type, unitId: s.currentUnit.id });
|
|
966
1023
|
const dbSkipDiag = diagnoseExpectedArtifact(s.currentUnit.type, s.currentUnit.id, s.basePath);
|
|
@@ -1032,7 +1089,7 @@ export async function postUnitPostVerification(pctx) {
|
|
|
1032
1089
|
const { s, ctx, pi, buildSnapshotOpts, lockBase, stopAuto, pauseAuto, updateProgressWidget } = pctx;
|
|
1033
1090
|
if (s.currentUnit) {
|
|
1034
1091
|
if (shouldDeferCloseoutGitAction(s.currentUnit.type)) {
|
|
1035
|
-
const gitActionResult = await runCloseoutGitAction(pctx, s.currentUnit);
|
|
1092
|
+
const gitActionResult = await runCloseoutGitAction(pctx, s.currentUnit, { softFailure: true });
|
|
1036
1093
|
if (gitActionResult === "dispatched") {
|
|
1037
1094
|
return "stopped";
|
|
1038
1095
|
}
|
|
@@ -1404,15 +1461,19 @@ export async function postUnitPostVerification(pctx) {
|
|
|
1404
1461
|
// Without this notify(), /gsd in step mode finishes a unit and silently
|
|
1405
1462
|
// exits the loop, leaving the user with no hint to /clear and /gsd again.
|
|
1406
1463
|
if (s.stepMode) {
|
|
1464
|
+
let phaseAfterUnit = null;
|
|
1407
1465
|
try {
|
|
1408
1466
|
const nextState = await deriveState(s.canonicalProjectRoot);
|
|
1467
|
+
phaseAfterUnit = nextState.phase;
|
|
1409
1468
|
ctx.ui.notify(buildStepCompleteMessage(nextState), "info");
|
|
1410
1469
|
}
|
|
1411
1470
|
catch (e) {
|
|
1412
1471
|
debugLog("postUnit", { phase: "step-wizard-notify", error: String(e) });
|
|
1413
1472
|
ctx.ui.notify(STEP_COMPLETE_FALLBACK_MESSAGE, "info");
|
|
1414
1473
|
}
|
|
1415
|
-
return
|
|
1474
|
+
return shouldReturnStepWizardAfterUnit(s.currentUnit?.type, phaseAfterUnit)
|
|
1475
|
+
? "step-wizard"
|
|
1476
|
+
: "continue";
|
|
1416
1477
|
}
|
|
1417
1478
|
return "continue";
|
|
1418
1479
|
}
|
|
@@ -14,7 +14,8 @@ import { clearParseCache } from "./files.js";
|
|
|
14
14
|
import { parseRoadmap as parseLegacyRoadmap, parsePlan as parseLegacyPlan } from "./parsers-legacy.js";
|
|
15
15
|
import { isDbAvailable, getTask, getSlice, getSliceTasks, getPendingGates, updateTaskStatus, updateSliceStatus, insertSlice, getMilestone, refreshOpenDatabaseFromDisk, getCompletedMilestoneTaskFileHints, getMilestoneCommitAttributionShas, recordMilestoneCommitAttribution } from "./gsd-db.js";
|
|
16
16
|
import { isValidationTerminal } from "./state.js";
|
|
17
|
-
import {
|
|
17
|
+
import { getErrorMessage } from "./error-utils.js";
|
|
18
|
+
import { logWarning, logError } from "./workflow-logger.js";
|
|
18
19
|
import { readIntegrationBranch } from "./git-service.js";
|
|
19
20
|
import { isClosedStatus } from "./status-guards.js";
|
|
20
21
|
import { resolveSlicePath, resolveSliceFile, resolveTasksDir, resolveTaskFiles, relMilestoneFile, relSliceFile, buildSliceFileName, resolveMilestoneFile, clearPathCache, resolveGsdRootFile, } from "./paths.js";
|
|
@@ -25,9 +26,33 @@ import { resolveExpectedArtifactPath, diagnoseExpectedArtifact, } from "./auto-a
|
|
|
25
26
|
import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
|
|
26
27
|
import { validateArtifact } from "./schemas/validate.js";
|
|
27
28
|
import { getProjectResearchStatus } from "./project-research-policy.js";
|
|
29
|
+
import { isGsdWorktreePath } from "./worktree-root.js";
|
|
28
30
|
// Re-export so existing consumers of auto-recovery.ts keep working.
|
|
29
31
|
export { resolveExpectedArtifactPath, diagnoseExpectedArtifact };
|
|
30
32
|
export { classifyMilestoneSummaryContent, } from "./milestone-summary-classifier.js";
|
|
33
|
+
// ─── Artifact Resolution & Verification ───────────────────────────────────────
|
|
34
|
+
export function diagnoseWorktreeIntegrityFailure(basePath) {
|
|
35
|
+
if (!isGsdWorktreePath(basePath))
|
|
36
|
+
return null;
|
|
37
|
+
if (!existsSync(basePath)) {
|
|
38
|
+
return `Worktree integrity failure: ${basePath} does not exist. Repair or recreate the worktree before retrying.`;
|
|
39
|
+
}
|
|
40
|
+
const gitPath = join(basePath, ".git");
|
|
41
|
+
if (!existsSync(gitPath)) {
|
|
42
|
+
return `Worktree integrity failure: ${basePath} is not a valid git worktree (.git missing). Repair or recreate the worktree before retrying.`;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
execFileSync("git", ["rev-parse", "--git-dir"], {
|
|
46
|
+
cwd: basePath,
|
|
47
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
48
|
+
encoding: "utf-8",
|
|
49
|
+
});
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
return `Worktree integrity failure: ${basePath} is not a valid git worktree (git rev-parse failed: ${getErrorMessage(err).split("\n")[0]}). Repair or recreate the worktree before retrying.`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
31
56
|
export function refreshRecoveryDbForArtifact(unitType, unitId) {
|
|
32
57
|
if (unitType !== "plan-slice" && unitType !== "execute-task")
|
|
33
58
|
return { ok: true };
|
|
@@ -673,6 +698,11 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
|
|
|
673
698
|
return false;
|
|
674
699
|
}
|
|
675
700
|
if (!existsSync(absPath)) {
|
|
701
|
+
const worktreeFailure = diagnoseWorktreeIntegrityFailure(base);
|
|
702
|
+
if (worktreeFailure) {
|
|
703
|
+
logError("recovery", `${worktreeFailure} Unit: ${unitType} ${unitId}.`);
|
|
704
|
+
return false;
|
|
705
|
+
}
|
|
676
706
|
logWarning("recovery", `verify-fail ${unitType} ${unitId}: existsSync false for ${absPath}`);
|
|
677
707
|
return false;
|
|
678
708
|
}
|