gsd-pi 2.82.0-dev.725028083 → 2.82.0-dev.98ea09b1e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +10 -1
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
- package/dist/resources/extensions/cmux/index.js +5 -0
- package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
- package/dist/resources/extensions/gsd/auto/loop.js +5 -5
- package/dist/resources/extensions/gsd/auto/orchestrator.js +124 -6
- package/dist/resources/extensions/gsd/auto/phases.js +8 -1
- package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +13 -6
- package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +233 -127
- package/dist/resources/extensions/gsd/auto-prompts.js +2 -2
- package/dist/resources/extensions/gsd/auto-recovery.js +31 -1
- package/dist/resources/extensions/gsd/auto-start.js +85 -12
- package/dist/resources/extensions/gsd/auto-verification.js +28 -22
- package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
- package/dist/resources/extensions/gsd/auto.js +158 -55
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +4 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +9 -8
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -2
- package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
- package/dist/resources/extensions/gsd/commands/catalog.js +4 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +37 -0
- package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
- package/dist/resources/extensions/gsd/crash-recovery.js +31 -5
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
- package/dist/resources/extensions/gsd/doctor.js +2 -28
- package/dist/resources/extensions/gsd/export-html.js +27 -425
- package/dist/resources/extensions/gsd/git-service.js +39 -1
- package/dist/resources/extensions/gsd/gsd-db.js +1 -0
- package/dist/resources/extensions/gsd/guided-flow.js +13 -6
- package/dist/resources/extensions/gsd/md-importer.js +1 -1
- package/dist/resources/extensions/gsd/migrate/command.js +5 -0
- package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
- package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
- package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
- package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
- package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
- package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
- package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
- package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
- package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
- package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
- package/dist/resources/extensions/gsd/status-guards.js +4 -0
- package/dist/resources/extensions/gsd/templates/plan.md +8 -5
- package/dist/resources/extensions/gsd/templates/task-plan.md +4 -2
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
- package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
- package/dist/resources/extensions/gsd/tools/plan-slice.js +89 -14
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
- package/dist/resources/extensions/gsd/validation.js +23 -1
- package/dist/resources/extensions/gsd/verification-gate.js +68 -7
- package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
- package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
- package/dist/resources/extensions/shared/html-shell.js +388 -0
- package/dist/resources/extensions/subagent/index.js +448 -78
- package/dist/resources/extensions/subagent/launch.js +77 -0
- package/dist/resources/extensions/subagent/run-store.js +148 -0
- package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
- package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/dist/resources/extensions/visual-brief/index.js +5 -0
- package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
- package/dist/resources/extensions/visual-brief/prompts.js +140 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -7
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
- package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
- package/dist/web/standalone/.next/static/chunks/{8359.e059d86b255fce1c.js → 8359.7eb3bb8f8ecf4c01.js} +2 -2
- package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-9a4db269f9ed63ad.js} +1 -1
- package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
- package/package.json +4 -4
- package/packages/contracts/dist/rpc.test.js +7 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +21 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +24 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/src/rpc.test.ts +8 -0
- package/packages/contracts/src/workflow.ts +24 -0
- package/packages/mcp-server/README.md +13 -4
- package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +80 -0
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
- package/packages/mcp-server/src/workflow-tools.ts +168 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/tsconfig.json +2 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +5 -6
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
- package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
- package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
- package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
- package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
- package/packages/pi-ai/src/providers/simple-options.ts +5 -6
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +5 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/tui.ts +6 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/src/resources/GSD-WORKFLOW.md +10 -1
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
- package/src/resources/extensions/cmux/index.ts +6 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +59 -16
- package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
- package/src/resources/extensions/gsd/auto/loop.ts +8 -5
- package/src/resources/extensions/gsd/auto/orchestrator.ts +129 -6
- package/src/resources/extensions/gsd/auto/phases.ts +7 -1
- package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +14 -6
- package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +266 -139
- package/src/resources/extensions/gsd/auto-prompts.ts +2 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +29 -0
- package/src/resources/extensions/gsd/auto-start.ts +92 -9
- package/src/resources/extensions/gsd/auto-verification.ts +36 -34
- package/src/resources/extensions/gsd/auto-worktree.ts +119 -1
- package/src/resources/extensions/gsd/auto.ts +167 -53
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +6 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +9 -8
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -3
- package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
- package/src/resources/extensions/gsd/commands/catalog.ts +4 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +40 -0
- package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
- package/src/resources/extensions/gsd/crash-recovery.ts +30 -4
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
- package/src/resources/extensions/gsd/doctor.ts +2 -27
- package/src/resources/extensions/gsd/export-html.ts +27 -427
- package/src/resources/extensions/gsd/git-service.ts +45 -1
- package/src/resources/extensions/gsd/gsd-db.ts +3 -0
- package/src/resources/extensions/gsd/guided-flow.ts +14 -7
- package/src/resources/extensions/gsd/md-importer.ts +1 -1
- package/src/resources/extensions/gsd/migrate/command.ts +5 -0
- package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
- package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
- package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
- package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
- package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
- package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
- package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
- package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
- package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/src/resources/extensions/gsd/prompts/queue.md +4 -4
- package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
- package/src/resources/extensions/gsd/status-guards.ts +5 -0
- package/src/resources/extensions/gsd/templates/plan.md +8 -5
- package/src/resources/extensions/gsd/templates/task-plan.md +4 -2
- package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +487 -4
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +12 -11
- package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +12 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
- package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
- package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +43 -2
- package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +103 -1
- package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +225 -1
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
- package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +46 -2
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +31 -1
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
- package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +86 -7
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
- package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
- package/src/resources/extensions/gsd/tools/plan-slice.ts +98 -12
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
- package/src/resources/extensions/gsd/types.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
- package/src/resources/extensions/gsd/validation.ts +23 -1
- package/src/resources/extensions/gsd/verification-gate.ts +78 -6
- package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
- package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
- package/src/resources/extensions/shared/html-shell.ts +412 -0
- package/src/resources/extensions/subagent/index.ts +567 -103
- package/src/resources/extensions/subagent/launch.ts +131 -0
- package/src/resources/extensions/subagent/run-store.ts +218 -0
- package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
- package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
- package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
- package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/src/resources/extensions/visual-brief/index.ts +8 -0
- package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
- package/src/resources/extensions/visual-brief/prompts.ts +183 -0
- package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
- package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
- package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
- package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
- package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
- /package/dist/web/standalone/.next/static/{KDRTXR-22LPCsa80X9dey → euQ0CLP_v8V4e76Tu3odJ}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{KDRTXR-22LPCsa80X9dey → euQ0CLP_v8V4e76Tu3odJ}/_ssgManifest.js +0 -0
|
@@ -2,27 +2,31 @@
|
|
|
2
2
|
// File Purpose: Auto Orchestration module interfaces and ADR-015 invariant adapter contracts.
|
|
3
3
|
|
|
4
4
|
import type { GSDState } from "../types.js";
|
|
5
|
+
import type { MinimalModelRegistry } from "../context-budget.js";
|
|
5
6
|
|
|
6
7
|
export interface AutoSessionContext {
|
|
7
8
|
basePath: string;
|
|
8
9
|
trigger: "guided-flow" | "resume" | "auto-loop" | "manual";
|
|
9
10
|
}
|
|
10
11
|
|
|
12
|
+
export interface UnitRef {
|
|
13
|
+
unitType: string;
|
|
14
|
+
unitId: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
export interface AutoStatus {
|
|
12
18
|
phase: "idle" | "running" | "paused" | "stopped" | "error";
|
|
13
|
-
activeUnit?:
|
|
14
|
-
unitType: string;
|
|
15
|
-
unitId: string;
|
|
16
|
-
};
|
|
19
|
+
activeUnit?: UnitRef;
|
|
17
20
|
lastTransitionAt?: number;
|
|
18
21
|
transitionCount: number;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
export
|
|
22
|
-
kind: "advanced"
|
|
23
|
-
reason
|
|
24
|
-
stateSnapshot?: GSDState
|
|
25
|
-
}
|
|
24
|
+
export type AutoAdvanceResult =
|
|
25
|
+
| { kind: "advanced"; unit: UnitRef; stateSnapshot: GSDState }
|
|
26
|
+
| { kind: "blocked"; reason: string; action: "pause" | "stop"; stateSnapshot?: GSDState }
|
|
27
|
+
| { kind: "stopped"; reason: string; stateSnapshot?: GSDState }
|
|
28
|
+
| { kind: "paused"; reason: string }
|
|
29
|
+
| { kind: "error"; reason: string };
|
|
26
30
|
|
|
27
31
|
export interface AutoOrchestrationModule {
|
|
28
32
|
start(sessionContext: AutoSessionContext): Promise<AutoAdvanceResult>;
|
|
@@ -33,12 +37,30 @@ export interface AutoOrchestrationModule {
|
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
export interface DispatchAdapter {
|
|
36
|
-
decideNextUnit(input: {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
decideNextUnit(input: {
|
|
41
|
+
stateSnapshot: GSDState;
|
|
42
|
+
/** Mirrors `DispatchContext.structuredQuestionsAvailable` — "true"/"false" string per the dispatch contract. */
|
|
43
|
+
structuredQuestionsAvailable?: "true" | "false";
|
|
44
|
+
/** Session model context window in tokens, forwarded to the budget engine. */
|
|
45
|
+
sessionContextWindow?: number;
|
|
46
|
+
/** Session model provider, used for provider-specific effective context windows. */
|
|
47
|
+
sessionProvider?: string;
|
|
48
|
+
/** Model registry for executor-model lookups inside the budget engine. */
|
|
49
|
+
modelRegistry?: MinimalModelRegistry;
|
|
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
|
+
>;
|
|
42
64
|
}
|
|
43
65
|
|
|
44
66
|
export interface RecoveryAdapter {
|
|
@@ -70,11 +92,31 @@ export interface WorktreeAdapter {
|
|
|
70
92
|
cleanupOnStop(reason: string): Promise<void>;
|
|
71
93
|
}
|
|
72
94
|
|
|
95
|
+
export type HealthGateResult =
|
|
96
|
+
| { kind: "pass"; fixesApplied?: readonly string[] }
|
|
97
|
+
| { kind: "fail"; reason: string }
|
|
98
|
+
| { kind: "threw"; error: unknown };
|
|
99
|
+
|
|
73
100
|
export interface HealthAdapter {
|
|
74
|
-
|
|
101
|
+
checkResourcesStale(): string | null;
|
|
102
|
+
preAdvanceGate(): Promise<HealthGateResult>;
|
|
75
103
|
postAdvanceRecord(result: AutoAdvanceResult): Promise<void>;
|
|
76
104
|
}
|
|
77
105
|
|
|
106
|
+
export interface UokGateInput {
|
|
107
|
+
gateId: string;
|
|
108
|
+
gateType: "policy" | "execution";
|
|
109
|
+
outcome: "pass" | "fail" | "manual-attention";
|
|
110
|
+
failureClass: "none" | "policy" | "manual-attention";
|
|
111
|
+
rationale: string;
|
|
112
|
+
findings?: string;
|
|
113
|
+
milestoneId?: string;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface UokGateAdapter {
|
|
117
|
+
emit(input: UokGateInput): Promise<void>;
|
|
118
|
+
}
|
|
119
|
+
|
|
78
120
|
export interface RuntimePersistenceAdapter {
|
|
79
121
|
ensureLockOwnership(): Promise<void>;
|
|
80
122
|
journalTransition(event: {
|
|
@@ -101,4 +143,5 @@ export interface AutoOrchestratorDeps {
|
|
|
101
143
|
health: HealthAdapter;
|
|
102
144
|
runtime: RuntimePersistenceAdapter;
|
|
103
145
|
notifications: NotificationAdapter;
|
|
146
|
+
uokGate: UokGateAdapter;
|
|
104
147
|
}
|
|
@@ -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 });
|
|
@@ -7,6 +7,16 @@ function now(): number {
|
|
|
7
7
|
return Date.now();
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Size of the dispatch-decision ring buffer used by the Auto Orchestration
|
|
12
|
+
* module's stuck-loop detector. When the same `${unitType}:${unitId}` key
|
|
13
|
+
* fills the window, advance() blocks with `action: "stop"`.
|
|
14
|
+
*
|
|
15
|
+
* Mirrors the legacy `STUCK_WINDOW_SIZE` in auto/phases.ts so behaviour is
|
|
16
|
+
* preserved across the eventual cutover (issue #5791).
|
|
17
|
+
*/
|
|
18
|
+
export const STUCK_WINDOW_SIZE = 6;
|
|
19
|
+
|
|
10
20
|
export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
11
21
|
private status: AutoStatus = {
|
|
12
22
|
phase: "idle",
|
|
@@ -14,6 +24,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
14
24
|
};
|
|
15
25
|
private readonly deps: AutoOrchestratorDeps;
|
|
16
26
|
private lastAdvanceKey: string | null = null;
|
|
27
|
+
private dispatchKeyWindow: string[] = [];
|
|
17
28
|
|
|
18
29
|
public constructor(deps: AutoOrchestratorDeps) {
|
|
19
30
|
this.deps = deps;
|
|
@@ -21,6 +32,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
21
32
|
|
|
22
33
|
public async start(_sessionContext: AutoSessionContext): Promise<AutoAdvanceResult> {
|
|
23
34
|
this.lastAdvanceKey = null;
|
|
35
|
+
this.dispatchKeyWindow = [];
|
|
24
36
|
this.status.phase = "running";
|
|
25
37
|
this.bumpTransition();
|
|
26
38
|
await this.deps.runtime.journalTransition({ name: "start" });
|
|
@@ -31,19 +43,72 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
31
43
|
public async advance(): Promise<AutoAdvanceResult> {
|
|
32
44
|
try {
|
|
33
45
|
await this.deps.runtime.ensureLockOwnership();
|
|
46
|
+
|
|
47
|
+
const staleMsg = this.deps.health.checkResourcesStale();
|
|
48
|
+
if (staleMsg) {
|
|
49
|
+
await this.deps.uokGate.emit({
|
|
50
|
+
gateId: "resource-version-guard",
|
|
51
|
+
gateType: "policy",
|
|
52
|
+
outcome: "fail",
|
|
53
|
+
failureClass: "policy",
|
|
54
|
+
rationale: "resource version guard blocked dispatch",
|
|
55
|
+
findings: staleMsg,
|
|
56
|
+
});
|
|
57
|
+
const blocked: AutoAdvanceResult = { kind: "blocked", reason: staleMsg, action: "stop" };
|
|
58
|
+
await this.deps.runtime.journalTransition({ name: "advance-blocked", reason: blocked.reason });
|
|
59
|
+
await this.deps.health.postAdvanceRecord(blocked);
|
|
60
|
+
return blocked;
|
|
61
|
+
}
|
|
62
|
+
await this.deps.uokGate.emit({
|
|
63
|
+
gateId: "resource-version-guard",
|
|
64
|
+
gateType: "policy",
|
|
65
|
+
outcome: "pass",
|
|
66
|
+
failureClass: "none",
|
|
67
|
+
rationale: "resource version guard passed",
|
|
68
|
+
});
|
|
69
|
+
|
|
34
70
|
const gate = await this.deps.health.preAdvanceGate();
|
|
35
|
-
if (
|
|
36
|
-
|
|
71
|
+
if (gate.kind === "fail") {
|
|
72
|
+
await this.deps.uokGate.emit({
|
|
73
|
+
gateId: "pre-dispatch-health-gate",
|
|
74
|
+
gateType: "execution",
|
|
75
|
+
outcome: "manual-attention",
|
|
76
|
+
failureClass: "manual-attention",
|
|
77
|
+
rationale: "pre-dispatch health gate blocked dispatch",
|
|
78
|
+
findings: gate.reason,
|
|
79
|
+
});
|
|
80
|
+
const blocked: AutoAdvanceResult = { kind: "blocked", reason: gate.reason, action: "pause" };
|
|
37
81
|
await this.deps.runtime.journalTransition({ name: "advance-blocked", reason: blocked.reason });
|
|
38
82
|
await this.deps.health.postAdvanceRecord(blocked);
|
|
39
83
|
return blocked;
|
|
40
84
|
}
|
|
85
|
+
if (gate.kind === "threw") {
|
|
86
|
+
await this.deps.uokGate.emit({
|
|
87
|
+
gateId: "pre-dispatch-health-gate",
|
|
88
|
+
gateType: "execution",
|
|
89
|
+
outcome: "manual-attention",
|
|
90
|
+
failureClass: "manual-attention",
|
|
91
|
+
rationale: "pre-dispatch health gate threw unexpectedly",
|
|
92
|
+
findings: String(gate.error),
|
|
93
|
+
});
|
|
94
|
+
// intentional fall-through: matches runPreDispatch behaviour
|
|
95
|
+
} else {
|
|
96
|
+
await this.deps.uokGate.emit({
|
|
97
|
+
gateId: "pre-dispatch-health-gate",
|
|
98
|
+
gateType: "execution",
|
|
99
|
+
outcome: "pass",
|
|
100
|
+
failureClass: "none",
|
|
101
|
+
rationale: "pre-dispatch health gate passed",
|
|
102
|
+
findings: gate.fixesApplied?.join(", ") ?? "",
|
|
103
|
+
});
|
|
104
|
+
}
|
|
41
105
|
|
|
42
106
|
const reconciliation = await this.deps.stateReconciliation.reconcileBeforeDispatch();
|
|
43
107
|
if (!reconciliation.ok || !reconciliation.stateSnapshot) {
|
|
44
108
|
const blocked: AutoAdvanceResult = {
|
|
45
109
|
kind: "blocked",
|
|
46
|
-
reason: reconciliation.reason,
|
|
110
|
+
reason: reconciliation.reason ?? "state reconciliation produced no snapshot",
|
|
111
|
+
action: "pause",
|
|
47
112
|
stateSnapshot: reconciliation.stateSnapshot,
|
|
48
113
|
};
|
|
49
114
|
await this.deps.runtime.journalTransition({ name: "advance-blocked", reason: blocked.reason });
|
|
@@ -57,15 +122,64 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
57
122
|
this.status.phase = "stopped";
|
|
58
123
|
this.status.activeUnit = undefined;
|
|
59
124
|
this.lastAdvanceKey = null;
|
|
125
|
+
this.dispatchKeyWindow = [];
|
|
60
126
|
this.bumpTransition();
|
|
61
127
|
await this.deps.runtime.journalTransition({ name: "advance-stopped", reason: stopped.reason });
|
|
62
128
|
await this.deps.health.postAdvanceRecord(stopped);
|
|
63
129
|
return stopped;
|
|
64
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
|
+
}
|
|
65
142
|
|
|
66
143
|
const nextKey = `${decision.unitType}:${decision.unitId}`;
|
|
67
|
-
|
|
68
|
-
|
|
144
|
+
|
|
145
|
+
// Record every dispatch decision in the ring buffer before pre-flight
|
|
146
|
+
// checks so the stuck-loop detector observes the full decision history
|
|
147
|
+
// (including decisions that idempotency would otherwise short-circuit).
|
|
148
|
+
// The ring is capped at STUCK_WINDOW_SIZE and evicts oldest-first.
|
|
149
|
+
this.dispatchKeyWindow.push(nextKey);
|
|
150
|
+
if (this.dispatchKeyWindow.length > STUCK_WINDOW_SIZE) {
|
|
151
|
+
this.dispatchKeyWindow.shift();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Idempotency: same key as immediately previous successful advance.
|
|
155
|
+
// This is the soft, fast-path block kept from #5786. It only fires when
|
|
156
|
+
// the ring is NOT yet saturated for this key — once the ring is full of
|
|
157
|
+
// `nextKey`, the stuck-loop verdict takes precedence (see below). Both
|
|
158
|
+
// checks coexist: idempotency for the common immediate-repeat case,
|
|
159
|
+
// stuck-loop for the saturated-window case.
|
|
160
|
+
const matchingCount = this.dispatchKeyWindow.filter((k) => k === nextKey).length;
|
|
161
|
+
if (this.lastAdvanceKey === nextKey && matchingCount < STUCK_WINDOW_SIZE) {
|
|
162
|
+
const blocked: AutoAdvanceResult = { kind: "blocked", reason: "idempotent advance: unit already active", action: "stop" };
|
|
163
|
+
await this.deps.runtime.journalTransition({
|
|
164
|
+
name: "advance-blocked",
|
|
165
|
+
reason: blocked.reason,
|
|
166
|
+
unitType: decision.unitType,
|
|
167
|
+
unitId: decision.unitId,
|
|
168
|
+
});
|
|
169
|
+
await this.deps.health.postAdvanceRecord(blocked);
|
|
170
|
+
return blocked;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Stuck-loop detection: when the ring is saturated with copies of
|
|
174
|
+
// `nextKey` (count >= STUCK_WINDOW_SIZE), the orchestrator has been
|
|
175
|
+
// picking the same unit across the whole window and must hard-stop with
|
|
176
|
+
// a diagnosable reason.
|
|
177
|
+
if (matchingCount >= STUCK_WINDOW_SIZE) {
|
|
178
|
+
const blocked: AutoAdvanceResult = {
|
|
179
|
+
kind: "blocked",
|
|
180
|
+
reason: `stuck-loop: ${nextKey} picked ${matchingCount} times`,
|
|
181
|
+
action: "stop",
|
|
182
|
+
};
|
|
69
183
|
await this.deps.runtime.journalTransition({
|
|
70
184
|
name: "advance-blocked",
|
|
71
185
|
reason: blocked.reason,
|
|
@@ -81,6 +195,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
81
195
|
const blocked: AutoAdvanceResult = {
|
|
82
196
|
kind: "blocked",
|
|
83
197
|
reason: contract.reason,
|
|
198
|
+
action: "pause",
|
|
84
199
|
stateSnapshot: reconciliation.stateSnapshot,
|
|
85
200
|
};
|
|
86
201
|
await this.deps.runtime.journalTransition({
|
|
@@ -98,6 +213,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
98
213
|
const blocked: AutoAdvanceResult = {
|
|
99
214
|
kind: "blocked",
|
|
100
215
|
reason: worktree.reason,
|
|
216
|
+
action: "pause",
|
|
101
217
|
stateSnapshot: reconciliation.stateSnapshot,
|
|
102
218
|
};
|
|
103
219
|
await this.deps.runtime.journalTransition({
|
|
@@ -123,7 +239,11 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
123
239
|
});
|
|
124
240
|
await this.deps.worktree.syncAfterUnit(decision.unitType, decision.unitId);
|
|
125
241
|
|
|
126
|
-
const advanced: AutoAdvanceResult = {
|
|
242
|
+
const advanced: AutoAdvanceResult = {
|
|
243
|
+
kind: "advanced",
|
|
244
|
+
unit: { unitType: decision.unitType, unitId: decision.unitId },
|
|
245
|
+
stateSnapshot: reconciliation.stateSnapshot,
|
|
246
|
+
};
|
|
127
247
|
await this.deps.health.postAdvanceRecord(advanced);
|
|
128
248
|
return advanced;
|
|
129
249
|
} catch (error) {
|
|
@@ -148,6 +268,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
148
268
|
|
|
149
269
|
if (result.kind === "stopped") {
|
|
150
270
|
this.lastAdvanceKey = null;
|
|
271
|
+
this.dispatchKeyWindow = [];
|
|
151
272
|
this.status.activeUnit = undefined;
|
|
152
273
|
}
|
|
153
274
|
this.bumpTransition();
|
|
@@ -173,6 +294,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
173
294
|
|
|
174
295
|
public async resume(): Promise<AutoAdvanceResult> {
|
|
175
296
|
this.lastAdvanceKey = null;
|
|
297
|
+
this.dispatchKeyWindow = [];
|
|
176
298
|
this.status.phase = "running";
|
|
177
299
|
this.bumpTransition();
|
|
178
300
|
await this.deps.runtime.journalTransition({ name: "resume" });
|
|
@@ -188,6 +310,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
|
|
|
188
310
|
this.status.phase = "stopped";
|
|
189
311
|
this.status.activeUnit = undefined;
|
|
190
312
|
this.lastAdvanceKey = null;
|
|
313
|
+
this.dispatchKeyWindow = [];
|
|
191
314
|
this.bumpTransition();
|
|
192
315
|
await this.deps.runtime.journalTransition({ name: "stop", reason });
|
|
193
316
|
await this.deps.notifications.notifyLifecycle({ name: "stop", detail: reason });
|
|
@@ -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) {
|