gsd-pi 2.63.0 → 2.64.0-dev.9c14bd0
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 +46 -134
- package/dist/cli.js +48 -6
- package/dist/headless-query.js +11 -1
- package/dist/help-text.js +4 -1
- package/dist/onboarding.js +15 -8
- package/dist/resource-loader.js +18 -3
- package/dist/resources/extensions/cmux/index.js +21 -12
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +27 -0
- package/dist/resources/extensions/gsd/auto/finalize-timeout.js +40 -0
- package/dist/resources/extensions/gsd/auto/loop.js +4 -0
- package/dist/resources/extensions/gsd/auto/phases.js +157 -22
- package/dist/resources/extensions/gsd/auto/session.js +12 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +14 -8
- package/dist/resources/extensions/gsd/auto-model-selection.js +32 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +222 -11
- package/dist/resources/extensions/gsd/auto-prompts.js +25 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +15 -7
- package/dist/resources/extensions/gsd/auto-start.js +10 -21
- package/dist/resources/extensions/gsd/auto-timers.js +2 -1
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +17 -0
- package/dist/resources/extensions/gsd/auto-verification.js +138 -1
- package/dist/resources/extensions/gsd/auto-worktree.js +13 -7
- package/dist/resources/extensions/gsd/auto.js +24 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +147 -75
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +13 -0
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +85 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +3 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +32 -1
- package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +54 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +30 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +9 -4
- package/dist/resources/extensions/gsd/constants.js +42 -0
- package/dist/resources/extensions/gsd/db-writer.js +72 -4
- package/dist/resources/extensions/gsd/forensics.js +20 -4
- package/dist/resources/extensions/gsd/gsd-db.js +64 -17
- package/dist/resources/extensions/gsd/guided-flow.js +19 -0
- package/dist/resources/extensions/gsd/metrics.js +27 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +5 -3
- package/dist/resources/extensions/gsd/post-execution-checks.js +407 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +464 -0
- package/dist/resources/extensions/gsd/preferences-types.js +6 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +33 -0
- package/dist/resources/extensions/gsd/preferences.js +11 -2
- package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -0
- package/dist/resources/extensions/gsd/prompts/doctor-heal.md +1 -0
- package/dist/resources/extensions/gsd/prompts/forensics.md +2 -0
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +2 -0
- package/dist/resources/extensions/gsd/prompts/system.md +4 -7
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
- package/dist/resources/extensions/gsd/roadmap-mutations.js +1 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +9 -5
- package/dist/resources/extensions/gsd/safety/content-validator.js +73 -0
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +34 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +109 -0
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +83 -0
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +71 -0
- package/dist/resources/extensions/gsd/safety/git-checkpoint.js +91 -0
- package/dist/resources/extensions/gsd/safety/safety-harness.js +64 -0
- package/dist/resources/extensions/gsd/slice-parallel-conflict.js +67 -0
- package/dist/resources/extensions/gsd/slice-parallel-eligibility.js +51 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +378 -0
- package/dist/resources/extensions/gsd/state.js +74 -14
- package/dist/resources/extensions/gsd/status-guards.js +11 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +17 -12
- package/dist/resources/extensions/gsd/tools/complete-slice.js +40 -26
- package/dist/resources/extensions/gsd/tools/complete-task.js +12 -12
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +33 -25
- package/dist/resources/extensions/gsd/tools/plan-slice.js +5 -8
- package/dist/resources/extensions/gsd/verification-evidence.js +18 -0
- package/dist/resources/extensions/gsd/workflow-projections.js +21 -5
- package/dist/resources/extensions/gsd/worktree-manager.js +82 -29
- package/dist/resources/extensions/gsd/worktree-resolver.js +4 -3
- package/dist/resources/extensions/mcp-client/auth.js +101 -0
- package/dist/resources/extensions/mcp-client/index.js +10 -1
- package/dist/resources/extensions/ollama/index.js +28 -22
- package/dist/resources/extensions/ollama/model-capabilities.js +37 -34
- package/dist/resources/extensions/ollama/ndjson-stream.js +54 -0
- package/dist/resources/extensions/ollama/ollama-chat-provider.js +380 -0
- package/dist/resources/extensions/ollama/ollama-client.js +23 -32
- package/dist/resources/extensions/ollama/ollama-discovery.js +2 -7
- package/dist/resources/extensions/ollama/ollama-tool.js +62 -0
- package/dist/resources/extensions/ollama/thinking-parser.js +104 -0
- package/dist/update-cmd.js +4 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
- 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/required-server-files.json +4 -4
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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/boot/route_client-reference-manifest.js +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/input/route_client-reference-manifest.js +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/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- 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/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +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/captures/route_client-reference-manifest.js +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/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +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/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +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/export-data/route_client-reference-manifest.js +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/files/route_client-reference-manifest.js +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/forensics/route_client-reference-manifest.js +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/git/route_client-reference-manifest.js +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/history/route_client-reference-manifest.js +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/hooks/route_client-reference-manifest.js +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/inspect/route_client-reference-manifest.js +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/knowledge/route_client-reference-manifest.js +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/live-state/route_client-reference-manifest.js +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/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +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/projects/route_client-reference-manifest.js +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/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +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/browser/route_client-reference-manifest.js +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/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- 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/events/route_client-reference-manifest.js +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/session/manage/route_client-reference-manifest.js +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/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +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/skill-health/route_client-reference-manifest.js +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/steer/route_client-reference-manifest.js +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/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- 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/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +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/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +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/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
- package/dist/web/standalone/.next/server/chunks/6897.js +12 -0
- package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-0c485498795110d6.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.js +1 -1
- package/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.d.ts +8 -0
- package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +50 -0
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +221 -5
- package/packages/pi-agent-core/src/agent-loop.ts +53 -0
- package/packages/pi-ai/dist/types.d.ts +16 -1
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/src/types.ts +18 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +50 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +41 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +7 -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 +31 -4
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.js +28 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.js +46 -0
- package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +12 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +3 -3
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +23 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +80 -56
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +9 -0
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +53 -0
- package/packages/pi-coding-agent/src/core/auth-storage.ts +66 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +39 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +34 -4
- package/packages/pi-coding-agent/src/core/extensions/provider-registration.test.ts +81 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +14 -0
- package/packages/pi-coding-agent/src/core/model-resolver.ts +3 -3
- package/packages/pi-coding-agent/src/core/resource-loader.ts +89 -56
- package/packages/pi-coding-agent/src/core/sdk.ts +10 -0
- package/pkg/package.json +1 -1
- package/src/resources/extensions/cmux/index.ts +18 -12
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +27 -0
- package/src/resources/extensions/gsd/auto/finalize-timeout.ts +46 -0
- package/src/resources/extensions/gsd/auto/loop.ts +5 -0
- package/src/resources/extensions/gsd/auto/phases.ts +194 -33
- package/src/resources/extensions/gsd/auto/session.ts +14 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +16 -7
- package/src/resources/extensions/gsd/auto-model-selection.ts +36 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +263 -12
- package/src/resources/extensions/gsd/auto-prompts.ts +21 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +9 -8
- package/src/resources/extensions/gsd/auto-start.ts +11 -20
- package/src/resources/extensions/gsd/auto-timers.ts +2 -1
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
- package/src/resources/extensions/gsd/auto-verification.ts +190 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +14 -6
- package/src/resources/extensions/gsd/auto.ts +26 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +160 -88
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +15 -0
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +98 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +36 -1
- package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +57 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +31 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +10 -4
- package/src/resources/extensions/gsd/constants.ts +44 -0
- package/src/resources/extensions/gsd/db-writer.ts +78 -4
- package/src/resources/extensions/gsd/forensics.ts +21 -5
- package/src/resources/extensions/gsd/gsd-db.ts +64 -17
- package/src/resources/extensions/gsd/guided-flow.ts +22 -0
- package/src/resources/extensions/gsd/metrics.ts +28 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +5 -3
- package/src/resources/extensions/gsd/post-execution-checks.ts +539 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +573 -0
- package/src/resources/extensions/gsd/preferences-types.ts +44 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +33 -0
- package/src/resources/extensions/gsd/preferences.ts +13 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -0
- package/src/resources/extensions/gsd/prompts/doctor-heal.md +1 -0
- package/src/resources/extensions/gsd/prompts/forensics.md +2 -0
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +2 -0
- package/src/resources/extensions/gsd/prompts/system.md +4 -7
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
- package/src/resources/extensions/gsd/roadmap-mutations.ts +1 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +10 -5
- package/src/resources/extensions/gsd/safety/content-validator.ts +98 -0
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +49 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +151 -0
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +120 -0
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +108 -0
- package/src/resources/extensions/gsd/safety/git-checkpoint.ts +106 -0
- package/src/resources/extensions/gsd/safety/safety-harness.ts +105 -0
- package/src/resources/extensions/gsd/slice-parallel-conflict.ts +86 -0
- package/src/resources/extensions/gsd/slice-parallel-eligibility.ts +73 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +477 -0
- package/src/resources/extensions/gsd/state.ts +67 -12
- package/src/resources/extensions/gsd/status-guards.ts +13 -0
- package/src/resources/extensions/gsd/tests/artifact-corruption-2630.test.ts +288 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +34 -13
- package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/cmux.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/complete-slice-string-coercion.test.ts +211 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +109 -0
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +13 -9
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/deferred-slice-dispatch.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +130 -0
- package/src/resources/extensions/gsd/tests/doctor-fix-flag.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +526 -0
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/git-checkpoint.test.ts +94 -0
- package/src/resources/extensions/gsd/tests/insert-slice-no-wipe.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +27 -7
- package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/metrics.test.ts +116 -1
- package/src/resources/extensions/gsd/tests/milestone-status-tool.test.ts +201 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +82 -18
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +813 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +999 -0
- package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +266 -0
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +457 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/slice-parallel-conflict.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/slice-parallel-eligibility.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +349 -0
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +35 -2
- package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +148 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +34 -20
- package/src/resources/extensions/gsd/tools/complete-slice.ts +41 -26
- package/src/resources/extensions/gsd/tools/complete-task.ts +12 -12
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +55 -30
- package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -8
- package/src/resources/extensions/gsd/types.ts +44 -22
- package/src/resources/extensions/gsd/verification-evidence.ts +68 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +2 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +23 -5
- package/src/resources/extensions/gsd/worktree-manager.ts +76 -28
- package/src/resources/extensions/gsd/worktree-resolver.ts +4 -3
- package/src/resources/extensions/mcp-client/auth.ts +149 -0
- package/src/resources/extensions/mcp-client/index.ts +16 -1
- package/src/resources/extensions/ollama/index.ts +26 -25
- package/src/resources/extensions/ollama/model-capabilities.ts +41 -34
- package/src/resources/extensions/ollama/ndjson-stream.ts +63 -0
- package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +20 -0
- package/src/resources/extensions/ollama/ollama-chat-provider.ts +459 -0
- package/src/resources/extensions/ollama/ollama-client.ts +30 -30
- package/src/resources/extensions/ollama/ollama-discovery.ts +5 -8
- package/src/resources/extensions/ollama/ollama-tool.ts +69 -0
- package/src/resources/extensions/ollama/tests/ollama-chat-provider-stream.test.ts +82 -0
- package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +0 -27
- package/src/resources/extensions/ollama/thinking-parser.ts +116 -0
- package/src/resources/extensions/ollama/types.ts +23 -0
- package/dist/web/standalone/.next/server/chunks/2229.js +0 -12
- package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- /package/dist/web/standalone/.next/static/{5FLUBNdqolRyyehCyChPd → SoxM61WC_ia7R2gk4VMpJ}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{5FLUBNdqolRyyehCyChPd → SoxM61WC_ia7R2gk4VMpJ}/_ssgManifest.js +0 -0
|
@@ -26,13 +26,20 @@ import { runUnit } from "./run-unit.js";
|
|
|
26
26
|
import { debugLog } from "../debug-logger.js";
|
|
27
27
|
import { PROJECT_FILES } from "../detection.js";
|
|
28
28
|
import { MergeConflictError } from "../git-service.js";
|
|
29
|
-
import { join, basename } from "node:path";
|
|
30
|
-
import { existsSync, cpSync } from "node:fs";
|
|
29
|
+
import { join, basename, dirname, parse as parsePath } from "node:path";
|
|
30
|
+
import { existsSync, cpSync, readdirSync } from "node:fs";
|
|
31
31
|
import { logWarning, logError } from "../workflow-logger.js";
|
|
32
32
|
import { gsdRoot } from "../paths.js";
|
|
33
33
|
import { atomicWriteSync } from "../atomic-write.js";
|
|
34
34
|
import { verifyExpectedArtifact, diagnoseExpectedArtifact, buildLoopRemediationSteps } from "../auto-recovery.js";
|
|
35
35
|
import { writeUnitRuntimeRecord } from "../unit-runtime.js";
|
|
36
|
+
import { withTimeout, FINALIZE_POST_TIMEOUT_MS } from "./finalize-timeout.js";
|
|
37
|
+
import { getEligibleSlices } from "../slice-parallel-eligibility.js";
|
|
38
|
+
import { startSliceParallel } from "../slice-parallel-orchestrator.js";
|
|
39
|
+
import { isDbAvailable, getMilestoneSlices } from "../gsd-db.js";
|
|
40
|
+
import { resetEvidence } from "../safety/evidence-collector.js";
|
|
41
|
+
import { createCheckpoint, cleanupCheckpoint, rollbackToCheckpoint } from "../safety/git-checkpoint.js";
|
|
42
|
+
import { resolveSafetyHarnessConfig } from "../safety/safety-harness.js";
|
|
36
43
|
|
|
37
44
|
// ─── generateMilestoneReport ──────────────────────────────────────────────────
|
|
38
45
|
|
|
@@ -218,6 +225,63 @@ export async function runPreDispatch(
|
|
|
218
225
|
statePhase: state.phase,
|
|
219
226
|
});
|
|
220
227
|
|
|
228
|
+
// ── Slice-level parallelism gate (#2340) ─────────────────────────────
|
|
229
|
+
// When slice_parallel is enabled, check if multiple slices are eligible
|
|
230
|
+
// for parallel execution. If so, dispatch them in parallel and stop the
|
|
231
|
+
// sequential loop. Workers are spawned via slice-parallel-orchestrator.ts.
|
|
232
|
+
if (
|
|
233
|
+
prefs?.slice_parallel?.enabled &&
|
|
234
|
+
mid &&
|
|
235
|
+
!process.env.GSD_PARALLEL_WORKER &&
|
|
236
|
+
isDbAvailable()
|
|
237
|
+
) {
|
|
238
|
+
try {
|
|
239
|
+
const dbSlices = getMilestoneSlices(mid);
|
|
240
|
+
if (dbSlices.length > 0) {
|
|
241
|
+
const doneIds = new Set(dbSlices.filter(sl => sl.status === "complete" || sl.status === "done").map(sl => sl.id));
|
|
242
|
+
const sliceInputs = dbSlices.map(sl => ({
|
|
243
|
+
id: sl.id,
|
|
244
|
+
done: doneIds.has(sl.id),
|
|
245
|
+
depends: sl.depends ?? [],
|
|
246
|
+
}));
|
|
247
|
+
const eligible = getEligibleSlices(sliceInputs, doneIds);
|
|
248
|
+
if (eligible.length > 1) {
|
|
249
|
+
debugLog("autoLoop", {
|
|
250
|
+
phase: "slice-parallel-dispatch",
|
|
251
|
+
iteration: ic.iteration,
|
|
252
|
+
mid,
|
|
253
|
+
eligibleSlices: eligible.map(e => e.id),
|
|
254
|
+
});
|
|
255
|
+
ctx.ui.notify(
|
|
256
|
+
`Slice-parallel: dispatching ${eligible.length} eligible slices for ${mid}.`,
|
|
257
|
+
"info",
|
|
258
|
+
);
|
|
259
|
+
const result = await startSliceParallel(
|
|
260
|
+
s.basePath,
|
|
261
|
+
mid,
|
|
262
|
+
eligible,
|
|
263
|
+
{ maxWorkers: prefs.slice_parallel.max_workers ?? 2 },
|
|
264
|
+
);
|
|
265
|
+
if (result.started.length > 0) {
|
|
266
|
+
ctx.ui.notify(
|
|
267
|
+
`Slice-parallel: started ${result.started.length} worker(s): ${result.started.join(", ")}.`,
|
|
268
|
+
"info",
|
|
269
|
+
);
|
|
270
|
+
await deps.stopAuto(ctx, pi, `Slice-parallel dispatched for ${mid}`);
|
|
271
|
+
return { action: "break", reason: "slice-parallel-dispatched" };
|
|
272
|
+
}
|
|
273
|
+
// Fall through to sequential if no workers started
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
} catch (err) {
|
|
277
|
+
debugLog("autoLoop", {
|
|
278
|
+
phase: "slice-parallel-check-error",
|
|
279
|
+
error: err instanceof Error ? err.message : String(err),
|
|
280
|
+
});
|
|
281
|
+
// Non-fatal — fall through to sequential dispatch
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
221
285
|
// ── Milestone transition ────────────────────────────────────────────
|
|
222
286
|
if (mid && s.currentMilestoneId && mid !== s.currentMilestoneId) {
|
|
223
287
|
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: ic.nextSeq(), eventType: "milestone-transition", data: { from: s.currentMilestoneId, to: mid } });
|
|
@@ -948,11 +1012,38 @@ export async function runUnitPhase(
|
|
|
948
1012
|
}
|
|
949
1013
|
const hasProjectFile = PROJECT_FILES.some((f) => deps.existsSync(join(s.basePath, f)));
|
|
950
1014
|
const hasSrcDir = deps.existsSync(join(s.basePath, "src"));
|
|
951
|
-
|
|
1015
|
+
// Xcode bundles have project-specific names (*.xcodeproj, *.xcworkspace)
|
|
1016
|
+
// that cannot be matched by exact filename — scan the directory by suffix.
|
|
1017
|
+
let hasXcodeBundle = false;
|
|
1018
|
+
try {
|
|
1019
|
+
const entries = deps.existsSync(s.basePath) ? readdirSync(s.basePath) : [];
|
|
1020
|
+
hasXcodeBundle = entries.some((e: string) => e.endsWith(".xcodeproj") || e.endsWith(".xcworkspace"));
|
|
1021
|
+
} catch (err) {
|
|
1022
|
+
debugLog("runUnitPhase", { phase: "xcode-bundle-scan-failed", basePath: s.basePath, error: String(err) });
|
|
1023
|
+
}
|
|
1024
|
+
// Monorepo support (#2347): if no project files in the worktree directory,
|
|
1025
|
+
// walk parent directories up to the filesystem root. In monorepos,
|
|
1026
|
+
// package.json / Cargo.toml etc. live in a parent directory.
|
|
1027
|
+
let hasProjectFileInParent = false;
|
|
1028
|
+
if (!hasProjectFile && !hasSrcDir && !hasXcodeBundle) {
|
|
1029
|
+
let checkDir = dirname(s.basePath);
|
|
1030
|
+
const { root } = parsePath(checkDir);
|
|
1031
|
+
while (checkDir !== root) {
|
|
1032
|
+
// Stop at git repository boundary — ancestors above the repo root
|
|
1033
|
+
// (e.g. ~ or /usr/local) may contain unrelated project files.
|
|
1034
|
+
if (deps.existsSync(join(checkDir, ".git"))) break;
|
|
1035
|
+
if (PROJECT_FILES.some((f) => deps.existsSync(join(checkDir, f)))) {
|
|
1036
|
+
hasProjectFileInParent = true;
|
|
1037
|
+
break;
|
|
1038
|
+
}
|
|
1039
|
+
checkDir = dirname(checkDir);
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
if (!hasProjectFile && !hasSrcDir && !hasXcodeBundle && !hasProjectFileInParent) {
|
|
952
1043
|
// Greenfield projects won't have project files yet — the first task creates them.
|
|
953
1044
|
// Log a warning but allow execution to proceed. The .git check above is sufficient
|
|
954
1045
|
// to ensure we're in a valid working directory.
|
|
955
|
-
debugLog("runUnitPhase", { phase: "worktree-health-warn-greenfield", basePath: s.basePath, hasProjectFile, hasSrcDir });
|
|
1046
|
+
debugLog("runUnitPhase", { phase: "worktree-health-warn-greenfield", basePath: s.basePath, hasProjectFile, hasSrcDir, hasXcodeBundle });
|
|
956
1047
|
ctx.ui.notify(`Warning: ${s.basePath} has no recognized project files — proceeding as greenfield project`, "warning");
|
|
957
1048
|
}
|
|
958
1049
|
}
|
|
@@ -966,6 +1057,7 @@ export async function runUnitPhase(
|
|
|
966
1057
|
const previousTier = s.currentUnitRouting?.tier;
|
|
967
1058
|
|
|
968
1059
|
s.currentUnit = { type: unitType, id: unitId, startedAt: Date.now() };
|
|
1060
|
+
s.lastToolInvocationError = null; // #2883: clear stale error from previous unit
|
|
969
1061
|
const unitStartSeq = ic.nextSeq();
|
|
970
1062
|
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: unitStartSeq, eventType: "unit-start", data: { unitType, unitId } });
|
|
971
1063
|
deps.captureAvailableSkills();
|
|
@@ -985,30 +1077,25 @@ export async function runUnitPhase(
|
|
|
985
1077
|
},
|
|
986
1078
|
);
|
|
987
1079
|
|
|
988
|
-
//
|
|
989
|
-
const modelResult = await deps.selectAndApplyModel(
|
|
990
|
-
ctx,
|
|
991
|
-
pi,
|
|
992
|
-
unitType,
|
|
993
|
-
unitId,
|
|
994
|
-
s.basePath,
|
|
995
|
-
prefs,
|
|
996
|
-
s.verbose,
|
|
997
|
-
s.autoModeStartModel,
|
|
998
|
-
sidecarItem ? undefined : { isRetry, previousTier },
|
|
999
|
-
);
|
|
1000
|
-
s.currentUnitRouting =
|
|
1001
|
-
modelResult.routing as AutoSession["currentUnitRouting"];
|
|
1002
|
-
s.currentUnitModel =
|
|
1003
|
-
modelResult.appliedModel as AutoSession["currentUnitModel"];
|
|
1004
|
-
|
|
1005
|
-
// Status bar + progress widget
|
|
1080
|
+
// Status bar (widget + preconditions deferred until after model selection — see #2899)
|
|
1006
1081
|
ctx.ui.setStatus("gsd-auto", "auto");
|
|
1007
1082
|
if (mid)
|
|
1008
1083
|
deps.updateSliceProgressCache(s.basePath, mid, state.activeSlice?.id);
|
|
1009
|
-
deps.updateProgressWidget(ctx, unitType, unitId, state);
|
|
1010
1084
|
|
|
1011
|
-
|
|
1085
|
+
// ── Safety harness: reset evidence + create checkpoint ──
|
|
1086
|
+
const safetyConfig = resolveSafetyHarnessConfig(
|
|
1087
|
+
prefs?.safety_harness as Record<string, unknown> | undefined,
|
|
1088
|
+
);
|
|
1089
|
+
if (safetyConfig.enabled && safetyConfig.evidence_collection) {
|
|
1090
|
+
resetEvidence();
|
|
1091
|
+
}
|
|
1092
|
+
// Only checkpoint code-executing units (not lifecycle/planning units)
|
|
1093
|
+
if (safetyConfig.enabled && safetyConfig.checkpoints && unitType === "execute-task") {
|
|
1094
|
+
s.checkpointSha = createCheckpoint(s.basePath, unitId);
|
|
1095
|
+
if (s.checkpointSha) {
|
|
1096
|
+
debugLog("runUnitPhase", { phase: "checkpoint-created", unitId, sha: s.checkpointSha.slice(0, 8) });
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1012
1099
|
|
|
1013
1100
|
// Prompt injection
|
|
1014
1101
|
let finalPrompt = prompt;
|
|
@@ -1074,6 +1161,23 @@ export async function runUnitPhase(
|
|
|
1074
1161
|
logWarning("engine", "Prompt reorder failed", { error: msg });
|
|
1075
1162
|
}
|
|
1076
1163
|
|
|
1164
|
+
// Select and apply model (with tier escalation on retry — normal units only)
|
|
1165
|
+
const modelResult = await deps.selectAndApplyModel(
|
|
1166
|
+
ctx,
|
|
1167
|
+
pi,
|
|
1168
|
+
unitType,
|
|
1169
|
+
unitId,
|
|
1170
|
+
s.basePath,
|
|
1171
|
+
prefs,
|
|
1172
|
+
s.verbose,
|
|
1173
|
+
s.autoModeStartModel,
|
|
1174
|
+
sidecarItem ? undefined : { isRetry, previousTier },
|
|
1175
|
+
);
|
|
1176
|
+
s.currentUnitRouting =
|
|
1177
|
+
modelResult.routing as AutoSession["currentUnitRouting"];
|
|
1178
|
+
s.currentUnitModel =
|
|
1179
|
+
modelResult.appliedModel as AutoSession["currentUnitModel"];
|
|
1180
|
+
|
|
1077
1181
|
// Apply sidecar/pre-dispatch hook model override (takes priority over standard model selection)
|
|
1078
1182
|
const hookModelOverride = sidecarItem?.model ?? iterData.hookModelOverride;
|
|
1079
1183
|
if (hookModelOverride) {
|
|
@@ -1099,6 +1203,17 @@ export async function runUnitPhase(
|
|
|
1099
1203
|
}
|
|
1100
1204
|
}
|
|
1101
1205
|
|
|
1206
|
+
// Store the final dispatched model ID so the dashboard can read it (#2899).
|
|
1207
|
+
// This accounts for hook model overrides applied after selectAndApplyModel.
|
|
1208
|
+
s.currentDispatchedModelId = s.currentUnitModel
|
|
1209
|
+
? `${(s.currentUnitModel as any).provider ?? ""}/${(s.currentUnitModel as any).id ?? ""}`
|
|
1210
|
+
: null;
|
|
1211
|
+
|
|
1212
|
+
// Progress widget + preconditions — deferred to after model selection so the
|
|
1213
|
+
// widget's first render tick shows the correct model (#2899).
|
|
1214
|
+
deps.updateProgressWidget(ctx, unitType, unitId, state);
|
|
1215
|
+
deps.ensurePreconditions(unitType, unitId, s.basePath, state);
|
|
1216
|
+
|
|
1102
1217
|
// Start unit supervision
|
|
1103
1218
|
deps.clearUnitTimeout();
|
|
1104
1219
|
deps.startUnitSupervision({
|
|
@@ -1211,11 +1326,13 @@ export async function runUnitPhase(
|
|
|
1211
1326
|
);
|
|
1212
1327
|
}
|
|
1213
1328
|
|
|
1214
|
-
// ── Zero tool-call guard (#1833)
|
|
1215
|
-
//
|
|
1216
|
-
//
|
|
1217
|
-
// the
|
|
1218
|
-
|
|
1329
|
+
// ── Zero tool-call guard (#1833, #2653) ──────────────────────────
|
|
1330
|
+
// Any unit that completes with 0 tool calls made no real progress —
|
|
1331
|
+
// likely context exhaustion where all tool calls errored out. Treat
|
|
1332
|
+
// as failed so the unit is retried in a fresh context instead of
|
|
1333
|
+
// silently passing through to artifact verification (which loops
|
|
1334
|
+
// forever when the unit never produced its artifact).
|
|
1335
|
+
{
|
|
1219
1336
|
const currentLedger = deps.getLedger() as { units: Array<{ type: string; id: string; startedAt: number; toolCalls: number }> } | null;
|
|
1220
1337
|
if (currentLedger?.units) {
|
|
1221
1338
|
const lastUnit = [...currentLedger.units].reverse().find(
|
|
@@ -1226,14 +1343,14 @@ export async function runUnitPhase(
|
|
|
1226
1343
|
phase: "zero-tool-calls",
|
|
1227
1344
|
unitType,
|
|
1228
1345
|
unitId,
|
|
1229
|
-
warning: "
|
|
1346
|
+
warning: "Unit completed with 0 tool calls — likely context exhaustion, marking as failed",
|
|
1230
1347
|
});
|
|
1231
1348
|
ctx.ui.notify(
|
|
1232
|
-
`${unitType} ${unitId} completed with 0 tool calls —
|
|
1349
|
+
`${unitType} ${unitId} completed with 0 tool calls — context exhaustion, will retry`,
|
|
1233
1350
|
"warning",
|
|
1234
1351
|
);
|
|
1235
1352
|
// Fall through to next iteration where dispatch will re-derive
|
|
1236
|
-
// and re-dispatch this
|
|
1353
|
+
// and re-dispatch this unit.
|
|
1237
1354
|
return { action: "next", data: { unitStartedAt: s.currentUnit?.startedAt } };
|
|
1238
1355
|
}
|
|
1239
1356
|
}
|
|
@@ -1277,6 +1394,27 @@ export async function runUnitPhase(
|
|
|
1277
1394
|
|
|
1278
1395
|
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: ic.nextSeq(), eventType: "unit-end", data: { unitType, unitId, status: unitResult.status, artifactVerified, ...(unitResult.errorContext ? { errorContext: unitResult.errorContext } : {}) }, causedBy: { flowId: ic.flowId, seq: unitStartSeq } });
|
|
1279
1396
|
|
|
1397
|
+
// ── Safety harness: checkpoint cleanup or rollback ──
|
|
1398
|
+
if (s.checkpointSha) {
|
|
1399
|
+
if (unitResult.status === "error" && safetyConfig.auto_rollback) {
|
|
1400
|
+
const rolled = rollbackToCheckpoint(s.basePath, unitId, s.checkpointSha);
|
|
1401
|
+
if (rolled) {
|
|
1402
|
+
ctx.ui.notify(`Rolled back to pre-unit checkpoint for ${unitId}`, "info");
|
|
1403
|
+
debugLog("runUnitPhase", { phase: "checkpoint-rollback", unitId });
|
|
1404
|
+
}
|
|
1405
|
+
} else if (unitResult.status === "error") {
|
|
1406
|
+
ctx.ui.notify(
|
|
1407
|
+
`Unit ${unitId} failed. Pre-unit checkpoint available at ${s.checkpointSha.slice(0, 8)}`,
|
|
1408
|
+
"warning",
|
|
1409
|
+
);
|
|
1410
|
+
} else {
|
|
1411
|
+
// Success — clean up checkpoint ref
|
|
1412
|
+
cleanupCheckpoint(s.basePath, unitId);
|
|
1413
|
+
debugLog("runUnitPhase", { phase: "checkpoint-cleaned", unitId });
|
|
1414
|
+
}
|
|
1415
|
+
s.checkpointSha = null;
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1280
1418
|
return { action: "next", data: { unitStartedAt: s.currentUnit?.startedAt } };
|
|
1281
1419
|
}
|
|
1282
1420
|
|
|
@@ -1377,7 +1515,30 @@ export async function runFinalize(
|
|
|
1377
1515
|
}
|
|
1378
1516
|
|
|
1379
1517
|
// Post-verification processing (DB dual-write, hooks, triage, quick-tasks)
|
|
1380
|
-
|
|
1518
|
+
// Timeout guard: if postUnitPostVerification hangs (e.g., module import
|
|
1519
|
+
// deadlock, SQLite transaction hang), force-continue after timeout so the
|
|
1520
|
+
// auto-loop is not permanently frozen (#2344).
|
|
1521
|
+
const postResultGuard = await withTimeout(
|
|
1522
|
+
deps.postUnitPostVerification(postUnitCtx),
|
|
1523
|
+
FINALIZE_POST_TIMEOUT_MS,
|
|
1524
|
+
"postUnitPostVerification",
|
|
1525
|
+
);
|
|
1526
|
+
|
|
1527
|
+
if (postResultGuard.timedOut) {
|
|
1528
|
+
debugLog("autoLoop", {
|
|
1529
|
+
phase: "post-verification-timeout",
|
|
1530
|
+
iteration: ic.iteration,
|
|
1531
|
+
unitType: iterData.unitType,
|
|
1532
|
+
unitId: iterData.unitId,
|
|
1533
|
+
});
|
|
1534
|
+
ctx.ui.notify(
|
|
1535
|
+
`postUnitPostVerification timed out after ${FINALIZE_POST_TIMEOUT_MS / 1000}s for ${iterData.unitType} ${iterData.unitId} — continuing to next iteration`,
|
|
1536
|
+
"warning",
|
|
1537
|
+
);
|
|
1538
|
+
return { action: "next", data: undefined as void };
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
const postResult = postResultGuard.value;
|
|
1381
1542
|
|
|
1382
1543
|
if (postResult === "stopped") {
|
|
1383
1544
|
debugLog("autoLoop", {
|
|
@@ -105,6 +105,8 @@ export class AutoSession {
|
|
|
105
105
|
// ── Model state ──────────────────────────────────────────────────────────
|
|
106
106
|
autoModeStartModel: StartModel | null = null;
|
|
107
107
|
currentUnitModel: Model<Api> | null = null;
|
|
108
|
+
/** Fully-qualified model ID (provider/id) set after selectAndApplyModel + hook overrides (#2899). */
|
|
109
|
+
currentDispatchedModelId: string | null = null;
|
|
108
110
|
originalModelId: string | null = null;
|
|
109
111
|
originalModelProvider: string | null = null;
|
|
110
112
|
lastBudgetAlertLevel: BudgetAlertLevel = 0;
|
|
@@ -120,6 +122,11 @@ export class AutoSession {
|
|
|
120
122
|
// ── Sidecar queue ─────────────────────────────────────────────────────
|
|
121
123
|
sidecarQueue: SidecarItem[] = [];
|
|
122
124
|
|
|
125
|
+
// ── Tool invocation errors (#2883) ──────────────────────────────────
|
|
126
|
+
/** Set when a GSD tool execution ends with isError due to malformed/truncated
|
|
127
|
+
* JSON arguments. Checked by postUnitPreVerification to break retry loops. */
|
|
128
|
+
lastToolInvocationError: string | null = null;
|
|
129
|
+
|
|
123
130
|
// ── Isolation degradation ────────────────────────────────────────────
|
|
124
131
|
/** Set to true when worktree creation fails; prevents merge of nonexistent branch. */
|
|
125
132
|
isolationDegraded = false;
|
|
@@ -138,6 +145,10 @@ export class AutoSession {
|
|
|
138
145
|
lastBaselineCharCount: number | undefined;
|
|
139
146
|
pendingQuickTasks: CaptureEntry[] = [];
|
|
140
147
|
|
|
148
|
+
// ── Safety harness ───────────────────────────────────────────────────────
|
|
149
|
+
/** SHA of the pre-unit git checkpoint ref. Cleared on success or rollback. */
|
|
150
|
+
checkpointSha: string | null = null;
|
|
151
|
+
|
|
141
152
|
// ── Signal handler ───────────────────────────────────────────────────────
|
|
142
153
|
sigtermHandler: (() => void) | null = null;
|
|
143
154
|
|
|
@@ -193,6 +204,7 @@ export class AutoSession {
|
|
|
193
204
|
// Model
|
|
194
205
|
this.autoModeStartModel = null;
|
|
195
206
|
this.currentUnitModel = null;
|
|
207
|
+
this.currentDispatchedModelId = null;
|
|
196
208
|
this.originalModelId = null;
|
|
197
209
|
this.originalModelProvider = null;
|
|
198
210
|
this.lastBudgetAlertLevel = 0;
|
|
@@ -212,8 +224,10 @@ export class AutoSession {
|
|
|
212
224
|
this.pendingQuickTasks = [];
|
|
213
225
|
this.sidecarQueue = [];
|
|
214
226
|
this.rewriteAttemptCount = 0;
|
|
227
|
+
this.lastToolInvocationError = null;
|
|
215
228
|
this.isolationDegraded = false;
|
|
216
229
|
this.milestoneMergedInPhases = false;
|
|
230
|
+
this.checkpointSha = null;
|
|
217
231
|
|
|
218
232
|
// Signal handler
|
|
219
233
|
this.sigtermHandler = null;
|
|
@@ -438,6 +438,8 @@ export interface WidgetStateAccessors {
|
|
|
438
438
|
isVerbose(): boolean;
|
|
439
439
|
/** True while newSession() is in-flight — render must not access session state. */
|
|
440
440
|
isSessionSwitching(): boolean;
|
|
441
|
+
/** Fully-qualified dispatched model ID (provider/id) set after model selection + hook overrides (#2899). */
|
|
442
|
+
getCurrentDispatchedModelId(): string | null;
|
|
441
443
|
}
|
|
442
444
|
|
|
443
445
|
export function updateProgressWidget(
|
|
@@ -583,10 +585,11 @@ export function updateProgressWidget(
|
|
|
583
585
|
lines.push(rightAlign(headerLeft, headerRight, width));
|
|
584
586
|
|
|
585
587
|
// Worktree/branch right-aligned below header
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
588
|
+
const branchLabel = worktreeName && cachedBranch
|
|
589
|
+
? `${worktreeName} (${cachedBranch})`
|
|
590
|
+
: cachedBranch ?? "";
|
|
591
|
+
if (branchLabel) {
|
|
592
|
+
lines.push(rightAlign("", theme.fg("dim", branchLabel), width));
|
|
590
593
|
}
|
|
591
594
|
|
|
592
595
|
// Show health signal details when degraded (yellow/red)
|
|
@@ -629,9 +632,15 @@ export function updateProgressWidget(
|
|
|
629
632
|
const cxPctVal = cxUsage?.percent ?? 0;
|
|
630
633
|
const cxPct = cxUsage?.percent !== null ? cxPctVal.toFixed(1) : "?";
|
|
631
634
|
|
|
632
|
-
// Model display —
|
|
633
|
-
|
|
634
|
-
const
|
|
635
|
+
// Model display — prefer dispatched model ID (set after selectAndApplyModel
|
|
636
|
+
// + hook overrides) over cmdCtx?.model which can be stale (#2899).
|
|
637
|
+
const dispatchedModelId = accessors.getCurrentDispatchedModelId();
|
|
638
|
+
const modelId = dispatchedModelId
|
|
639
|
+
? dispatchedModelId.split("/").slice(1).join("/") || dispatchedModelId
|
|
640
|
+
: (cmdCtx?.model?.id ?? "");
|
|
641
|
+
const modelProvider = dispatchedModelId
|
|
642
|
+
? dispatchedModelId.split("/")[0] || ""
|
|
643
|
+
: (cmdCtx?.model?.provider ?? "");
|
|
635
644
|
const tierIcon = resolveServiceTierIcon(effectiveServiceTier, modelId);
|
|
636
645
|
const modelDisplay = (modelProvider && modelId
|
|
637
646
|
? `${modelProvider}/${modelId}`
|
|
@@ -31,6 +31,9 @@ export function resolvePreferredModelConfig(
|
|
|
31
31
|
const routingConfig = resolveDynamicRoutingConfig();
|
|
32
32
|
if (!routingConfig.enabled || !routingConfig.tier_models) return undefined;
|
|
33
33
|
|
|
34
|
+
// Don't synthesize a routing config for flat-rate providers (#3453).
|
|
35
|
+
if (autoModeStartModel && isFlatRateProvider(autoModeStartModel.provider)) return undefined;
|
|
36
|
+
|
|
34
37
|
const ceilingModel = routingConfig.tier_models.heavy
|
|
35
38
|
?? (autoModeStartModel ? `${autoModeStartModel.provider}/${autoModeStartModel.id}` : undefined);
|
|
36
39
|
if (!ceilingModel) return undefined;
|
|
@@ -71,6 +74,27 @@ export async function selectAndApplyModel(
|
|
|
71
74
|
let effectiveModelConfig = modelConfig;
|
|
72
75
|
let routingTierLabel = "";
|
|
73
76
|
|
|
77
|
+
// Disable routing for flat-rate providers like GitHub Copilot (#3453).
|
|
78
|
+
// All models cost the same per request, so downgrading to a cheaper
|
|
79
|
+
// model provides no cost benefit — it only degrades quality.
|
|
80
|
+
// Fail-closed: if primary model can't be resolved, fall back to
|
|
81
|
+
// provider-level signals rather than allowing unwanted downgrades.
|
|
82
|
+
if (routingConfig.enabled) {
|
|
83
|
+
const primaryModel = resolveModelId(modelConfig.primary, availableModels, ctx.model?.provider);
|
|
84
|
+
if (primaryModel) {
|
|
85
|
+
if (isFlatRateProvider(primaryModel.provider)) {
|
|
86
|
+
routingConfig.enabled = false;
|
|
87
|
+
}
|
|
88
|
+
} else if (
|
|
89
|
+
(autoModeStartModel && isFlatRateProvider(autoModeStartModel.provider))
|
|
90
|
+
|| (ctx.model?.provider && isFlatRateProvider(ctx.model.provider))
|
|
91
|
+
) {
|
|
92
|
+
// Primary model unresolvable but provider signals indicate flat-rate —
|
|
93
|
+
// disable routing to prevent quality degradation.
|
|
94
|
+
routingConfig.enabled = false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
74
98
|
if (routingConfig.enabled) {
|
|
75
99
|
let budgetPct: number | undefined;
|
|
76
100
|
if (routingConfig.budget_pressure !== false) {
|
|
@@ -320,3 +344,15 @@ export function resolveModelId<T extends { id: string; provider: string }>(
|
|
|
320
344
|
// Fall back to first non-extension candidate, or any candidate
|
|
321
345
|
return candidates.find(m => !EXTENSION_PROVIDERS.has(m.provider)) ?? candidates[0];
|
|
322
346
|
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Flat-rate providers charge the same per request regardless of model.
|
|
350
|
+
* Dynamic routing provides no cost benefit — it only degrades quality (#3453).
|
|
351
|
+
* Uses case-insensitive matching with alias support to prevent fail-open on
|
|
352
|
+
* provider naming variations (e.g. "copilot" vs "github-copilot").
|
|
353
|
+
*/
|
|
354
|
+
const FLAT_RATE_PROVIDERS = new Set(["github-copilot", "copilot"]);
|
|
355
|
+
|
|
356
|
+
export function isFlatRateProvider(provider: string): boolean {
|
|
357
|
+
return FLAT_RATE_PROVIDERS.has(provider.toLowerCase());
|
|
358
|
+
}
|