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
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
type ParallelCandidates,
|
|
42
42
|
} from "./parallel-eligibility.js";
|
|
43
43
|
import { getErrorMessage } from "./error-utils.js";
|
|
44
|
+
import { logWarning } from "./workflow-logger.js";
|
|
44
45
|
|
|
45
46
|
// ─── Types ─────────────────────────────────────────────────────────────────
|
|
46
47
|
|
|
@@ -126,7 +127,7 @@ export function persistState(basePath: string): void {
|
|
|
126
127
|
const tmp = dest + TMP_SUFFIX;
|
|
127
128
|
writeFileSync(tmp, JSON.stringify(persisted, null, 2), "utf-8");
|
|
128
129
|
renameSync(tmp, dest);
|
|
129
|
-
} catch {
|
|
130
|
+
} catch (e) { logWarning("parallel", `persist parallel state failed: ${(e as Error).message}`); }
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
/**
|
|
@@ -136,7 +137,7 @@ function removeStateFile(basePath: string): void {
|
|
|
136
137
|
try {
|
|
137
138
|
const p = stateFilePath(basePath);
|
|
138
139
|
if (existsSync(p)) unlinkSync(p);
|
|
139
|
-
} catch {
|
|
140
|
+
} catch (e) { logWarning("parallel", `clear parallel state file failed: ${(e as Error).message}`); }
|
|
140
141
|
}
|
|
141
142
|
|
|
142
143
|
function isPidAlive(pid: number): boolean {
|
|
@@ -144,7 +145,8 @@ function isPidAlive(pid: number): boolean {
|
|
|
144
145
|
try {
|
|
145
146
|
process.kill(pid, 0);
|
|
146
147
|
return true;
|
|
147
|
-
} catch {
|
|
148
|
+
} catch (e) {
|
|
149
|
+
logWarning("parallel", `pid alive check failed for pid ${pid}: ${(e as Error).message}`);
|
|
148
150
|
return false;
|
|
149
151
|
}
|
|
150
152
|
}
|
|
@@ -176,7 +178,8 @@ export function restoreState(basePath: string): PersistedState | null {
|
|
|
176
178
|
}
|
|
177
179
|
|
|
178
180
|
return persisted;
|
|
179
|
-
} catch {
|
|
181
|
+
} catch (e) {
|
|
182
|
+
logWarning("parallel", `readParallelState JSON parse failed: ${(e as Error).message}`);
|
|
180
183
|
return null;
|
|
181
184
|
}
|
|
182
185
|
}
|
|
@@ -190,8 +193,8 @@ function appendWorkerLog(basePath: string, milestoneId: string, chunk: string):
|
|
|
190
193
|
const dir = join(gsdRoot(basePath), "parallel");
|
|
191
194
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
192
195
|
appendFileSync(workerLogPath(basePath, milestoneId), chunk, "utf-8");
|
|
193
|
-
} catch {
|
|
194
|
-
|
|
196
|
+
} catch (e) {
|
|
197
|
+
logWarning("parallel", `appendFileSync worker log failed for ${milestoneId}: ${(e as Error).message}`);
|
|
195
198
|
}
|
|
196
199
|
}
|
|
197
200
|
|
|
@@ -430,9 +433,8 @@ export async function startParallel(
|
|
|
430
433
|
let wtPath: string;
|
|
431
434
|
try {
|
|
432
435
|
wtPath = createMilestoneWorktree(basePath, mid);
|
|
433
|
-
} catch {
|
|
434
|
-
|
|
435
|
-
// is not available. Fall back to a placeholder path.
|
|
436
|
+
} catch (e) {
|
|
437
|
+
logWarning("parallel", `createMilestoneWorktree fallback for ${mid}: ${(e as Error).message}`);
|
|
436
438
|
wtPath = worktreePath(basePath, mid);
|
|
437
439
|
}
|
|
438
440
|
|
|
@@ -564,7 +566,8 @@ export function spawnWorker(
|
|
|
564
566
|
stdio: ["ignore", "pipe", "pipe"],
|
|
565
567
|
detached: false,
|
|
566
568
|
});
|
|
567
|
-
} catch {
|
|
569
|
+
} catch (e) {
|
|
570
|
+
logWarning("parallel", `spawnSync worker failed for ${milestoneId}: ${(e as Error).message}`);
|
|
568
571
|
return false;
|
|
569
572
|
}
|
|
570
573
|
|
|
@@ -694,7 +697,8 @@ function resolveGsdBin(): string | null {
|
|
|
694
697
|
let thisDir: string;
|
|
695
698
|
try {
|
|
696
699
|
thisDir = dirname(fileURLToPath(import.meta.url));
|
|
697
|
-
} catch {
|
|
700
|
+
} catch (e) {
|
|
701
|
+
logWarning("parallel", `dirname(fileURLToPath) failed: ${(e as Error).message}`);
|
|
698
702
|
thisDir = process.cwd();
|
|
699
703
|
}
|
|
700
704
|
const candidates = [
|
|
@@ -722,7 +726,7 @@ function processWorkerLine(basePath: string, milestoneId: string, line: string):
|
|
|
722
726
|
try {
|
|
723
727
|
event = JSON.parse(line);
|
|
724
728
|
} catch {
|
|
725
|
-
return; //
|
|
729
|
+
return; // Non-NDJSON lines (progress text, tool output) are expected — silent drop
|
|
726
730
|
}
|
|
727
731
|
|
|
728
732
|
const type = String(event.type ?? "");
|
|
@@ -817,7 +821,7 @@ export async function stopParallel(
|
|
|
817
821
|
} else if (worker.pid !== process.pid) {
|
|
818
822
|
process.kill(worker.pid, "SIGTERM");
|
|
819
823
|
}
|
|
820
|
-
} catch {
|
|
824
|
+
} catch (e) { logWarning("parallel", `process.kill SIGTERM failed for pid ${worker.pid}: ${(e as Error).message}`); }
|
|
821
825
|
}
|
|
822
826
|
|
|
823
827
|
// Wait for the headless process to cascade SIGTERM to its RPC child.
|
|
@@ -833,7 +837,7 @@ export async function stopParallel(
|
|
|
833
837
|
} else if (worker.pid !== process.pid) {
|
|
834
838
|
process.kill(worker.pid, "SIGKILL");
|
|
835
839
|
}
|
|
836
|
-
} catch {
|
|
840
|
+
} catch (e) { logWarning("parallel", `process.kill SIGKILL failed for pid ${worker.pid}: ${(e as Error).message}`); }
|
|
837
841
|
await waitForWorkerExit(worker, 250);
|
|
838
842
|
}
|
|
839
843
|
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase handoff anchors — compact structured summaries written between
|
|
3
|
+
* GSD auto-mode phases so downstream agents inherit decisions, blockers,
|
|
4
|
+
* and intent without re-inferring from scratch.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { gsdRoot } from "./paths.js";
|
|
10
|
+
|
|
11
|
+
export interface PhaseAnchor {
|
|
12
|
+
phase: string;
|
|
13
|
+
milestoneId: string;
|
|
14
|
+
generatedAt: string;
|
|
15
|
+
intent: string;
|
|
16
|
+
decisions: string[];
|
|
17
|
+
blockers: string[];
|
|
18
|
+
nextSteps: string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function anchorsDir(basePath: string, milestoneId: string): string {
|
|
22
|
+
return join(gsdRoot(basePath), "milestones", milestoneId, "anchors");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function anchorPath(basePath: string, milestoneId: string, phase: string): string {
|
|
26
|
+
return join(anchorsDir(basePath, milestoneId), `${phase}.json`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function writePhaseAnchor(basePath: string, milestoneId: string, anchor: PhaseAnchor): void {
|
|
30
|
+
const dir = anchorsDir(basePath, milestoneId);
|
|
31
|
+
if (!existsSync(dir)) {
|
|
32
|
+
mkdirSync(dir, { recursive: true });
|
|
33
|
+
}
|
|
34
|
+
writeFileSync(anchorPath(basePath, milestoneId, anchor.phase), JSON.stringify(anchor, null, 2), "utf-8");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function readPhaseAnchor(basePath: string, milestoneId: string, phase: string): PhaseAnchor | null {
|
|
38
|
+
const path = anchorPath(basePath, milestoneId, phase);
|
|
39
|
+
if (!existsSync(path)) return null;
|
|
40
|
+
try {
|
|
41
|
+
return JSON.parse(readFileSync(path, "utf-8")) as PhaseAnchor;
|
|
42
|
+
} catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function formatAnchorForPrompt(anchor: PhaseAnchor): string {
|
|
48
|
+
const lines: string[] = [
|
|
49
|
+
`## Handoff from ${anchor.phase}`,
|
|
50
|
+
"",
|
|
51
|
+
`**Intent:** ${anchor.intent}`,
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
if (anchor.decisions.length > 0) {
|
|
55
|
+
lines.push("", "**Decisions:**");
|
|
56
|
+
for (const d of anchor.decisions) lines.push(`- ${d}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (anchor.blockers.length > 0) {
|
|
60
|
+
lines.push("", "**Blockers:**");
|
|
61
|
+
for (const b of anchor.blockers) lines.push(`- ${b}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (anchor.nextSteps.length > 0) {
|
|
65
|
+
lines.push("", "**Next steps:**");
|
|
66
|
+
for (const s of anchor.nextSteps) lines.push(`- ${s}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
lines.push("", "---");
|
|
70
|
+
return lines.join("\n");
|
|
71
|
+
}
|
|
@@ -21,6 +21,13 @@ import type {
|
|
|
21
21
|
GateEvaluationConfig,
|
|
22
22
|
} from "./types.js";
|
|
23
23
|
import type { DynamicRoutingConfig } from "./model-router.js";
|
|
24
|
+
|
|
25
|
+
export interface ContextManagementConfig {
|
|
26
|
+
observation_masking?: boolean; // default: true
|
|
27
|
+
observation_mask_turns?: number; // default: 8, range: 1-50
|
|
28
|
+
compaction_threshold_percent?: number; // default: 0.70, range: 0.5-0.95
|
|
29
|
+
tool_result_max_chars?: number; // default: 800, range: 200-10000
|
|
30
|
+
}
|
|
24
31
|
import type { GitHubSyncConfig } from "../github-sync/types.js";
|
|
25
32
|
|
|
26
33
|
// ─── Workflow Modes ──────────────────────────────────────────────────────────
|
|
@@ -94,7 +101,9 @@ export const KNOWN_PREFERENCE_KEYS = new Set<string>([
|
|
|
94
101
|
"forensics_dedup",
|
|
95
102
|
"show_token_cost",
|
|
96
103
|
"stale_commit_threshold_minutes",
|
|
104
|
+
"context_management",
|
|
97
105
|
"experimental",
|
|
106
|
+
"codebase",
|
|
98
107
|
]);
|
|
99
108
|
|
|
100
109
|
/** Canonical list of all dispatch unit types. */
|
|
@@ -203,6 +212,16 @@ export interface ExperimentalPreferences {
|
|
|
203
212
|
rtk?: boolean;
|
|
204
213
|
}
|
|
205
214
|
|
|
215
|
+
/** Configuration for the codebase map generator (/gsd codebase). */
|
|
216
|
+
export interface CodebaseMapPreferences {
|
|
217
|
+
/** Additional directory/file patterns to exclude (e.g. ["docs/", "fixtures/"]). Merged with built-in defaults. */
|
|
218
|
+
exclude_patterns?: string[];
|
|
219
|
+
/** Max files to include in the map. Default: 500. */
|
|
220
|
+
max_files?: number;
|
|
221
|
+
/** Files-per-directory threshold before collapsing to a summary line. Default: 20. */
|
|
222
|
+
collapse_threshold?: number;
|
|
223
|
+
}
|
|
224
|
+
|
|
206
225
|
export interface GSDPreferences {
|
|
207
226
|
version?: number;
|
|
208
227
|
mode?: WorkflowMode;
|
|
@@ -227,6 +246,7 @@ export interface GSDPreferences {
|
|
|
227
246
|
post_unit_hooks?: PostUnitHookConfig[];
|
|
228
247
|
pre_dispatch_hooks?: PreDispatchHookConfig[];
|
|
229
248
|
dynamic_routing?: DynamicRoutingConfig;
|
|
249
|
+
context_management?: ContextManagementConfig;
|
|
230
250
|
token_profile?: TokenProfile;
|
|
231
251
|
phases?: PhaseSkipPreferences;
|
|
232
252
|
auto_visualize?: boolean;
|
|
@@ -266,6 +286,8 @@ export interface GSDPreferences {
|
|
|
266
286
|
* See the preferences reference for details on each feature.
|
|
267
287
|
*/
|
|
268
288
|
experimental?: ExperimentalPreferences;
|
|
289
|
+
/** Configuration for the codebase map generator (/gsd codebase). */
|
|
290
|
+
codebase?: CodebaseMapPreferences;
|
|
269
291
|
}
|
|
270
292
|
|
|
271
293
|
export interface LoadedGSDPreferences {
|
|
@@ -428,6 +428,10 @@ export function validatePreferences(preferences: GSDPreferences): {
|
|
|
428
428
|
if (typeof dr.hooks === "boolean") validDr.hooks = dr.hooks;
|
|
429
429
|
else errors.push("dynamic_routing.hooks must be a boolean");
|
|
430
430
|
}
|
|
431
|
+
if (dr.capability_routing !== undefined) {
|
|
432
|
+
if (typeof dr.capability_routing === "boolean") validDr.capability_routing = dr.capability_routing;
|
|
433
|
+
else errors.push("dynamic_routing.capability_routing must be a boolean");
|
|
434
|
+
}
|
|
431
435
|
if (dr.tier_models !== undefined) {
|
|
432
436
|
if (typeof dr.tier_models === "object" && dr.tier_models !== null) {
|
|
433
437
|
const tm = dr.tier_models as Record<string, unknown>;
|
|
@@ -452,6 +456,40 @@ export function validatePreferences(preferences: GSDPreferences): {
|
|
|
452
456
|
}
|
|
453
457
|
}
|
|
454
458
|
|
|
459
|
+
// ─── Context Management ──────────────────────────────────────────────
|
|
460
|
+
if (preferences.context_management !== undefined) {
|
|
461
|
+
if (typeof preferences.context_management === "object" && preferences.context_management !== null) {
|
|
462
|
+
const cm = preferences.context_management as unknown as Record<string, unknown>;
|
|
463
|
+
const validCm: Record<string, unknown> = {};
|
|
464
|
+
|
|
465
|
+
if (cm.observation_masking !== undefined) {
|
|
466
|
+
if (typeof cm.observation_masking === "boolean") validCm.observation_masking = cm.observation_masking;
|
|
467
|
+
else errors.push("context_management.observation_masking must be a boolean");
|
|
468
|
+
}
|
|
469
|
+
if (cm.observation_mask_turns !== undefined) {
|
|
470
|
+
const turns = cm.observation_mask_turns;
|
|
471
|
+
if (typeof turns === "number" && turns >= 1 && turns <= 50) validCm.observation_mask_turns = turns;
|
|
472
|
+
else errors.push("context_management.observation_mask_turns must be a number between 1 and 50");
|
|
473
|
+
}
|
|
474
|
+
if (cm.compaction_threshold_percent !== undefined) {
|
|
475
|
+
const pct = cm.compaction_threshold_percent;
|
|
476
|
+
if (typeof pct === "number" && pct >= 0.5 && pct <= 0.95) validCm.compaction_threshold_percent = pct;
|
|
477
|
+
else errors.push("context_management.compaction_threshold_percent must be a number between 0.5 and 0.95");
|
|
478
|
+
}
|
|
479
|
+
if (cm.tool_result_max_chars !== undefined) {
|
|
480
|
+
const chars = cm.tool_result_max_chars;
|
|
481
|
+
if (typeof chars === "number" && chars >= 200 && chars <= 10000) validCm.tool_result_max_chars = chars;
|
|
482
|
+
else errors.push("context_management.tool_result_max_chars must be a number between 200 and 10000");
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (Object.keys(validCm).length > 0) {
|
|
486
|
+
validated.context_management = validCm as any;
|
|
487
|
+
}
|
|
488
|
+
} else {
|
|
489
|
+
errors.push("context_management must be an object");
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
455
493
|
// ─── Parallel Config ────────────────────────────────────────────────────
|
|
456
494
|
if (preferences.parallel && typeof preferences.parallel === "object") {
|
|
457
495
|
const p = preferences.parallel as unknown as Record<string, unknown>;
|
|
@@ -819,5 +857,50 @@ export function validatePreferences(preferences: GSDPreferences): {
|
|
|
819
857
|
}
|
|
820
858
|
}
|
|
821
859
|
|
|
860
|
+
// ─── Codebase Map ──────────────────────────────────────────────────
|
|
861
|
+
if (preferences.codebase !== undefined) {
|
|
862
|
+
if (typeof preferences.codebase === "object" && preferences.codebase !== null) {
|
|
863
|
+
const cb = preferences.codebase as Record<string, unknown>;
|
|
864
|
+
const validCb: import("./preferences-types.js").CodebaseMapPreferences = {};
|
|
865
|
+
|
|
866
|
+
if (cb.exclude_patterns !== undefined) {
|
|
867
|
+
if (Array.isArray(cb.exclude_patterns) && cb.exclude_patterns.every((p: unknown) => typeof p === "string")) {
|
|
868
|
+
validCb.exclude_patterns = cb.exclude_patterns as string[];
|
|
869
|
+
} else {
|
|
870
|
+
errors.push("codebase.exclude_patterns must be an array of strings");
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
if (cb.max_files !== undefined) {
|
|
874
|
+
const mf = typeof cb.max_files === "number" ? cb.max_files : Number(cb.max_files);
|
|
875
|
+
if (Number.isFinite(mf) && mf >= 1) {
|
|
876
|
+
validCb.max_files = Math.floor(mf);
|
|
877
|
+
} else {
|
|
878
|
+
errors.push("codebase.max_files must be a positive integer");
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
if (cb.collapse_threshold !== undefined) {
|
|
882
|
+
const ct = typeof cb.collapse_threshold === "number" ? cb.collapse_threshold : Number(cb.collapse_threshold);
|
|
883
|
+
if (Number.isFinite(ct) && ct >= 1) {
|
|
884
|
+
validCb.collapse_threshold = Math.floor(ct);
|
|
885
|
+
} else {
|
|
886
|
+
errors.push("codebase.collapse_threshold must be a positive integer");
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
const knownCbKeys = new Set(["exclude_patterns", "max_files", "collapse_threshold"]);
|
|
891
|
+
for (const key of Object.keys(cb)) {
|
|
892
|
+
if (!knownCbKeys.has(key)) {
|
|
893
|
+
warnings.push(`unknown codebase key "${key}" — ignored`);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
if (Object.keys(validCb).length > 0) {
|
|
898
|
+
validated.codebase = validCb;
|
|
899
|
+
}
|
|
900
|
+
} else {
|
|
901
|
+
errors.push("codebase must be an object");
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
822
905
|
return { preferences: validated, errors, warnings };
|
|
823
906
|
}
|
|
@@ -19,6 +19,7 @@ import { parse as parseYaml } from "yaml";
|
|
|
19
19
|
import type { PostUnitHookConfig, PreDispatchHookConfig, TokenProfile } from "./types.js";
|
|
20
20
|
import type { DynamicRoutingConfig } from "./model-router.js";
|
|
21
21
|
import { normalizeStringArray } from "../shared/format-utils.js";
|
|
22
|
+
import { logWarning } from "./workflow-logger.js";
|
|
22
23
|
import { resolveProfileDefaults as _resolveProfileDefaults } from "./preferences-models.js";
|
|
23
24
|
|
|
24
25
|
import {
|
|
@@ -48,6 +49,7 @@ export type {
|
|
|
48
49
|
AutoSupervisorConfig,
|
|
49
50
|
RemoteQuestionsConfig,
|
|
50
51
|
CmuxPreferences,
|
|
52
|
+
CodebaseMapPreferences,
|
|
51
53
|
GSDPreferences,
|
|
52
54
|
LoadedGSDPreferences,
|
|
53
55
|
SkillResolution,
|
|
@@ -237,7 +239,7 @@ function parseFrontmatterBlock(frontmatter: string): GSDPreferences {
|
|
|
237
239
|
}
|
|
238
240
|
return parsed as GSDPreferences;
|
|
239
241
|
} catch (e) {
|
|
240
|
-
|
|
242
|
+
logWarning("guided", `YAML parse error in frontmatter block: ${(e as Error).message}`);
|
|
241
243
|
return {} as GSDPreferences;
|
|
242
244
|
}
|
|
243
245
|
}
|
|
@@ -296,8 +298,8 @@ function parseHeadingListFormat(content: string): GSDPreferences {
|
|
|
296
298
|
}
|
|
297
299
|
|
|
298
300
|
typed[targetSection] = value;
|
|
299
|
-
} catch {
|
|
300
|
-
|
|
301
|
+
} catch (e) {
|
|
302
|
+
logWarning("guided", `preferences section parse failed: ${(e as Error).message}`);
|
|
301
303
|
}
|
|
302
304
|
}
|
|
303
305
|
|
|
@@ -371,6 +373,17 @@ function mergePreferences(base: GSDPreferences, override: GSDPreferences): GSDPr
|
|
|
371
373
|
service_tier: override.service_tier ?? base.service_tier,
|
|
372
374
|
forensics_dedup: override.forensics_dedup ?? base.forensics_dedup,
|
|
373
375
|
show_token_cost: override.show_token_cost ?? base.show_token_cost,
|
|
376
|
+
codebase: (base.codebase || override.codebase)
|
|
377
|
+
? {
|
|
378
|
+
...(base.codebase ?? {}),
|
|
379
|
+
...(override.codebase ?? {}),
|
|
380
|
+
// Merge exclude_patterns arrays rather than overriding
|
|
381
|
+
exclude_patterns: [
|
|
382
|
+
...((base.codebase?.exclude_patterns) ?? []),
|
|
383
|
+
...((override.codebase?.exclude_patterns) ?? []),
|
|
384
|
+
].filter(Boolean),
|
|
385
|
+
}
|
|
386
|
+
: undefined,
|
|
374
387
|
};
|
|
375
388
|
}
|
|
376
389
|
|
|
@@ -22,6 +22,7 @@ import { GSDError, GSD_PARSE_ERROR } from "./errors.js";
|
|
|
22
22
|
import { join, dirname } from "node:path";
|
|
23
23
|
import { fileURLToPath } from "node:url";
|
|
24
24
|
import { homedir } from "node:os";
|
|
25
|
+
import { logWarning } from "./workflow-logger.js";
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* Resolve the GSD extension directory.
|
|
@@ -72,7 +73,7 @@ function warmCache(): void {
|
|
|
72
73
|
// prompts/ may not exist in test environments — lazy loading still works.
|
|
73
74
|
// Emit a diagnostic when running outside tests so wrong-path bugs are visible.
|
|
74
75
|
if (!process.env.VITEST && !process.env.NODE_TEST) {
|
|
75
|
-
|
|
76
|
+
logWarning("prompt", `warmCache: prompts dir not found: ${promptsDir}`);
|
|
76
77
|
}
|
|
77
78
|
}
|
|
78
79
|
|
|
@@ -87,7 +88,7 @@ function warmCache(): void {
|
|
|
87
88
|
} catch {
|
|
88
89
|
// templates/ may not exist in test environments — lazy loading still works.
|
|
89
90
|
if (!process.env.VITEST && !process.env.NODE_TEST) {
|
|
90
|
-
|
|
91
|
+
logWarning("prompt", `warmCache: templates dir not found: ${templatesDir}`);
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
}
|
|
@@ -45,6 +45,13 @@ reason: "<reason>"
|
|
|
45
45
|
### Unpark a milestone
|
|
46
46
|
Remove the `{ID}-PARKED.md` file from the milestone directory to reactivate it.
|
|
47
47
|
|
|
48
|
+
### Skip a slice
|
|
49
|
+
Mark a slice as skipped so auto-mode advances past it without executing. Use the `gsd_skip_slice` tool:
|
|
50
|
+
```
|
|
51
|
+
gsd_skip_slice({ milestoneId: "M003", sliceId: "S02", reason: "Descoped — feature moved to M005" })
|
|
52
|
+
```
|
|
53
|
+
Skipped slices are treated as closed by the state machine (like "complete" but distinct). Use when a slice is no longer needed or has been superseded. The slice data is preserved for reference.
|
|
54
|
+
|
|
48
55
|
### Discard a milestone
|
|
49
56
|
**Permanently** delete a milestone directory and prune it from QUEUE-ORDER.json. **Always confirm with the user before discarding.** Warn explicitly if the milestone has completed work.
|
|
50
57
|
|
|
@@ -20,6 +20,8 @@ The user captured thoughts during execution using `/gsd capture`. Your job is to
|
|
|
20
20
|
|
|
21
21
|
For each capture, classify it as one of:
|
|
22
22
|
|
|
23
|
+
- **stop**: User directive to halt auto-mode immediately. Use when the user says "stop", "halt", "abort", "don't continue", "pause", or otherwise wants execution to cease. Auto-mode will pause after the current unit completes. Examples: "stop running", "halt execution", "don't continue".
|
|
24
|
+
- **backtrack**: User directive to abandon the current milestone and return to a previous one. The user believes earlier milestones missed critical features or need rework. Include the target milestone ID (e.g., M003) in the Resolution field. Auto-mode will pause and write a regression marker. Examples: "restart from M003", "go back to milestone 3", "M004 and M005 failed, restart from M003".
|
|
23
25
|
- **quick-task**: Small, self-contained, no downstream impact. Can be done in minutes without modifying the plan. Examples: fix a typo, add a missing import, tweak a config value.
|
|
24
26
|
- **inject**: Belongs in the current slice but wasn't planned. Needs a new task added to the slice plan. Examples: add error handling to a module being built, add a missing test case for current work.
|
|
25
27
|
- **defer**: Belongs in a future slice or milestone. Not urgent for current work. Examples: performance optimization, feature that depends on unbuilt infrastructure, nice-to-have enhancement.
|
|
@@ -28,10 +30,12 @@ For each capture, classify it as one of:
|
|
|
28
30
|
|
|
29
31
|
## Decision Guidelines
|
|
30
32
|
|
|
33
|
+
- **ALWAYS classify as stop** when the user explicitly says "stop", "halt", "abort", or "don't continue". Never shoe-horn a stop directive into "replan" or "note".
|
|
34
|
+
- **ALWAYS classify as backtrack** when the user references returning to a previous milestone, restarting from an earlier point, or abandoning current milestone work. Include the target milestone ID in the Resolution field (e.g., "Backtrack to M003").
|
|
31
35
|
- Prefer **quick-task** when the work is clearly small and self-contained.
|
|
32
36
|
- Prefer **inject** over **replan** when only a new task is needed, not rewriting existing ones.
|
|
33
37
|
- Prefer **defer** over **inject** when the work doesn't belong in the current slice's scope.
|
|
34
|
-
- Use **replan** only when remaining incomplete tasks need to change — not
|
|
38
|
+
- Use **replan** only when remaining incomplete tasks in the *current slice* need to change — not for cross-milestone issues.
|
|
35
39
|
- Use **note** for observations that don't require action.
|
|
36
40
|
- When unsure between quick-task and inject, consider: will this take more than 10 minutes? If yes, inject.
|
|
37
41
|
|
|
@@ -46,6 +50,7 @@ For each capture, classify it as one of:
|
|
|
46
50
|
- If applicable, which files would be affected
|
|
47
51
|
|
|
48
52
|
For captures classified as **note** or **defer**, auto-confirm without asking — these are low-impact.
|
|
53
|
+
For captures classified as **stop** or **backtrack**, auto-confirm without asking — these are urgent user directives that must be honored immediately.
|
|
49
54
|
For captures classified as **quick-task**, **inject**, or **replan**, ask the user to confirm or choose a different classification.
|
|
50
55
|
|
|
51
56
|
3. **Update** `.gsd/CAPTURES.md` — for each capture, update its section with the confirmed classification:
|
|
@@ -112,8 +112,11 @@ function buildRethinkData(
|
|
|
112
112
|
if (dbAvailable && status !== "complete") {
|
|
113
113
|
const slices = getMilestoneSlices(mid);
|
|
114
114
|
if (slices.length > 0) {
|
|
115
|
-
const done = slices.filter(s => s.status === "complete").length;
|
|
116
|
-
|
|
115
|
+
const done = slices.filter(s => s.status === "complete" || s.status === "done").length;
|
|
116
|
+
const skipped = slices.filter(s => s.status === "skipped").length;
|
|
117
|
+
sliceInfo = skipped > 0
|
|
118
|
+
? `${done}/${slices.length} complete, ${skipped} skipped`
|
|
119
|
+
: `${done}/${slices.length} complete`;
|
|
117
120
|
}
|
|
118
121
|
}
|
|
119
122
|
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
//
|
|
7
7
|
// A module-level singleton accessor allows existing code to migrate incrementally.
|
|
8
8
|
|
|
9
|
+
import { logWarning } from "./workflow-logger.js";
|
|
9
10
|
import type { UnifiedRule, RulePhase } from "./rule-types.js";
|
|
10
11
|
import type { DispatchAction, DispatchContext, DispatchRule } from "./auto-dispatch.js";
|
|
11
12
|
import type {
|
|
@@ -387,8 +388,8 @@ export class RuleRegistry {
|
|
|
387
388
|
const dir = join(basePath, ".gsd");
|
|
388
389
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
389
390
|
writeFileSync(this._hookStatePath(basePath), JSON.stringify(state, null, 2), "utf-8");
|
|
390
|
-
} catch {
|
|
391
|
-
|
|
391
|
+
} catch (e) {
|
|
392
|
+
logWarning("registry", `failed to persist hook state: ${(e as Error).message}`);
|
|
392
393
|
}
|
|
393
394
|
}
|
|
394
395
|
|
|
@@ -407,8 +408,8 @@ export class RuleRegistry {
|
|
|
407
408
|
}
|
|
408
409
|
}
|
|
409
410
|
}
|
|
410
|
-
} catch {
|
|
411
|
-
|
|
411
|
+
} catch (e) {
|
|
412
|
+
logWarning("registry", `failed to restore hook state: ${(e as Error).message}`);
|
|
412
413
|
}
|
|
413
414
|
}
|
|
414
415
|
|
|
@@ -423,8 +424,8 @@ export class RuleRegistry {
|
|
|
423
424
|
"utf-8",
|
|
424
425
|
);
|
|
425
426
|
}
|
|
426
|
-
} catch {
|
|
427
|
-
|
|
427
|
+
} catch (e) {
|
|
428
|
+
logWarning("registry", `failed to clear hook state: ${(e as Error).message}`);
|
|
428
429
|
}
|
|
429
430
|
}
|
|
430
431
|
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, cpSync, type CopySyncOptions } from "node:fs"
|
|
2
2
|
import { dirname } from "node:path"
|
|
3
|
+
import { logWarning } from "./workflow-logger.js"
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Safely creates a directory. Returns true if successful, false on error.
|
|
6
|
-
* Logs
|
|
7
|
+
* Logs warnings via workflow-logger on failure.
|
|
7
8
|
*/
|
|
8
9
|
export function safeMkdir(dirPath: string): boolean {
|
|
9
10
|
try {
|
|
10
11
|
mkdirSync(dirPath, { recursive: true })
|
|
11
12
|
return true
|
|
12
13
|
} catch (err) {
|
|
13
|
-
|
|
14
|
+
logWarning("fs", `mkdir failed: ${dirPath}: ${(err as Error).message}`)
|
|
14
15
|
return false
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* Safely copies src to dst. Returns true if successful, false if src doesn't exist or copy fails.
|
|
20
|
-
* Logs
|
|
21
|
+
* Logs warnings via workflow-logger on failure.
|
|
21
22
|
*/
|
|
22
23
|
export function safeCopy(src: string, dst: string, opts?: CopySyncOptions): boolean {
|
|
23
24
|
if (!existsSync(src)) return false
|
|
@@ -25,7 +26,7 @@ export function safeCopy(src: string, dst: string, opts?: CopySyncOptions): bool
|
|
|
25
26
|
cpSync(src, dst, opts)
|
|
26
27
|
return true
|
|
27
28
|
} catch (err) {
|
|
28
|
-
|
|
29
|
+
logWarning("fs", `copy failed: ${src} → ${dst}: ${(err as Error).message}`)
|
|
29
30
|
return false
|
|
30
31
|
}
|
|
31
32
|
}
|
|
@@ -41,7 +42,7 @@ export function safeCopyRecursive(src: string, dst: string, opts?: Omit<CopySync
|
|
|
41
42
|
cpSync(src, dst, { ...opts, recursive: true })
|
|
42
43
|
return true
|
|
43
44
|
} catch (err) {
|
|
44
|
-
|
|
45
|
+
logWarning("fs", `recursive copy failed: ${src} → ${dst}: ${(err as Error).message}`)
|
|
45
46
|
return false
|
|
46
47
|
}
|
|
47
48
|
}
|
|
@@ -295,7 +295,7 @@ function extractContextTitle(content: string | null, fallback: string): string {
|
|
|
295
295
|
* Helper: check if a DB status counts as "done" (handles K002 ambiguity).
|
|
296
296
|
*/
|
|
297
297
|
function isStatusDone(status: string): boolean {
|
|
298
|
-
return status === 'complete' || status === 'done';
|
|
298
|
+
return status === 'complete' || status === 'done' || status === 'skipped';
|
|
299
299
|
}
|
|
300
300
|
|
|
301
301
|
/**
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Status predicates for GSD state-machine guards.
|
|
3
3
|
*
|
|
4
|
-
* The DB stores status as free-form strings.
|
|
5
|
-
* "closed": "complete" (canonical)
|
|
4
|
+
* The DB stores status as free-form strings. Three values indicate
|
|
5
|
+
* "closed": "complete" (canonical), "done" (legacy / alias), and
|
|
6
|
+
* "skipped" (user-directed skip via rethink or backtrack).
|
|
6
7
|
* Every inline `status === "complete" || status === "done"` should
|
|
7
8
|
* use isClosedStatus() instead.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
/** Returns true when a milestone, slice, or task status indicates closure. */
|
|
11
12
|
export function isClosedStatus(status: string): boolean {
|
|
12
|
-
return status === "complete" || status === "done";
|
|
13
|
+
return status === "complete" || status === "done" || status === "skipped";
|
|
13
14
|
}
|