gsd-pi 2.59.0 → 2.60.0-dev.2580e65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/resources/extensions/ask-user-questions.js +7 -4
- package/dist/resources/extensions/gsd/auto/phases.js +62 -1
- package/dist/resources/extensions/gsd/auto-dashboard.js +21 -8
- package/dist/resources/extensions/gsd/auto-dispatch.js +6 -3
- package/dist/resources/extensions/gsd/auto-model-selection.js +57 -3
- package/dist/resources/extensions/gsd/auto-post-unit.js +43 -3
- package/dist/resources/extensions/gsd/auto-prompts.js +49 -20
- package/dist/resources/extensions/gsd/auto-recovery.js +37 -18
- package/dist/resources/extensions/gsd/auto-start.js +9 -5
- package/dist/resources/extensions/gsd/auto-timers.js +11 -5
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +5 -3
- package/dist/resources/extensions/gsd/auto-verification.js +3 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +120 -55
- package/dist/resources/extensions/gsd/auto.js +39 -17
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +6 -3
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +72 -2
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +4 -10
- package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +2 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +58 -5
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +11 -10
- package/dist/resources/extensions/gsd/captures.js +54 -1
- package/dist/resources/extensions/gsd/commands/catalog.js +2 -0
- package/dist/resources/extensions/gsd/commands-codebase.js +48 -21
- package/dist/resources/extensions/gsd/commands-inspect.js +2 -1
- package/dist/resources/extensions/gsd/commands-maintenance.js +32 -19
- package/dist/resources/extensions/gsd/complexity-classifier.js +9 -5
- package/dist/resources/extensions/gsd/context-masker.js +68 -0
- package/dist/resources/extensions/gsd/custom-verification.js +3 -2
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +7 -0
- package/dist/resources/extensions/gsd/gsd-db.js +35 -15
- package/dist/resources/extensions/gsd/guided-flow.js +19 -9
- package/dist/resources/extensions/gsd/init-wizard.js +12 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +11 -9
- package/dist/resources/extensions/gsd/md-importer.js +5 -4
- package/dist/resources/extensions/gsd/milestone-actions.js +3 -2
- package/dist/resources/extensions/gsd/milestone-ids.js +2 -1
- package/dist/resources/extensions/gsd/model-router.js +199 -45
- package/dist/resources/extensions/gsd/parallel-merge.js +5 -3
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +26 -14
- package/dist/resources/extensions/gsd/phase-anchor.js +56 -0
- package/dist/resources/extensions/gsd/preferences-types.js +2 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +91 -0
- package/dist/resources/extensions/gsd/preferences.js +15 -3
- package/dist/resources/extensions/gsd/prompt-loader.js +3 -2
- package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/dist/resources/extensions/gsd/prompts/rethink.md +7 -0
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +6 -1
- package/dist/resources/extensions/gsd/rethink.js +5 -2
- package/dist/resources/extensions/gsd/rule-registry.js +7 -6
- package/dist/resources/extensions/gsd/safe-fs.js +6 -8
- package/dist/resources/extensions/gsd/state.js +1 -1
- package/dist/resources/extensions/gsd/status-guards.js +4 -3
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +3 -2
- package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +3 -2
- package/dist/resources/extensions/gsd/tools/plan-slice.js +3 -2
- package/dist/resources/extensions/gsd/tools/plan-task.js +2 -1
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +4 -4
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -1
- package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -1
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -1
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +2 -1
- package/dist/resources/extensions/gsd/triage-resolution.js +135 -1
- package/dist/resources/extensions/gsd/triage-ui.js +12 -3
- package/dist/resources/extensions/gsd/workflow-events.js +2 -1
- package/dist/resources/extensions/gsd/workflow-logger.js +37 -4
- package/dist/resources/extensions/gsd/workflow-migration.js +14 -12
- package/dist/resources/extensions/gsd/workflow-projections.js +2 -2
- package/dist/resources/extensions/gsd/workflow-reconcile.js +2 -2
- package/dist/resources/extensions/gsd/worktree-manager.js +26 -14
- package/dist/resources/extensions/shared/interview-ui.js +3 -1
- package/dist/resources/skills/btw/SKILL.md +42 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
- 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 +3 -3
- 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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 +17 -17
- package/dist/web/standalone/.next/server/chunks/2229.js +1 -1
- 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/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +16 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +26 -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/lsp/config.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/config.js +6 -1
- package/packages/pi-coding-agent/dist/core/lsp/config.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/defaults.json +2 -2
- package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.js +47 -0
- package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts +1 -0
- 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 +6 -0
- 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.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +122 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +1 -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 +30 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +1 -7
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +6 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +19 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +26 -0
- package/packages/pi-coding-agent/src/core/lsp/config.ts +7 -1
- package/packages/pi-coding-agent/src/core/lsp/defaults.json +2 -2
- package/packages/pi-coding-agent/src/core/lsp/lsp-legacy-alias.test.ts +70 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +156 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +7 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +38 -0
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +1 -8
- package/pkg/package.json +1 -1
- package/src/resources/extensions/ask-user-questions.ts +7 -3
- package/src/resources/extensions/gsd/auto/phases.ts +70 -1
- package/src/resources/extensions/gsd/auto-dashboard.ts +22 -8
- package/src/resources/extensions/gsd/auto-dispatch.ts +7 -3
- package/src/resources/extensions/gsd/auto-model-selection.ts +77 -6
- package/src/resources/extensions/gsd/auto-post-unit.ts +52 -5
- package/src/resources/extensions/gsd/auto-prompts.ts +54 -20
- package/src/resources/extensions/gsd/auto-recovery.ts +38 -18
- package/src/resources/extensions/gsd/auto-start.ts +10 -9
- package/src/resources/extensions/gsd/auto-timers.ts +12 -5
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +6 -2
- package/src/resources/extensions/gsd/auto-verification.ts +3 -6
- package/src/resources/extensions/gsd/auto-worktree.ts +121 -55
- package/src/resources/extensions/gsd/auto.ts +40 -17
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +4 -3
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +80 -2
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +4 -16
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +2 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +61 -4
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -10
- package/src/resources/extensions/gsd/captures.ts +71 -2
- package/src/resources/extensions/gsd/commands/catalog.ts +2 -0
- package/src/resources/extensions/gsd/commands-codebase.ts +52 -20
- package/src/resources/extensions/gsd/commands-inspect.ts +2 -1
- package/src/resources/extensions/gsd/commands-maintenance.ts +28 -19
- package/src/resources/extensions/gsd/complexity-classifier.ts +10 -5
- package/src/resources/extensions/gsd/context-masker.ts +74 -0
- package/src/resources/extensions/gsd/custom-verification.ts +3 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +7 -0
- package/src/resources/extensions/gsd/gsd-db.ts +14 -16
- package/src/resources/extensions/gsd/guided-flow.ts +9 -8
- package/src/resources/extensions/gsd/init-wizard.ts +12 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +11 -17
- package/src/resources/extensions/gsd/md-importer.ts +5 -4
- package/src/resources/extensions/gsd/milestone-actions.ts +3 -2
- package/src/resources/extensions/gsd/milestone-ids.ts +2 -1
- package/src/resources/extensions/gsd/model-router.ts +245 -56
- package/src/resources/extensions/gsd/parallel-merge.ts +5 -3
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +18 -14
- package/src/resources/extensions/gsd/phase-anchor.ts +71 -0
- package/src/resources/extensions/gsd/preferences-types.ts +22 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +83 -0
- package/src/resources/extensions/gsd/preferences.ts +16 -3
- package/src/resources/extensions/gsd/prompt-loader.ts +3 -2
- package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/src/resources/extensions/gsd/prompts/rethink.md +7 -0
- package/src/resources/extensions/gsd/prompts/triage-captures.md +6 -1
- package/src/resources/extensions/gsd/rethink.ts +5 -2
- package/src/resources/extensions/gsd/rule-registry.ts +7 -6
- package/src/resources/extensions/gsd/safe-fs.ts +6 -5
- package/src/resources/extensions/gsd/state.ts +1 -1
- package/src/resources/extensions/gsd/status-guards.ts +4 -3
- package/src/resources/extensions/gsd/tests/capability-router.test.ts +347 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +27 -2
- package/src/resources/extensions/gsd/tests/context-masker.test.ts +122 -0
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +1188 -0
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +841 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +488 -2
- package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/remote-questions.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +284 -0
- package/src/resources/extensions/gsd/tests/status-guards.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/stop-backtrack.test.ts +216 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/workflow-logger-audit.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +6 -6
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -6
- package/src/resources/extensions/gsd/tools/complete-slice.ts +3 -6
- package/src/resources/extensions/gsd/tools/complete-task.ts +3 -6
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +3 -6
- package/src/resources/extensions/gsd/tools/plan-slice.ts +3 -6
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -3
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +4 -6
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -3
- package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -3
- package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -3
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +2 -3
- package/src/resources/extensions/gsd/triage-resolution.ts +151 -1
- package/src/resources/extensions/gsd/triage-ui.ts +12 -3
- package/src/resources/extensions/gsd/types.ts +1 -0
- package/src/resources/extensions/gsd/workflow-events.ts +2 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +52 -5
- package/src/resources/extensions/gsd/workflow-migration.ts +14 -12
- package/src/resources/extensions/gsd/workflow-projections.ts +2 -2
- package/src/resources/extensions/gsd/workflow-reconcile.ts +2 -2
- package/src/resources/extensions/gsd/worktree-manager.ts +16 -14
- package/src/resources/extensions/shared/interview-ui.ts +3 -1
- package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +144 -0
- package/src/resources/skills/btw/SKILL.md +42 -0
- 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/{DGvT_c5Vb7Wu3X-fEOVUU → ogyMN7M-3bGGuRY08L5HR}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{DGvT_c5Vb7Wu3X-fEOVUU → ogyMN7M-3bGGuRY08L5HR}/_ssgManifest.js +0 -0
|
@@ -82,11 +82,14 @@ export default function AskUserQuestions(pi) {
|
|
|
82
82
|
return errorResult(`Error: ask_user_questions requires non-empty options for every question (question "${q.id}" has none)`, params.questions);
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
+
// Try remote first if configured (works in both interactive and headless modes).
|
|
86
|
+
// tryRemoteQuestions returns null when no remote channel is configured, so
|
|
87
|
+
// this is a no-op when the user has not set up Slack/Discord/Telegram.
|
|
88
|
+
const { tryRemoteQuestions } = await import("./remote-questions/manager.js");
|
|
89
|
+
const remoteResult = await tryRemoteQuestions(params.questions, signal);
|
|
90
|
+
if (remoteResult)
|
|
91
|
+
return { ...remoteResult, details: remoteResult.details };
|
|
85
92
|
if (!ctx.hasUI) {
|
|
86
|
-
const { tryRemoteQuestions } = await import("./remote-questions/manager.js");
|
|
87
|
-
const remoteResult = await tryRemoteQuestions(params.questions, signal);
|
|
88
|
-
if (remoteResult)
|
|
89
|
-
return { ...remoteResult, details: remoteResult.details };
|
|
90
93
|
return errorResult("Error: UI not available (non-interactive mode)", params.questions);
|
|
91
94
|
}
|
|
92
95
|
// Delegate to shared interview UI
|
|
@@ -487,11 +487,53 @@ export async function runDispatch(ic, preData, loopState) {
|
|
|
487
487
|
}
|
|
488
488
|
// ─── runGuards ────────────────────────────────────────────────────────────────
|
|
489
489
|
/**
|
|
490
|
-
* Phase 2: Guards — budget ceiling, context window, secrets re-check.
|
|
490
|
+
* Phase 2: Guards — stop directives, budget ceiling, context window, secrets re-check.
|
|
491
491
|
* Returns break to exit the loop, or next to proceed to dispatch.
|
|
492
492
|
*/
|
|
493
493
|
export async function runGuards(ic, mid) {
|
|
494
494
|
const { ctx, pi, s, deps, prefs } = ic;
|
|
495
|
+
// ── Stop/Backtrack directive guard (#3487) ──
|
|
496
|
+
// Check for unexecuted stop or backtrack captures BEFORE dispatching any unit.
|
|
497
|
+
// This ensures user "halt" directives are honored immediately.
|
|
498
|
+
// IMPORTANT: Fail-closed — any exception during stop handling still breaks the loop
|
|
499
|
+
// to ensure user halt intent is never silently dropped.
|
|
500
|
+
try {
|
|
501
|
+
const { loadStopCaptures, markCaptureExecuted } = await import("../captures.js");
|
|
502
|
+
const stopCaptures = loadStopCaptures(s.basePath);
|
|
503
|
+
if (stopCaptures.length > 0) {
|
|
504
|
+
const first = stopCaptures[0];
|
|
505
|
+
const isBacktrack = first.classification === "backtrack";
|
|
506
|
+
const label = isBacktrack
|
|
507
|
+
? `Backtrack directive: ${first.text}`
|
|
508
|
+
: `Stop directive: ${first.text}`;
|
|
509
|
+
ctx.ui.notify(label, "warning");
|
|
510
|
+
deps.sendDesktopNotification("GSD", label, "warning", "stop-directive", basename(s.originalBasePath || s.basePath));
|
|
511
|
+
// Pause first — ensures auto-mode stops even if later steps fail
|
|
512
|
+
await deps.pauseAuto(ctx, pi);
|
|
513
|
+
// For backtrack captures, write the backtrack trigger after pausing
|
|
514
|
+
if (isBacktrack) {
|
|
515
|
+
try {
|
|
516
|
+
const { executeBacktrack } = await import("../triage-resolution.js");
|
|
517
|
+
executeBacktrack(s.basePath, mid, first);
|
|
518
|
+
}
|
|
519
|
+
catch (e) {
|
|
520
|
+
debugLog("guards", { phase: "backtrack-execution-error", error: String(e) });
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
// Mark captures as executed only after successful pause/transition
|
|
524
|
+
for (const cap of stopCaptures) {
|
|
525
|
+
markCaptureExecuted(s.basePath, cap.id);
|
|
526
|
+
}
|
|
527
|
+
debugLog("autoLoop", { phase: "exit", reason: isBacktrack ? "user-backtrack" : "user-stop" });
|
|
528
|
+
return { action: "break", reason: isBacktrack ? "user-backtrack" : "user-stop" };
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
catch (e) {
|
|
532
|
+
// Fail-closed: if anything in the stop guard throws, break the loop
|
|
533
|
+
// rather than silently continuing and dropping user halt intent
|
|
534
|
+
debugLog("guards", { phase: "stop-guard-error", error: String(e) });
|
|
535
|
+
return { action: "break", reason: "stop-guard-error" };
|
|
536
|
+
}
|
|
495
537
|
// Budget ceiling guard
|
|
496
538
|
const budgetCeiling = prefs?.budget_ceiling;
|
|
497
539
|
if (budgetCeiling !== undefined && budgetCeiling > 0) {
|
|
@@ -843,6 +885,25 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
843
885
|
s.unitDispatchCount.delete(`${unitType}/${unitId}`);
|
|
844
886
|
s.unitRecoveryCount.delete(`${unitType}/${unitId}`);
|
|
845
887
|
}
|
|
888
|
+
// Write phase handoff anchor after successful research/planning completion
|
|
889
|
+
const anchorPhases = new Set(["research-milestone", "research-slice", "plan-milestone", "plan-slice"]);
|
|
890
|
+
if (artifactVerified && mid && anchorPhases.has(unitType)) {
|
|
891
|
+
try {
|
|
892
|
+
const { writePhaseAnchor } = await import("../phase-anchor.js");
|
|
893
|
+
writePhaseAnchor(s.basePath, mid, {
|
|
894
|
+
phase: unitType,
|
|
895
|
+
milestoneId: mid,
|
|
896
|
+
generatedAt: new Date().toISOString(),
|
|
897
|
+
intent: `Completed ${unitType} for ${unitId}`,
|
|
898
|
+
decisions: [],
|
|
899
|
+
blockers: [],
|
|
900
|
+
nextSteps: [],
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
catch (err) { /* non-fatal — anchor is advisory */
|
|
904
|
+
logWarning("engine", `phase anchor failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
846
907
|
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 } });
|
|
847
908
|
return { action: "next", data: { unitStartedAt: s.currentUnit?.startedAt } };
|
|
848
909
|
}
|
|
@@ -20,6 +20,7 @@ import { loadEffectiveGSDPreferences, getGlobalGSDPreferencesPath } from "./pref
|
|
|
20
20
|
import { resolveServiceTierIcon, getEffectiveServiceTier } from "./service-tier.js";
|
|
21
21
|
import { parseUnitId } from "./unit-id.js";
|
|
22
22
|
import { formatRtkSavingsLabel, getRtkSessionSavings, } from "../shared/rtk-session-stats.js";
|
|
23
|
+
import { logWarning } from "./workflow-logger.js";
|
|
23
24
|
// ─── UAT Slice Extraction ─────────────────────────────────────────────────────
|
|
24
25
|
/**
|
|
25
26
|
* Extract the target slice ID from a run-uat unit ID (e.g. "M001/S01" → "S01").
|
|
@@ -220,8 +221,9 @@ export function updateSliceProgressCache(base, mid, activeSid) {
|
|
|
220
221
|
}
|
|
221
222
|
}
|
|
222
223
|
}
|
|
223
|
-
catch {
|
|
224
|
+
catch (err) {
|
|
224
225
|
// Non-fatal — just omit task count
|
|
226
|
+
logWarning("dashboard", `operation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
225
227
|
}
|
|
226
228
|
}
|
|
227
229
|
cachedSliceProgress = {
|
|
@@ -232,8 +234,9 @@ export function updateSliceProgressCache(base, mid, activeSid) {
|
|
|
232
234
|
taskDetails,
|
|
233
235
|
};
|
|
234
236
|
}
|
|
235
|
-
catch {
|
|
237
|
+
catch (err) {
|
|
236
238
|
// Non-fatal — widget just won't show progress bar
|
|
239
|
+
logWarning("dashboard", `operation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
237
240
|
}
|
|
238
241
|
}
|
|
239
242
|
export function getRoadmapSlicesSync() {
|
|
@@ -263,8 +266,9 @@ function refreshLastCommit(basePath) {
|
|
|
263
266
|
}
|
|
264
267
|
lastCommitFetchedAt = Date.now();
|
|
265
268
|
}
|
|
266
|
-
catch {
|
|
269
|
+
catch (err) {
|
|
267
270
|
// Non-fatal — just skip last commit display
|
|
271
|
+
logWarning("dashboard", `operation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
268
272
|
}
|
|
269
273
|
}
|
|
270
274
|
function getLastCommit(basePath) {
|
|
@@ -300,7 +304,9 @@ function ensureWidgetModeLoaded() {
|
|
|
300
304
|
widgetMode = saved;
|
|
301
305
|
}
|
|
302
306
|
}
|
|
303
|
-
catch { /* non-fatal — use default */
|
|
307
|
+
catch (err) { /* non-fatal — use default */
|
|
308
|
+
logWarning("dashboard", `operation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
309
|
+
}
|
|
304
310
|
}
|
|
305
311
|
/** Persist widget mode to global preferences YAML. */
|
|
306
312
|
function persistWidgetMode(mode) {
|
|
@@ -320,7 +326,9 @@ function persistWidgetMode(mode) {
|
|
|
320
326
|
}
|
|
321
327
|
writeFileSync(prefsPath, content, "utf-8");
|
|
322
328
|
}
|
|
323
|
-
catch { /* non-fatal — mode still set in memory */
|
|
329
|
+
catch (err) { /* non-fatal — mode still set in memory */
|
|
330
|
+
logWarning("dashboard", `file write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
331
|
+
}
|
|
324
332
|
}
|
|
325
333
|
/** Cycle to the next widget mode. Returns the new mode. */
|
|
326
334
|
export function cycleWidgetMode() {
|
|
@@ -360,7 +368,9 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
360
368
|
try {
|
|
361
369
|
cachedBranch = getCurrentBranch(accessors.getBasePath());
|
|
362
370
|
}
|
|
363
|
-
catch { /* not in git repo */
|
|
371
|
+
catch (err) { /* not in git repo */
|
|
372
|
+
logWarning("dashboard", `git branch detection failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
373
|
+
}
|
|
364
374
|
// Cache short pwd (last 2 path segments only) + worktree/branch info
|
|
365
375
|
let widgetPwd;
|
|
366
376
|
{
|
|
@@ -394,7 +404,8 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
394
404
|
const savings = sessionId ? getRtkSessionSavings(accessors.getBasePath(), sessionId) : null;
|
|
395
405
|
cachedRtkLabel = formatRtkSavingsLabel(savings);
|
|
396
406
|
}
|
|
397
|
-
catch {
|
|
407
|
+
catch (err) {
|
|
408
|
+
logWarning("dashboard", `RTK savings lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
398
409
|
cachedRtkLabel = null;
|
|
399
410
|
}
|
|
400
411
|
};
|
|
@@ -416,7 +427,9 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
416
427
|
refreshRtkLabel();
|
|
417
428
|
cachedLines = undefined;
|
|
418
429
|
}
|
|
419
|
-
catch { /* non-fatal */
|
|
430
|
+
catch (err) { /* non-fatal */
|
|
431
|
+
logWarning("dashboard", `DB status update failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
432
|
+
}
|
|
420
433
|
}, 15_000);
|
|
421
434
|
return {
|
|
422
435
|
render(width) {
|
|
@@ -13,7 +13,7 @@ import { isDbAvailable, getMilestoneSlices, getPendingGates, markAllGatesOmitted
|
|
|
13
13
|
import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
|
|
14
14
|
import { gsdRoot, resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveTaskFile, relSliceFile, buildMilestoneFileName, } from "./paths.js";
|
|
15
15
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
16
|
-
import { logError } from "./workflow-logger.js";
|
|
16
|
+
import { logWarning, logError } from "./workflow-logger.js";
|
|
17
17
|
import { join } from "node:path";
|
|
18
18
|
import { hasImplementationArtifacts } from "./auto-recovery.js";
|
|
19
19
|
import { buildDiscussMilestonePrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, buildGateEvaluatePrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
|
|
@@ -564,7 +564,9 @@ export const DISPATCH_RULES = [
|
|
|
564
564
|
}
|
|
565
565
|
}
|
|
566
566
|
}
|
|
567
|
-
catch { /* fall through — don't block on DB errors */
|
|
567
|
+
catch (err) { /* fall through — don't block on DB errors */
|
|
568
|
+
logWarning("dispatch", `verification class check failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
569
|
+
}
|
|
568
570
|
return {
|
|
569
571
|
action: "dispatch",
|
|
570
572
|
unitType: "complete-milestone",
|
|
@@ -602,8 +604,9 @@ export async function resolveDispatch(ctx) {
|
|
|
602
604
|
const registry = getRegistry();
|
|
603
605
|
return await registry.evaluateDispatch(ctx);
|
|
604
606
|
}
|
|
605
|
-
catch {
|
|
607
|
+
catch (err) {
|
|
606
608
|
// Registry not initialized — fall back to inline loop
|
|
609
|
+
logWarning("dispatch", `registry dispatch failed, falling back to inline rules: ${err instanceof Error ? err.message : String(err)}`);
|
|
607
610
|
}
|
|
608
611
|
for (const rule of DISPATCH_RULES) {
|
|
609
612
|
const result = await rule.match(ctx);
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { resolveModelWithFallbacksForUnit, resolveDynamicRoutingConfig } from "./preferences.js";
|
|
7
7
|
import { classifyUnitComplexity, tierLabel } from "./complexity-classifier.js";
|
|
8
|
-
import { resolveModelForComplexity, escalateTier } from "./model-router.js";
|
|
8
|
+
import { resolveModelForComplexity, escalateTier, getEligibleModels, loadCapabilityOverrides } from "./model-router.js";
|
|
9
9
|
import { getLedger, getProjectTotals } from "./metrics.js";
|
|
10
10
|
import { unitPhaseLabel } from "./auto-dashboard.js";
|
|
11
11
|
export function resolvePreferredModelConfig(unitType, autoModeStartModel) {
|
|
@@ -68,14 +68,68 @@ export async function selectAndApplyModel(ctx, pi, unitType, unitId, basePath, p
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
|
|
71
|
+
// Load user capability overrides from preferences (D-17: deep-merged with built-in profiles)
|
|
72
|
+
const capabilityOverrides = loadCapabilityOverrides(prefs ?? {});
|
|
73
|
+
// Fire before_model_select hook (ADR-004, D-03)
|
|
74
|
+
// Hook can override model selection entirely by returning { modelId }
|
|
75
|
+
let hookOverride;
|
|
76
|
+
if (routingConfig.hooks !== false) {
|
|
77
|
+
const eligible = getEligibleModels(classification.tier, availableModelIds, routingConfig);
|
|
78
|
+
const hookResult = await pi.emitBeforeModelSelect({
|
|
79
|
+
unitType,
|
|
80
|
+
unitId,
|
|
81
|
+
classification: {
|
|
82
|
+
tier: classification.tier,
|
|
83
|
+
reason: classification.reason,
|
|
84
|
+
downgraded: classification.downgraded,
|
|
85
|
+
},
|
|
86
|
+
taskMetadata: classification.taskMetadata,
|
|
87
|
+
eligibleModels: eligible,
|
|
88
|
+
phaseConfig: modelConfig ? {
|
|
89
|
+
primary: modelConfig.primary,
|
|
90
|
+
fallbacks: modelConfig.fallbacks ?? [],
|
|
91
|
+
} : undefined,
|
|
92
|
+
});
|
|
93
|
+
if (hookResult?.modelId) {
|
|
94
|
+
hookOverride = hookResult.modelId;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
let routingResult;
|
|
98
|
+
if (hookOverride) {
|
|
99
|
+
// Hook override bypasses capability scoring entirely
|
|
100
|
+
routingResult = {
|
|
101
|
+
modelId: hookOverride,
|
|
102
|
+
fallbacks: [
|
|
103
|
+
...(modelConfig?.fallbacks ?? []).filter(f => f !== hookOverride),
|
|
104
|
+
...(modelConfig?.primary && modelConfig.primary !== hookOverride ? [modelConfig.primary] : []),
|
|
105
|
+
],
|
|
106
|
+
tier: classification.tier,
|
|
107
|
+
wasDowngraded: hookOverride !== modelConfig?.primary,
|
|
108
|
+
reason: `hook override: ${hookOverride}`,
|
|
109
|
+
selectionMethod: "tier-only",
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
routingResult = resolveModelForComplexity(classification, modelConfig, routingConfig, availableModelIds, unitType, classification.taskMetadata, capabilityOverrides);
|
|
114
|
+
}
|
|
72
115
|
if (routingResult.wasDowngraded) {
|
|
73
116
|
effectiveModelConfig = {
|
|
74
117
|
primary: routingResult.modelId,
|
|
75
118
|
fallbacks: routingResult.fallbacks,
|
|
76
119
|
};
|
|
77
120
|
if (verbose) {
|
|
78
|
-
|
|
121
|
+
if (routingResult.selectionMethod === "capability-scored" && routingResult.capabilityScores) {
|
|
122
|
+
// Verbose scoring breakdown for capability-scored decisions (D-20)
|
|
123
|
+
const tierLbl = tierLabel(classification.tier);
|
|
124
|
+
const scores = Object.entries(routingResult.capabilityScores)
|
|
125
|
+
.sort(([, a], [, b]) => b - a)
|
|
126
|
+
.map(([id, score]) => `${id}: ${score.toFixed(1)}`)
|
|
127
|
+
.join(", ");
|
|
128
|
+
ctx.ui.notify(`Dynamic routing [${tierLbl}]: ${routingResult.modelId} (capability-scored) — ${scores}`, "info");
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
ctx.ui.notify(`Dynamic routing [${tierLabel(classification.tier)}]: ${routingResult.modelId} (${classification.reason})`, "info");
|
|
132
|
+
}
|
|
79
133
|
}
|
|
80
134
|
}
|
|
81
135
|
routingTierLabel = ` [${tierLabel(classification.tier)}]`;
|
|
@@ -26,7 +26,7 @@ import { isDbAvailable, getTask, getSlice, getMilestone, updateTaskStatus, _getA
|
|
|
26
26
|
import { renderPlanCheckboxes } from "./markdown-renderer.js";
|
|
27
27
|
import { consumeSignal } from "./session-status-io.js";
|
|
28
28
|
import { checkPostUnitHooks, isRetryPending, consumeRetryTrigger, persistHookState, resolveHookArtifactPath, } from "./post-unit-hooks.js";
|
|
29
|
-
import { hasPendingCaptures, loadPendingCaptures } from "./captures.js";
|
|
29
|
+
import { hasPendingCaptures, loadPendingCaptures, revertExecutorResolvedCaptures } from "./captures.js";
|
|
30
30
|
import { debugLog } from "./debug-logger.js";
|
|
31
31
|
import { runSafely } from "./auto-utils.js";
|
|
32
32
|
/** Enqueue a sidecar item (hook, triage, or quick-task) for the main loop to
|
|
@@ -208,8 +208,9 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
208
208
|
const { getTaskIssueNumberForCommit } = await import("../github-sync/sync.js");
|
|
209
209
|
ghIssueNumber = getTaskIssueNumberForCommit(s.basePath, mid, sid, tid) ?? undefined;
|
|
210
210
|
}
|
|
211
|
-
catch {
|
|
211
|
+
catch (err) {
|
|
212
212
|
// GitHub sync not available — skip
|
|
213
|
+
logWarning("engine", `GitHub issue lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
213
214
|
}
|
|
214
215
|
taskContext = {
|
|
215
216
|
taskId: `${sid}/${tid}`,
|
|
@@ -448,7 +449,7 @@ export async function postUnitPostVerification(pctx) {
|
|
|
448
449
|
catch (dbErr) {
|
|
449
450
|
// DB unavailable — fail explicitly rather than silently reverting to markdown mutation.
|
|
450
451
|
// Use 'gsd recover' to rebuild DB state from disk if needed.
|
|
451
|
-
|
|
452
|
+
logError("engine", `retry state-reset failed (DB unavailable): ${dbErr.message}. Run 'gsd recover' to reconcile.`);
|
|
452
453
|
}
|
|
453
454
|
}
|
|
454
455
|
// 2. Delete SUMMARY.md for the task
|
|
@@ -478,6 +479,45 @@ export async function postUnitPostVerification(pctx) {
|
|
|
478
479
|
}
|
|
479
480
|
}
|
|
480
481
|
}
|
|
482
|
+
// ── Fast-path stop detection (#3487) ──
|
|
483
|
+
// Before waiting for triage, check if any PENDING captures contain explicit
|
|
484
|
+
// stop/halt language. If so, pause immediately — don't wait for triage.
|
|
485
|
+
if (s.currentUnit && s.currentUnit.type !== "triage-captures") {
|
|
486
|
+
try {
|
|
487
|
+
const pending = loadPendingCaptures(s.basePath);
|
|
488
|
+
// Match only when the capture text starts with a stop/halt directive word,
|
|
489
|
+
// or the entire text is short and dominated by such a word. This avoids
|
|
490
|
+
// false positives on captures like "add a pause button" or "stop the timer
|
|
491
|
+
// from re-rendering" — those are feature descriptions, not halt directives.
|
|
492
|
+
const STOP_PATTERN = /^(stop|halt|abort|don'?t continue|pause|cease)\b/i;
|
|
493
|
+
const stopCapture = pending.find(c => STOP_PATTERN.test(c.text.trim()));
|
|
494
|
+
if (stopCapture) {
|
|
495
|
+
ctx.ui.notify(`Stop directive detected in pending capture ${stopCapture.id}: "${stopCapture.text}" — pausing auto-mode.`, "warning");
|
|
496
|
+
debugLog("postUnit", { phase: "fast-stop", captureId: stopCapture.id });
|
|
497
|
+
await pauseAuto(ctx, pi);
|
|
498
|
+
return "stopped";
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
catch (e) {
|
|
502
|
+
debugLog("postUnit", { phase: "fast-stop-error", error: String(e) });
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
// ── Capture protection: revert executor-silenced captures (#3487) ──
|
|
506
|
+
// Non-triage agents can write **Status:** resolved to CAPTURES.md, bypassing
|
|
507
|
+
// the triage pipeline. Revert those to pending before the triage check.
|
|
508
|
+
if (s.currentUnit &&
|
|
509
|
+
s.currentUnit.type !== "triage-captures") {
|
|
510
|
+
try {
|
|
511
|
+
const reverted = revertExecutorResolvedCaptures(s.basePath);
|
|
512
|
+
if (reverted > 0) {
|
|
513
|
+
debugLog("postUnit", { phase: "capture-protection", reverted });
|
|
514
|
+
ctx.ui.notify(`Reverted ${reverted} capture${reverted === 1 ? "" : "s"} silenced by executor — re-queuing for triage.`, "warning");
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
catch (e) {
|
|
518
|
+
debugLog("postUnit", { phase: "capture-protection-error", error: String(e) });
|
|
519
|
+
}
|
|
520
|
+
}
|
|
481
521
|
// ── Triage check ──
|
|
482
522
|
if (!s.stepMode &&
|
|
483
523
|
s.currentUnit &&
|
|
@@ -17,6 +17,8 @@ import { existsSync } from "node:fs";
|
|
|
17
17
|
import { computeBudgets, resolveExecutorContextWindow, truncateAtSectionBoundary } from "./context-budget.js";
|
|
18
18
|
import { getPendingGates } from "./gsd-db.js";
|
|
19
19
|
import { formatDecisionsCompact, formatRequirementsCompact } from "./structured-data-formatter.js";
|
|
20
|
+
import { readPhaseAnchor, formatAnchorForPrompt } from "./phase-anchor.js";
|
|
21
|
+
import { logWarning } from "./workflow-logger.js";
|
|
20
22
|
// ─── Preamble Cap ─────────────────────────────────────────────────────────────
|
|
21
23
|
const MAX_PREAMBLE_CHARS = 30_000;
|
|
22
24
|
function capPreamble(preamble) {
|
|
@@ -36,7 +38,8 @@ function formatExecutorConstraints() {
|
|
|
36
38
|
const prefs = loadEffectiveGSDPreferences();
|
|
37
39
|
windowTokens = resolveExecutorContextWindow(undefined, prefs?.preferences);
|
|
38
40
|
}
|
|
39
|
-
catch {
|
|
41
|
+
catch (e) {
|
|
42
|
+
logWarning("prompt", `resolveExecutorContextWindow failed: ${e.message}`);
|
|
40
43
|
windowTokens = 200_000; // safe default
|
|
41
44
|
}
|
|
42
45
|
const budgets = computeBudgets(windowTokens);
|
|
@@ -160,7 +163,9 @@ export async function inlineDependencySummaries(mid, sid, base, budgetChars) {
|
|
|
160
163
|
// If slice not found in DB, fall through to file-based parsing
|
|
161
164
|
}
|
|
162
165
|
}
|
|
163
|
-
catch {
|
|
166
|
+
catch (err) {
|
|
167
|
+
logWarning("prompt", `inlineDependencySummaries DB lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
168
|
+
}
|
|
164
169
|
// If DB didn't provide depends, fall back to roadmap parsing
|
|
165
170
|
if (!depends) {
|
|
166
171
|
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
@@ -232,8 +237,8 @@ export async function inlineDecisionsFromDb(base, milestoneId, scope, level) {
|
|
|
232
237
|
}
|
|
233
238
|
}
|
|
234
239
|
}
|
|
235
|
-
catch {
|
|
236
|
-
|
|
240
|
+
catch (err) {
|
|
241
|
+
logWarning("prompt", `inlineDecisionsFromDb failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
237
242
|
}
|
|
238
243
|
return inlineGsdRootFile(base, "decisions.md", "Decisions");
|
|
239
244
|
}
|
|
@@ -257,8 +262,8 @@ export async function inlineRequirementsFromDb(base, sliceId, level) {
|
|
|
257
262
|
}
|
|
258
263
|
}
|
|
259
264
|
}
|
|
260
|
-
catch {
|
|
261
|
-
|
|
265
|
+
catch (err) {
|
|
266
|
+
logWarning("prompt", `inlineRequirementsFromDb failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
262
267
|
}
|
|
263
268
|
return inlineGsdRootFile(base, "requirements.md", "Requirements");
|
|
264
269
|
}
|
|
@@ -277,8 +282,8 @@ export async function inlineProjectFromDb(base) {
|
|
|
277
282
|
}
|
|
278
283
|
}
|
|
279
284
|
}
|
|
280
|
-
catch {
|
|
281
|
-
|
|
285
|
+
catch (err) {
|
|
286
|
+
logWarning("prompt", `inlineProjectFromDb failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
282
287
|
}
|
|
283
288
|
return inlineGsdRootFile(base, "project.md", "Project");
|
|
284
289
|
}
|
|
@@ -398,8 +403,8 @@ export function buildSkillActivationBlock(params) {
|
|
|
398
403
|
matched.add(normalizeSkillReference(skillName));
|
|
399
404
|
}
|
|
400
405
|
}
|
|
401
|
-
catch {
|
|
402
|
-
|
|
406
|
+
catch (err) {
|
|
407
|
+
logWarning("prompt", `parseTaskPlanFile failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
403
408
|
}
|
|
404
409
|
}
|
|
405
410
|
const ordered = [...matched]
|
|
@@ -618,7 +623,9 @@ export async function checkNeedsReassessment(base, mid, state) {
|
|
|
618
623
|
}
|
|
619
624
|
}
|
|
620
625
|
}
|
|
621
|
-
catch {
|
|
626
|
+
catch (err) {
|
|
627
|
+
logWarning("prompt", `checkNeedsReassessment DB lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
628
|
+
}
|
|
622
629
|
// File-based fallback using roadmap checkboxes
|
|
623
630
|
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
624
631
|
if (!roadmapPath)
|
|
@@ -693,7 +700,9 @@ export async function checkNeedsRunUat(base, mid, state, prefs) {
|
|
|
693
700
|
}
|
|
694
701
|
}
|
|
695
702
|
}
|
|
696
|
-
catch {
|
|
703
|
+
catch (err) {
|
|
704
|
+
logWarning("prompt", `checkNeedsRunUat DB lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
705
|
+
}
|
|
697
706
|
// File-based fallback using roadmap checkboxes
|
|
698
707
|
if (!prefs?.uat_dispatch)
|
|
699
708
|
return null;
|
|
@@ -797,6 +806,10 @@ export async function buildPlanMilestonePrompt(mid, midTitle, base, level) {
|
|
|
797
806
|
const researchPath = resolveMilestoneFile(base, mid, "RESEARCH");
|
|
798
807
|
const researchRel = relMilestoneFile(base, mid, "RESEARCH");
|
|
799
808
|
const inlined = [];
|
|
809
|
+
// Inject phase handoff anchor from research phase (if available)
|
|
810
|
+
const researchAnchor = readPhaseAnchor(base, mid, "research-milestone");
|
|
811
|
+
if (researchAnchor)
|
|
812
|
+
inlined.push(formatAnchorForPrompt(researchAnchor));
|
|
800
813
|
inlined.push(await inlineFile(contextPath, contextRel, "Milestone Context"));
|
|
801
814
|
const researchInline = await inlineFileOptional(researchPath, researchRel, "Milestone Research");
|
|
802
815
|
if (researchInline)
|
|
@@ -919,6 +932,10 @@ export async function buildPlanSlicePrompt(mid, _midTitle, sid, sTitle, base, le
|
|
|
919
932
|
const researchPath = resolveSliceFile(base, mid, sid, "RESEARCH");
|
|
920
933
|
const researchRel = relSliceFile(base, mid, sid, "RESEARCH");
|
|
921
934
|
const inlined = [];
|
|
935
|
+
// Inject phase handoff anchor from research phase (if available)
|
|
936
|
+
const researchSliceAnchor = readPhaseAnchor(base, mid, "research-slice");
|
|
937
|
+
if (researchSliceAnchor)
|
|
938
|
+
inlined.push(formatAnchorForPrompt(researchSliceAnchor));
|
|
922
939
|
inlined.push(await inlineFile(roadmapPath, roadmapRel, "Milestone Roadmap"));
|
|
923
940
|
const researchInline = await inlineFileOptional(researchPath, researchRel, "Slice Research");
|
|
924
941
|
if (researchInline)
|
|
@@ -974,6 +991,8 @@ export async function buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle, base
|
|
|
974
991
|
? level
|
|
975
992
|
: { level: level };
|
|
976
993
|
const inlineLevel = opts.level ?? resolveInlineLevel();
|
|
994
|
+
// Inject phase handoff anchor from planning phase (if available)
|
|
995
|
+
const planAnchor = readPhaseAnchor(base, mid, "plan-slice");
|
|
977
996
|
const priorSummaries = opts.carryForwardPaths ?? await getPriorTaskSummaryPaths(mid, sid, tid, base);
|
|
978
997
|
const priorLines = priorSummaries.length > 0
|
|
979
998
|
? priorSummaries.map(p => `- \`${p}\``).join("\n")
|
|
@@ -1042,9 +1061,11 @@ export async function buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle, base
|
|
|
1042
1061
|
const runtimeContext = runtimeContent
|
|
1043
1062
|
? `### Runtime Context\nSource: \`.gsd/RUNTIME.md\`\n\n${runtimeContent.trim()}`
|
|
1044
1063
|
: "";
|
|
1064
|
+
const phaseAnchorSection = planAnchor ? formatAnchorForPrompt(planAnchor) : "";
|
|
1045
1065
|
return loadPrompt("execute-task", {
|
|
1046
1066
|
overridesSection,
|
|
1047
1067
|
runtimeContext,
|
|
1068
|
+
phaseAnchorSection,
|
|
1048
1069
|
workingDirectory: base,
|
|
1049
1070
|
milestoneId: mid, sliceId: sid, sliceTitle: sTitle, taskId: tid, taskTitle: tTitle,
|
|
1050
1071
|
planPath: join(base, relSliceFile(base, mid, sid, "PLAN")),
|
|
@@ -1137,7 +1158,9 @@ export async function buildCompleteMilestonePrompt(mid, midTitle, base, level) {
|
|
|
1137
1158
|
sliceIds = getMilestoneSlices(mid).map(s => s.id);
|
|
1138
1159
|
}
|
|
1139
1160
|
}
|
|
1140
|
-
catch {
|
|
1161
|
+
catch (err) {
|
|
1162
|
+
logWarning("prompt", `buildCompleteMilestonePrompt DB lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1163
|
+
}
|
|
1141
1164
|
// File-based fallback: parse roadmap for slice IDs when DB has no data
|
|
1142
1165
|
if (sliceIds.length === 0 && roadmapPath) {
|
|
1143
1166
|
const roadmapContent = await loadFile(roadmapPath);
|
|
@@ -1220,7 +1243,9 @@ export async function buildValidateMilestonePrompt(mid, midTitle, base, level) {
|
|
|
1220
1243
|
}
|
|
1221
1244
|
}
|
|
1222
1245
|
}
|
|
1223
|
-
catch {
|
|
1246
|
+
catch (err) {
|
|
1247
|
+
logWarning("prompt", `buildValidateMilestonePrompt verification classes lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1248
|
+
}
|
|
1224
1249
|
// Inline all slice summaries and UAT results
|
|
1225
1250
|
let valSliceIds = [];
|
|
1226
1251
|
try {
|
|
@@ -1229,7 +1254,9 @@ export async function buildValidateMilestonePrompt(mid, midTitle, base, level) {
|
|
|
1229
1254
|
valSliceIds = getMilestoneSlices(mid).map(s => s.id);
|
|
1230
1255
|
}
|
|
1231
1256
|
}
|
|
1232
|
-
catch {
|
|
1257
|
+
catch (err) {
|
|
1258
|
+
logWarning("prompt", `buildValidateMilestonePrompt slice IDs lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1259
|
+
}
|
|
1233
1260
|
// File-based fallback: parse roadmap for slice IDs when DB has no data
|
|
1234
1261
|
if (valSliceIds.length === 0 && roadmapPath) {
|
|
1235
1262
|
const roadmapContent = await loadFile(roadmapPath);
|
|
@@ -1365,8 +1392,8 @@ export async function buildReplanSlicePrompt(mid, midTitle, sid, sTitle, base) {
|
|
|
1365
1392
|
captureContext = replanCaptures.map(c => `- **${c.id}**: "${c.text}" — ${c.rationale ?? "no rationale"}`).join("\n");
|
|
1366
1393
|
}
|
|
1367
1394
|
}
|
|
1368
|
-
catch {
|
|
1369
|
-
|
|
1395
|
+
catch (err) {
|
|
1396
|
+
logWarning("prompt", `loadReplanCaptures failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1370
1397
|
}
|
|
1371
1398
|
return loadPrompt("replan-slice", {
|
|
1372
1399
|
workingDirectory: base,
|
|
@@ -1455,8 +1482,8 @@ export async function buildReassessRoadmapPrompt(mid, midTitle, completedSliceId
|
|
|
1455
1482
|
deferredCaptures = deferred.map(c => `- **${c.id}**: "${c.text}" — ${c.rationale ?? "deferred during triage"}`).join("\n");
|
|
1456
1483
|
}
|
|
1457
1484
|
}
|
|
1458
|
-
catch {
|
|
1459
|
-
|
|
1485
|
+
catch (err) {
|
|
1486
|
+
logWarning("prompt", `loadDeferredCaptures failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1460
1487
|
}
|
|
1461
1488
|
const reassessCommitInstruction = "Do not commit — .gsd/ planning docs are managed externally and not tracked in git.";
|
|
1462
1489
|
return loadPrompt("reassess-roadmap", {
|
|
@@ -1633,7 +1660,9 @@ export async function buildRewriteDocsPrompt(mid, midTitle, activeSlice, base, o
|
|
|
1633
1660
|
.map(t => ({ id: t.id }));
|
|
1634
1661
|
}
|
|
1635
1662
|
}
|
|
1636
|
-
catch {
|
|
1663
|
+
catch (err) {
|
|
1664
|
+
logWarning("prompt", `buildRewriteDocsPrompt DB task lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1665
|
+
}
|
|
1637
1666
|
if (!incompleteTasks) {
|
|
1638
1667
|
// DB unavailable — no task data to inline
|
|
1639
1668
|
incompleteTasks = [];
|