gsd-pi 2.82.0-dev.2841a1e44 → 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 +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 +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 +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 +30 -3
- 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 +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-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/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/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/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 +13 -13
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/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 +13 -13
- 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/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/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 +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 +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 +32 -3
- 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 +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-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/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/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 +80 -1
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +6 -6
- 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-worktree-registry.test.ts +69 -1
- 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/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/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/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/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-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 → euQ0CLP_v8V4e76Tu3odJ}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Qgr2B_MRhPxC0z8fwv4vT → euQ0CLP_v8V4e76Tu3odJ}/_ssgManifest.js +0 -0
|
@@ -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.
|
|
@@ -134,10 +134,11 @@ export function mapUsage(sdkUsage: NonNullableUsage, totalCostUsd: number): Usag
|
|
|
134
134
|
output: sdkUsage.output_tokens,
|
|
135
135
|
cacheRead: sdkUsage.cache_read_input_tokens,
|
|
136
136
|
cacheWrite: sdkUsage.cache_creation_input_tokens,
|
|
137
|
+
// Claude Agent SDK result usage is cumulative across its internal loop;
|
|
138
|
+
// repeated cache reads do not represent additional live context.
|
|
137
139
|
totalTokens:
|
|
138
140
|
sdkUsage.input_tokens +
|
|
139
141
|
sdkUsage.output_tokens +
|
|
140
|
-
sdkUsage.cache_read_input_tokens +
|
|
141
142
|
sdkUsage.cache_creation_input_tokens,
|
|
142
143
|
cost: {
|
|
143
144
|
input: 0,
|
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
import { describe, test } from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import { mapContentBlock, parseMcpToolName, PartialMessageBuilder } from "../partial-builder.ts";
|
|
4
|
-
import type { BetaContentBlock, BetaRawMessageStreamEvent } from "../sdk-types.ts";
|
|
3
|
+
import { mapContentBlock, mapUsage, parseMcpToolName, PartialMessageBuilder } from "../partial-builder.ts";
|
|
4
|
+
import type { BetaContentBlock, BetaRawMessageStreamEvent, NonNullableUsage } from "../sdk-types.ts";
|
|
5
|
+
|
|
6
|
+
describe("mapUsage", () => {
|
|
7
|
+
test("excludes cumulative cache reads from context-sized totalTokens (#5243)", () => {
|
|
8
|
+
const usage: NonNullableUsage = {
|
|
9
|
+
input_tokens: 150_000,
|
|
10
|
+
output_tokens: 2_000,
|
|
11
|
+
cache_read_input_tokens: 900_000,
|
|
12
|
+
cache_creation_input_tokens: 3_000,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const mapped = mapUsage(usage, 1.23);
|
|
16
|
+
|
|
17
|
+
assert.equal(mapped.cacheRead, 900_000);
|
|
18
|
+
assert.equal(mapped.totalTokens, 155_000);
|
|
19
|
+
assert.equal(mapped.cost.total, 1.23);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
5
22
|
|
|
6
23
|
describe("PartialMessageBuilder — malformed tool arguments (#2574)", () => {
|
|
7
24
|
/**
|
|
@@ -47,12 +47,20 @@ export interface DispatchAdapter {
|
|
|
47
47
|
sessionProvider?: string;
|
|
48
48
|
/** Model registry for executor-model lookups inside the budget engine. */
|
|
49
49
|
modelRegistry?: MinimalModelRegistry;
|
|
50
|
-
}): Promise<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
}): Promise<
|
|
51
|
+
| {
|
|
52
|
+
kind: "blocked";
|
|
53
|
+
reason: string;
|
|
54
|
+
action: "pause" | "stop";
|
|
55
|
+
}
|
|
56
|
+
| {
|
|
57
|
+
unitType: string;
|
|
58
|
+
unitId: string;
|
|
59
|
+
reason: string;
|
|
60
|
+
preconditions: string[];
|
|
61
|
+
}
|
|
62
|
+
| null
|
|
63
|
+
>;
|
|
56
64
|
}
|
|
57
65
|
|
|
58
66
|
export interface RecoveryAdapter {
|
|
@@ -7,9 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Error codes indicating infrastructure failures
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Error codes indicating infrastructure-level failures from the OS,
|
|
11
|
+
* filesystem, or network. This set includes permanent resource failures
|
|
12
|
+
* (ENOSPC, ENOMEM, EROFS), transient resource exhaustion (EAGAIN, ENOBUFS),
|
|
13
|
+
* and network/offline errors (ECONNREFUSED, ENOTFOUND, ENETUNREACH).
|
|
14
|
+
*
|
|
15
|
+
* Transient git failures are retried separately through
|
|
16
|
+
* TRANSIENT_GIT_RETRY_CODES in native-git-bridge.ts before escalating to the
|
|
17
|
+
* auto-loop.
|
|
13
18
|
*/
|
|
14
19
|
export const INFRA_ERROR_CODES: ReadonlySet<string> = new Set([
|
|
15
20
|
"ENOSPC", // disk full
|
|
@@ -19,6 +24,7 @@ export const INFRA_ERROR_CODES: ReadonlySet<string> = new Set([
|
|
|
19
24
|
"EMFILE", // too many open files (process)
|
|
20
25
|
"ENFILE", // too many open files (system)
|
|
21
26
|
"EAGAIN", // resource temporarily unavailable (resource exhaustion)
|
|
27
|
+
"ENOBUFS", // no buffer space available (transient pipe exhaustion)
|
|
22
28
|
"ECONNREFUSED", // connection refused (offline / local server down)
|
|
23
29
|
"ENOTFOUND", // DNS lookup failed (offline / no network)
|
|
24
30
|
"ENETUNREACH", // network unreachable (offline / no route)
|
|
@@ -78,7 +78,10 @@ import { createWorkflowTurnReporter } from "./workflow-turn-reporter.js";
|
|
|
78
78
|
import { validateWorkflowSessionLock } from "./workflow-session-lock.js";
|
|
79
79
|
import { dequeueSidecarItem } from "./workflow-sidecar-queue.js";
|
|
80
80
|
import { maintainWorkerHeartbeat } from "./workflow-worker-heartbeat.js";
|
|
81
|
-
import {
|
|
81
|
+
import {
|
|
82
|
+
measureMemoryPressure,
|
|
83
|
+
shouldCheckMemoryPressure,
|
|
84
|
+
} from "./workflow-memory-pressure.js";
|
|
82
85
|
import { buildSidecarIterationData } from "./workflow-sidecar-iteration.js";
|
|
83
86
|
import {
|
|
84
87
|
createExecutionGraphUnitDispatchDeps,
|
|
@@ -203,9 +206,9 @@ function logCustomVerifyRetrySaveFailure(err: unknown): void {
|
|
|
203
206
|
}
|
|
204
207
|
|
|
205
208
|
// ── Memory pressure monitoring (#3331) ──────────────────────────────────
|
|
206
|
-
// Check heap usage every N iterations and trigger
|
|
207
|
-
// the OS OOM killer sends SIGKILL. The threshold is
|
|
208
|
-
// limit (--max-old-space-size or default ~1.5-4GB depending on platform).
|
|
209
|
+
// Check heap usage on session startup, then every N iterations, and trigger
|
|
210
|
+
// graceful shutdown before the OS OOM killer sends SIGKILL. The threshold is
|
|
211
|
+
// 90% of the V8 heap limit (--max-old-space-size or default ~1.5-4GB depending on platform).
|
|
209
212
|
const MEMORY_CHECK_INTERVAL = 5; // check every 5 iterations
|
|
210
213
|
const MAX_CUSTOM_ENGINE_VERIFY_RETRIES = 3;
|
|
211
214
|
|
|
@@ -372,7 +375,7 @@ export async function autoLoop(
|
|
|
372
375
|
|
|
373
376
|
// ── Memory pressure check (#3331) ──
|
|
374
377
|
// Graceful shutdown before OOM killer sends SIGKILL.
|
|
375
|
-
if (iteration
|
|
378
|
+
if (shouldCheckMemoryPressure(iteration, MEMORY_CHECK_INTERVAL)) {
|
|
376
379
|
const mem = measureMemoryPressure();
|
|
377
380
|
debugLog("autoLoop", { phase: "memory-check", ...mem });
|
|
378
381
|
const memoryDecision = decideMemoryPressure({ ...mem, iteration });
|
|
@@ -128,6 +128,17 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
128
128
|
await this.deps.health.postAdvanceRecord(stopped);
|
|
129
129
|
return stopped;
|
|
130
130
|
}
|
|
131
|
+
if (!("unitType" in decision)) {
|
|
132
|
+
const blocked: AutoAdvanceResult = {
|
|
133
|
+
kind: "blocked",
|
|
134
|
+
reason: decision.reason,
|
|
135
|
+
action: decision.action,
|
|
136
|
+
stateSnapshot: reconciliation.stateSnapshot,
|
|
137
|
+
};
|
|
138
|
+
await this.deps.runtime.journalTransition({ name: "advance-blocked", reason: blocked.reason });
|
|
139
|
+
await this.deps.health.postAdvanceRecord(blocked);
|
|
140
|
+
return blocked;
|
|
141
|
+
}
|
|
131
142
|
|
|
132
143
|
const nextKey = `${decision.unitType}:${decision.unitId}`;
|
|
133
144
|
|
|
@@ -1327,9 +1327,15 @@ export async function runDispatch(
|
|
|
1327
1327
|
}
|
|
1328
1328
|
|
|
1329
1329
|
const guardBasePath = _resolveDispatchGuardBasePath(s);
|
|
1330
|
+
let mainBranch = "main";
|
|
1331
|
+
try {
|
|
1332
|
+
mainBranch = deps.getMainBranch(guardBasePath);
|
|
1333
|
+
} catch (err) {
|
|
1334
|
+
debugLog("autoLoop", { phase: "getMainBranch-failed", error: String(err) });
|
|
1335
|
+
}
|
|
1330
1336
|
const priorSliceBlocker = deps.getPriorSliceCompletionBlocker(
|
|
1331
1337
|
guardBasePath,
|
|
1332
|
-
|
|
1338
|
+
mainBranch,
|
|
1333
1339
|
unitType,
|
|
1334
1340
|
unitId,
|
|
1335
1341
|
);
|
|
@@ -19,6 +19,19 @@ export interface MeasureMemoryPressureDeps {
|
|
|
19
19
|
heapLimitBytes: () => number;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Returns true on auto-mode startup, then every configured interval.
|
|
24
|
+
*
|
|
25
|
+
* Iteration 1 is checked explicitly so early session memory pressure cannot
|
|
26
|
+
* bypass the periodic interval guard.
|
|
27
|
+
*/
|
|
28
|
+
export function shouldCheckMemoryPressure(iteration: number, interval: number): boolean {
|
|
29
|
+
if (!Number.isInteger(interval) || interval <= 0) {
|
|
30
|
+
throw new Error("Memory pressure check interval must be a positive integer");
|
|
31
|
+
}
|
|
32
|
+
return iteration === 1 || iteration % interval === 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
22
35
|
function defaultHeapLimitBytes(): number {
|
|
23
36
|
const v8 = require("node:v8") as {
|
|
24
37
|
getHeapStatistics?: () => { heap_size_limit?: number };
|
|
@@ -239,6 +239,12 @@ function missingSliceStop(mid: string, phase: string): DispatchAction {
|
|
|
239
239
|
};
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
+
function isRegistryMilestoneComplete(state: GSDState, mid: string): boolean {
|
|
243
|
+
return state.registry.some((milestone) =>
|
|
244
|
+
milestone.id === mid && milestone.status === "complete"
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
242
248
|
/**
|
|
243
249
|
* Check for milestone slices missing SUMMARY files.
|
|
244
250
|
* Returns array of missing slice IDs, or empty array if all present or DB unavailable.
|
|
@@ -395,6 +401,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
395
401
|
match: async ({ state, mid, midTitle, basePath, prefs, structuredQuestionsAvailable }) => {
|
|
396
402
|
if (!EXECUTION_ENTRY_PHASES.has(state.phase)) return null;
|
|
397
403
|
if (!MILESTONE_ID_RE.test(mid)) return null;
|
|
404
|
+
if (isRegistryMilestoneComplete(state, mid)) return null;
|
|
398
405
|
// Align with the plan-v2 gate's lookup semantics: whitespace-only counts
|
|
399
406
|
// as missing, and an auto worktree may fall back to GSD_PROJECT_ROOT.
|
|
400
407
|
if (hasFinalizedMilestoneContext(basePath, mid)) return null;
|
|
@@ -709,6 +716,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
709
716
|
name: "pre-planning (no context) → discuss-milestone",
|
|
710
717
|
match: async ({ state, mid, midTitle, basePath, prefs, structuredQuestionsAvailable }) => {
|
|
711
718
|
if (state.phase !== "pre-planning") return null;
|
|
719
|
+
if (isRegistryMilestoneComplete(state, mid)) return null;
|
|
712
720
|
const contextFile = resolveMilestoneFile(basePath, mid, "CONTEXT");
|
|
713
721
|
const hasContext = !!(contextFile && (await loadFile(contextFile)));
|
|
714
722
|
if (hasContext) return null; // fall through to next rule
|
|
@@ -1322,19 +1330,19 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1322
1330
|
}
|
|
1323
1331
|
}
|
|
1324
1332
|
|
|
1325
|
-
// Safety guard (#2675): block completion when VALIDATION
|
|
1326
|
-
//
|
|
1327
|
-
// terminal
|
|
1328
|
-
//
|
|
1333
|
+
// Safety guard (#2675, #5747): block completion when VALIDATION
|
|
1334
|
+
// verdict is non-passing. The state machine treats these verdicts as
|
|
1335
|
+
// terminal, but completing-milestone should NOT proceed — remediation
|
|
1336
|
+
// or human attention is needed.
|
|
1329
1337
|
const validationFile = resolveMilestoneFile(basePath, mid, "VALIDATION");
|
|
1330
1338
|
if (validationFile) {
|
|
1331
1339
|
const validationContent = await loadFile(validationFile);
|
|
1332
1340
|
if (validationContent) {
|
|
1333
1341
|
const verdict = extractVerdict(validationContent);
|
|
1334
|
-
if (verdict === "needs-remediation") {
|
|
1342
|
+
if (verdict === "needs-remediation" || verdict === "needs-attention") {
|
|
1335
1343
|
return {
|
|
1336
1344
|
action: "stop",
|
|
1337
|
-
reason: `Cannot complete milestone ${mid}: VALIDATION verdict is "
|
|
1345
|
+
reason: `Cannot complete milestone ${mid}: VALIDATION verdict is "${verdict}". Address the validation findings and re-run validation, or update the verdict manually.`,
|
|
1338
1346
|
level: "warning",
|
|
1339
1347
|
};
|
|
1340
1348
|
}
|
|
@@ -615,10 +615,11 @@ export async function selectAndApplyModel(
|
|
|
615
615
|
* Handles formats: "provider/model", "bare-id", "org/model-name" (OpenRouter).
|
|
616
616
|
*/
|
|
617
617
|
export function resolveModelId<T extends { id: string; provider: string }>(
|
|
618
|
-
modelId: string,
|
|
618
|
+
modelId: string | undefined,
|
|
619
619
|
availableModels: T[],
|
|
620
620
|
currentProvider: string | undefined,
|
|
621
621
|
): T | undefined {
|
|
622
|
+
if (!modelId) return undefined;
|
|
622
623
|
const slashIdx = modelId.indexOf("/");
|
|
623
624
|
|
|
624
625
|
if (slashIdx !== -1) {
|
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
resolveExpectedArtifactPath,
|
|
42
42
|
writeBlockerPlaceholder,
|
|
43
43
|
diagnoseExpectedArtifact,
|
|
44
|
+
diagnoseWorktreeIntegrityFailure,
|
|
44
45
|
} from "./auto-recovery.js";
|
|
45
46
|
import { regenerateIfMissing } from "./workflow-projections.js";
|
|
46
47
|
import { WorktreeStateProjection } from "./worktree-state-projection.js";
|
|
@@ -163,7 +164,7 @@ async function buildTaskCommitContextForUnit(
|
|
|
163
164
|
sliceTitle: stripKnownIdPrefix(slice?.title, sid),
|
|
164
165
|
oneLiner: summary?.oneLiner || task?.one_liner || undefined,
|
|
165
166
|
keyFiles:
|
|
166
|
-
summary?.frontmatter.key_files?.filter(f => !f.includes("{{")) ??
|
|
167
|
+
summary?.frontmatter.key_files?.filter(f => !f.includes("{{") && f.trim() !== "(none)") ??
|
|
167
168
|
task?.key_files ??
|
|
168
169
|
undefined,
|
|
169
170
|
issueNumber: ghIssueNumber,
|
|
@@ -381,6 +382,23 @@ export function buildStepCompleteMessage(nextState: import("./types.js").GSDStat
|
|
|
381
382
|
+ `Run /clear, then /gsd to continue (or /gsd auto to run continuously).`;
|
|
382
383
|
}
|
|
383
384
|
|
|
385
|
+
/**
|
|
386
|
+
* Decide whether step mode should stop at the step wizard after a unit finishes.
|
|
387
|
+
*
|
|
388
|
+
* @param currentUnitType The just-finished unit type, such as "execute-task" or
|
|
389
|
+
* "complete-milestone"; may be null/undefined when no current unit is known.
|
|
390
|
+
* @param phaseAfterUnit The freshly derived next phase, such as "executing" or
|
|
391
|
+
* "complete"; may be null/undefined if state derivation failed.
|
|
392
|
+
* @returns true to show the step wizard; false to keep the loop running so
|
|
393
|
+
* terminal milestone completion can reach the merge/finalization path.
|
|
394
|
+
*/
|
|
395
|
+
export function shouldReturnStepWizardAfterUnit(
|
|
396
|
+
currentUnitType: string | null | undefined,
|
|
397
|
+
phaseAfterUnit: string | null | undefined,
|
|
398
|
+
): boolean {
|
|
399
|
+
return currentUnitType !== "complete-milestone" && phaseAfterUnit !== "complete";
|
|
400
|
+
}
|
|
401
|
+
|
|
384
402
|
export interface PreVerificationOpts {
|
|
385
403
|
skipSettleDelay?: boolean;
|
|
386
404
|
skipWorktreeSync?: boolean;
|
|
@@ -413,6 +431,11 @@ function artifactValidationKind(unitType: string): "project" | "requirements" |
|
|
|
413
431
|
}
|
|
414
432
|
|
|
415
433
|
function describeArtifactVerificationFailure(unitType: string, unitId: string, basePath: string): string {
|
|
434
|
+
const worktreeFailure = diagnoseWorktreeIntegrityFailure(basePath);
|
|
435
|
+
if (worktreeFailure) {
|
|
436
|
+
return `${worktreeFailure} Unit: ${unitType} ${unitId}.`;
|
|
437
|
+
}
|
|
438
|
+
|
|
416
439
|
const artifactPath = resolveExpectedArtifactPath(unitType, unitId, basePath);
|
|
417
440
|
if (!artifactPath) {
|
|
418
441
|
return `Artifact verification failed: ${unitType} "${unitId}" has no resolvable artifact path.`;
|
|
@@ -469,9 +492,17 @@ export async function autoCommitUnit(
|
|
|
469
492
|
}
|
|
470
493
|
}
|
|
471
494
|
|
|
495
|
+
/**
|
|
496
|
+
* Execute the turn-level git action (commit, snapshot, or status-only).
|
|
497
|
+
*
|
|
498
|
+
* @param opts.softFailure - Defaults to false. When true, retry git failures,
|
|
499
|
+
* warn, and continue without pausing auto-mode; use for best-effort deferred
|
|
500
|
+
* closeout work where a git failure should not block the run.
|
|
501
|
+
*/
|
|
472
502
|
async function runCloseoutGitAction(
|
|
473
503
|
pctx: PostUnitContext,
|
|
474
504
|
unit: NonNullable<AutoSession["currentUnit"]>,
|
|
505
|
+
opts?: { softFailure?: boolean },
|
|
475
506
|
): Promise<"continue" | "dispatched"> {
|
|
476
507
|
const { s, ctx, pi, pauseAuto } = pctx;
|
|
477
508
|
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
@@ -506,13 +537,24 @@ async function runCloseoutGitAction(
|
|
|
506
537
|
unitId: unit.id,
|
|
507
538
|
});
|
|
508
539
|
} else {
|
|
509
|
-
const
|
|
540
|
+
const maxAttempts = opts?.softFailure ? 3 : 1;
|
|
541
|
+
let gitResult = runTurnGitAction({
|
|
510
542
|
basePath: s.basePath,
|
|
511
543
|
action: turnAction,
|
|
512
544
|
unitType: unit.type,
|
|
513
545
|
unitId: unit.id,
|
|
514
546
|
taskContext,
|
|
515
547
|
});
|
|
548
|
+
for (let attempt = 1; gitResult.status === "failed" && attempt < maxAttempts; attempt++) {
|
|
549
|
+
await new Promise((resolve) => setTimeout(resolve, 250 * attempt));
|
|
550
|
+
gitResult = runTurnGitAction({
|
|
551
|
+
basePath: s.basePath,
|
|
552
|
+
action: turnAction,
|
|
553
|
+
unitType: unit.type,
|
|
554
|
+
unitId: unit.id,
|
|
555
|
+
taskContext,
|
|
556
|
+
});
|
|
557
|
+
}
|
|
516
558
|
|
|
517
559
|
if (uokFlags.gitops) {
|
|
518
560
|
writeTurnGitTransaction({
|
|
@@ -563,12 +605,15 @@ async function runCloseoutGitAction(
|
|
|
563
605
|
}
|
|
564
606
|
|
|
565
607
|
const failureMsg = `Git ${turnAction} failed: ${(gitResult.error ?? "unknown error").split("\n")[0]}`;
|
|
566
|
-
ctx.ui.notify(failureMsg, "error");
|
|
608
|
+
ctx.ui.notify(failureMsg, opts?.softFailure ? "warning" : "error");
|
|
567
609
|
debugLog("postUnit", {
|
|
568
|
-
phase: "git-action-failed-blocking",
|
|
610
|
+
phase: opts?.softFailure ? "git-action-failed-soft" : "git-action-failed-blocking",
|
|
569
611
|
action: turnAction,
|
|
570
612
|
error: gitResult.error ?? "unknown error",
|
|
571
613
|
});
|
|
614
|
+
if (opts?.softFailure) {
|
|
615
|
+
return "continue";
|
|
616
|
+
}
|
|
572
617
|
await pauseAuto(ctx, pi);
|
|
573
618
|
return "dispatched";
|
|
574
619
|
}
|
|
@@ -586,7 +631,10 @@ async function runCloseoutGitAction(
|
|
|
586
631
|
s.lastGitActionFailure = message;
|
|
587
632
|
s.lastGitActionStatus = "failed";
|
|
588
633
|
debugLog("postUnit", { phase: "git-action", error: message, action: turnAction });
|
|
589
|
-
ctx.ui.notify(`Git ${turnAction} failed: ${message.split("\n")[0]}`,
|
|
634
|
+
ctx.ui.notify(`Git ${turnAction} failed: ${message.split("\n")[0]}`, opts?.softFailure ? "warning" : "error");
|
|
635
|
+
if (opts?.softFailure) {
|
|
636
|
+
return "continue";
|
|
637
|
+
}
|
|
590
638
|
if (uokFlags.gitops) {
|
|
591
639
|
await pauseAuto(ctx, pi);
|
|
592
640
|
return "dispatched";
|
|
@@ -1133,6 +1181,24 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
1133
1181
|
"warning",
|
|
1134
1182
|
);
|
|
1135
1183
|
// Fall through to "continue" — do NOT enter the retry or db-unavailable paths.
|
|
1184
|
+
} else if (!triggerArtifactVerified && diagnoseWorktreeIntegrityFailure(s.basePath)) {
|
|
1185
|
+
const retryKey = `${s.currentUnit.type}:${s.currentUnit.id}`;
|
|
1186
|
+
const worktreeFailure = diagnoseWorktreeIntegrityFailure(s.basePath)!;
|
|
1187
|
+
s.pendingVerificationRetry = null;
|
|
1188
|
+
s.verificationRetryCount.delete(retryKey);
|
|
1189
|
+
s.verificationRetryFailureHashes.delete(retryKey);
|
|
1190
|
+
debugLog("postUnit", {
|
|
1191
|
+
phase: "worktree-integrity-failure",
|
|
1192
|
+
unitType: s.currentUnit.type,
|
|
1193
|
+
unitId: s.currentUnit.id,
|
|
1194
|
+
basePath: s.basePath,
|
|
1195
|
+
});
|
|
1196
|
+
ctx.ui.notify(
|
|
1197
|
+
`${worktreeFailure} Retry ${s.currentUnit.id} after repair.`,
|
|
1198
|
+
"error",
|
|
1199
|
+
);
|
|
1200
|
+
await pauseAuto(ctx, pi);
|
|
1201
|
+
return "dispatched";
|
|
1136
1202
|
} else if (!triggerArtifactVerified && !isDbAvailable()) {
|
|
1137
1203
|
debugLog("postUnit", { phase: "artifact-verify-skip-db-unavailable", unitType: s.currentUnit.type, unitId: s.currentUnit.id });
|
|
1138
1204
|
const dbSkipDiag = diagnoseExpectedArtifact(s.currentUnit.type, s.currentUnit.id, s.basePath);
|
|
@@ -1220,7 +1286,7 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
1220
1286
|
|
|
1221
1287
|
if (s.currentUnit) {
|
|
1222
1288
|
if (shouldDeferCloseoutGitAction(s.currentUnit.type)) {
|
|
1223
|
-
const gitActionResult = await runCloseoutGitAction(pctx, s.currentUnit);
|
|
1289
|
+
const gitActionResult = await runCloseoutGitAction(pctx, s.currentUnit, { softFailure: true });
|
|
1224
1290
|
if (gitActionResult === "dispatched") {
|
|
1225
1291
|
return "stopped";
|
|
1226
1292
|
}
|
|
@@ -1668,14 +1734,18 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
1668
1734
|
// Without this notify(), /gsd in step mode finishes a unit and silently
|
|
1669
1735
|
// exits the loop, leaving the user with no hint to /clear and /gsd again.
|
|
1670
1736
|
if (s.stepMode) {
|
|
1737
|
+
let phaseAfterUnit: string | null = null;
|
|
1671
1738
|
try {
|
|
1672
1739
|
const nextState = await deriveState(s.canonicalProjectRoot);
|
|
1740
|
+
phaseAfterUnit = nextState.phase;
|
|
1673
1741
|
ctx.ui.notify(buildStepCompleteMessage(nextState), "info");
|
|
1674
1742
|
} catch (e) {
|
|
1675
1743
|
debugLog("postUnit", { phase: "step-wizard-notify", error: String(e) });
|
|
1676
1744
|
ctx.ui.notify(STEP_COMPLETE_FALLBACK_MESSAGE, "info");
|
|
1677
1745
|
}
|
|
1678
|
-
return
|
|
1746
|
+
return shouldReturnStepWizardAfterUnit(s.currentUnit?.type, phaseAfterUnit)
|
|
1747
|
+
? "step-wizard"
|
|
1748
|
+
: "continue";
|
|
1679
1749
|
}
|
|
1680
1750
|
|
|
1681
1751
|
return "continue";
|
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
|
|
47
47
|
import { validateArtifact } from "./schemas/validate.js";
|
|
48
48
|
import { getProjectResearchStatus } from "./project-research-policy.js";
|
|
49
|
+
import { isGsdWorktreePath } from "./worktree-root.js";
|
|
49
50
|
|
|
50
51
|
// Re-export so existing consumers of auto-recovery.ts keep working.
|
|
51
52
|
export { resolveExpectedArtifactPath, diagnoseExpectedArtifact };
|
|
@@ -56,6 +57,29 @@ export {
|
|
|
56
57
|
|
|
57
58
|
// ─── Artifact Resolution & Verification ───────────────────────────────────────
|
|
58
59
|
|
|
60
|
+
export function diagnoseWorktreeIntegrityFailure(basePath: string): string | null {
|
|
61
|
+
if (!isGsdWorktreePath(basePath)) return null;
|
|
62
|
+
if (!existsSync(basePath)) {
|
|
63
|
+
return `Worktree integrity failure: ${basePath} does not exist. Repair or recreate the worktree before retrying.`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const gitPath = join(basePath, ".git");
|
|
67
|
+
if (!existsSync(gitPath)) {
|
|
68
|
+
return `Worktree integrity failure: ${basePath} is not a valid git worktree (.git missing). Repair or recreate the worktree before retrying.`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
execFileSync("git", ["rev-parse", "--git-dir"], {
|
|
73
|
+
cwd: basePath,
|
|
74
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
75
|
+
encoding: "utf-8",
|
|
76
|
+
});
|
|
77
|
+
return null;
|
|
78
|
+
} catch (err) {
|
|
79
|
+
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.`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
59
83
|
export type ArtifactRecoveryDbRefreshResult =
|
|
60
84
|
| { ok: true }
|
|
61
85
|
| { ok: false; fatal: boolean; message: string; reason: string };
|
|
@@ -752,6 +776,11 @@ export function verifyExpectedArtifact(
|
|
|
752
776
|
return false;
|
|
753
777
|
}
|
|
754
778
|
if (!existsSync(absPath)) {
|
|
779
|
+
const worktreeFailure = diagnoseWorktreeIntegrityFailure(base);
|
|
780
|
+
if (worktreeFailure) {
|
|
781
|
+
logError("recovery", `${worktreeFailure} Unit: ${unitType} ${unitId}.`);
|
|
782
|
+
return false;
|
|
783
|
+
}
|
|
755
784
|
logWarning("recovery", `verify-fail ${unitType} ${unitId}: existsSync false for ${absPath}`);
|
|
756
785
|
return false;
|
|
757
786
|
}
|