@opengsd/gsd-pi 1.1.1-dev.a5a2de8 → 1.1.1-dev.b2556262
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/dist/headless-recover.js +56 -1
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +18 -2
- package/dist/resources/extensions/browser-tools/engine/selection.js +1 -1
- package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/dist/resources/extensions/browser-tools/index.js +68 -24
- package/dist/resources/extensions/browser-tools/state.js +12 -0
- package/dist/resources/extensions/browser-tools/tools/session.js +3 -2
- package/dist/resources/extensions/browser-tools/utils.js +3 -3
- package/dist/resources/extensions/browser-tools/web-app-detect.js +52 -0
- package/dist/resources/extensions/gsd/auto/loop.js +4 -2
- package/dist/resources/extensions/gsd/auto/phases.js +87 -12
- package/dist/resources/extensions/gsd/auto/session.js +22 -1
- package/dist/resources/extensions/gsd/auto/workflow-kernel.js +1 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +81 -13
- package/dist/resources/extensions/gsd/auto-model-selection.js +154 -9
- package/dist/resources/extensions/gsd/auto-post-unit.js +19 -2
- package/dist/resources/extensions/gsd/auto-prompts.js +26 -21
- package/dist/resources/extensions/gsd/auto-recovery.js +4 -2
- package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
- package/dist/resources/extensions/gsd/auto-start.js +1 -1
- package/dist/resources/extensions/gsd/auto-timers.js +24 -10
- package/dist/resources/extensions/gsd/auto.js +40 -15
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +192 -77
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +1 -1
- package/dist/resources/extensions/gsd/closeout-wizard.js +32 -9
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +10 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -9
- package/dist/resources/extensions/gsd/commands-maintenance.js +93 -15
- package/dist/resources/extensions/gsd/commands-mcp-status.js +1 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +2 -2
- package/dist/resources/extensions/gsd/config-overlay.js +1 -0
- package/dist/resources/extensions/gsd/context-masker.js +129 -5
- package/dist/resources/extensions/gsd/db-writer.js +35 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +50 -1
- package/dist/resources/extensions/gsd/gsd-db.js +480 -172
- package/dist/resources/extensions/gsd/guided-flow.js +4 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +37 -53
- package/dist/resources/extensions/gsd/md-importer.js +38 -3
- package/dist/resources/extensions/gsd/migration-auto-check.js +126 -31
- package/dist/resources/extensions/gsd/parsers-legacy.js +23 -0
- package/dist/resources/extensions/gsd/planner-handoff.js +98 -0
- package/dist/resources/extensions/gsd/planning-path-scope.js +22 -4
- package/dist/resources/extensions/gsd/pre-execution-checks.js +10 -2
- package/dist/resources/extensions/gsd/preferences-models.js +111 -43
- package/dist/resources/extensions/gsd/preferences-types.js +13 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +68 -3
- package/dist/resources/extensions/gsd/preferences.js +4 -1
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +2 -2
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +5 -1
- package/dist/resources/extensions/gsd/safety/content-validator.js +6 -4
- package/dist/resources/extensions/gsd/skill-manifest.js +12 -0
- package/dist/resources/extensions/gsd/source-observations.js +306 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +15 -8
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +33 -5
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-worker.js +34 -13
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +39 -14
- package/dist/resources/extensions/gsd/state-reconciliation/spawn-gate.js +4 -4
- package/dist/resources/extensions/gsd/state.js +7 -3
- package/dist/resources/extensions/gsd/tool-contract.js +15 -1
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +24 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +28 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +42 -11
- package/dist/resources/extensions/gsd/tools/plan-task.js +7 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +62 -406
- package/dist/resources/extensions/gsd/uat-policy.js +130 -0
- package/dist/resources/extensions/gsd/uat-run.js +414 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +3 -4
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +38 -14
- package/dist/resources/extensions/gsd/verdict-parser.js +3 -8
- package/dist/resources/extensions/gsd/workflow-manifest.js +132 -5
- package/dist/resources/extensions/gsd/workflow-mcp.js +2 -3
- package/dist/resources/extensions/gsd/workflow-projections.js +8 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +26 -0
- package/dist/resources/extensions/gsd/worktree-reentry.js +96 -0
- package/dist/resources/extensions/gsd/worktree-state-projection.js +18 -17
- package/dist/resources/extensions/shared/gsd-browser-cli.js +6 -0
- package/dist/resources/extensions/subagent/agents.js +1 -0
- package/dist/resources/extensions/subagent/index.js +27 -12
- package/dist/resources/extensions/subagent/launch.js +7 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- 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 +1 -1
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- 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 +1 -1
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +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/node_modules/@gsd/native/dist/native.js +22 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +4 -4
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js +21 -23
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +66 -12
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +18 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +16 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/workflow-tools.js +1 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/dist/native.js +22 -0
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/image-models.generated.d.ts +30 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/image-models.generated.js +30 -0
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +174 -29
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +178 -54
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.js +8 -1
- package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/themes.js +1 -1
- package/packages/pi-coding-agent/dist/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/utils.d.ts +11 -0
- package/packages/pi-tui/dist/utils.d.ts.map +1 -1
- package/packages/pi-tui/dist/utils.js +119 -6
- package/packages/pi-tui/dist/utils.js.map +1 -1
- package/packages/pi-tui/package.json +2 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/themes.js +1 -1
- package/pkg/dist/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/scripts/install/handoff.js +16 -3
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +21 -2
- package/src/resources/extensions/browser-tools/engine/selection.ts +1 -1
- package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/src/resources/extensions/browser-tools/index.ts +75 -27
- package/src/resources/extensions/browser-tools/state.ts +13 -0
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +2 -2
- package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +57 -0
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +37 -0
- package/src/resources/extensions/browser-tools/tests/web-app-detect.test.mjs +68 -0
- package/src/resources/extensions/browser-tools/tools/session.ts +4 -2
- package/src/resources/extensions/browser-tools/utils.ts +3 -3
- package/src/resources/extensions/browser-tools/web-app-detect.ts +63 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/loop.ts +4 -2
- package/src/resources/extensions/gsd/auto/phases.ts +89 -15
- package/src/resources/extensions/gsd/auto/session.ts +24 -1
- package/src/resources/extensions/gsd/auto/workflow-kernel.ts +1 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +117 -12
- package/src/resources/extensions/gsd/auto-model-selection.ts +190 -12
- package/src/resources/extensions/gsd/auto-post-unit.ts +20 -2
- package/src/resources/extensions/gsd/auto-prompts.ts +25 -22
- package/src/resources/extensions/gsd/auto-recovery.ts +22 -3
- package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto-timers.ts +25 -9
- package/src/resources/extensions/gsd/auto.ts +41 -14
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +250 -78
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +1 -1
- package/src/resources/extensions/gsd/closeout-wizard.ts +47 -13
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +2 -17
- package/src/resources/extensions/gsd/commands-maintenance.ts +124 -13
- package/src/resources/extensions/gsd/commands-mcp-status.ts +1 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +2 -2
- package/src/resources/extensions/gsd/config-overlay.ts +1 -0
- package/src/resources/extensions/gsd/context-masker.ts +152 -5
- package/src/resources/extensions/gsd/db-writer.ts +38 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +50 -1
- package/src/resources/extensions/gsd/gsd-db.ts +564 -186
- package/src/resources/extensions/gsd/guided-flow.ts +4 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +44 -66
- package/src/resources/extensions/gsd/md-importer.ts +49 -2
- package/src/resources/extensions/gsd/migration-auto-check.ts +154 -34
- package/src/resources/extensions/gsd/parsers-legacy.ts +20 -0
- package/src/resources/extensions/gsd/planner-handoff.ts +149 -0
- package/src/resources/extensions/gsd/planning-path-scope.ts +22 -4
- package/src/resources/extensions/gsd/pre-execution-checks.ts +9 -2
- package/src/resources/extensions/gsd/preferences-models.ts +113 -43
- package/src/resources/extensions/gsd/preferences-types.ts +47 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +76 -2
- package/src/resources/extensions/gsd/preferences.ts +5 -0
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +2 -2
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +6 -1
- package/src/resources/extensions/gsd/safety/content-validator.ts +8 -5
- package/src/resources/extensions/gsd/skill-manifest.ts +12 -0
- package/src/resources/extensions/gsd/source-observations.ts +402 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +20 -8
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +44 -5
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +39 -11
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +45 -15
- package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +4 -4
- package/src/resources/extensions/gsd/state.ts +7 -4
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +66 -4
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +299 -1
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +75 -3
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +22 -1
- package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +4 -0
- package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/closeout-wizard.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +118 -0
- package/src/resources/extensions/gsd/tests/content-validator.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/context-masker.test.ts +56 -1
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +17 -2
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +1 -11
- package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +62 -1
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +99 -2
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/planner-handoff.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +162 -18
- package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/source-observations.test.ts +275 -0
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +76 -21
- package/src/resources/extensions/gsd/tests/thinking-level-resolution.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +170 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +306 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +77 -10
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +260 -5
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +511 -1
- package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +44 -0
- package/src/resources/extensions/gsd/tool-contract.ts +29 -1
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +41 -6
- package/src/resources/extensions/gsd/tools/complete-slice.ts +29 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +54 -12
- package/src/resources/extensions/gsd/tools/plan-task.ts +8 -1
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +71 -489
- package/src/resources/extensions/gsd/types.ts +1 -0
- package/src/resources/extensions/gsd/uat-policy.ts +191 -0
- package/src/resources/extensions/gsd/uat-run.ts +550 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +3 -4
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +38 -14
- package/src/resources/extensions/gsd/verdict-parser.ts +3 -10
- package/src/resources/extensions/gsd/workflow-manifest.ts +193 -7
- package/src/resources/extensions/gsd/workflow-mcp.ts +2 -3
- package/src/resources/extensions/gsd/workflow-projections.ts +9 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +32 -0
- package/src/resources/extensions/gsd/worktree-reentry.ts +103 -0
- package/src/resources/extensions/gsd/worktree-state-projection.ts +22 -22
- package/src/resources/extensions/shared/gsd-browser-cli.ts +6 -0
- package/src/resources/extensions/shared/tests/format-utils.test.ts +8 -3
- package/src/resources/extensions/subagent/agents.ts +4 -0
- package/src/resources/extensions/subagent/index.ts +28 -3
- package/src/resources/extensions/subagent/launch.ts +8 -0
- package/src/resources/extensions/subagent/tests/model-override.test.ts +31 -0
- /package/dist/web/standalone/.next/static/{9y3LeeR2uGr2yRj9RjY3D → tJOKQbQRO-9MiFDO8DIDS}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{9y3LeeR2uGr2yRj9RjY3D → tJOKQbQRO-9MiFDO8DIDS}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* web-app-detect — lightweight, synchronous heuristic for deciding whether the
|
|
3
|
+
* project under development is a web app. Used only when the optional managed
|
|
4
|
+
* gsd-browser engine is selected and can be warmed before first use.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
+
import { resolve } from "node:path";
|
|
8
|
+
|
|
9
|
+
// Frontend frameworks / bundlers whose presence in dependencies indicates a
|
|
10
|
+
// browser-facing web app worth warming the optional managed engine for.
|
|
11
|
+
const WEB_DEPENDENCY_RE =
|
|
12
|
+
/^(react|react-dom|next|nuxt|vue|@vue\/|svelte|@sveltejs\/|solid-js|astro|@remix-run\/|gatsby|preact|@angular\/core|vite|@vitejs\/|@builder\.io\/qwik|@web\/dev-server|@11ty\/eleventy)/;
|
|
13
|
+
|
|
14
|
+
// package.json scripts that imply a dev server / browser-facing build.
|
|
15
|
+
const WEB_SCRIPT_RE = /\b(vite|next|nuxt|astro|remix|webpack(-dev-server)?|parcel|ng serve|serve\b|http-server|live-server|gatsby)\b/;
|
|
16
|
+
|
|
17
|
+
interface MinimalPackageJson {
|
|
18
|
+
dependencies?: Record<string, unknown>;
|
|
19
|
+
devDependencies?: Record<string, unknown>;
|
|
20
|
+
peerDependencies?: Record<string, unknown>;
|
|
21
|
+
scripts?: Record<string, unknown>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function readPackageJson(projectRoot: string): MinimalPackageJson | null {
|
|
25
|
+
const packageJsonPath = resolve(projectRoot, "package.json");
|
|
26
|
+
if (!existsSync(packageJsonPath)) return null;
|
|
27
|
+
try {
|
|
28
|
+
const parsed = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as unknown;
|
|
29
|
+
return parsed && typeof parsed === "object" ? (parsed as MinimalPackageJson) : null;
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function dependencyNames(pkg: MinimalPackageJson): string[] {
|
|
36
|
+
return [
|
|
37
|
+
...Object.keys(pkg.dependencies ?? {}),
|
|
38
|
+
...Object.keys(pkg.devDependencies ?? {}),
|
|
39
|
+
...Object.keys(pkg.peerDependencies ?? {}),
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Returns true when the project looks like a browser-facing web app. Conservative
|
|
45
|
+
* and dependency-free: a false negative just means lazy connection (the prior
|
|
46
|
+
* behavior); a false positive only warms an idle engine connection.
|
|
47
|
+
*/
|
|
48
|
+
export function detectWebApp(projectRoot: string): boolean {
|
|
49
|
+
const pkg = readPackageJson(projectRoot);
|
|
50
|
+
if (pkg) {
|
|
51
|
+
if (dependencyNames(pkg).some((name) => WEB_DEPENDENCY_RE.test(name))) return true;
|
|
52
|
+
const scriptValues = Object.values(pkg.scripts ?? {}).filter(
|
|
53
|
+
(value): value is string => typeof value === "string",
|
|
54
|
+
);
|
|
55
|
+
if (scriptValues.some((script) => WEB_SCRIPT_RE.test(script))) return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// No package.json signal — fall back to a top-level index.html (static sites).
|
|
59
|
+
if (existsSync(resolve(projectRoot, "index.html"))) return true;
|
|
60
|
+
if (existsSync(resolve(projectRoot, "public", "index.html"))) return true;
|
|
61
|
+
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
@@ -259,6 +259,7 @@ export interface LoopDeps {
|
|
|
259
259
|
) => Promise<{
|
|
260
260
|
routing: { tier: string; modelDowngraded: boolean } | null;
|
|
261
261
|
appliedModel: { provider: string; id: string } | null;
|
|
262
|
+
appliedThinkingLevel?: ReturnType<ExtensionAPI["getThinkingLevel"]> | null;
|
|
262
263
|
}>;
|
|
263
264
|
resolveModelId: <T extends { id: string; provider: string }>(
|
|
264
265
|
modelId: string,
|
|
@@ -1284,7 +1284,7 @@ export async function autoLoop(
|
|
|
1284
1284
|
unitId: iterData.unitId,
|
|
1285
1285
|
});
|
|
1286
1286
|
const finalizeReason = finalizeResult.action === "break" ? finalizeResult.reason : undefined;
|
|
1287
|
-
const finalizeStatus = finalizeReason === "step-wizard"
|
|
1287
|
+
const finalizeStatus = (finalizeReason === "step-wizard" || finalizeReason === "milestone-complete")
|
|
1288
1288
|
? "completed"
|
|
1289
1289
|
: finalizeResult.action === "next"
|
|
1290
1290
|
? "completed"
|
|
@@ -1353,7 +1353,9 @@ export async function autoLoop(
|
|
|
1353
1353
|
stuckStatePersistedThisIteration = true;
|
|
1354
1354
|
finishTurn("completed");
|
|
1355
1355
|
if (finalizeDecision.action === "complete-and-break") {
|
|
1356
|
-
s.
|
|
1356
|
+
if (!s.completionStopInProgress) {
|
|
1357
|
+
s.preserveStepSurfaceAfterLoopExit = true;
|
|
1358
|
+
}
|
|
1357
1359
|
break;
|
|
1358
1360
|
}
|
|
1359
1361
|
} catch (loopErr) {
|
|
@@ -35,6 +35,8 @@ import { detectStuck } from "./detect-stuck.js";
|
|
|
35
35
|
import { runUnit } from "./run-unit.js";
|
|
36
36
|
import { debugLog } from "../debug-logger.js";
|
|
37
37
|
import { resolveWorktreeProjectRoot, normalizeWorktreePathForCompare } from "../worktree-root.js";
|
|
38
|
+
import { buildManualValidationGuidance } from "../worktree-manager.js";
|
|
39
|
+
import { relSliceFile } from "../paths.js";
|
|
38
40
|
import { classifyProject } from "../detection.js";
|
|
39
41
|
import { MergeConflictError } from "../git-service.js";
|
|
40
42
|
import { setCurrentPhase, clearCurrentPhase } from "../../shared/gsd-phase-state.js";
|
|
@@ -83,6 +85,7 @@ import {
|
|
|
83
85
|
supportsStructuredQuestions,
|
|
84
86
|
} from "../workflow-mcp.js";
|
|
85
87
|
import { prepareWorkflowMcpForProject } from "../workflow-mcp-auto-prep.js";
|
|
88
|
+
import { getToolBaselineSnapshot, applyThinkingLevelForModel, floorThinkingLevelForUnit } from "../auto-model-selection.js";
|
|
86
89
|
import type { DispatchAction } from "../auto-dispatch.js";
|
|
87
90
|
import { resolveManifest } from "../unit-context-manifest.js";
|
|
88
91
|
import { createWorktreeSafetyModule, type WorktreeSafetyResult } from "../worktree-safety.js";
|
|
@@ -397,6 +400,8 @@ async function validateSourceWriteWorktreeSafety(
|
|
|
397
400
|
|
|
398
401
|
let consecutiveSessionTimeouts = 0;
|
|
399
402
|
const MAX_SESSION_TIMEOUT_AUTO_RESUMES = 3;
|
|
403
|
+
/** Maximum zero-tool-call retries before pausing — context exhaustion is deterministic. */
|
|
404
|
+
const MAX_ZERO_TOOL_RETRIES = 1;
|
|
400
405
|
|
|
401
406
|
export function resetSessionTimeoutState(): void {
|
|
402
407
|
consecutiveSessionTimeouts = 0;
|
|
@@ -534,7 +539,7 @@ async function closeoutAndStop(
|
|
|
534
539
|
s.currentUnit.startedAt,
|
|
535
540
|
deps.buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id),
|
|
536
541
|
);
|
|
537
|
-
s.
|
|
542
|
+
s.clearCurrentUnit();
|
|
538
543
|
}
|
|
539
544
|
await deps.stopAuto(ctx, pi, reason);
|
|
540
545
|
}
|
|
@@ -802,7 +807,7 @@ async function failClosedOnFinalizeTimeout(
|
|
|
802
807
|
);
|
|
803
808
|
|
|
804
809
|
await deps.pauseAuto(ctx, pi);
|
|
805
|
-
s.
|
|
810
|
+
s.clearCurrentUnit();
|
|
806
811
|
clearCurrentPhase();
|
|
807
812
|
drainLogs();
|
|
808
813
|
return { action: "break", reason: progressKind };
|
|
@@ -1384,7 +1389,7 @@ export async function runPreDispatch(
|
|
|
1384
1389
|
s.currentUnit.startedAt,
|
|
1385
1390
|
deps.buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id),
|
|
1386
1391
|
);
|
|
1387
|
-
s.
|
|
1392
|
+
s.clearCurrentUnit();
|
|
1388
1393
|
}
|
|
1389
1394
|
await deps.stopAuto(ctx, pi, `Milestone ${mid} complete`, {
|
|
1390
1395
|
completionWidget: {
|
|
@@ -1446,7 +1451,13 @@ export async function runDispatch(
|
|
|
1446
1451
|
const authMode = provider && typeof ctx.modelRegistry?.getProviderAuthMode === "function"
|
|
1447
1452
|
? ctx.modelRegistry.getProviderAuthMode(provider)
|
|
1448
1453
|
: undefined;
|
|
1449
|
-
|
|
1454
|
+
// Use the baseline snapshot rather than the live active-tool set: a prior
|
|
1455
|
+
// unit's per-provider narrowing (hook overrides, Groq 128-tool cap, etc.)
|
|
1456
|
+
// can strip required MCP tools from the live set even though
|
|
1457
|
+
// selectAndApplyModel will restore them before the unit is dispatched.
|
|
1458
|
+
// Checking a stale-narrowed set causes false transport-preflight warnings
|
|
1459
|
+
// that repeat on every /gsd auto resume (#477 follow-up).
|
|
1460
|
+
const activeTools = getToolBaselineSnapshot(pi);
|
|
1450
1461
|
// Deep planning intentionally keeps human checkpoints in plain chat. In
|
|
1451
1462
|
// Claude Code/local MCP transports, structured question requests can be
|
|
1452
1463
|
// cancelled outside the normal chat flow, which made approval gates easy to
|
|
@@ -1470,6 +1481,9 @@ export async function runDispatch(
|
|
|
1470
1481
|
sessionContextWindow: ctx.model?.contextWindow,
|
|
1471
1482
|
sessionProvider: ctx.model?.provider,
|
|
1472
1483
|
modelRegistry: ctx.modelRegistry as MinimalModelRegistry | undefined,
|
|
1484
|
+
activeTools,
|
|
1485
|
+
sessionBaseUrl: ctx.model?.baseUrl,
|
|
1486
|
+
sessionAuthMode: authMode,
|
|
1473
1487
|
});
|
|
1474
1488
|
if (isUnhandledPhaseWarning(dispatchResult)) {
|
|
1475
1489
|
deps.invalidateAllCaches();
|
|
@@ -1493,6 +1507,9 @@ export async function runDispatch(
|
|
|
1493
1507
|
sessionContextWindow: ctx.model?.contextWindow,
|
|
1494
1508
|
sessionProvider: ctx.model?.provider,
|
|
1495
1509
|
modelRegistry: ctx.modelRegistry as MinimalModelRegistry | undefined,
|
|
1510
|
+
activeTools,
|
|
1511
|
+
sessionBaseUrl: ctx.model?.baseUrl,
|
|
1512
|
+
sessionAuthMode: authMode,
|
|
1496
1513
|
});
|
|
1497
1514
|
}
|
|
1498
1515
|
|
|
@@ -2233,9 +2250,16 @@ export async function runUnitPhase(
|
|
|
2233
2250
|
if (match) {
|
|
2234
2251
|
const ok = await pi.setModel(match, { persist: false });
|
|
2235
2252
|
if (ok) {
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2253
|
+
// Apply the per-phase reasoning effort selectAndApplyModel resolved for
|
|
2254
|
+
// this unit — not the auto-start session snapshot — but route it through
|
|
2255
|
+
// the same floor + capability-clamp pipeline against the *hook* model
|
|
2256
|
+
// (ADR-026). The hook override can pick a different model family than the
|
|
2257
|
+
// one selectAndApplyModel clamped against, so re-clamping here prevents
|
|
2258
|
+
// sending an unsupported level; the floor fills in when no phase level
|
|
2259
|
+
// resolved so a hook-overridden execute-task still meets the floor.
|
|
2260
|
+
const hookThinkingBase = modelResult.appliedThinkingLevel
|
|
2261
|
+
?? floorThinkingLevelForUnit(unitType, s.autoModeStartThinkingLevel);
|
|
2262
|
+
applyThinkingLevelForModel(pi, hookThinkingBase, match, ctx);
|
|
2239
2263
|
s.currentUnitModel = match as AutoSession["currentUnitModel"];
|
|
2240
2264
|
ctx.ui.notify(`Hook model override: ${match.provider}/${match.id}`, "info");
|
|
2241
2265
|
} else {
|
|
@@ -2318,7 +2342,19 @@ export async function runUnitPhase(
|
|
|
2318
2342
|
_resetLogs();
|
|
2319
2343
|
const unitStartedAt = Date.now();
|
|
2320
2344
|
s.unitDispatchCount.set(dispatchKey, nextDispatchCount);
|
|
2321
|
-
s.
|
|
2345
|
+
s.setCurrentUnit({ type: unitType, id: unitId, startedAt: unitStartedAt, workspaceRoot: s.basePath });
|
|
2346
|
+
if (unitType === "execute-task") {
|
|
2347
|
+
const { milestone, slice, task } = parseUnitId(unitId);
|
|
2348
|
+
if (milestone && slice && task && isDbAvailable()) {
|
|
2349
|
+
try {
|
|
2350
|
+
const taskRow = getTask(milestone, slice, task);
|
|
2351
|
+
if (taskRow) s.sourceObservations.observePlanTask(taskRow);
|
|
2352
|
+
} catch (err) {
|
|
2353
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2354
|
+
logWarning("prompt", `failed to preload source observations for ${unitId}: ${message}`);
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2322
2358
|
s.rootWriteBaseline = isIsolatedWorktreeSession(s)
|
|
2323
2359
|
? captureRootDirtySnapshot(s.originalBasePath)
|
|
2324
2360
|
: null;
|
|
@@ -2429,7 +2465,7 @@ export async function runUnitPhase(
|
|
|
2429
2465
|
category: "unknown",
|
|
2430
2466
|
isTransient: true,
|
|
2431
2467
|
});
|
|
2432
|
-
s.
|
|
2468
|
+
s.clearCurrentUnit();
|
|
2433
2469
|
await deps.pauseAuto(ctx, pi);
|
|
2434
2470
|
return { action: "break", reason: "ghost-completion" };
|
|
2435
2471
|
}
|
|
@@ -2711,14 +2747,27 @@ export async function runUnitPhase(
|
|
|
2711
2747
|
unitId,
|
|
2712
2748
|
});
|
|
2713
2749
|
} else {
|
|
2750
|
+
const zeroToolKey = `${unitType}/${unitId}`;
|
|
2751
|
+
const attempt = (s.zeroToolRetryCount.get(zeroToolKey) ?? 0) + 1;
|
|
2714
2752
|
debugLog("runUnitPhase", {
|
|
2715
2753
|
phase: "zero-tool-calls",
|
|
2716
2754
|
unitType,
|
|
2717
2755
|
unitId,
|
|
2756
|
+
attempt,
|
|
2718
2757
|
warning: "Unit completed with 0 tool calls — likely context exhaustion, marking as failed",
|
|
2719
2758
|
});
|
|
2759
|
+
if (attempt > MAX_ZERO_TOOL_RETRIES) {
|
|
2760
|
+
s.zeroToolRetryCount.delete(zeroToolKey);
|
|
2761
|
+
ctx.ui.notify(
|
|
2762
|
+
`${unitType} ${unitId} completed with 0 tool calls — context exhaustion, pausing auto-mode after ${MAX_ZERO_TOOL_RETRIES} retry.`,
|
|
2763
|
+
"error",
|
|
2764
|
+
);
|
|
2765
|
+
await deps.pauseAuto(ctx, pi);
|
|
2766
|
+
return { action: "break", reason: "zero-tool-calls-exhausted" };
|
|
2767
|
+
}
|
|
2768
|
+
s.zeroToolRetryCount.set(zeroToolKey, attempt);
|
|
2720
2769
|
ctx.ui.notify(
|
|
2721
|
-
`${unitType} ${unitId} completed with 0 tool calls — context exhaustion, will retry`,
|
|
2770
|
+
`${unitType} ${unitId} completed with 0 tool calls — context exhaustion, will retry (attempt ${attempt}/${MAX_ZERO_TOOL_RETRIES})`,
|
|
2722
2771
|
"warning",
|
|
2723
2772
|
);
|
|
2724
2773
|
return {
|
|
@@ -2748,6 +2797,7 @@ export async function runUnitPhase(
|
|
|
2748
2797
|
if (artifactVerified) {
|
|
2749
2798
|
s.unitDispatchCount.delete(dispatchKey);
|
|
2750
2799
|
s.unitRecoveryCount.delete(`${unitType}/${unitId}`);
|
|
2800
|
+
s.zeroToolRetryCount.delete(dispatchKey);
|
|
2751
2801
|
}
|
|
2752
2802
|
|
|
2753
2803
|
// Write phase handoff anchor after successful research/planning completion
|
|
@@ -2855,7 +2905,7 @@ export async function runFinalize(
|
|
|
2855
2905
|
s.currentUnit?.id === preUnitSnapshot.id &&
|
|
2856
2906
|
s.currentUnit?.startedAt === preUnitSnapshot.startedAt
|
|
2857
2907
|
) {
|
|
2858
|
-
s.
|
|
2908
|
+
s.clearCurrentUnit();
|
|
2859
2909
|
}
|
|
2860
2910
|
s.rootWriteBaseline = null;
|
|
2861
2911
|
};
|
|
@@ -2927,10 +2977,21 @@ export async function runFinalize(
|
|
|
2927
2977
|
}
|
|
2928
2978
|
|
|
2929
2979
|
if (pauseAfterUatDispatch) {
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2980
|
+
const pauseMid = iterData.mid;
|
|
2981
|
+
const pauseSliceId = pauseMid && iterData.unitId.startsWith(`${pauseMid}/`)
|
|
2982
|
+
? iterData.unitId.slice(pauseMid.length + 1)
|
|
2983
|
+
: undefined;
|
|
2984
|
+
const guidance = pauseMid
|
|
2985
|
+
? buildManualValidationGuidance(s.basePath, pauseMid, {
|
|
2986
|
+
uatPath: pauseSliceId
|
|
2987
|
+
? relSliceFile(s.basePath, pauseMid, pauseSliceId, "UAT")
|
|
2988
|
+
: undefined,
|
|
2989
|
+
})
|
|
2990
|
+
: null;
|
|
2991
|
+
const pauseMessage = guidance
|
|
2992
|
+
? `UAT requires human execution. Auto-mode will pause after this unit writes the result file.\n\n${guidance}`
|
|
2993
|
+
: "UAT requires human execution. Auto-mode will pause after this unit writes the result file.";
|
|
2994
|
+
ctx.ui.notify(pauseMessage, "info");
|
|
2934
2995
|
await deps.pauseAuto(ctx, pi);
|
|
2935
2996
|
debugLog("autoLoop", { phase: "exit", reason: "uat-pause" });
|
|
2936
2997
|
clearFinalizingUnit();
|
|
@@ -3128,5 +3189,18 @@ export async function runFinalize(
|
|
|
3128
3189
|
}
|
|
3129
3190
|
}
|
|
3130
3191
|
|
|
3192
|
+
if (preUnitSnapshot?.type === "complete-milestone" && s.currentMilestoneId) {
|
|
3193
|
+
// cleanupAfterLoopExit skips gsd-progress when preserveCompletionSurface is true, so clear stale controls here.
|
|
3194
|
+
ctx.ui.setStatus?.("gsd-step", undefined);
|
|
3195
|
+
ctx.ui.setWidget?.("gsd-progress", undefined);
|
|
3196
|
+
await deps.stopAuto(ctx, pi, `Milestone ${s.currentMilestoneId} complete`, {
|
|
3197
|
+
completionWidget: {
|
|
3198
|
+
milestoneId: s.currentMilestoneId,
|
|
3199
|
+
milestoneTitle: iterData.midTitle,
|
|
3200
|
+
},
|
|
3201
|
+
});
|
|
3202
|
+
return { action: "break", reason: "milestone-complete" };
|
|
3203
|
+
}
|
|
3204
|
+
|
|
3131
3205
|
return { action: "next", data: undefined as void };
|
|
3132
3206
|
}
|
|
@@ -22,6 +22,7 @@ import type { Api, Model } from "@gsd/pi-ai";
|
|
|
22
22
|
import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
23
23
|
import type { GitServiceImpl } from "../git-service.js";
|
|
24
24
|
import type { CaptureEntry } from "../captures.js";
|
|
25
|
+
import { SourceObservationStore, supportsSourceObservationsForUnit } from "../source-observations.js";
|
|
25
26
|
import type { BudgetAlertLevel } from "../auto-budget.js";
|
|
26
27
|
import type { AutoOrchestrationModule } from "./contracts.js";
|
|
27
28
|
import { resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
@@ -156,6 +157,7 @@ export class AutoSession {
|
|
|
156
157
|
currentTurnId: string | null = null;
|
|
157
158
|
currentUnitRouting: UnitRouting | null = null;
|
|
158
159
|
currentMilestoneId: string | null = null;
|
|
160
|
+
readonly sourceObservations = new SourceObservationStore();
|
|
159
161
|
|
|
160
162
|
// ── Model state ──────────────────────────────────────────────────────────
|
|
161
163
|
autoModeStartModel: StartModel | null = null;
|
|
@@ -176,6 +178,7 @@ export class AutoSession {
|
|
|
176
178
|
readonly verificationRetryCount = new Map<string, number>();
|
|
177
179
|
readonly verificationRetryFailureHashes = new Map<string, string>();
|
|
178
180
|
readonly exhaustedVerificationUnits = new Set<string>();
|
|
181
|
+
readonly zeroToolRetryCount = new Map<string, number>();
|
|
179
182
|
pausedSessionFile: string | null = null;
|
|
180
183
|
pausedUnitType: string | null = null;
|
|
181
184
|
pausedUnitId: string | null = null;
|
|
@@ -282,6 +285,25 @@ export class AutoSession {
|
|
|
282
285
|
this.unitLifetimeDispatches.clear();
|
|
283
286
|
}
|
|
284
287
|
|
|
288
|
+
setCurrentUnit(unit: CurrentUnit): void {
|
|
289
|
+
this.currentUnit = unit;
|
|
290
|
+
if (!supportsSourceObservationsForUnit(unit.type)) {
|
|
291
|
+
this.sourceObservations.clear();
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
this.sourceObservations.beginUnit({
|
|
295
|
+
unitType: unit.type,
|
|
296
|
+
unitId: unit.id,
|
|
297
|
+
startedAt: unit.startedAt,
|
|
298
|
+
basePath: unit.workspaceRoot ?? this.basePath,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
clearCurrentUnit(): void {
|
|
303
|
+
this.currentUnit = null;
|
|
304
|
+
this.sourceObservations.clear();
|
|
305
|
+
}
|
|
306
|
+
|
|
285
307
|
get lockBasePath(): string {
|
|
286
308
|
return resolveWorktreeProjectRoot(this.basePath, this.originalBasePath);
|
|
287
309
|
}
|
|
@@ -339,7 +361,7 @@ export class AutoSession {
|
|
|
339
361
|
this.unitRecoveryCount.clear();
|
|
340
362
|
|
|
341
363
|
// Unit
|
|
342
|
-
this.
|
|
364
|
+
this.clearCurrentUnit();
|
|
343
365
|
this.currentTraceId = null;
|
|
344
366
|
this.currentTurnId = null;
|
|
345
367
|
this.currentUnitRouting = null;
|
|
@@ -362,6 +384,7 @@ export class AutoSession {
|
|
|
362
384
|
this.verificationRetryCount.clear();
|
|
363
385
|
this.verificationRetryFailureHashes.clear();
|
|
364
386
|
this.exhaustedVerificationUnits.clear();
|
|
387
|
+
this.zeroToolRetryCount.clear();
|
|
365
388
|
this.pausedSessionFile = null;
|
|
366
389
|
this.pausedUnitType = null;
|
|
367
390
|
this.pausedUnitId = null;
|
|
@@ -14,10 +14,21 @@
|
|
|
14
14
|
|
|
15
15
|
import type { GSDState } from "./types.js";
|
|
16
16
|
import type { GSDPreferences } from "./preferences.js";
|
|
17
|
-
import type { UatType } from "./files.js";
|
|
18
17
|
import type { MinimalModelRegistry } from "./context-budget.js";
|
|
19
18
|
import { loadFile, extractUatType, loadActiveOverrides } from "./files.js";
|
|
20
|
-
import {
|
|
19
|
+
import { getUatBrowserToolSupportError, type UatType } from "./uat-policy.js";
|
|
20
|
+
import {
|
|
21
|
+
isDbAvailable,
|
|
22
|
+
getMilestoneSlices,
|
|
23
|
+
getPendingGatesForTurn,
|
|
24
|
+
markPendingGatesOmittedForTurn,
|
|
25
|
+
getMilestone,
|
|
26
|
+
insertArtifact,
|
|
27
|
+
insertAssessment,
|
|
28
|
+
setSliceSketchFlag,
|
|
29
|
+
transaction,
|
|
30
|
+
getAssessment,
|
|
31
|
+
} from "./gsd-db.js";
|
|
21
32
|
import { isClosedStatus } from "./status-guards.js";
|
|
22
33
|
import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
|
|
23
34
|
|
|
@@ -67,7 +78,7 @@ import {
|
|
|
67
78
|
checkNeedsReassessment,
|
|
68
79
|
checkNeedsRunUat,
|
|
69
80
|
} from "./auto-prompts.js";
|
|
70
|
-
import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
|
|
81
|
+
import { resolveModelWithFallbacksForUnit, resolveThinkingLevelForUnit } from "./preferences-models.js";
|
|
71
82
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
72
83
|
import { selectReactiveDispatchBatch } from "./uok/execution-graph.js";
|
|
73
84
|
import { getMilestonePipelineVariant } from "./milestone-scope-classifier.js";
|
|
@@ -76,6 +87,10 @@ import { isAutoActive } from "./auto.js";
|
|
|
76
87
|
import { markDepthVerified } from "./bootstrap/write-gate.js";
|
|
77
88
|
import { ensureWorkflowPreferencesCaptured } from "./planning-depth.js";
|
|
78
89
|
import { MILESTONE_ID_RE } from "./milestone-ids.js";
|
|
90
|
+
import {
|
|
91
|
+
getWorkflowTransportSupportError,
|
|
92
|
+
getRequiredWorkflowToolsForAutoUnit,
|
|
93
|
+
} from "./workflow-mcp.js";
|
|
79
94
|
import {
|
|
80
95
|
PROJECT_RESEARCH_INFLIGHT_MARKER,
|
|
81
96
|
} from "./project-research-policy.js";
|
|
@@ -136,6 +151,12 @@ export interface DispatchContext {
|
|
|
136
151
|
modelRegistry?: MinimalModelRegistry;
|
|
137
152
|
/** Session model provider, used for provider-specific effective context windows. */
|
|
138
153
|
sessionProvider?: string;
|
|
154
|
+
/** Active tools in the current session, used for transport preflight checks. */
|
|
155
|
+
activeTools?: string[];
|
|
156
|
+
/** Session model base URL, used for transport preflight checks. */
|
|
157
|
+
sessionBaseUrl?: string;
|
|
158
|
+
/** Session model auth mode, used for transport preflight checks. */
|
|
159
|
+
sessionAuthMode?: "apiKey" | "oauth" | "externalCli" | "none";
|
|
139
160
|
}
|
|
140
161
|
|
|
141
162
|
function resolveExistingExpectedArtifact(
|
|
@@ -419,6 +440,53 @@ export function findMissingSummaries(basePath: string, mid: string): string[] {
|
|
|
419
440
|
.map(s => s.id);
|
|
420
441
|
}
|
|
421
442
|
|
|
443
|
+
function stringField(row: Record<string, unknown> | null, key: string): string | null {
|
|
444
|
+
const value = row?.[key];
|
|
445
|
+
return typeof value === "string" ? value : null;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function stripGsdPrefix(path: string): string {
|
|
449
|
+
return path.startsWith(".gsd/") ? path.slice(".gsd/".length) : path;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
function persistSliceAssessmentBackfill(
|
|
453
|
+
assessmentRelPath: string,
|
|
454
|
+
mid: string,
|
|
455
|
+
sliceId: string,
|
|
456
|
+
content: string,
|
|
457
|
+
): void {
|
|
458
|
+
const artifactPath = stripGsdPrefix(assessmentRelPath);
|
|
459
|
+
const existingAssessment =
|
|
460
|
+
getAssessment(assessmentRelPath) ??
|
|
461
|
+
getAssessment(artifactPath);
|
|
462
|
+
const scope = stringField(existingAssessment, "scope") ?? "run-uat";
|
|
463
|
+
const status = stringField(existingAssessment, "status") ??
|
|
464
|
+
extractVerdict(content)?.toLowerCase() ??
|
|
465
|
+
"unknown";
|
|
466
|
+
|
|
467
|
+
transaction(() => {
|
|
468
|
+
insertArtifact({
|
|
469
|
+
path: artifactPath,
|
|
470
|
+
artifact_type: "ASSESSMENT",
|
|
471
|
+
milestone_id: mid,
|
|
472
|
+
slice_id: sliceId,
|
|
473
|
+
task_id: null,
|
|
474
|
+
full_content: content,
|
|
475
|
+
});
|
|
476
|
+
if (!getAssessment(assessmentRelPath)) {
|
|
477
|
+
insertAssessment({
|
|
478
|
+
path: assessmentRelPath,
|
|
479
|
+
milestoneId: mid,
|
|
480
|
+
sliceId,
|
|
481
|
+
taskId: null,
|
|
482
|
+
status,
|
|
483
|
+
scope,
|
|
484
|
+
fullContent: content,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
422
490
|
function backfillMissingAssessmentsFromSummaries(basePath: string, mid: string): void {
|
|
423
491
|
const completedSliceIds = new Set<string>();
|
|
424
492
|
if (isDbAvailable()) {
|
|
@@ -447,11 +515,12 @@ function backfillMissingAssessmentsFromSummaries(basePath: string, mid: string):
|
|
|
447
515
|
const slicePath = resolveSlicePath(basePath, mid, sliceId);
|
|
448
516
|
const assessmentPath = resolveSliceFile(basePath, mid, sliceId, "ASSESSMENT")
|
|
449
517
|
?? (slicePath ? join(slicePath, buildSliceFileName(sliceId, "ASSESSMENT")) : null);
|
|
450
|
-
if (!assessmentPath
|
|
518
|
+
if (!assessmentPath) continue;
|
|
451
519
|
|
|
452
|
-
|
|
520
|
+
const assessmentRelPath = relSliceFile(basePath, mid, sliceId, "ASSESSMENT");
|
|
453
521
|
const now = new Date().toISOString();
|
|
454
|
-
const
|
|
522
|
+
const didCreateAssessment = !existsSync(assessmentPath);
|
|
523
|
+
const content = didCreateAssessment ? [
|
|
455
524
|
"---",
|
|
456
525
|
`sliceId: ${sliceId}`,
|
|
457
526
|
"verdict: PASS",
|
|
@@ -463,8 +532,20 @@ function backfillMissingAssessmentsFromSummaries(basePath: string, mid: string):
|
|
|
463
532
|
"Auto-created during milestone validation because this completed slice had a SUMMARY but no ASSESSMENT artifact.",
|
|
464
533
|
"No additional reassessment changes were detected in this backfill step.",
|
|
465
534
|
"",
|
|
466
|
-
].join("\n");
|
|
467
|
-
|
|
535
|
+
].join("\n") : readFileSync(assessmentPath, "utf-8");
|
|
536
|
+
|
|
537
|
+
if (isDbAvailable()) {
|
|
538
|
+
try {
|
|
539
|
+
persistSliceAssessmentBackfill(assessmentRelPath, mid, sliceId, content);
|
|
540
|
+
} catch (err) {
|
|
541
|
+
logWarning("dispatch", `failed to backfill assessment DB rows for ${mid}/${sliceId}: ${(err as Error).message}`);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
if (didCreateAssessment) {
|
|
546
|
+
mkdirSync(dirname(assessmentPath), { recursive: true });
|
|
547
|
+
writeFileSync(assessmentPath, content, "utf-8");
|
|
548
|
+
}
|
|
468
549
|
}
|
|
469
550
|
}
|
|
470
551
|
|
|
@@ -653,11 +734,32 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
653
734
|
},
|
|
654
735
|
{
|
|
655
736
|
name: "run-uat (post-completion)",
|
|
656
|
-
match: async ({ state, mid, basePath, prefs }) => {
|
|
737
|
+
match: async ({ state, mid, basePath, prefs, sessionProvider, sessionAuthMode, activeTools, sessionBaseUrl }) => {
|
|
657
738
|
const needsRunUat = await checkNeedsRunUat(basePath, mid, state, prefs);
|
|
658
739
|
if (!needsRunUat) return null;
|
|
659
740
|
const { sliceId, uatType } = needsRunUat;
|
|
660
741
|
|
|
742
|
+
// Transport preflight: verify required MCP tools are actually connected
|
|
743
|
+
// before consuming a retry attempt. Fixes tool-starved sessions burning
|
|
744
|
+
// all MAX_UAT_ATTEMPTS before stopping (#477).
|
|
745
|
+
const transportError = getWorkflowTransportSupportError(
|
|
746
|
+
sessionProvider,
|
|
747
|
+
getRequiredWorkflowToolsForAutoUnit("run-uat"),
|
|
748
|
+
{ projectRoot: basePath, surface: "auto-mode", unitType: "run-uat", authMode: sessionAuthMode, baseUrl: sessionBaseUrl, activeTools },
|
|
749
|
+
);
|
|
750
|
+
if (transportError) {
|
|
751
|
+
return { action: "stop" as const, reason: transportError, level: "warning" as const };
|
|
752
|
+
}
|
|
753
|
+
const browserToolError = getUatBrowserToolSupportError({
|
|
754
|
+
uatType,
|
|
755
|
+
activeTools,
|
|
756
|
+
milestoneId: mid,
|
|
757
|
+
sliceId,
|
|
758
|
+
});
|
|
759
|
+
if (browserToolError) {
|
|
760
|
+
return { action: "stop" as const, reason: browserToolError, level: "warning" as const };
|
|
761
|
+
}
|
|
762
|
+
|
|
661
763
|
// Cap run-uat dispatch attempts to prevent infinite replay (#3624).
|
|
662
764
|
// Check before incrementing so an exhausted counter cannot create a
|
|
663
765
|
// no-progress skip loop that starves later dispatch rules.
|
|
@@ -1063,6 +1165,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1063
1165
|
researchReadySlices,
|
|
1064
1166
|
basePath,
|
|
1065
1167
|
resolveModelWithFallbacksForUnit("subagent")?.primary,
|
|
1168
|
+
resolveThinkingLevelForUnit("subagent"),
|
|
1066
1169
|
),
|
|
1067
1170
|
};
|
|
1068
1171
|
},
|
|
@@ -1232,11 +1335,11 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1232
1335
|
// Gate evaluation is opt-in via preferences
|
|
1233
1336
|
const gateConfig = prefs?.gate_evaluation;
|
|
1234
1337
|
if (!gateConfig?.enabled) {
|
|
1235
|
-
|
|
1338
|
+
markPendingGatesOmittedForTurn(mid, sid, "gate-evaluate");
|
|
1236
1339
|
return { action: "skip" };
|
|
1237
1340
|
}
|
|
1238
1341
|
|
|
1239
|
-
const pending =
|
|
1342
|
+
const pending = getPendingGatesForTurn(mid, sid, "gate-evaluate");
|
|
1240
1343
|
if (pending.length === 0) return { action: "skip" };
|
|
1241
1344
|
|
|
1242
1345
|
return {
|
|
@@ -1250,6 +1353,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1250
1353
|
sTitle,
|
|
1251
1354
|
basePath,
|
|
1252
1355
|
resolveModelWithFallbacksForUnit("subagent")?.primary,
|
|
1356
|
+
resolveThinkingLevelForUnit("subagent"),
|
|
1253
1357
|
),
|
|
1254
1358
|
};
|
|
1255
1359
|
},
|
|
@@ -1295,6 +1399,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1295
1399
|
if (resolveSliceFile(basePath, mid, sid, "REACTIVE-BLOCKER")) return null;
|
|
1296
1400
|
const maxParallel = reactiveConfig?.max_parallel ?? 2;
|
|
1297
1401
|
const subagentModel = reactiveConfig?.subagent_model ?? resolveModelWithFallbacksForUnit("subagent")?.primary;
|
|
1402
|
+
const subagentThinking = resolveThinkingLevelForUnit("subagent");
|
|
1298
1403
|
// Default-on safety threshold: only activate reactive dispatch when at
|
|
1299
1404
|
// least N tasks are ready. Users who explicitly enabled reactive_execution
|
|
1300
1405
|
// keep the legacy threshold of 2 (matches the prior "any parallelism is
|
|
@@ -1381,7 +1486,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1381
1486
|
selected,
|
|
1382
1487
|
basePath,
|
|
1383
1488
|
subagentModel,
|
|
1384
|
-
{ sessionContextWindow, modelRegistry, sessionProvider },
|
|
1489
|
+
{ sessionContextWindow, modelRegistry, sessionProvider, subagentThinking },
|
|
1385
1490
|
),
|
|
1386
1491
|
};
|
|
1387
1492
|
} catch (err) {
|