gsd-pi 2.77.0-dev.c9c8932c6 → 2.77.0-dev.cfd69e714
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 +1 -1
- package/dist/claude-cli-check.js +5 -1
- package/dist/cli-web-branch.d.ts +1 -0
- package/dist/cli-web-branch.js +3 -0
- package/dist/cli.js +24 -2
- package/dist/headless.js +49 -4
- package/dist/provider-migrations.d.ts +18 -0
- package/dist/provider-migrations.js +14 -0
- package/dist/resource-loader.d.ts +40 -0
- package/dist/resource-loader.js +32 -13
- package/dist/resources/extensions/browser-tools/capture.js +9 -0
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
- package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
- package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
- package/dist/resources/extensions/claude-code-cli/readiness.js +5 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +495 -27
- package/dist/resources/extensions/github-sync/templates.js +103 -0
- package/dist/resources/extensions/google-search/index.js +3 -2
- package/dist/resources/extensions/gsd/abandon-detect.js +44 -0
- package/dist/resources/extensions/gsd/auto/loop.js +124 -2
- package/dist/resources/extensions/gsd/auto/phases.js +57 -39
- package/dist/resources/extensions/gsd/auto/resolve.js +24 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +10 -2
- package/dist/resources/extensions/gsd/auto/session.js +6 -2
- package/dist/resources/extensions/gsd/auto/turn-epoch.js +95 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +166 -29
- package/dist/resources/extensions/gsd/auto-loop.js +1 -1
- package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
- package/dist/resources/extensions/gsd/auto-post-unit.js +181 -64
- package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
- package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
- package/dist/resources/extensions/gsd/auto-start.js +107 -29
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +11 -5
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +11 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +180 -34
- package/dist/resources/extensions/gsd/auto.js +80 -21
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
- package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +5 -6
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +31 -4
- package/dist/resources/extensions/gsd/component-loader.js +447 -0
- package/dist/resources/extensions/gsd/component-types.js +69 -0
- package/dist/resources/extensions/gsd/context-store.js +23 -7
- package/dist/resources/extensions/gsd/detection.js +49 -1
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/file-lock.js +49 -9
- package/dist/resources/extensions/gsd/forensics.js +106 -0
- package/dist/resources/extensions/gsd/gate-registry.js +2 -2
- package/dist/resources/extensions/gsd/git-constants.js +28 -1
- package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
- package/dist/resources/extensions/gsd/git-service.js +127 -2
- package/dist/resources/extensions/gsd/gitignore.js +1 -0
- package/dist/resources/extensions/gsd/gsd-db.js +6 -3
- package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -1
- package/dist/resources/extensions/gsd/guided-flow.js +39 -13
- package/dist/resources/extensions/gsd/journal.js +17 -2
- package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
- package/dist/resources/extensions/gsd/milestone-actions.js +15 -0
- package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
- package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
- package/dist/resources/extensions/gsd/model-router.js +6 -0
- package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
- package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
- package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
- package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
- package/dist/resources/extensions/gsd/reports.js +5 -4
- package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
- package/dist/resources/extensions/gsd/service-tier.js +5 -2
- package/dist/resources/extensions/gsd/session-lock.js +19 -10
- package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
- package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
- package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
- package/dist/resources/extensions/gsd/state.js +69 -58
- package/dist/resources/extensions/gsd/sync-lock.js +98 -42
- package/dist/resources/extensions/gsd/tools/complete-slice.js +21 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +31 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
- package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
- package/dist/resources/extensions/gsd/uok/audit.js +18 -2
- package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
- package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
- package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
- package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
- package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
- package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
- package/dist/resources/extensions/gsd/uok/writer.js +82 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +10 -2
- package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +86 -8
- package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
- package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
- package/dist/resources/extensions/mcp-client/auth.js +10 -1
- package/dist/resources/extensions/mcp-client/index.js +121 -10
- package/dist/resources/extensions/ollama/index.js +5 -1
- package/dist/resources/extensions/remote-questions/manager.js +11 -5
- package/dist/resources/skills/create-skill/SKILL.md +2 -2
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
- package/dist/resources/skills/create-skill/workflows/audit-skill.md +4 -4
- package/dist/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
- 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 +12 -12
- 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 +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.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/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +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 +12 -12
- package/dist/web/standalone/.next/server/chunks/1926.js +1 -0
- package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/middleware-react-loadable-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/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-1832629448831fdc.js → webpack-2e68521d7c82f7c2.js} +1 -1
- package/package.json +4 -5
- package/packages/daemon/src/logger.ts +4 -3
- package/packages/mcp-server/README.md +3 -3
- package/packages/mcp-server/dist/env-writer.d.ts +1 -0
- package/packages/mcp-server/dist/env-writer.d.ts.map +1 -1
- package/packages/mcp-server/dist/env-writer.js +74 -6
- package/packages/mcp-server/dist/env-writer.js.map +1 -1
- package/packages/mcp-server/dist/server.d.ts +24 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +111 -87
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +15 -6
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/env-writer.test.ts +79 -1
- package/packages/mcp-server/src/env-writer.ts +76 -6
- package/packages/mcp-server/src/mcp-server.test.ts +25 -3
- package/packages/mcp-server/src/readers/graph.test.ts +87 -15
- package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
- package/packages/mcp-server/src/server.ts +158 -105
- package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
- package/packages/mcp-server/src/workflow-tools.ts +19 -6
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
- package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
- package/packages/native/src/__tests__/ps.test.mjs +14 -8
- package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
- package/packages/native/src/__tests__/truncate.test.mjs +17 -2
- package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
- package/packages/pi-agent-core/src/agent.test.ts +96 -102
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/capability-patches.js +9 -2
- package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
- package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
- package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
- package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai.js +17 -0
- package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.test.js +43 -70
- package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
- package/packages/pi-ai/dist/models.test.js +36 -11
- package/packages/pi-ai/dist/models.test.js.map +1 -1
- package/packages/pi-ai/scripts/generate-models.ts +44 -0
- package/packages/pi-ai/src/models/capability-patches.ts +10 -2
- package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
- package/packages/pi-ai/src/models/generated/openai.ts +17 -0
- package/packages/pi-ai/src/models.generated.test.ts +46 -73
- package/packages/pi-ai/src/models.test.ts +48 -11
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
- package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +21 -16
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js +130 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +4 -1
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.test.js +19 -1
- package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -0
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js +15 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +7 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +31 -9
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +105 -13
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
- package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
- package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +24 -17
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
- package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
- package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
- package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
- package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
- package/packages/pi-coding-agent/src/core/sdk.test.ts +25 -1
- package/packages/pi-coding-agent/src/core/sdk.ts +10 -3
- package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
- package/packages/pi-coding-agent/src/index.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +17 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +14 -5
- package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +45 -11
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
- package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +51 -6
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
- package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
- package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
- package/packages/pi-tui/dist/components/editor.d.ts +14 -0
- package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/editor.js +19 -0
- package/packages/pi-tui/dist/components/editor.js.map +1 -1
- package/packages/pi-tui/dist/components/image.test.js +6 -5
- package/packages/pi-tui/dist/components/image.test.js.map +1 -1
- package/packages/pi-tui/dist/editor-component.d.ts +2 -0
- package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
- package/packages/pi-tui/dist/editor-component.js.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.d.ts +7 -0
- package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.js +20 -0
- package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
- package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
- package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +62 -6
- package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
- package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
- package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
- package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
- package/packages/pi-tui/src/components/editor.ts +22 -0
- package/packages/pi-tui/src/components/image.test.ts +10 -5
- package/packages/pi-tui/src/editor-component.ts +3 -0
- package/packages/pi-tui/src/stdin-buffer.ts +26 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/dist/rpc-client.test.js +101 -51
- package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
- package/packages/rpc-client/src/rpc-client.test.ts +109 -52
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/scripts/install.js +15 -1
- package/src/resources/extensions/browser-tools/capture.ts +12 -0
- package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
- package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
- package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
- package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
- package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +5 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +532 -29
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +941 -91
- package/src/resources/extensions/github-sync/templates.ts +151 -0
- package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
- package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
- package/src/resources/extensions/google-search/index.ts +3 -2
- package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
- package/src/resources/extensions/gsd/auto/loop.ts +142 -2
- package/src/resources/extensions/gsd/auto/phases.ts +62 -38
- package/src/resources/extensions/gsd/auto/resolve.ts +29 -0
- package/src/resources/extensions/gsd/auto/run-unit.ts +16 -2
- package/src/resources/extensions/gsd/auto/session.ts +7 -2
- package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +176 -29
- package/src/resources/extensions/gsd/auto-loop.ts +1 -1
- package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
- package/src/resources/extensions/gsd/auto-post-unit.ts +193 -73
- package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
- package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
- package/src/resources/extensions/gsd/auto-start.ts +127 -9
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -5
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +14 -3
- package/src/resources/extensions/gsd/auto-worktree.ts +190 -31
- package/src/resources/extensions/gsd/auto.ts +95 -23
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
- package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +6 -6
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +27 -8
- package/src/resources/extensions/gsd/component-loader.ts +598 -0
- package/src/resources/extensions/gsd/component-types.ts +362 -0
- package/src/resources/extensions/gsd/context-store.ts +25 -8
- package/src/resources/extensions/gsd/detection.ts +58 -1
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/file-lock.ts +84 -11
- package/src/resources/extensions/gsd/forensics.ts +118 -1
- package/src/resources/extensions/gsd/gate-registry.ts +2 -2
- package/src/resources/extensions/gsd/git-constants.ts +30 -1
- package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
- package/src/resources/extensions/gsd/git-service.ts +150 -2
- package/src/resources/extensions/gsd/gitignore.ts +1 -0
- package/src/resources/extensions/gsd/gsd-db.ts +6 -3
- package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -1
- package/src/resources/extensions/gsd/guided-flow.ts +57 -14
- package/src/resources/extensions/gsd/journal.ts +38 -3
- package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
- package/src/resources/extensions/gsd/milestone-actions.ts +18 -0
- package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
- package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
- package/src/resources/extensions/gsd/model-router.ts +6 -0
- package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
- package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
- package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
- package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
- package/src/resources/extensions/gsd/reports.ts +5 -4
- package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
- package/src/resources/extensions/gsd/service-tier.ts +5 -2
- package/src/resources/extensions/gsd/session-lock.ts +20 -10
- package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
- package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
- package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
- package/src/resources/extensions/gsd/state.ts +76 -66
- package/src/resources/extensions/gsd/sync-lock.ts +97 -39
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
- package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +135 -285
- package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
- package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
- package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
- package/src/resources/extensions/gsd/tests/file-lock.test.ts +86 -12
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
- package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
- package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
- package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
- package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
- package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +54 -41
- package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +213 -0
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +13 -7
- package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
- package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
- package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
- package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
- package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
- package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
- package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
- package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
- package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
- package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +50 -2
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +162 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
- package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
- package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
- package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
- package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
- package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
- package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
- package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
- package/src/resources/extensions/gsd/tools/complete-slice.ts +38 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +49 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
- package/src/resources/extensions/gsd/types.ts +3 -3
- package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
- package/src/resources/extensions/gsd/uok/audit.ts +20 -2
- package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
- package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
- package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
- package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
- package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
- package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
- package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
- package/src/resources/extensions/gsd/uok/writer.ts +113 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +22 -3
- package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +109 -7
- package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
- package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
- package/src/resources/extensions/mcp-client/auth.ts +12 -1
- package/src/resources/extensions/mcp-client/index.ts +132 -11
- package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
- package/src/resources/extensions/ollama/index.ts +5 -1
- package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
- package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
- package/src/resources/extensions/remote-questions/manager.ts +36 -4
- package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
- package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
- package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
- package/src/resources/skills/create-skill/SKILL.md +2 -2
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
- package/src/resources/skills/create-skill/workflows/audit-skill.md +4 -4
- package/src/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
- package/dist/web/standalone/.next/server/chunks/7461.js +0 -1
- package/dist/web/standalone/.next/static/chunks/2826.d445fb428ef41fa1.js +0 -9
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
- package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
- package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
- package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
- package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
- package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
- package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
- package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
- package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
- package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
- package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
- package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
- /package/dist/web/standalone/.next/static/{H51SzzS_EEgdBsDVhrLBv → SvCJDZPQW104bR1KnBQg1}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{H51SzzS_EEgdBsDVhrLBv → SvCJDZPQW104bR1KnBQg1}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* auto/turn-epoch.ts — Turn generation counter + AsyncLocalStorage-backed
|
|
3
|
+
* capture for stale-turn write dropping.
|
|
4
|
+
*
|
|
5
|
+
* Problem: when auto-timeout-recovery synthetically resolves a timed-out
|
|
6
|
+
* unit so the loop can advance, the original LLM turn keeps running in the
|
|
7
|
+
* background. Its subsequent writes (journal events, audit events, tool
|
|
8
|
+
* calls that flow through closeout) then race the replacement unit's
|
|
9
|
+
* writes. DB-level guards (complete-task/complete-slice) block double
|
|
10
|
+
* state transitions, but journal/audit/closeout side-effects still fire
|
|
11
|
+
* with fresh identifiers and pollute forensics.
|
|
12
|
+
*
|
|
13
|
+
* Containment: every time we decide a turn is done (timeout recovery,
|
|
14
|
+
* explicit cancellation), bump a module-level generation counter.
|
|
15
|
+
* Turn-aware call sites wrap their body in `runWithTurnGeneration`, which
|
|
16
|
+
* captures the generation into AsyncLocalStorage. Write sites deep in the
|
|
17
|
+
* stack call `isStaleWrite` — if the captured generation is older than
|
|
18
|
+
* current, the turn has been superseded and the write is dropped.
|
|
19
|
+
*
|
|
20
|
+
* Failure mode: if AsyncLocalStorage context is lost across some exotic
|
|
21
|
+
* async boundary (e.g. a native-side worker callback), the write site sees
|
|
22
|
+
* `no-store` and falls through to current behavior — the write proceeds
|
|
23
|
+
* normally. That is a safe default; the correctness regression is only
|
|
24
|
+
* "noisier forensics under rare boundary loss," not duplicated state.
|
|
25
|
+
*/
|
|
26
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
27
|
+
import { debugLog } from "../debug-logger.js";
|
|
28
|
+
let _currentGeneration = 0;
|
|
29
|
+
const turnContext = new AsyncLocalStorage();
|
|
30
|
+
/** Current turn generation. Mutated only by bumpTurnGeneration. */
|
|
31
|
+
export function getCurrentTurnGeneration() {
|
|
32
|
+
return _currentGeneration;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Bump the turn generation and return the new value. Every caller should
|
|
36
|
+
* pass a short `reason` string so forensics can reconstruct why a given
|
|
37
|
+
* turn was marked stale.
|
|
38
|
+
*/
|
|
39
|
+
export function bumpTurnGeneration(reason) {
|
|
40
|
+
_currentGeneration += 1;
|
|
41
|
+
debugLog("turnEpoch.bump", { reason, newGeneration: _currentGeneration });
|
|
42
|
+
return _currentGeneration;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Run fn() with `capturedGen` attached to AsyncLocalStorage so that any
|
|
46
|
+
* write site reached from within fn() can check for staleness without
|
|
47
|
+
* parameter threading.
|
|
48
|
+
*/
|
|
49
|
+
export function runWithTurnGeneration(capturedGen, fn) {
|
|
50
|
+
return turnContext.run({ capturedGen }, fn);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* True when the current async context was started at a turn generation
|
|
54
|
+
* older than the current one — meaning the turn has been superseded by
|
|
55
|
+
* recovery/cancellation since it began.
|
|
56
|
+
*
|
|
57
|
+
* Returns false when there is no captured generation (e.g. the write is
|
|
58
|
+
* happening outside any wrapped turn). That is the safe default: writes
|
|
59
|
+
* proceed as they did before this epoch was introduced.
|
|
60
|
+
*/
|
|
61
|
+
export function isStaleWrite(component) {
|
|
62
|
+
const store = turnContext.getStore();
|
|
63
|
+
if (!store)
|
|
64
|
+
return false;
|
|
65
|
+
const captured = store.capturedGen;
|
|
66
|
+
const current = _currentGeneration;
|
|
67
|
+
if (captured < current) {
|
|
68
|
+
debugLog("turnEpoch.stale", {
|
|
69
|
+
component: component ?? "unknown",
|
|
70
|
+
captured,
|
|
71
|
+
current,
|
|
72
|
+
});
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Snapshot of both the captured turn generation and the current one.
|
|
79
|
+
* Used by closeoutUnit to persist an orphan-marker entry instead of
|
|
80
|
+
* silently skipping the full closeout on a stale turn.
|
|
81
|
+
*/
|
|
82
|
+
export function describeTurnEpoch() {
|
|
83
|
+
const store = turnContext.getStore();
|
|
84
|
+
const captured = store?.capturedGen ?? null;
|
|
85
|
+
const current = _currentGeneration;
|
|
86
|
+
return {
|
|
87
|
+
captured,
|
|
88
|
+
current,
|
|
89
|
+
stale: captured !== null && captured < current,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/** Test helper — resets module state so tests start from a known baseline. */
|
|
93
|
+
export function _resetTurnEpoch() {
|
|
94
|
+
_currentGeneration = 0;
|
|
95
|
+
}
|
|
@@ -17,11 +17,47 @@ import { parseRoadmap } from "./parsers-legacy.js";
|
|
|
17
17
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
18
18
|
import { logWarning, logError } from "./workflow-logger.js";
|
|
19
19
|
import { join } from "node:path";
|
|
20
|
-
import { hasImplementationArtifacts
|
|
20
|
+
import { hasImplementationArtifacts } from "./auto-recovery.js";
|
|
21
|
+
import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
|
|
21
22
|
import { buildDiscussMilestonePrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildRefineSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, buildGateEvaluatePrompt, buildParallelResearchSlicesPrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
|
|
22
23
|
import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
|
|
23
24
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
24
25
|
import { selectReactiveDispatchBatch } from "./uok/execution-graph.js";
|
|
26
|
+
import { getMilestonePipelineVariant } from "./milestone-scope-classifier.js";
|
|
27
|
+
import { EXECUTION_ENTRY_PHASES, hasFinalizedMilestoneContext } from "./uok/plan-v2.js";
|
|
28
|
+
import { isAutoActive } from "./auto.js";
|
|
29
|
+
import { markDepthVerified } from "./bootstrap/write-gate.js";
|
|
30
|
+
let reassessmentChecker = checkNeedsReassessment;
|
|
31
|
+
export function setReassessmentCheckerForTest(checker) {
|
|
32
|
+
const previous = reassessmentChecker;
|
|
33
|
+
reassessmentChecker = checker;
|
|
34
|
+
return () => {
|
|
35
|
+
reassessmentChecker = previous;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async function readUatGateVerdict(basePath, mid, sliceId) {
|
|
39
|
+
const uatFile = resolveSliceFile(basePath, mid, sliceId, "UAT");
|
|
40
|
+
const assessmentFile = resolveSliceFile(basePath, mid, sliceId, "ASSESSMENT");
|
|
41
|
+
const uatContent = uatFile ? await loadFile(uatFile) : null;
|
|
42
|
+
const uatType = uatContent ? extractUatType(uatContent) : undefined;
|
|
43
|
+
const assessmentContent = assessmentFile ? await loadFile(assessmentFile) : null;
|
|
44
|
+
if (assessmentContent) {
|
|
45
|
+
const assessmentVerdict = extractVerdict(assessmentContent);
|
|
46
|
+
if (assessmentVerdict) {
|
|
47
|
+
return {
|
|
48
|
+
verdict: assessmentVerdict,
|
|
49
|
+
uatType: uatType ?? extractUatType(assessmentContent),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (uatContent) {
|
|
54
|
+
const legacyUatVerdict = extractVerdict(uatContent);
|
|
55
|
+
if (legacyUatVerdict) {
|
|
56
|
+
return { verdict: legacyUatVerdict, uatType };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
25
61
|
function missingSliceStop(mid, phase) {
|
|
26
62
|
return {
|
|
27
63
|
action: "stop",
|
|
@@ -155,6 +191,45 @@ export const DISPATCH_RULES = [
|
|
|
155
191
|
};
|
|
156
192
|
},
|
|
157
193
|
},
|
|
194
|
+
{
|
|
195
|
+
// #4671 — Recovery path for execution-entry phases with missing CONTEXT.md.
|
|
196
|
+
//
|
|
197
|
+
// Once `deriveStateFromDb` returns an execution-entry phase (executing /
|
|
198
|
+
// summarizing / validating-milestone / completing-milestone), the
|
|
199
|
+
// pre-planning guard at `pre-planning (no context) → discuss-milestone`
|
|
200
|
+
// no longer fires. The plan-v2 gate correctly detects the missing context
|
|
201
|
+
// but can only block — it cannot redispatch. Without this rule the
|
|
202
|
+
// milestone is stuck until `/gsd doctor heal` repairs it (and heal
|
|
203
|
+
// historically missed this check too).
|
|
204
|
+
//
|
|
205
|
+
// Fire BEFORE the execution-entry phase rules so we redispatch to
|
|
206
|
+
// `discuss-milestone` instead of hitting the plan-v2 gate.
|
|
207
|
+
name: "execution-entry phase (no context) → discuss-milestone",
|
|
208
|
+
match: async ({ state, mid, midTitle, basePath, structuredQuestionsAvailable }) => {
|
|
209
|
+
if (!EXECUTION_ENTRY_PHASES.has(state.phase))
|
|
210
|
+
return null;
|
|
211
|
+
// Align with the plan-v2 gate's lookup semantics: whitespace-only counts
|
|
212
|
+
// as missing, and an auto worktree may fall back to GSD_PROJECT_ROOT.
|
|
213
|
+
if (hasFinalizedMilestoneContext(basePath, mid))
|
|
214
|
+
return null;
|
|
215
|
+
// H6 fix (#4973): In auto-mode there is no human to answer the
|
|
216
|
+
// depth-verification ask_user_questions, so the write-gate deadlocks.
|
|
217
|
+
// Pre-mark the milestone as depth-verified so gsd_summary_save({artifact_type:"CONTEXT"})
|
|
218
|
+
// is not blocked. Safe ordering: session_switch fires clearDiscussionFlowState()
|
|
219
|
+
// (register-hooks.ts:106) before before_agent_start, which fires before resolveDispatch
|
|
220
|
+
// reaches this match fn — so this call always happens after any session-switch reset.
|
|
221
|
+
// Interactive sessions (isAutoActive()===false) are unaffected.
|
|
222
|
+
if (isAutoActive()) {
|
|
223
|
+
markDepthVerified(mid, basePath);
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
action: "dispatch",
|
|
227
|
+
unitType: "discuss-milestone",
|
|
228
|
+
unitId: mid,
|
|
229
|
+
prompt: await buildDiscussMilestonePrompt(mid, midTitle, basePath, structuredQuestionsAvailable),
|
|
230
|
+
};
|
|
231
|
+
},
|
|
232
|
+
},
|
|
158
233
|
{
|
|
159
234
|
name: "summarizing → complete-slice",
|
|
160
235
|
match: async ({ state, mid, midTitle, basePath }) => {
|
|
@@ -205,27 +280,29 @@ export const DISPATCH_RULES = [
|
|
|
205
280
|
// Only applies when UAT dispatch is enabled
|
|
206
281
|
if (!prefs?.uat_dispatch)
|
|
207
282
|
return null;
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
let completedSliceIds;
|
|
283
|
+
// DB-first: prefer closed slices from DB; fall back to ROADMAP on disk.
|
|
284
|
+
let closedSliceIds;
|
|
211
285
|
if (isDbAvailable()) {
|
|
212
|
-
|
|
213
|
-
.filter(s => s.status
|
|
286
|
+
closedSliceIds = getMilestoneSlices(mid)
|
|
287
|
+
.filter(s => isClosedStatus(s.status))
|
|
214
288
|
.map(s => s.id);
|
|
215
289
|
}
|
|
216
290
|
else {
|
|
217
|
-
|
|
291
|
+
// Filesystem fallback for degraded / unmigrated projects.
|
|
292
|
+
// `slice.done` in the parsed ROADMAP is the disk-level closed signal.
|
|
293
|
+
const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
|
|
294
|
+
const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
|
|
295
|
+
if (!roadmapContent)
|
|
296
|
+
return null;
|
|
297
|
+
const roadmap = parseRoadmap(roadmapContent);
|
|
298
|
+
closedSliceIds = roadmap.slices.filter(s => s.done).map(s => s.id);
|
|
218
299
|
}
|
|
219
|
-
for (const sliceId of
|
|
220
|
-
const
|
|
221
|
-
if (!
|
|
300
|
+
for (const sliceId of closedSliceIds) {
|
|
301
|
+
const result = await readUatGateVerdict(basePath, mid, sliceId);
|
|
302
|
+
if (!result)
|
|
222
303
|
continue;
|
|
223
|
-
const
|
|
224
|
-
if (!
|
|
225
|
-
continue;
|
|
226
|
-
const verdict = extractVerdict(content);
|
|
227
|
-
const uatType = extractUatType(content);
|
|
228
|
-
if (verdict && !isAcceptableUatVerdict(verdict, uatType)) {
|
|
304
|
+
const { verdict, uatType } = result;
|
|
305
|
+
if (!isAcceptableUatVerdict(verdict, uatType)) {
|
|
229
306
|
return {
|
|
230
307
|
action: "stop",
|
|
231
308
|
reason: `UAT verdict for ${sliceId} is "${verdict}" — blocking progression until resolved.\nReview the UAT result and update the verdict to PASS, or re-run /gsd auto after fixing.`,
|
|
@@ -241,12 +318,16 @@ export const DISPATCH_RULES = [
|
|
|
241
318
|
match: async ({ state, mid, midTitle, basePath, prefs }) => {
|
|
242
319
|
if (prefs?.phases?.skip_reassess)
|
|
243
320
|
return null;
|
|
244
|
-
// Default reassess_after_slice to
|
|
245
|
-
// is
|
|
246
|
-
|
|
321
|
+
// Default reassess_after_slice to false per ADR-003 §4 — most reassess
|
|
322
|
+
// units conclude "roadmap is fine" and burn a session for no change.
|
|
323
|
+
// The plan-slice prompt now carries a reassessment preamble so the
|
|
324
|
+
// next slice's planner does JIT roadmap verification at zero extra
|
|
325
|
+
// cost. Opt-in via explicit `reassess_after_slice: true` (e.g.
|
|
326
|
+
// burn-max profile) when you want the dedicated reassess session.
|
|
327
|
+
const reassessEnabled = prefs?.phases?.reassess_after_slice ?? false;
|
|
247
328
|
if (!reassessEnabled)
|
|
248
329
|
return null;
|
|
249
|
-
const needsReassess = await
|
|
330
|
+
const needsReassess = await reassessmentChecker(basePath, mid, state);
|
|
250
331
|
if (!needsReassess)
|
|
251
332
|
return null;
|
|
252
333
|
return {
|
|
@@ -262,6 +343,12 @@ export const DISPATCH_RULES = [
|
|
|
262
343
|
match: async ({ state, mid, midTitle, basePath, structuredQuestionsAvailable }) => {
|
|
263
344
|
if (state.phase !== "needs-discussion")
|
|
264
345
|
return null;
|
|
346
|
+
// H6 fix (#4973): auto-mark depth-verified so the write-gate does not
|
|
347
|
+
// deadlock in non-interactive (auto-mode) runs. See ordering note at
|
|
348
|
+
// "execution-entry phase (no context) → discuss-milestone" above.
|
|
349
|
+
if (isAutoActive()) {
|
|
350
|
+
markDepthVerified(mid, basePath);
|
|
351
|
+
}
|
|
265
352
|
return {
|
|
266
353
|
action: "dispatch",
|
|
267
354
|
unitType: "discuss-milestone",
|
|
@@ -279,6 +366,12 @@ export const DISPATCH_RULES = [
|
|
|
279
366
|
const hasContext = !!(contextFile && (await loadFile(contextFile)));
|
|
280
367
|
if (hasContext)
|
|
281
368
|
return null; // fall through to next rule
|
|
369
|
+
// H6 fix (#4973): auto-mark depth-verified so the write-gate does not
|
|
370
|
+
// deadlock in non-interactive (auto-mode) runs. See ordering note at
|
|
371
|
+
// "execution-entry phase (no context) → discuss-milestone" above.
|
|
372
|
+
if (isAutoActive()) {
|
|
373
|
+
markDepthVerified(mid, basePath);
|
|
374
|
+
}
|
|
282
375
|
return {
|
|
283
376
|
action: "dispatch",
|
|
284
377
|
unitType: "discuss-milestone",
|
|
@@ -319,6 +412,30 @@ export const DISPATCH_RULES = [
|
|
|
319
412
|
};
|
|
320
413
|
},
|
|
321
414
|
},
|
|
415
|
+
{
|
|
416
|
+
name: "planning (require_slice_discussion) → pause for discussion (#3454)",
|
|
417
|
+
match: async ({ state, mid, basePath, prefs }) => {
|
|
418
|
+
if (state.phase !== "planning")
|
|
419
|
+
return null;
|
|
420
|
+
if (!prefs?.phases?.require_slice_discussion)
|
|
421
|
+
return null;
|
|
422
|
+
if (!state.activeSlice)
|
|
423
|
+
return null;
|
|
424
|
+
// Only pause if the slice has no context file yet (discussion not done).
|
|
425
|
+
// resolveSliceFile returns null when the file does not exist on disk,
|
|
426
|
+
// but cachedReaddir could return a stale hit — verify with existsSync
|
|
427
|
+
// so the guard is defence-in-depth and the contract is explicit at the
|
|
428
|
+
// call site.
|
|
429
|
+
const sliceContextFile = resolveSliceFile(basePath, mid, state.activeSlice.id, "CONTEXT");
|
|
430
|
+
if (sliceContextFile && existsSync(sliceContextFile))
|
|
431
|
+
return null; // discussion already done, proceed
|
|
432
|
+
return {
|
|
433
|
+
action: "stop",
|
|
434
|
+
reason: `Slice ${state.activeSlice.id} requires discussion before planning (require_slice_discussion is enabled). Run /gsd discuss to discuss this slice, then /gsd auto to resume.`,
|
|
435
|
+
level: "info",
|
|
436
|
+
};
|
|
437
|
+
},
|
|
438
|
+
},
|
|
322
439
|
{
|
|
323
440
|
// Keep this rule before the single-slice research rule so the multi-slice
|
|
324
441
|
// path wins whenever 2+ slices are ready.
|
|
@@ -328,6 +445,12 @@ export const DISPATCH_RULES = [
|
|
|
328
445
|
return null;
|
|
329
446
|
if (prefs?.phases?.skip_research || prefs?.phases?.skip_slice_research)
|
|
330
447
|
return null;
|
|
448
|
+
// #4781 phase 2: trivial-scope milestones skip dedicated slice research.
|
|
449
|
+
// plan-slice absorbs the lightweight discovery a trivial deliverable
|
|
450
|
+
// needs. Null result (DB unavailable / unknown) falls through to today's
|
|
451
|
+
// behavior.
|
|
452
|
+
if (await getMilestonePipelineVariant(mid) === "trivial")
|
|
453
|
+
return null;
|
|
331
454
|
// Load roadmap to find all slices
|
|
332
455
|
const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
|
|
333
456
|
const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
|
|
@@ -377,6 +500,9 @@ export const DISPATCH_RULES = [
|
|
|
377
500
|
// Phase skip: skip research when preference or profile says so
|
|
378
501
|
if (prefs?.phases?.skip_research || prefs?.phases?.skip_slice_research)
|
|
379
502
|
return null;
|
|
503
|
+
// #4781 phase 2: trivial-scope milestones skip dedicated slice research.
|
|
504
|
+
if (await getMilestonePipelineVariant(mid) === "trivial")
|
|
505
|
+
return null;
|
|
380
506
|
if (!state.activeSlice)
|
|
381
507
|
return missingSliceStop(mid, state.phase);
|
|
382
508
|
const sid = state.activeSlice.id;
|
|
@@ -658,22 +784,29 @@ export const DISPATCH_RULES = [
|
|
|
658
784
|
level: "error",
|
|
659
785
|
};
|
|
660
786
|
}
|
|
661
|
-
//
|
|
662
|
-
|
|
787
|
+
// #4781 phase 2: trivial-scope milestones skip the dedicated validate
|
|
788
|
+
// unit — complete-milestone's own verification steps (3/4/5 in the
|
|
789
|
+
// closer prompt) are sufficient proof for contained deliverables.
|
|
790
|
+
const trivialVariant = await getMilestonePipelineVariant(mid) === "trivial";
|
|
791
|
+
// Skip preference OR trivial scope: write a minimal pass-through VALIDATION file.
|
|
792
|
+
if (prefs?.phases?.skip_milestone_validation || trivialVariant) {
|
|
663
793
|
const mDir = resolveMilestonePath(basePath, mid);
|
|
664
794
|
if (mDir) {
|
|
665
795
|
if (!existsSync(mDir))
|
|
666
796
|
mkdirSync(mDir, { recursive: true });
|
|
667
797
|
const validationPath = join(mDir, buildMilestoneFileName(mid, "VALIDATION"));
|
|
798
|
+
const skipSource = trivialVariant
|
|
799
|
+
? "trivial-scope pipeline variant (#4781)"
|
|
800
|
+
: "`skip_milestone_validation` preference";
|
|
668
801
|
const content = [
|
|
669
802
|
"---",
|
|
670
803
|
"verdict: pass",
|
|
671
804
|
"remediation_round: 0",
|
|
672
805
|
"---",
|
|
673
806
|
"",
|
|
674
|
-
"# Milestone Validation (skipped
|
|
807
|
+
"# Milestone Validation (skipped)",
|
|
675
808
|
"",
|
|
676
|
-
|
|
809
|
+
`Milestone validation was skipped via ${skipSource}.`,
|
|
677
810
|
].join("\n");
|
|
678
811
|
writeFileSync(validationPath, content, "utf-8");
|
|
679
812
|
}
|
|
@@ -704,7 +837,7 @@ export const DISPATCH_RULES = [
|
|
|
704
837
|
}
|
|
705
838
|
const existingSummary = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
706
839
|
let summaryOutcome = "unknown";
|
|
707
|
-
if (existingSummary
|
|
840
|
+
if (existingSummary) {
|
|
708
841
|
const summaryContent = await loadFile(existingSummary);
|
|
709
842
|
if (summaryContent) {
|
|
710
843
|
summaryOutcome = classifyMilestoneSummaryContent(summaryContent);
|
|
@@ -740,7 +873,7 @@ export const DISPATCH_RULES = [
|
|
|
740
873
|
// Safety guard (#1703): verify the milestone produced implementation
|
|
741
874
|
// artifacts (non-.gsd/ files). A milestone with only plan files and
|
|
742
875
|
// zero implementation code should not be marked complete.
|
|
743
|
-
const artifactCheck = hasImplementationArtifacts(basePath);
|
|
876
|
+
const artifactCheck = hasImplementationArtifacts(basePath, mid);
|
|
744
877
|
if (artifactCheck === "absent") {
|
|
745
878
|
return {
|
|
746
879
|
action: "stop",
|
|
@@ -791,10 +924,14 @@ export const DISPATCH_RULES = [
|
|
|
791
924
|
// - success summary: reconcile DB and skip re-dispatch
|
|
792
925
|
// - failure summary: pause/fail-closed
|
|
793
926
|
// - unknown summary: pause/fail-closed
|
|
794
|
-
if (existingSummary
|
|
795
|
-
const milestone = getMilestone(mid);
|
|
796
|
-
const status = milestone?.status ?? "missing";
|
|
927
|
+
if (existingSummary) {
|
|
928
|
+
const milestone = isDbAvailable() ? getMilestone(mid) : null;
|
|
929
|
+
const status = milestone?.status ?? (isDbAvailable() ? "missing" : "unavailable");
|
|
797
930
|
if (summaryOutcome === "success") {
|
|
931
|
+
if (!isDbAvailable()) {
|
|
932
|
+
logWarning("dispatch", `Milestone ${mid} SUMMARY indicates completion while DB is unavailable — skipping duplicate complete-milestone dispatch`);
|
|
933
|
+
return { action: "skip" };
|
|
934
|
+
}
|
|
798
935
|
try {
|
|
799
936
|
updateMilestoneStatus(mid, "complete", new Date().toISOString());
|
|
800
937
|
logWarning("dispatch", `Milestone ${mid} SUMMARY indicates completion while DB status was "${status}" — reconciled DB to complete (#4658)`);
|
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export { autoLoop, runUokKernelLoop, runLegacyAutoLoop } from "./auto/loop.js";
|
|
10
10
|
export { isInfrastructureError, INFRA_ERROR_CODES } from "./auto/infra-errors.js";
|
|
11
|
-
export { resolveAgentEnd, resolveAgentEndCancelled, isSessionSwitchInFlight, _resetPendingResolve, _setActiveSession } from "./auto/resolve.js";
|
|
11
|
+
export { resolveAgentEnd, resolveAgentEndCancelled, isSessionSwitchInFlight, _hasPendingResolveForTest, _resetPendingResolve, _setActiveSession } from "./auto/resolve.js";
|
|
12
12
|
export { detectStuck } from "./auto/detect-stuck.js";
|
|
13
13
|
export { runUnit } from "./auto/run-unit.js";
|
|
@@ -13,6 +13,75 @@ import { logWarning } from "./workflow-logger.js";
|
|
|
13
13
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
14
14
|
import { applyModelPolicyFilter } from "./uok/model-policy.js";
|
|
15
15
|
import { isModelBlocked } from "./blocked-models.js";
|
|
16
|
+
import { getRequiredWorkflowToolsForAutoUnit } from "./workflow-mcp.js";
|
|
17
|
+
/**
|
|
18
|
+
* Thrown when the model-policy gate rejects every candidate model for a unit
|
|
19
|
+
* dispatch (#4959 / #4681 / #4850). The auto-loop catches this specifically
|
|
20
|
+
* to classify the unit as `blocked` rather than counting it as a retryable
|
|
21
|
+
* iteration error — pre-send policy denial is a configuration problem, not a
|
|
22
|
+
* transient runtime failure, so retrying just burns the consecutive-error
|
|
23
|
+
* budget toward a hard stop.
|
|
24
|
+
*/
|
|
25
|
+
export class ModelPolicyDispatchBlockedError extends Error {
|
|
26
|
+
unitType;
|
|
27
|
+
unitId;
|
|
28
|
+
reasons;
|
|
29
|
+
constructor(unitType, unitId, reasons) {
|
|
30
|
+
const summary = reasons.length === 0
|
|
31
|
+
? "no candidate models"
|
|
32
|
+
: reasons
|
|
33
|
+
.slice(0, 4)
|
|
34
|
+
.map((r) => `${r.provider}/${r.modelId} (${r.reason})`)
|
|
35
|
+
.join("; ");
|
|
36
|
+
super(`Model policy denied dispatch for ${unitType}/${unitId} before prompt send. Rejected: ${summary}`);
|
|
37
|
+
this.name = "ModelPolicyDispatchBlockedError";
|
|
38
|
+
this.unitType = unitType;
|
|
39
|
+
this.unitId = unitId;
|
|
40
|
+
this.reasons = reasons;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Baseline active-tool set per-`pi` instance, captured the first time
|
|
44
|
+
// `selectAndApplyModel` runs against that instance during an auto session
|
|
45
|
+
// and re-applied before each subsequent dispatch. WeakMap so that test
|
|
46
|
+
// fakes / disposed sessions are garbage-collected normally. See
|
|
47
|
+
// #4959 / #4681 cross-unit poisoning notes at the call site below.
|
|
48
|
+
//
|
|
49
|
+
// LIFECYCLE: the baseline is tied to a single auto session, NOT to the
|
|
50
|
+
// lifetime of the `pi` instance (which can outlive many auto runs and have
|
|
51
|
+
// the user mutate tools between them). `clearToolBaseline` MUST be called
|
|
52
|
+
// at auto start AND auto stop so that a second `/gsd auto` run on the same
|
|
53
|
+
// `pi` does not silently restore a stale snapshot from the prior run and
|
|
54
|
+
// undo any tool changes the user made between sessions.
|
|
55
|
+
const TOOL_BASELINE = new WeakMap();
|
|
56
|
+
/**
|
|
57
|
+
* Drop the captured tool baseline for `pi` so the next `selectAndApplyModel`
|
|
58
|
+
* call re-captures from the live active set. Wired into `startAuto` and
|
|
59
|
+
* `stopAuto` in `auto.ts` to bound the baseline to a single auto session.
|
|
60
|
+
*
|
|
61
|
+
* Safe to call when no baseline is recorded (no-op).
|
|
62
|
+
*/
|
|
63
|
+
export function clearToolBaseline(pi) {
|
|
64
|
+
TOOL_BASELINE.delete(pi);
|
|
65
|
+
}
|
|
66
|
+
function restoreToolBaseline(pi) {
|
|
67
|
+
const key = pi;
|
|
68
|
+
const baseline = TOOL_BASELINE.get(key);
|
|
69
|
+
if (baseline === undefined) {
|
|
70
|
+
// First call: capture the canonical pre-dispatch tool set. At auto-mode
|
|
71
|
+
// start the active set has not yet been narrowed for any provider.
|
|
72
|
+
// Guarded against test fakes that omit getActiveTools — record an empty
|
|
73
|
+
// baseline so subsequent calls don't keep re-probing.
|
|
74
|
+
const initial = typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [];
|
|
75
|
+
TOOL_BASELINE.set(key, [...initial]);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
// Restore baseline before the next unit reads getActiveTools / applies
|
|
79
|
+
// post-selection adjustToolSet. Older fakes that omit setActiveTools are
|
|
80
|
+
// tolerated — the test asserts call order on real fakes.
|
|
81
|
+
if (typeof pi.setActiveTools === "function") {
|
|
82
|
+
pi.setActiveTools([...baseline]);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
16
85
|
function reapplyThinkingLevel(pi, level) {
|
|
17
86
|
if (!level)
|
|
18
87
|
return;
|
|
@@ -86,6 +155,29 @@ autoModeStartThinkingLevel) {
|
|
|
86
155
|
: resolvePreferredModelConfig(unitType, autoModeStartModel, isAutoMode);
|
|
87
156
|
let routing = null;
|
|
88
157
|
let appliedModel = null;
|
|
158
|
+
// ── Restore active-tool baseline before policy evaluation (#4959, #4681, #4850) ──
|
|
159
|
+
// Per-unit narrowing at the bottom of this function (line ~417) calls
|
|
160
|
+
// `pi.setActiveTools(finalToolNames)` and monotonically narrows the active
|
|
161
|
+
// set across units. Without restoration, a previously-dispatched unit on a
|
|
162
|
+
// narrow-API provider (e.g. openai-completions) leaves the active set
|
|
163
|
+
// missing tools that the next unit's selected model fully supports, but
|
|
164
|
+
// `pi.getActiveTools()` snapshot-as-hard-gate (the old behaviour) blocked
|
|
165
|
+
// dispatch with "tool policy denied" anyway.
|
|
166
|
+
//
|
|
167
|
+
// The baseline is captured once per `pi` instance via a WeakMap and
|
|
168
|
+
// re-applied here so each unit starts from a clean slate. Soft adaptation
|
|
169
|
+
// (adjustToolSet at the bottom of this function) still trims for the
|
|
170
|
+
// selected model.
|
|
171
|
+
//
|
|
172
|
+
// Auto-mode only (#4965): `guided-flow.ts:dispatchWorkflow` also calls
|
|
173
|
+
// `selectAndApplyModel` with `isAutoMode=false`. Guided-flow has its own
|
|
174
|
+
// narrow/restore via discuss-tool-scoping (guided-flow.ts:587-622) and no
|
|
175
|
+
// baseline-clear hook of its own, so an unconditional restore here would
|
|
176
|
+
// resurrect an auto-era baseline on guided-flow dispatches — silently
|
|
177
|
+
// overwriting any tool changes made interactively between auto sessions.
|
|
178
|
+
// The baseline is structurally an auto-mode concept; gate it accordingly.
|
|
179
|
+
if (isAutoMode)
|
|
180
|
+
restoreToolBaseline(pi);
|
|
89
181
|
if (modelConfig) {
|
|
90
182
|
const availableModels = ctx.modelRegistry.getAvailable();
|
|
91
183
|
const modelPolicyTraceId = `model:${ctx.sessionManager.getSessionId()}:${Date.now()}`;
|
|
@@ -114,7 +206,16 @@ autoModeStartThinkingLevel) {
|
|
|
114
206
|
const taskMetadataForPolicy = unitType === "execute-task"
|
|
115
207
|
? extractTaskMetadata(unitId, basePath)
|
|
116
208
|
: undefined;
|
|
209
|
+
let policyDenyReasons = [];
|
|
117
210
|
if (uokFlags.modelPolicy) {
|
|
211
|
+
// Use the workflow-spec required-tool subset for the unit type rather
|
|
212
|
+
// than the live `pi.getActiveTools()` snapshot (#4959). The active set
|
|
213
|
+
// is poisoned by per-unit narrowing for narrow-API providers — using it
|
|
214
|
+
// as a hard gate promotes soft adaptation (adjustToolSet at line ~417)
|
|
215
|
+
// into a layering violation that throws before dispatch. The smaller
|
|
216
|
+
// workflow-required subset reflects what the unit actually needs; soft
|
|
217
|
+
// adaptation post-selection still trims provider-incompatible tools.
|
|
218
|
+
const requiredTools = getRequiredWorkflowToolsForAutoUnit(unitType);
|
|
118
219
|
const policy = applyModelPolicyFilter(availableModels, {
|
|
119
220
|
basePath,
|
|
120
221
|
traceId: modelPolicyTraceId,
|
|
@@ -123,12 +224,15 @@ autoModeStartThinkingLevel) {
|
|
|
123
224
|
taskMetadata: taskMetadataForPolicy,
|
|
124
225
|
currentProvider: ctx.model?.provider,
|
|
125
226
|
allowCrossProvider: routingConfig.cross_provider !== false,
|
|
126
|
-
requiredTools
|
|
227
|
+
requiredTools,
|
|
127
228
|
});
|
|
128
229
|
routingEligibleModels = policy.eligible;
|
|
129
230
|
policyAllowedModelKeys = new Set(policy.eligible.map((m) => `${m.provider.toLowerCase()}/${m.id.toLowerCase()}`));
|
|
231
|
+
policyDenyReasons = policy.decisions
|
|
232
|
+
.filter((d) => !d.allowed)
|
|
233
|
+
.map((d) => ({ provider: d.provider, modelId: d.modelId, reason: d.reason }));
|
|
130
234
|
if (routingEligibleModels.length === 0) {
|
|
131
|
-
throw new
|
|
235
|
+
throw new ModelPolicyDispatchBlockedError(unitType, unitId, policyDenyReasons);
|
|
132
236
|
}
|
|
133
237
|
}
|
|
134
238
|
// Disable routing for flat-rate providers like GitHub Copilot (#3453).
|
|
@@ -169,7 +273,11 @@ autoModeStartThinkingLevel) {
|
|
|
169
273
|
if (shouldClassify) {
|
|
170
274
|
let classification = classifyUnitComplexity(unitType, unitId, basePath, budgetPct, taskMetadataForPolicy);
|
|
171
275
|
const availableModelIds = routingEligibleModels.map(m => `${m.provider}/${m.id}`);
|
|
172
|
-
// Escalate tier on retry when escalate_on_failure is enabled (default: true)
|
|
276
|
+
// Escalate tier on retry when escalate_on_failure is enabled (default: true).
|
|
277
|
+
// #4973: Deterministic policy errors are short-circuited at the postUnit
|
|
278
|
+
// level (auto-post-unit.ts writes a placeholder and returns "continue"),
|
|
279
|
+
// so this code path only runs for legitimate model-quality retries where
|
|
280
|
+
// tier escalation is the right response.
|
|
173
281
|
if (retryContext?.isRetry &&
|
|
174
282
|
retryContext.previousTier &&
|
|
175
283
|
routingConfig.escalate_on_failure !== false) {
|
|
@@ -179,6 +287,18 @@ autoModeStartThinkingLevel) {
|
|
|
179
287
|
// Always notify on tier escalation — model changes should be visible (#3962)
|
|
180
288
|
ctx.ui.notify(`Tier escalation: ${retryContext.previousTier} → ${escalated} (retry after failure)`, "info");
|
|
181
289
|
}
|
|
290
|
+
else {
|
|
291
|
+
// #4973: Already at max tier — keep previousTier rather than letting
|
|
292
|
+
// fresh classification silently downgrade the model back to a lower tier.
|
|
293
|
+
// Without this, a light-start unit on retry 3 would revert to the light
|
|
294
|
+
// model after escalating to heavy on retries 1 and 2.
|
|
295
|
+
const tierOrder = { light: 0, standard: 1, heavy: 2 };
|
|
296
|
+
const prevOrder = tierOrder[retryContext.previousTier] ?? 0;
|
|
297
|
+
const freshOrder = tierOrder[classification.tier] ?? 0;
|
|
298
|
+
if (prevOrder > freshOrder) {
|
|
299
|
+
classification = { ...classification, tier: retryContext.previousTier, reason: "retained escalated tier from retry" };
|
|
300
|
+
}
|
|
301
|
+
}
|
|
182
302
|
}
|
|
183
303
|
// Load user capability overrides from preferences (D-17: deep-merged with built-in profiles)
|
|
184
304
|
const capabilityOverrides = loadCapabilityOverrides(prefs ?? {});
|
|
@@ -335,7 +455,7 @@ autoModeStartThinkingLevel) {
|
|
|
335
455
|
}
|
|
336
456
|
}
|
|
337
457
|
if (uokFlags.modelPolicy && policyAllowedModelKeys && !attemptedPolicyEligible) {
|
|
338
|
-
throw new
|
|
458
|
+
throw new ModelPolicyDispatchBlockedError(unitType, unitId, policyDenyReasons);
|
|
339
459
|
}
|
|
340
460
|
}
|
|
341
461
|
else if (autoModeStartModel) {
|