gsd-pi 2.82.0-dev.2841a1e44 → 2.82.0-dev.3a3c6509d
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 +3 -3
- 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/claude-code-cli/stream-adapter.js +1 -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 +81 -31
- package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +1 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +20 -19
- package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +71 -10
- package/dist/resources/extensions/gsd/auto-recovery.js +71 -14
- package/dist/resources/extensions/gsd/auto-start.js +87 -14
- package/dist/resources/extensions/gsd/auto-verification.js +17 -4
- package/dist/resources/extensions/gsd/auto-worktree.js +176 -10
- package/dist/resources/extensions/gsd/auto.js +37 -5
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +31 -7
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -9
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +4 -2
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +5 -2
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +14 -2
- package/dist/resources/extensions/gsd/commands/handlers/core.js +17 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +7 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +43 -5
- package/dist/resources/extensions/gsd/db/milestone-leases.js +24 -0
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
- package/dist/resources/extensions/gsd/doctor-git-checks.js +46 -1
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
- package/dist/resources/extensions/gsd/doctor.js +2 -28
- package/dist/resources/extensions/gsd/export-html.js +27 -425
- package/dist/resources/extensions/gsd/forensics.js +3 -3
- package/dist/resources/extensions/gsd/git-service.js +45 -3
- package/dist/resources/extensions/gsd/gsd-db.js +21 -6
- package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -3
- package/dist/resources/extensions/gsd/guided-flow.js +101 -116
- package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
- package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
- package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
- package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
- package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
- package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
- package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
- package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
- package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/queue-reorder-ui.js +30 -13
- package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
- package/dist/resources/extensions/gsd/state.js +1 -1
- package/dist/resources/extensions/gsd/status-guards.js +11 -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-mcp.js +17 -1
- package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +33 -8
- package/dist/resources/extensions/gsd/worktree-manager.js +1 -1
- 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 +11 -11
- 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/browse-directories/route.js +1 -1
- 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 +11 -11
- 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/google-gemini-cli.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.js +5 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.js +41 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.js.map +1 -0
- 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/google-gemini-cli.test.ts +49 -0
- package/packages/pi-ai/src/providers/google-gemini-cli.ts +7 -0
- package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
- package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
- package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
- package/packages/pi-ai/src/providers/simple-options.ts +5 -6
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +44 -3
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +71 -97
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +12 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +19 -8
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +53 -3
- package/packages/pi-coding-agent/src/core/sdk.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +75 -102
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +14 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +23 -8
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/terminal.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.js +103 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.js.map +1 -0
- package/packages/pi-tui/dist/terminal.d.ts +2 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +12 -0
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
- package/packages/pi-tui/src/terminal.ts +11 -0
- package/packages/pi-tui/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/stream-adapter.ts +1 -1
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +9 -0
- 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 +90 -38
- package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +21 -19
- package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +78 -8
- package/src/resources/extensions/gsd/auto-recovery.ts +74 -11
- package/src/resources/extensions/gsd/auto-start.ts +94 -12
- package/src/resources/extensions/gsd/auto-verification.ts +22 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +193 -10
- package/src/resources/extensions/gsd/auto.ts +40 -5
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +42 -7
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +10 -9
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +4 -2
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +3 -1
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +17 -2
- package/src/resources/extensions/gsd/commands/handlers/core.ts +17 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +8 -3
- package/src/resources/extensions/gsd/crash-recovery.ts +44 -4
- package/src/resources/extensions/gsd/db/milestone-leases.ts +26 -0
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
- package/src/resources/extensions/gsd/doctor-git-checks.ts +45 -1
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
- package/src/resources/extensions/gsd/doctor-types.ts +1 -0
- package/src/resources/extensions/gsd/doctor.ts +2 -27
- package/src/resources/extensions/gsd/export-html.ts +27 -427
- package/src/resources/extensions/gsd/forensics.ts +3 -3
- package/src/resources/extensions/gsd/git-service.ts +51 -4
- package/src/resources/extensions/gsd/gsd-db.ts +21 -6
- package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -3
- package/src/resources/extensions/gsd/guided-flow.ts +134 -133
- package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
- package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
- package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
- package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
- package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
- package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
- package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/src/resources/extensions/gsd/prompts/queue.md +4 -4
- package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/queue-reorder-ui.ts +31 -13
- package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
- package/src/resources/extensions/gsd/state.ts +1 -1
- package/src/resources/extensions/gsd/status-guards.ts +13 -0
- package/src/resources/extensions/gsd/templates/plan.md +8 -5
- package/src/resources/extensions/gsd/templates/task-plan.md +4 -2
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +56 -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 +35 -7
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +12 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +91 -6
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
- package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +11 -2
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +86 -2
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
- 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 +66 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
- package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +112 -1
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
- package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +2 -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/prefs-wizard-coverage.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +37 -1
- package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +89 -2
- package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +2 -3
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -2
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
- package/src/resources/extensions/gsd/tests/status-guards.test.ts +13 -1
- 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 +82 -7
- package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +29 -2
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +19 -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-mcp.ts +18 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +41 -8
- package/src/resources/extensions/gsd/worktree-manager.ts +1 -1
- 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 → O6femb9LLl3nlgsDaYwS-}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Qgr2B_MRhPxC0z8fwv4vT → O6femb9LLl3nlgsDaYwS-}/_ssgManifest.js +0 -0
|
@@ -77,6 +77,7 @@ import { resolveManifest } from "../unit-context-manifest.js";
|
|
|
77
77
|
import { createWorktreeSafetyModule, type WorktreeSafetyResult } from "../worktree-safety.js";
|
|
78
78
|
import { isSuspiciousGhostCompletion } from "../auto-unit-closeout.js";
|
|
79
79
|
import { decideVerificationRetry, verificationRetryKey } from "./verification-retry-policy.js";
|
|
80
|
+
import { buildPhaseHandoffOutcome, setAutoOutcomeWidget } from "../auto-dashboard.js";
|
|
80
81
|
|
|
81
82
|
// ─── Path Comparison Helper ───────────────────────────────────────────────
|
|
82
83
|
/** Compare two paths for physical identity, tolerating trailing slashes and symlinks. */
|
|
@@ -155,6 +156,13 @@ function formatWorktreeSafetyFailure(result: Extract<WorktreeSafetyResult, { ok:
|
|
|
155
156
|
return `Worktree Safety failed (${result.kind}): ${result.reason} ${result.remediation}`;
|
|
156
157
|
}
|
|
157
158
|
|
|
159
|
+
function formatWorktreeSafetyStopReason(result: Extract<WorktreeSafetyResult, { ok: false }>): string {
|
|
160
|
+
if (result.kind === "empty-worktree-with-project-content") {
|
|
161
|
+
return `Worktree Safety failed (${result.kind}). Run /gsd doctor fix, then /gsd auto.`;
|
|
162
|
+
}
|
|
163
|
+
return `Worktree Safety failed (${result.kind}).`;
|
|
164
|
+
}
|
|
165
|
+
|
|
158
166
|
function resolveEmptyWorktreeWithProjectContent(
|
|
159
167
|
unitRoot: string,
|
|
160
168
|
projectRoot: string,
|
|
@@ -237,7 +245,7 @@ async function validateSourceWriteWorktreeSafety(
|
|
|
237
245
|
projectRoot,
|
|
238
246
|
});
|
|
239
247
|
ctx.ui.notify(msg, "error");
|
|
240
|
-
await deps.stopAuto(ctx, pi,
|
|
248
|
+
await deps.stopAuto(ctx, pi, formatWorktreeSafetyStopReason(result));
|
|
241
249
|
return { action: "break", reason: result.kind };
|
|
242
250
|
}
|
|
243
251
|
|
|
@@ -1327,9 +1335,15 @@ export async function runDispatch(
|
|
|
1327
1335
|
}
|
|
1328
1336
|
|
|
1329
1337
|
const guardBasePath = _resolveDispatchGuardBasePath(s);
|
|
1338
|
+
let mainBranch = "main";
|
|
1339
|
+
try {
|
|
1340
|
+
mainBranch = deps.getMainBranch(guardBasePath);
|
|
1341
|
+
} catch (err) {
|
|
1342
|
+
debugLog("autoLoop", { phase: "getMainBranch-failed", error: String(err) });
|
|
1343
|
+
}
|
|
1330
1344
|
const priorSliceBlocker = deps.getPriorSliceCompletionBlocker(
|
|
1331
1345
|
guardBasePath,
|
|
1332
|
-
|
|
1346
|
+
mainBranch,
|
|
1333
1347
|
unitType,
|
|
1334
1348
|
unitId,
|
|
1335
1349
|
);
|
|
@@ -1796,42 +1810,8 @@ export async function runUnitPhase(
|
|
|
1796
1810
|
s.currentUnit.id === unitId
|
|
1797
1811
|
);
|
|
1798
1812
|
const previousTier = s.currentUnitRouting?.tier;
|
|
1799
|
-
|
|
1800
|
-
// Scope workflow-logger buffer to this unit so post-finalize drains are
|
|
1801
|
-
// per-unit. Without this, the module-level _buffer accumulates across every
|
|
1802
|
-
// unit in the same Node process (see workflow-logger.ts module header).
|
|
1803
|
-
_resetLogs();
|
|
1804
1813
|
const dispatchKey = `${unitType}/${unitId}`;
|
|
1805
|
-
|
|
1806
|
-
s.currentUnit = { type: unitType, id: unitId, startedAt: Date.now() };
|
|
1807
|
-
s.lastGitActionFailure = null;
|
|
1808
|
-
s.lastGitActionStatus = null;
|
|
1809
|
-
s.lastUnitAgentEndMessages = null;
|
|
1810
|
-
setCurrentPhase(unitType, {
|
|
1811
|
-
basePath: s.basePath,
|
|
1812
|
-
traceId: ic.flowId,
|
|
1813
|
-
turnId: `iter-${ic.iteration}`,
|
|
1814
|
-
causedBy: "unit-start",
|
|
1815
|
-
});
|
|
1816
|
-
s.lastToolInvocationError = null; // #2883: clear stale error from previous unit
|
|
1817
|
-
const unitStartSeq = ic.nextSeq();
|
|
1818
|
-
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: unitStartSeq, eventType: "unit-start", data: { unitType, unitId } });
|
|
1819
|
-
deps.captureAvailableSkills();
|
|
1820
|
-
writeUnitRuntimeRecord(
|
|
1821
|
-
s.basePath,
|
|
1822
|
-
unitType,
|
|
1823
|
-
unitId,
|
|
1824
|
-
s.currentUnit.startedAt,
|
|
1825
|
-
{
|
|
1826
|
-
phase: "dispatched",
|
|
1827
|
-
wrapupWarningSent: false,
|
|
1828
|
-
timeoutAt: null,
|
|
1829
|
-
lastProgressAt: s.currentUnit.startedAt,
|
|
1830
|
-
progressCount: 0,
|
|
1831
|
-
lastProgressKind: "dispatch",
|
|
1832
|
-
recoveryAttempts: 0, // Reset so re-dispatched units get full recovery budget (#2322)
|
|
1833
|
-
},
|
|
1834
|
-
);
|
|
1814
|
+
const nextDispatchCount = (s.unitDispatchCount.get(dispatchKey) ?? 0) + 1;
|
|
1835
1815
|
|
|
1836
1816
|
// Status bar (widget + preconditions deferred until after model selection — see #2899)
|
|
1837
1817
|
ctx.ui.setStatus("gsd-auto", "auto");
|
|
@@ -1894,7 +1874,7 @@ export async function runUnitPhase(
|
|
|
1894
1874
|
: s.pendingCrashRecovery;
|
|
1895
1875
|
finalPrompt = `${capped}\n\n---\n\n${finalPrompt}`;
|
|
1896
1876
|
s.pendingCrashRecovery = null;
|
|
1897
|
-
} else if (
|
|
1877
|
+
} else if (nextDispatchCount > 1) {
|
|
1898
1878
|
const diagnostic = deps.getDeepDiagnostic(s.basePath);
|
|
1899
1879
|
if (diagnostic) {
|
|
1900
1880
|
const cappedDiag =
|
|
@@ -1937,6 +1917,11 @@ export async function runUnitPhase(
|
|
|
1937
1917
|
}
|
|
1938
1918
|
|
|
1939
1919
|
// Select and apply model (with tier escalation on retry — normal units only)
|
|
1920
|
+
const prevUnitRouting = s.currentUnitRouting;
|
|
1921
|
+
const prevUnitModel = s.currentUnitModel;
|
|
1922
|
+
const prevDispatchedModelId = s.currentDispatchedModelId;
|
|
1923
|
+
const prevSessionModel = ctx.model;
|
|
1924
|
+
const prevSessionThinkingLevel = pi.getThinkingLevel();
|
|
1940
1925
|
const modelResult = await deps.selectAndApplyModel(
|
|
1941
1926
|
ctx,
|
|
1942
1927
|
pi,
|
|
@@ -2003,14 +1988,67 @@ export async function runUnitPhase(
|
|
|
2003
1988
|
? ctx.modelRegistry.getProviderAuthMode(ctx.model.provider)
|
|
2004
1989
|
: undefined,
|
|
2005
1990
|
baseUrl: (s.currentUnitModel as any)?.baseUrl ?? ctx.model?.baseUrl,
|
|
1991
|
+
activeTools: typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [],
|
|
2006
1992
|
},
|
|
2007
1993
|
);
|
|
2008
1994
|
if (compatibilityError) {
|
|
1995
|
+
s.currentUnitRouting = prevUnitRouting;
|
|
1996
|
+
s.currentUnitModel = prevUnitModel;
|
|
1997
|
+
s.currentDispatchedModelId = prevDispatchedModelId;
|
|
1998
|
+
if (s.checkpointSha) {
|
|
1999
|
+
cleanupCheckpoint(s.basePath, unitId);
|
|
2000
|
+
s.checkpointSha = null;
|
|
2001
|
+
}
|
|
2002
|
+
if (prevSessionModel) {
|
|
2003
|
+
const ok = await pi.setModel(prevSessionModel, { persist: false });
|
|
2004
|
+
if (!ok) {
|
|
2005
|
+
ctx.ui.notify("Failed to restore previous session model after compatibility check failure.", "warning");
|
|
2006
|
+
}
|
|
2007
|
+
if (prevSessionThinkingLevel) {
|
|
2008
|
+
pi.setThinkingLevel(prevSessionThinkingLevel);
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2009
2011
|
ctx.ui.notify(compatibilityError, "error");
|
|
2010
2012
|
await deps.stopAuto(ctx, pi, compatibilityError);
|
|
2011
2013
|
return { action: "break", reason: "workflow-capability" };
|
|
2012
2014
|
}
|
|
2013
2015
|
|
|
2016
|
+
// Scope workflow-logger buffer to this unit so post-finalize drains are
|
|
2017
|
+
// per-unit. Without this, the module-level _buffer accumulates across every
|
|
2018
|
+
// unit in the same Node process (see workflow-logger.ts module header).
|
|
2019
|
+
_resetLogs();
|
|
2020
|
+
const unitStartedAt = Date.now();
|
|
2021
|
+
s.unitDispatchCount.set(dispatchKey, nextDispatchCount);
|
|
2022
|
+
s.currentUnit = { type: unitType, id: unitId, startedAt: unitStartedAt };
|
|
2023
|
+
s.lastGitActionFailure = null;
|
|
2024
|
+
s.lastGitActionStatus = null;
|
|
2025
|
+
s.lastUnitAgentEndMessages = null;
|
|
2026
|
+
setCurrentPhase(unitType, {
|
|
2027
|
+
basePath: s.basePath,
|
|
2028
|
+
traceId: ic.flowId,
|
|
2029
|
+
turnId: `iter-${ic.iteration}`,
|
|
2030
|
+
causedBy: "unit-start",
|
|
2031
|
+
});
|
|
2032
|
+
s.lastToolInvocationError = null; // #2883: clear stale error from previous unit
|
|
2033
|
+
const unitStartSeq = ic.nextSeq();
|
|
2034
|
+
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: unitStartSeq, eventType: "unit-start", data: { unitType, unitId } });
|
|
2035
|
+
deps.captureAvailableSkills();
|
|
2036
|
+
writeUnitRuntimeRecord(
|
|
2037
|
+
s.basePath,
|
|
2038
|
+
unitType,
|
|
2039
|
+
unitId,
|
|
2040
|
+
unitStartedAt,
|
|
2041
|
+
{
|
|
2042
|
+
phase: "dispatched",
|
|
2043
|
+
wrapupWarningSent: false,
|
|
2044
|
+
timeoutAt: null,
|
|
2045
|
+
lastProgressAt: unitStartedAt,
|
|
2046
|
+
progressCount: 0,
|
|
2047
|
+
lastProgressKind: "dispatch",
|
|
2048
|
+
recoveryAttempts: 0, // Reset so re-dispatched units get full recovery budget (#2322)
|
|
2049
|
+
},
|
|
2050
|
+
);
|
|
2051
|
+
|
|
2014
2052
|
// Progress widget + preconditions — deferred to after model selection so the
|
|
2015
2053
|
// widget's first render tick shows the correct model (#2899).
|
|
2016
2054
|
deps.updateProgressWidget(ctx, unitType, unitId, state);
|
|
@@ -2596,6 +2634,20 @@ export async function runFinalize(
|
|
|
2596
2634
|
lastProgressAt: Date.now(),
|
|
2597
2635
|
lastProgressKind: "finalize-success",
|
|
2598
2636
|
});
|
|
2637
|
+
if (
|
|
2638
|
+
!preUnitSnapshot.type.startsWith("hook/") &&
|
|
2639
|
+
preUnitSnapshot.type !== "custom-step" &&
|
|
2640
|
+
preUnitSnapshot.type !== "complete-milestone"
|
|
2641
|
+
) {
|
|
2642
|
+
setAutoOutcomeWidget(ctx, {
|
|
2643
|
+
...buildPhaseHandoffOutcome({
|
|
2644
|
+
unitType: preUnitSnapshot.type,
|
|
2645
|
+
unitId: preUnitSnapshot.id,
|
|
2646
|
+
agentEndMessages: s.lastUnitAgentEndMessages,
|
|
2647
|
+
}),
|
|
2648
|
+
startedAt: s.autoStartTime,
|
|
2649
|
+
});
|
|
2650
|
+
}
|
|
2599
2651
|
}
|
|
2600
2652
|
s.currentUnit = null;
|
|
2601
2653
|
clearCurrentPhase();
|
|
@@ -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 };
|
|
@@ -120,6 +120,26 @@ export interface AutoOutcomeSurfaceSnapshot {
|
|
|
120
120
|
startedAt?: number;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
export function buildPhaseHandoffOutcome(input: {
|
|
124
|
+
unitType: string;
|
|
125
|
+
unitId: string;
|
|
126
|
+
agentEndMessages?: unknown[] | null;
|
|
127
|
+
}): AutoOutcomeSurfaceSnapshot {
|
|
128
|
+
const phase = unitPhaseLabel(input.unitType);
|
|
129
|
+
const detail =
|
|
130
|
+
extractLastAssistantSummary(input.agentEndMessages) ??
|
|
131
|
+
`Completed ${unitVerb(input.unitType)} ${input.unitId}.`;
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
status: "complete",
|
|
135
|
+
title: `${phase} complete`,
|
|
136
|
+
detail,
|
|
137
|
+
unitLabel: `${unitVerb(input.unitType)} ${input.unitId}`,
|
|
138
|
+
nextAction: "Preparing the next phase. Review this handoff while the next session starts.",
|
|
139
|
+
commands: ["/gsd status for overview", "/gsd visualize to inspect", "/gsd notifications for history"],
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
123
143
|
// ─── Unit Description Helpers ─────────────────────────────────────────────────
|
|
124
144
|
|
|
125
145
|
export function unitVerb(unitType: string): string {
|
|
@@ -631,7 +651,6 @@ export function updateProgressWidget(
|
|
|
631
651
|
tierBadge?: string,
|
|
632
652
|
): void {
|
|
633
653
|
if (!ctx.hasUI) return;
|
|
634
|
-
ctx.ui.setWidget("gsd-outcome", undefined);
|
|
635
654
|
|
|
636
655
|
// Welcome header is a startup-only banner — permanently suppress it once
|
|
637
656
|
// auto-mode activates. The dashboard widget owns all status from here.
|
|
@@ -1145,3 +1164,55 @@ function normalizeRollupText(value: string | null | undefined): string | null {
|
|
|
1145
1164
|
if (!clean || clean === "(none)" || clean === "None." || clean === "Not provided.") return null;
|
|
1146
1165
|
return clean;
|
|
1147
1166
|
}
|
|
1167
|
+
|
|
1168
|
+
function isAssistantMessage(value: unknown): boolean {
|
|
1169
|
+
if (!value || typeof value !== "object") return false;
|
|
1170
|
+
const record = value as Record<string, unknown>;
|
|
1171
|
+
if (record.role === "assistant") return true;
|
|
1172
|
+
|
|
1173
|
+
const message = record.message;
|
|
1174
|
+
if (message && typeof message === "object") {
|
|
1175
|
+
return (message as Record<string, unknown>).role === "assistant";
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
return false;
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
function extractLastAssistantSummary(messages: unknown[] | null | undefined): string | null {
|
|
1182
|
+
if (!messages || messages.length === 0) return null;
|
|
1183
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1184
|
+
if (!isAssistantMessage(messages[i])) continue;
|
|
1185
|
+
const text = extractMessageText(messages[i]);
|
|
1186
|
+
const clean = normalizeRollupText(text);
|
|
1187
|
+
if (clean) return truncateToWidth(clean, 220, "…");
|
|
1188
|
+
}
|
|
1189
|
+
return null;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
function extractMessageText(value: unknown): string | null {
|
|
1193
|
+
if (typeof value === "string") return value;
|
|
1194
|
+
if (!value || typeof value !== "object") return null;
|
|
1195
|
+
|
|
1196
|
+
const record = value as Record<string, unknown>;
|
|
1197
|
+
if (typeof record.content === "string") return record.content;
|
|
1198
|
+
|
|
1199
|
+
const message = record.message;
|
|
1200
|
+
if (message && typeof message === "object") {
|
|
1201
|
+
return extractMessageText(message);
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
const content = record.content;
|
|
1205
|
+
if (Array.isArray(content)) {
|
|
1206
|
+
const parts = content
|
|
1207
|
+
.map((part) => {
|
|
1208
|
+
if (typeof part === "string") return part;
|
|
1209
|
+
if (!part || typeof part !== "object") return "";
|
|
1210
|
+
const partRecord = part as Record<string, unknown>;
|
|
1211
|
+
return typeof partRecord.text === "string" ? partRecord.text : "";
|
|
1212
|
+
})
|
|
1213
|
+
.filter(Boolean);
|
|
1214
|
+
return parts.length > 0 ? parts.join(" ") : null;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
return null;
|
|
1218
|
+
}
|
|
@@ -280,6 +280,7 @@ export async function dispatchDirectPhase(
|
|
|
280
280
|
unitType,
|
|
281
281
|
authMode: ctx.model?.provider ? ctx.modelRegistry.getProviderAuthMode(ctx.model.provider) : undefined,
|
|
282
282
|
baseUrl: ctx.model?.baseUrl,
|
|
283
|
+
activeTools: typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [],
|
|
283
284
|
},
|
|
284
285
|
);
|
|
285
286
|
if (compatibilityError) {
|
|
@@ -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;
|
|
@@ -450,9 +457,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
450
457
|
const attempts = incrementUatCount(basePath, mid, sliceId);
|
|
451
458
|
if (attempts > MAX_UAT_ATTEMPTS) {
|
|
452
459
|
return {
|
|
453
|
-
action: "
|
|
454
|
-
reason: `run-uat for ${mid}/${sliceId} has been dispatched ${attempts - 1} times without producing a verdict. Verification commands may be broken — fix the UAT spec or manually write an ASSESSMENT verdict.`,
|
|
455
|
-
level: "warning" as const,
|
|
460
|
+
action: "skip" as const,
|
|
456
461
|
};
|
|
457
462
|
}
|
|
458
463
|
const uatFile = resolveSliceFile(basePath, mid, sliceId, "UAT")!;
|
|
@@ -709,6 +714,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
709
714
|
name: "pre-planning (no context) → discuss-milestone",
|
|
710
715
|
match: async ({ state, mid, midTitle, basePath, prefs, structuredQuestionsAvailable }) => {
|
|
711
716
|
if (state.phase !== "pre-planning") return null;
|
|
717
|
+
if (isRegistryMilestoneComplete(state, mid)) return null;
|
|
712
718
|
const contextFile = resolveMilestoneFile(basePath, mid, "CONTEXT");
|
|
713
719
|
const hasContext = !!(contextFile && (await loadFile(contextFile)));
|
|
714
720
|
if (hasContext) return null; // fall through to next rule
|
|
@@ -760,7 +766,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
760
766
|
},
|
|
761
767
|
},
|
|
762
768
|
{
|
|
763
|
-
name: "planning (require_slice_discussion) → pause for discussion
|
|
769
|
+
name: "planning (require_slice_discussion) → pause for discussion",
|
|
764
770
|
match: async ({ state, mid, basePath, prefs }) => {
|
|
765
771
|
if (state.phase !== "planning") return null;
|
|
766
772
|
if (!prefs?.phases?.require_slice_discussion) return null;
|
|
@@ -1240,7 +1246,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1240
1246
|
buildMilestoneFileName(mid, "VALIDATION"),
|
|
1241
1247
|
);
|
|
1242
1248
|
const skipSource = trivialVariant
|
|
1243
|
-
? "trivial-scope pipeline variant
|
|
1249
|
+
? "trivial-scope pipeline variant"
|
|
1244
1250
|
: "`skip_milestone_validation` preference";
|
|
1245
1251
|
const skipValidationReason = trivialVariant ? "trivial-scope" : "preference";
|
|
1246
1252
|
const content = [
|
|
@@ -1322,19 +1328,19 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1322
1328
|
}
|
|
1323
1329
|
}
|
|
1324
1330
|
|
|
1325
|
-
// Safety guard (#2675): block completion when VALIDATION
|
|
1326
|
-
//
|
|
1327
|
-
// terminal
|
|
1328
|
-
//
|
|
1331
|
+
// Safety guard (#2675, #5747, #5920): block completion when VALIDATION
|
|
1332
|
+
// verdict is anything other than pass. The state machine treats these
|
|
1333
|
+
// verdicts as terminal, but completing-milestone should NOT proceed —
|
|
1334
|
+
// remediation or human attention is needed.
|
|
1329
1335
|
const validationFile = resolveMilestoneFile(basePath, mid, "VALIDATION");
|
|
1330
1336
|
if (validationFile) {
|
|
1331
1337
|
const validationContent = await loadFile(validationFile);
|
|
1332
1338
|
if (validationContent) {
|
|
1333
1339
|
const verdict = extractVerdict(validationContent);
|
|
1334
|
-
if (verdict
|
|
1340
|
+
if (verdict !== "pass") {
|
|
1335
1341
|
return {
|
|
1336
1342
|
action: "stop",
|
|
1337
|
-
reason: `Cannot complete milestone ${mid}: VALIDATION verdict is "
|
|
1343
|
+
reason: `Cannot complete milestone ${mid}: VALIDATION verdict is "${verdict}". Address the validation findings and re-run validation, or update the verdict manually.`,
|
|
1338
1344
|
level: "warning",
|
|
1339
1345
|
};
|
|
1340
1346
|
}
|
|
@@ -1351,16 +1357,12 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1351
1357
|
};
|
|
1352
1358
|
}
|
|
1353
1359
|
|
|
1354
|
-
// Safety
|
|
1355
|
-
// artifacts
|
|
1356
|
-
//
|
|
1360
|
+
// Safety signal (#1703, #5097): detect milestones with only .gsd/
|
|
1361
|
+
// artifacts. This no longer hard-blocks completion because some
|
|
1362
|
+
// milestones are intentionally planning/documentation-only.
|
|
1357
1363
|
const artifactCheck = hasImplementationArtifacts(basePath, mid);
|
|
1358
1364
|
if (artifactCheck === "absent") {
|
|
1359
|
-
|
|
1360
|
-
action: "stop",
|
|
1361
|
-
reason: `Cannot complete milestone ${mid}: no implementation files found outside .gsd/. The milestone has only plan files — actual code changes are required.`,
|
|
1362
|
-
level: "error",
|
|
1363
|
-
};
|
|
1365
|
+
logWarning("dispatch", `Milestone ${mid} has no implementation files outside .gsd/ — continuing complete-milestone dispatch (planning-only/documentation-only milestone).`);
|
|
1364
1366
|
}
|
|
1365
1367
|
if (artifactCheck === "unknown") {
|
|
1366
1368
|
logWarning("dispatch", `Implementation artifact check inconclusive for ${mid} — proceeding (git context unavailable)`);
|
|
@@ -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";
|
|
@@ -1129,10 +1177,28 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
1129
1177
|
s.verificationRetryFailureHashes.delete(retryKey);
|
|
1130
1178
|
writeBlockerPlaceholder(s.currentUnit.type, s.currentUnit.id, s.basePath, reason);
|
|
1131
1179
|
ctx.ui.notify(
|
|
1132
|
-
`${s.currentUnit.type} ${s.currentUnit.id} — deterministic policy rejection, wrote blocker placeholder (no retries)
|
|
1180
|
+
`${s.currentUnit.type} ${s.currentUnit.id} — deterministic policy rejection, wrote blocker placeholder (no retries)`,
|
|
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";
|