gsd-pi 2.82.0-dev.725028083 → 2.82.0-dev.98ea09b1e
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 +4 -3
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +10 -1
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
- package/dist/resources/extensions/cmux/index.js +5 -0
- 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 +124 -6
- package/dist/resources/extensions/gsd/auto/phases.js +8 -1
- package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
- 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 +233 -127
- package/dist/resources/extensions/gsd/auto-prompts.js +2 -2
- 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-verification.js +28 -22
- package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
- package/dist/resources/extensions/gsd/auto.js +158 -55
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +4 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +9 -8
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -2
- package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
- package/dist/resources/extensions/gsd/commands/catalog.js +4 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +37 -0
- package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
- 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-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 +13 -6
- package/dist/resources/extensions/gsd/md-importer.js +1 -1
- package/dist/resources/extensions/gsd/migrate/command.js +5 -0
- package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
- package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
- package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
- package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
- 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/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/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/tools/workflow-tool-executors.js +119 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
- package/dist/resources/extensions/gsd/validation.js +23 -1
- package/dist/resources/extensions/gsd/verification-gate.js +68 -7
- package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
- package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
- package/dist/resources/extensions/shared/html-shell.js +388 -0
- package/dist/resources/extensions/subagent/index.js +448 -78
- package/dist/resources/extensions/subagent/launch.js +77 -0
- package/dist/resources/extensions/subagent/run-store.js +148 -0
- package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
- package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/dist/resources/extensions/visual-brief/index.js +5 -0
- package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
- package/dist/resources/extensions/visual-brief/prompts.js +140 -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 +14 -14
- 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 +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 +14 -14
- 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/middleware-react-loadable-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/2973.33f26573894b6153.js +2 -0
- package/dist/web/standalone/.next/static/chunks/{8359.e059d86b255fce1c.js → 8359.7eb3bb8f8ecf4c01.js} +2 -2
- package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-9a4db269f9ed63ad.js} +1 -1
- package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
- package/package.json +4 -4
- package/packages/contracts/dist/rpc.test.js +7 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +21 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +24 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/src/rpc.test.ts +8 -0
- package/packages/contracts/src/workflow.ts +24 -0
- package/packages/mcp-server/README.md +13 -4
- package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +80 -0
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
- package/packages/mcp-server/src/workflow-tools.ts +168 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +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/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/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +5 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/tui.ts +6 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/src/resources/GSD-WORKFLOW.md +10 -1
- 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/cmux/index.ts +6 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +59 -16
- 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 +129 -6
- package/src/resources/extensions/gsd/auto/phases.ts +7 -1
- package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
- 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 +266 -139
- package/src/resources/extensions/gsd/auto-prompts.ts +2 -2
- 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-verification.ts +36 -34
- package/src/resources/extensions/gsd/auto-worktree.ts +119 -1
- package/src/resources/extensions/gsd/auto.ts +167 -53
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +6 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +9 -8
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -3
- package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
- package/src/resources/extensions/gsd/commands/catalog.ts +4 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +40 -0
- package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
- 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-runtime-checks.ts +25 -13
- 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 +14 -7
- package/src/resources/extensions/gsd/md-importer.ts +1 -1
- package/src/resources/extensions/gsd/migrate/command.ts +5 -0
- package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
- package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
- package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
- package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
- 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/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/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-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 +487 -4
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +12 -11
- 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-runtime-state.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
- package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
- package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
- 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/evidence-cross-ref.test.ts +38 -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-flow.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +6 -6
- 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/migrate-command.test.ts +48 -3
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -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/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-exec-retry-bypass.test.ts +79 -1
- 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/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/start-auto-detached.test.ts +31 -1
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
- 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 +86 -7
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
- 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/worktree-lifecycle.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -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/tools/workflow-tool-executors.ts +135 -0
- package/src/resources/extensions/gsd/types.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
- package/src/resources/extensions/gsd/validation.ts +23 -1
- package/src/resources/extensions/gsd/verification-gate.ts +78 -6
- package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
- package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
- package/src/resources/extensions/shared/html-shell.ts +412 -0
- package/src/resources/extensions/subagent/index.ts +567 -103
- package/src/resources/extensions/subagent/launch.ts +131 -0
- package/src/resources/extensions/subagent/run-store.ts +218 -0
- package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
- package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
- package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
- package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/src/resources/extensions/visual-brief/index.ts +8 -0
- package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
- package/src/resources/extensions/visual-brief/prompts.ts +183 -0
- package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
- package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
- package/dist/web/standalone/.next/static/css/54ec2745c1da488b.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/{KDRTXR-22LPCsa80X9dey → euQ0CLP_v8V4e76Tu3odJ}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{KDRTXR-22LPCsa80X9dey → euQ0CLP_v8V4e76Tu3odJ}/_ssgManifest.js +0 -0
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Split into two functions called sequentially by auto-loop with
|
|
9
9
|
* the verification gate between them:
|
|
10
|
-
* 1. postUnitPreVerification() —
|
|
11
|
-
* 2. postUnitPostVerification() — DB dual-write, hooks, triage, quick-tasks
|
|
10
|
+
* 1. postUnitPreVerification() — closeout git for non-task units, doctor, state rebuild, worktree sync, artifact verification
|
|
11
|
+
* 2. postUnitPostVerification() — post-verified task git, DB dual-write, hooks, triage, quick-tasks
|
|
12
12
|
*
|
|
13
13
|
* Extracted from the pre-loop agent_end handler in auto.ts.
|
|
14
14
|
*/
|
|
@@ -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";
|
|
@@ -37,8 +37,7 @@ import { debugLog } from "./debug-logger.js";
|
|
|
37
37
|
import { runSafely } from "./auto-utils.js";
|
|
38
38
|
import { getEvidence, clearEvidenceFromDisk } from "./safety/evidence-collector.js";
|
|
39
39
|
import { validateFileChanges } from "./safety/file-change-validator.js";
|
|
40
|
-
|
|
41
|
-
// import { crossReferenceEvidence, type ClaimedEvidence } from "./safety/evidence-cross-ref.js";
|
|
40
|
+
import { crossReferenceEvidence } from "./safety/evidence-cross-ref.js";
|
|
42
41
|
import { validateContent } from "./safety/content-validator.js";
|
|
43
42
|
import { resolveSafetyHarnessConfig } from "./safety/safety-harness.js";
|
|
44
43
|
import { resolveExpectedArtifactPath as resolveArtifactForContent } from "./auto-artifact-paths.js";
|
|
@@ -126,7 +125,7 @@ async function buildTaskCommitContextForUnit(basePath, unitId) {
|
|
|
126
125
|
sliceId: sid,
|
|
127
126
|
sliceTitle: stripKnownIdPrefix(slice?.title, sid),
|
|
128
127
|
oneLiner: summary?.oneLiner || task?.one_liner || undefined,
|
|
129
|
-
keyFiles: summary?.frontmatter.key_files?.filter(f => !f.includes("{{")) ??
|
|
128
|
+
keyFiles: summary?.frontmatter.key_files?.filter(f => !f.includes("{{") && f.trim() !== "(none)") ??
|
|
130
129
|
task?.key_files ??
|
|
131
130
|
undefined,
|
|
132
131
|
issueNumber: ghIssueNumber,
|
|
@@ -171,6 +170,9 @@ export function _shouldDispatchQuickTaskForTest(state) {
|
|
|
171
170
|
!!state.currentUnit &&
|
|
172
171
|
state.currentUnit.type !== "quick-task";
|
|
173
172
|
}
|
|
173
|
+
export function shouldDeferCloseoutGitAction(unitType) {
|
|
174
|
+
return unitType === "execute-task";
|
|
175
|
+
}
|
|
174
176
|
/** Unit types that only touch `.gsd/` internal state files (no code changes).
|
|
175
177
|
* Auto-commit is skipped for these — their state files are picked up by the
|
|
176
178
|
* next actual task commit via `smartStage()`. */
|
|
@@ -301,6 +303,19 @@ export function buildStepCompleteMessage(nextState) {
|
|
|
301
303
|
return `Step complete. Next: ${next.label}\n`
|
|
302
304
|
+ `Run /clear, then /gsd to continue (or /gsd auto to run continuously).`;
|
|
303
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
|
+
}
|
|
304
319
|
export const USER_DRIVEN_DEEP_UNITS = new Set([
|
|
305
320
|
"discuss-project",
|
|
306
321
|
"discuss-requirements",
|
|
@@ -316,6 +331,10 @@ function artifactValidationKind(unitType) {
|
|
|
316
331
|
return null;
|
|
317
332
|
}
|
|
318
333
|
function describeArtifactVerificationFailure(unitType, unitId, basePath) {
|
|
334
|
+
const worktreeFailure = diagnoseWorktreeIntegrityFailure(basePath);
|
|
335
|
+
if (worktreeFailure) {
|
|
336
|
+
return `${worktreeFailure} Unit: ${unitType} ${unitId}.`;
|
|
337
|
+
}
|
|
319
338
|
const artifactPath = resolveExpectedArtifactPath(unitType, unitId, basePath);
|
|
320
339
|
if (!artifactPath) {
|
|
321
340
|
return `Artifact verification failed: ${unitType} "${unitId}" has no resolvable artifact path.`;
|
|
@@ -360,6 +379,148 @@ export async function autoCommitUnit(basePath, unitType, unitId, ctx) {
|
|
|
360
379
|
return null;
|
|
361
380
|
}
|
|
362
381
|
}
|
|
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) {
|
|
390
|
+
const { s, ctx, pi, pauseAuto } = pctx;
|
|
391
|
+
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
392
|
+
const uokFlags = resolveUokFlags(prefs);
|
|
393
|
+
const turnAction = uokFlags.gitops ? uokFlags.gitopsTurnAction : "commit";
|
|
394
|
+
const traceId = s.currentTraceId ?? `turn:${unit.startedAt}`;
|
|
395
|
+
const turnId = s.currentTurnId ?? `${unit.type}/${unit.id}/${unit.startedAt}`;
|
|
396
|
+
s.lastGitActionFailure = null;
|
|
397
|
+
s.lastGitActionStatus = null;
|
|
398
|
+
try {
|
|
399
|
+
let taskContext;
|
|
400
|
+
if (turnAction === "commit" && unit.type === "execute-task") {
|
|
401
|
+
taskContext = await buildTaskCommitContextForUnit(s.basePath, unit.id);
|
|
402
|
+
}
|
|
403
|
+
// Invalidate the nativeHasChanges cache before auto-commit (#1853).
|
|
404
|
+
// The cache has a 10-second TTL and is keyed by basePath. A stale
|
|
405
|
+
// `false` result causes autoCommit to skip staging entirely.
|
|
406
|
+
_resetHasChangesCache();
|
|
407
|
+
const skipLifecycleCommit = turnAction === "commit" && LIFECYCLE_ONLY_UNITS.has(unit.type);
|
|
408
|
+
if (skipLifecycleCommit) {
|
|
409
|
+
debugLog("postUnit", {
|
|
410
|
+
phase: "git-action-skipped",
|
|
411
|
+
reason: "lifecycle-only-unit",
|
|
412
|
+
unitType: unit.type,
|
|
413
|
+
unitId: unit.id,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
const maxAttempts = opts?.softFailure ? 3 : 1;
|
|
418
|
+
let gitResult = runTurnGitAction({
|
|
419
|
+
basePath: s.basePath,
|
|
420
|
+
action: turnAction,
|
|
421
|
+
unitType: unit.type,
|
|
422
|
+
unitId: unit.id,
|
|
423
|
+
taskContext,
|
|
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
|
+
}
|
|
435
|
+
if (uokFlags.gitops) {
|
|
436
|
+
writeTurnGitTransaction({
|
|
437
|
+
basePath: s.basePath,
|
|
438
|
+
traceId,
|
|
439
|
+
turnId,
|
|
440
|
+
unitType: unit.type,
|
|
441
|
+
unitId: unit.id,
|
|
442
|
+
stage: "publish",
|
|
443
|
+
action: turnAction,
|
|
444
|
+
push: uokFlags.gitopsTurnPush,
|
|
445
|
+
status: gitResult.status,
|
|
446
|
+
error: gitResult.error,
|
|
447
|
+
metadata: {
|
|
448
|
+
dirty: gitResult.dirty,
|
|
449
|
+
commitMessage: gitResult.commitMessage,
|
|
450
|
+
snapshotLabel: gitResult.snapshotLabel,
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
if (gitResult.status === "failed") {
|
|
455
|
+
s.lastGitActionFailure = gitResult.error ?? `git ${turnAction} failed`;
|
|
456
|
+
s.lastGitActionStatus = "failed";
|
|
457
|
+
if (uokFlags.gitops && uokFlags.gates) {
|
|
458
|
+
const parsed = parseUnitId(unit.id);
|
|
459
|
+
const gateRunner = new UokGateRunner();
|
|
460
|
+
gateRunner.register({
|
|
461
|
+
id: "closeout-git-action",
|
|
462
|
+
type: "closeout",
|
|
463
|
+
execute: async () => ({
|
|
464
|
+
outcome: "fail",
|
|
465
|
+
failureClass: "git",
|
|
466
|
+
rationale: `turn git action "${turnAction}" failed`,
|
|
467
|
+
findings: gitResult.error ?? "unknown git failure",
|
|
468
|
+
}),
|
|
469
|
+
});
|
|
470
|
+
await gateRunner.run("closeout-git-action", {
|
|
471
|
+
basePath: s.basePath,
|
|
472
|
+
traceId,
|
|
473
|
+
turnId,
|
|
474
|
+
milestoneId: parsed.milestone ?? undefined,
|
|
475
|
+
sliceId: parsed.slice ?? undefined,
|
|
476
|
+
taskId: parsed.task ?? undefined,
|
|
477
|
+
unitType: unit.type,
|
|
478
|
+
unitId: unit.id,
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
const failureMsg = `Git ${turnAction} failed: ${(gitResult.error ?? "unknown error").split("\n")[0]}`;
|
|
482
|
+
ctx.ui.notify(failureMsg, opts?.softFailure ? "warning" : "error");
|
|
483
|
+
debugLog("postUnit", {
|
|
484
|
+
phase: opts?.softFailure ? "git-action-failed-soft" : "git-action-failed-blocking",
|
|
485
|
+
action: turnAction,
|
|
486
|
+
error: gitResult.error ?? "unknown error",
|
|
487
|
+
});
|
|
488
|
+
if (opts?.softFailure) {
|
|
489
|
+
return "continue";
|
|
490
|
+
}
|
|
491
|
+
await pauseAuto(ctx, pi);
|
|
492
|
+
return "dispatched";
|
|
493
|
+
}
|
|
494
|
+
s.lastGitActionStatus = "ok";
|
|
495
|
+
if (turnAction === "commit" && gitResult.commitMessage) {
|
|
496
|
+
ctx.ui.notify(`Committed: ${gitResult.commitMessage.split("\n")[0]}`, "info");
|
|
497
|
+
}
|
|
498
|
+
else if (turnAction === "snapshot" && gitResult.snapshotLabel) {
|
|
499
|
+
ctx.ui.notify(`Snapshot recorded: ${gitResult.snapshotLabel}`, "info");
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
catch (e) {
|
|
504
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
505
|
+
s.lastGitActionFailure = message;
|
|
506
|
+
s.lastGitActionStatus = "failed";
|
|
507
|
+
debugLog("postUnit", { phase: "git-action", error: message, action: turnAction });
|
|
508
|
+
ctx.ui.notify(`Git ${turnAction} failed: ${message.split("\n")[0]}`, opts?.softFailure ? "warning" : "error");
|
|
509
|
+
if (opts?.softFailure) {
|
|
510
|
+
return "continue";
|
|
511
|
+
}
|
|
512
|
+
if (uokFlags.gitops) {
|
|
513
|
+
await pauseAuto(ctx, pi);
|
|
514
|
+
return "dispatched";
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
// GitHub sync (non-blocking, opt-in)
|
|
518
|
+
await runSafely("postUnit", "github-sync", async () => {
|
|
519
|
+
const { runGitHubSync } = await import("../github-sync/sync.js");
|
|
520
|
+
await runGitHubSync(s.basePath, unit.type, unit.id);
|
|
521
|
+
});
|
|
522
|
+
return "continue";
|
|
523
|
+
}
|
|
363
524
|
/**
|
|
364
525
|
* Pre-verification processing: parallel worker signal check, cache invalidation,
|
|
365
526
|
* auto-commit, doctor run, state rebuild, worktree sync, artifact verification.
|
|
@@ -370,7 +531,7 @@ export async function autoCommitUnit(basePath, unitType, unitId, ctx) {
|
|
|
370
531
|
* - "retry" — artifact verification failed, s.pendingVerificationRetry set for loop re-iteration
|
|
371
532
|
*/
|
|
372
533
|
export async function postUnitPreVerification(pctx, opts) {
|
|
373
|
-
const { s, ctx, pi,
|
|
534
|
+
const { s, ctx, pi, stopAuto, pauseAuto } = pctx;
|
|
374
535
|
// ── Parallel worker signal check ──
|
|
375
536
|
const milestoneLock = process.env.GSD_MILESTONE_LOCK;
|
|
376
537
|
if (milestoneLock) {
|
|
@@ -392,125 +553,22 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
392
553
|
if (!opts?.skipSettleDelay) {
|
|
393
554
|
await new Promise(r => setTimeout(r, 100));
|
|
394
555
|
}
|
|
395
|
-
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
396
|
-
const uokFlags = resolveUokFlags(prefs);
|
|
397
556
|
// Turn-level git action (commit | snapshot | status-only)
|
|
398
557
|
if (s.currentUnit) {
|
|
399
558
|
const unit = s.currentUnit;
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
let taskContext;
|
|
407
|
-
if (turnAction === "commit" && s.currentUnit.type === "execute-task") {
|
|
408
|
-
taskContext = await buildTaskCommitContextForUnit(s.basePath, s.currentUnit.id);
|
|
409
|
-
}
|
|
410
|
-
// Invalidate the nativeHasChanges cache before auto-commit (#1853).
|
|
411
|
-
// The cache has a 10-second TTL and is keyed by basePath. A stale
|
|
412
|
-
// `false` result causes autoCommit to skip staging entirely, leaving
|
|
413
|
-
// code files only in the working tree where they are destroyed by
|
|
414
|
-
// `git worktree remove --force` during teardown.
|
|
415
|
-
_resetHasChangesCache();
|
|
416
|
-
const skipLifecycleCommit = turnAction === "commit" && LIFECYCLE_ONLY_UNITS.has(s.currentUnit.type);
|
|
417
|
-
if (skipLifecycleCommit) {
|
|
418
|
-
debugLog("postUnit", {
|
|
419
|
-
phase: "git-action-skipped",
|
|
420
|
-
reason: "lifecycle-only-unit",
|
|
421
|
-
unitType: s.currentUnit.type,
|
|
422
|
-
unitId: s.currentUnit.id,
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
else {
|
|
426
|
-
const gitResult = runTurnGitAction({
|
|
427
|
-
basePath: s.basePath,
|
|
428
|
-
action: turnAction,
|
|
429
|
-
unitType: s.currentUnit.type,
|
|
430
|
-
unitId: s.currentUnit.id,
|
|
431
|
-
taskContext,
|
|
432
|
-
});
|
|
433
|
-
if (uokFlags.gitops) {
|
|
434
|
-
writeTurnGitTransaction({
|
|
435
|
-
basePath: s.basePath,
|
|
436
|
-
traceId,
|
|
437
|
-
turnId,
|
|
438
|
-
unitType: unit.type,
|
|
439
|
-
unitId: unit.id,
|
|
440
|
-
stage: "publish",
|
|
441
|
-
action: turnAction,
|
|
442
|
-
push: uokFlags.gitopsTurnPush,
|
|
443
|
-
status: gitResult.status,
|
|
444
|
-
error: gitResult.error,
|
|
445
|
-
metadata: {
|
|
446
|
-
dirty: gitResult.dirty,
|
|
447
|
-
commitMessage: gitResult.commitMessage,
|
|
448
|
-
snapshotLabel: gitResult.snapshotLabel,
|
|
449
|
-
},
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
if (gitResult.status === "failed") {
|
|
453
|
-
s.lastGitActionFailure = gitResult.error ?? `git ${turnAction} failed`;
|
|
454
|
-
s.lastGitActionStatus = "failed";
|
|
455
|
-
if (uokFlags.gitops && uokFlags.gates) {
|
|
456
|
-
const parsed = parseUnitId(unit.id);
|
|
457
|
-
const gateRunner = new UokGateRunner();
|
|
458
|
-
gateRunner.register({
|
|
459
|
-
id: "closeout-git-action",
|
|
460
|
-
type: "closeout",
|
|
461
|
-
execute: async () => ({
|
|
462
|
-
outcome: "fail",
|
|
463
|
-
failureClass: "git",
|
|
464
|
-
rationale: `turn git action "${turnAction}" failed`,
|
|
465
|
-
findings: gitResult.error ?? "unknown git failure",
|
|
466
|
-
}),
|
|
467
|
-
});
|
|
468
|
-
await gateRunner.run("closeout-git-action", {
|
|
469
|
-
basePath: s.basePath,
|
|
470
|
-
traceId,
|
|
471
|
-
turnId,
|
|
472
|
-
milestoneId: parsed.milestone ?? undefined,
|
|
473
|
-
sliceId: parsed.slice ?? undefined,
|
|
474
|
-
taskId: parsed.task ?? undefined,
|
|
475
|
-
unitType: unit.type,
|
|
476
|
-
unitId: unit.id,
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
const failureMsg = `Git ${turnAction} failed: ${(gitResult.error ?? "unknown error").split("\n")[0]}`;
|
|
480
|
-
ctx.ui.notify(failureMsg, "error");
|
|
481
|
-
debugLog("postUnit", {
|
|
482
|
-
phase: "git-action-failed-blocking",
|
|
483
|
-
action: turnAction,
|
|
484
|
-
error: gitResult.error ?? "unknown error",
|
|
485
|
-
});
|
|
486
|
-
await pauseAuto(ctx, pi);
|
|
487
|
-
return "dispatched";
|
|
488
|
-
}
|
|
489
|
-
s.lastGitActionStatus = "ok";
|
|
490
|
-
if (turnAction === "commit" && gitResult.commitMessage) {
|
|
491
|
-
ctx.ui.notify(`Committed: ${gitResult.commitMessage.split("\n")[0]}`, "info");
|
|
492
|
-
}
|
|
493
|
-
else if (turnAction === "snapshot" && gitResult.snapshotLabel) {
|
|
494
|
-
ctx.ui.notify(`Snapshot recorded: ${gitResult.snapshotLabel}`, "info");
|
|
495
|
-
}
|
|
496
|
-
}
|
|
559
|
+
if (shouldDeferCloseoutGitAction(unit.type)) {
|
|
560
|
+
debugLog("postUnit", {
|
|
561
|
+
phase: "git-action-deferred-until-verification",
|
|
562
|
+
unitType: unit.type,
|
|
563
|
+
unitId: unit.id,
|
|
564
|
+
});
|
|
497
565
|
}
|
|
498
|
-
|
|
499
|
-
const
|
|
500
|
-
|
|
501
|
-
s.lastGitActionStatus = "failed";
|
|
502
|
-
debugLog("postUnit", { phase: "git-action", error: message, action: turnAction });
|
|
503
|
-
ctx.ui.notify(`Git ${turnAction} failed: ${message.split("\n")[0]}`, uokFlags.gitops ? "error" : "warning");
|
|
504
|
-
if (uokFlags.gitops) {
|
|
505
|
-
await pauseAuto(ctx, pi);
|
|
566
|
+
else {
|
|
567
|
+
const gitActionResult = await runCloseoutGitAction(pctx, unit);
|
|
568
|
+
if (gitActionResult === "dispatched") {
|
|
506
569
|
return "dispatched";
|
|
507
570
|
}
|
|
508
571
|
}
|
|
509
|
-
// GitHub sync (non-blocking, opt-in)
|
|
510
|
-
await runSafely("postUnit", "github-sync", async () => {
|
|
511
|
-
const { runGitHubSync } = await import("../github-sync/sync.js");
|
|
512
|
-
await runGitHubSync(s.basePath, unit.type, unit.id);
|
|
513
|
-
});
|
|
514
572
|
// Prune dead bg-shell processes
|
|
515
573
|
await runSafely("postUnit", "prune-bg-shell", async () => {
|
|
516
574
|
const { pruneDeadProcesses } = await import("../bg-shell/process-manager.js");
|
|
@@ -723,7 +781,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
723
781
|
const safetyConfig = resolveSafetyHarnessConfig(prefs?.safety_harness);
|
|
724
782
|
if (safetyConfig.enabled) {
|
|
725
783
|
const { milestone: sMid, slice: sSid, task: sTid } = parseUnitId(s.currentUnit.id);
|
|
726
|
-
// File change validation (execute-task only, after
|
|
784
|
+
// File change validation (execute-task only, after unit execution)
|
|
727
785
|
if (safetyConfig.file_change_validation && s.currentUnit.type === "execute-task" && sMid && sSid && sTid && isDbAvailable()) {
|
|
728
786
|
try {
|
|
729
787
|
const taskRow = getTask(sMid, sSid, sTid);
|
|
@@ -756,12 +814,34 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
756
814
|
const bashCalls = actual.filter(e => e.kind === "bash");
|
|
757
815
|
if (sMid && sSid && sTid && isDbAvailable()) {
|
|
758
816
|
const taskRow = getTask(sMid, sSid, sTid);
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
817
|
+
if (taskRow?.status === "complete") {
|
|
818
|
+
const claimedEvidence = getVerificationEvidence(sMid, sSid, sTid)
|
|
819
|
+
.map((row) => ({
|
|
820
|
+
command: row.command,
|
|
821
|
+
exitCode: row.exit_code,
|
|
822
|
+
verdict: row.verdict,
|
|
823
|
+
}))
|
|
824
|
+
.filter((row) => typeof row.command === "string" && row.command.trim().length > 0);
|
|
825
|
+
const mismatches = crossReferenceEvidence(claimedEvidence, actual);
|
|
826
|
+
for (const mismatch of mismatches) {
|
|
827
|
+
const logMessage = `evidence-xref: ${mismatch.reason}`;
|
|
828
|
+
if (mismatch.severity === "error") {
|
|
829
|
+
logError("safety", logMessage);
|
|
830
|
+
}
|
|
831
|
+
else {
|
|
832
|
+
logWarning("safety", logMessage);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
if (claimedEvidence.length > 0 && bashCalls.length === 0) {
|
|
836
|
+
logWarning("safety", "task claimed verification command evidence but no execution tool calls were recorded");
|
|
837
|
+
ctx.ui.notify(`Safety: task ${sTid} claimed command evidence but no execution tool calls were recorded`, "warning");
|
|
838
|
+
}
|
|
839
|
+
const blockingMismatch = mismatches.find((mismatch) => mismatch.severity === "error");
|
|
840
|
+
if (blockingMismatch) {
|
|
841
|
+
ctx.ui.notify(`Safety: task ${sTid} claimed passing verification that failed in recorded execution`, "error");
|
|
842
|
+
await pauseAuto(ctx, pi);
|
|
843
|
+
return "dispatched";
|
|
844
|
+
}
|
|
765
845
|
}
|
|
766
846
|
}
|
|
767
847
|
}
|
|
@@ -922,6 +1002,22 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
922
1002
|
ctx.ui.notify(`${s.currentUnit.type} ${s.currentUnit.id} — deterministic policy rejection, wrote blocker placeholder (no retries) (#4973)`, "warning");
|
|
923
1003
|
// Fall through to "continue" — do NOT enter the retry or db-unavailable paths.
|
|
924
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
|
+
}
|
|
925
1021
|
else if (!triggerArtifactVerified && !isDbAvailable()) {
|
|
926
1022
|
debugLog("postUnit", { phase: "artifact-verify-skip-db-unavailable", unitType: s.currentUnit.type, unitId: s.currentUnit.id });
|
|
927
1023
|
const dbSkipDiag = diagnoseExpectedArtifact(s.currentUnit.type, s.currentUnit.id, s.basePath);
|
|
@@ -992,6 +1088,12 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
992
1088
|
export async function postUnitPostVerification(pctx) {
|
|
993
1089
|
const { s, ctx, pi, buildSnapshotOpts, lockBase, stopAuto, pauseAuto, updateProgressWidget } = pctx;
|
|
994
1090
|
if (s.currentUnit) {
|
|
1091
|
+
if (shouldDeferCloseoutGitAction(s.currentUnit.type)) {
|
|
1092
|
+
const gitActionResult = await runCloseoutGitAction(pctx, s.currentUnit, { softFailure: true });
|
|
1093
|
+
if (gitActionResult === "dispatched") {
|
|
1094
|
+
return "stopped";
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
995
1097
|
try {
|
|
996
1098
|
const codebasePrefs = loadEffectiveGSDPreferences()?.preferences?.codebase;
|
|
997
1099
|
const refresh = ensureCodebaseMapFresh(s.basePath, codebasePrefs
|
|
@@ -1359,15 +1461,19 @@ export async function postUnitPostVerification(pctx) {
|
|
|
1359
1461
|
// Without this notify(), /gsd in step mode finishes a unit and silently
|
|
1360
1462
|
// exits the loop, leaving the user with no hint to /clear and /gsd again.
|
|
1361
1463
|
if (s.stepMode) {
|
|
1464
|
+
let phaseAfterUnit = null;
|
|
1362
1465
|
try {
|
|
1363
1466
|
const nextState = await deriveState(s.canonicalProjectRoot);
|
|
1467
|
+
phaseAfterUnit = nextState.phase;
|
|
1364
1468
|
ctx.ui.notify(buildStepCompleteMessage(nextState), "info");
|
|
1365
1469
|
}
|
|
1366
1470
|
catch (e) {
|
|
1367
1471
|
debugLog("postUnit", { phase: "step-wizard-notify", error: String(e) });
|
|
1368
1472
|
ctx.ui.notify(STEP_COMPLETE_FALLBACK_MESSAGE, "info");
|
|
1369
1473
|
}
|
|
1370
|
-
return
|
|
1474
|
+
return shouldReturnStepWizardAfterUnit(s.currentUnit?.type, phaseAfterUnit)
|
|
1475
|
+
? "step-wizard"
|
|
1476
|
+
: "continue";
|
|
1371
1477
|
}
|
|
1372
1478
|
return "continue";
|
|
1373
1479
|
}
|
|
@@ -2777,7 +2777,7 @@ export async function buildParallelResearchSlicesPrompt(mid, midTitle, slices, b
|
|
|
2777
2777
|
subagentSections.push([
|
|
2778
2778
|
`### ${slice.id}: ${slice.title}`,
|
|
2779
2779
|
"",
|
|
2780
|
-
`Use this as the prompt for a \`subagent\` call${modelSuffix} (agent: \`
|
|
2780
|
+
`Use this as the prompt for a \`subagent\` call${modelSuffix} (agent: \`scout\`):`,
|
|
2781
2781
|
"",
|
|
2782
2782
|
"```",
|
|
2783
2783
|
slicePrompt,
|
|
@@ -2846,7 +2846,7 @@ export async function buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, base,
|
|
|
2846
2846
|
subagentSections.push([
|
|
2847
2847
|
`### ${def.id}: ${def.question}`,
|
|
2848
2848
|
"",
|
|
2849
|
-
`Use this as the prompt for a \`subagent\` call${modelSuffix}:`,
|
|
2849
|
+
`Use this as the prompt for a \`subagent\` call${modelSuffix} (agent: \`tester\`):`,
|
|
2850
2850
|
"",
|
|
2851
2851
|
"```",
|
|
2852
2852
|
subPrompt,
|
|
@@ -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
|
}
|