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
|
@@ -240,13 +240,13 @@ describe("workflow-logger", () => {
|
|
|
240
240
|
|
|
241
241
|
test("writes entry to .gsd/audit-log.jsonl after setLogBasePath", () => {
|
|
242
242
|
setLogBasePath(dir);
|
|
243
|
-
|
|
243
|
+
logError("engine", "audit test entry");
|
|
244
244
|
|
|
245
245
|
const auditPath = join(dir, ".gsd", "audit-log.jsonl");
|
|
246
246
|
assert.ok(existsSync(auditPath), "audit-log.jsonl should exist");
|
|
247
247
|
const content = readFileSync(auditPath, "utf-8");
|
|
248
248
|
const entry = JSON.parse(content.trim());
|
|
249
|
-
assert.equal(entry.severity, "
|
|
249
|
+
assert.equal(entry.severity, "error");
|
|
250
250
|
assert.equal(entry.component, "engine");
|
|
251
251
|
assert.equal(entry.message, "audit test entry");
|
|
252
252
|
});
|
|
@@ -254,7 +254,7 @@ describe("workflow-logger", () => {
|
|
|
254
254
|
test("_resetLogs does not clear the audit base path", () => {
|
|
255
255
|
setLogBasePath(dir);
|
|
256
256
|
_resetLogs();
|
|
257
|
-
|
|
257
|
+
logError("engine", "post-reset entry");
|
|
258
258
|
|
|
259
259
|
const auditPath = join(dir, ".gsd", "audit-log.jsonl");
|
|
260
260
|
assert.ok(existsSync(auditPath), "audit-log.jsonl should exist after _resetLogs");
|
|
@@ -293,13 +293,13 @@ describe("workflow-logger", () => {
|
|
|
293
293
|
|
|
294
294
|
test("writes entry to .gsd/audit-log.jsonl after setLogBasePath", () => {
|
|
295
295
|
setLogBasePath(dir);
|
|
296
|
-
|
|
296
|
+
logError("engine", "audit test entry");
|
|
297
297
|
|
|
298
298
|
const auditPath = join(dir, ".gsd", "audit-log.jsonl");
|
|
299
299
|
assert.ok(existsSync(auditPath), "audit-log.jsonl should exist");
|
|
300
300
|
const content = readFileSync(auditPath, "utf-8");
|
|
301
301
|
const entry = JSON.parse(content.trim());
|
|
302
|
-
assert.equal(entry.severity, "
|
|
302
|
+
assert.equal(entry.severity, "error");
|
|
303
303
|
assert.equal(entry.component, "engine");
|
|
304
304
|
assert.equal(entry.message, "audit test entry");
|
|
305
305
|
});
|
|
@@ -307,7 +307,7 @@ describe("workflow-logger", () => {
|
|
|
307
307
|
test("_resetLogs does not clear the audit base path", () => {
|
|
308
308
|
setLogBasePath(dir);
|
|
309
309
|
_resetLogs();
|
|
310
|
-
|
|
310
|
+
logError("engine", "post-reset entry");
|
|
311
311
|
|
|
312
312
|
const auditPath = join(dir, ".gsd", "audit-log.jsonl");
|
|
313
313
|
assert.ok(existsSync(auditPath), "audit-log.jsonl should exist after _resetLogs");
|
|
@@ -23,6 +23,7 @@ import { invalidateStateCache } from "../state.js";
|
|
|
23
23
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
24
24
|
import { writeManifest } from "../workflow-manifest.js";
|
|
25
25
|
import { appendEvent } from "../workflow-events.js";
|
|
26
|
+
import { logWarning } from "../workflow-logger.js";
|
|
26
27
|
|
|
27
28
|
export interface CompleteMilestoneParams {
|
|
28
29
|
milestoneId: string;
|
|
@@ -191,9 +192,7 @@ export async function handleCompleteMilestone(
|
|
|
191
192
|
await saveFile(summaryPath, summaryMd);
|
|
192
193
|
} catch (renderErr) {
|
|
193
194
|
// Disk render failed — roll back DB status so state stays consistent
|
|
194
|
-
|
|
195
|
-
`gsd-db: complete_milestone — disk render failed, rolling back DB status: ${(renderErr as Error).message}\n`,
|
|
196
|
-
);
|
|
195
|
+
logWarning("tool", `complete_milestone — disk render failed, rolling back DB status: ${(renderErr as Error).message}`);
|
|
197
196
|
updateMilestoneStatus(params.milestoneId, 'active', null);
|
|
198
197
|
invalidateStateCache();
|
|
199
198
|
return { error: `disk render failed: ${(renderErr as Error).message}` };
|
|
@@ -217,9 +216,7 @@ export async function handleCompleteMilestone(
|
|
|
217
216
|
trigger_reason: params.triggerReason,
|
|
218
217
|
});
|
|
219
218
|
} catch (hookErr) {
|
|
220
|
-
|
|
221
|
-
`gsd: complete-milestone post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
222
|
-
);
|
|
219
|
+
logWarning("tool", `complete-milestone post-mutation hook warning: ${(hookErr as Error).message}`);
|
|
223
220
|
}
|
|
224
221
|
|
|
225
222
|
return {
|
|
@@ -30,6 +30,7 @@ import { renderRoadmapCheckboxes } from "../markdown-renderer.js";
|
|
|
30
30
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
31
31
|
import { writeManifest } from "../workflow-manifest.js";
|
|
32
32
|
import { appendEvent } from "../workflow-events.js";
|
|
33
|
+
import { logWarning } from "../workflow-logger.js";
|
|
33
34
|
|
|
34
35
|
export interface CompleteSliceResult {
|
|
35
36
|
sliceId: string;
|
|
@@ -297,9 +298,7 @@ export async function handleCompleteSlice(
|
|
|
297
298
|
}
|
|
298
299
|
} catch (renderErr) {
|
|
299
300
|
// Disk render failed — roll back DB status so state stays consistent
|
|
300
|
-
|
|
301
|
-
`gsd-db: complete_slice — disk render failed, rolling back DB status: ${(renderErr as Error).message}\n`,
|
|
302
|
-
);
|
|
301
|
+
logWarning("tool", `complete_slice — disk render failed, rolling back DB status: ${(renderErr as Error).message}`);
|
|
303
302
|
updateSliceStatus(params.milestoneId, params.sliceId, 'pending');
|
|
304
303
|
invalidateStateCache();
|
|
305
304
|
return { error: `disk render failed: ${(renderErr as Error).message}` };
|
|
@@ -326,9 +325,7 @@ export async function handleCompleteSlice(
|
|
|
326
325
|
trigger_reason: params.triggerReason,
|
|
327
326
|
});
|
|
328
327
|
} catch (hookErr) {
|
|
329
|
-
|
|
330
|
-
`gsd: complete-slice post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
331
|
-
);
|
|
328
|
+
logWarning("tool", `complete-slice post-mutation hook warning: ${(hookErr as Error).message}`);
|
|
332
329
|
}
|
|
333
330
|
|
|
334
331
|
return {
|
|
@@ -33,6 +33,7 @@ import { renderPlanCheckboxes } from "../markdown-renderer.js";
|
|
|
33
33
|
import { renderAllProjections, renderSummaryContent } from "../workflow-projections.js";
|
|
34
34
|
import { writeManifest } from "../workflow-manifest.js";
|
|
35
35
|
import { appendEvent } from "../workflow-events.js";
|
|
36
|
+
import { logWarning } from "../workflow-logger.js";
|
|
36
37
|
|
|
37
38
|
export interface CompleteTaskResult {
|
|
38
39
|
taskId: string;
|
|
@@ -210,9 +211,7 @@ export async function handleCompleteTask(
|
|
|
210
211
|
}
|
|
211
212
|
} catch (renderErr) {
|
|
212
213
|
// Disk render failed — roll back DB status so state stays consistent
|
|
213
|
-
|
|
214
|
-
`gsd-db: complete_task — disk render failed, rolling back DB status: ${(renderErr as Error).message}\n`,
|
|
215
|
-
);
|
|
214
|
+
logWarning("tool", `complete_task — disk render failed, rolling back DB status: ${(renderErr as Error).message}`);
|
|
216
215
|
// Delete orphaned verification_evidence rows first (FK constraint
|
|
217
216
|
// references tasks, so evidence must go before status change).
|
|
218
217
|
// Without this, retries accumulate duplicate evidence rows (#2724).
|
|
@@ -243,9 +242,7 @@ export async function handleCompleteTask(
|
|
|
243
242
|
trigger_reason: params.triggerReason,
|
|
244
243
|
});
|
|
245
244
|
} catch (hookErr) {
|
|
246
|
-
|
|
247
|
-
`gsd: complete-task post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
248
|
-
);
|
|
245
|
+
logWarning("tool", `complete-task post-mutation hook warning: ${(hookErr as Error).message}`);
|
|
249
246
|
}
|
|
250
247
|
|
|
251
248
|
return {
|
|
@@ -15,6 +15,7 @@ import { renderRoadmapFromDb } from "../markdown-renderer.js";
|
|
|
15
15
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
16
16
|
import { writeManifest } from "../workflow-manifest.js";
|
|
17
17
|
import { appendEvent } from "../workflow-events.js";
|
|
18
|
+
import { logWarning } from "../workflow-logger.js";
|
|
18
19
|
|
|
19
20
|
export interface PlanMilestoneSliceInput {
|
|
20
21
|
sliceId: string;
|
|
@@ -269,9 +270,7 @@ export async function handlePlanMilestone(
|
|
|
269
270
|
const renderResult = await renderRoadmapFromDb(basePath, params.milestoneId);
|
|
270
271
|
roadmapPath = renderResult.roadmapPath;
|
|
271
272
|
} catch (renderErr) {
|
|
272
|
-
|
|
273
|
-
`gsd-db: plan_milestone — render failed (DB rows preserved for debugging): ${(renderErr as Error).message}\n`,
|
|
274
|
-
);
|
|
273
|
+
logWarning("tool", `plan_milestone — render failed (DB rows preserved for debugging): ${(renderErr as Error).message}`);
|
|
275
274
|
invalidateStateCache();
|
|
276
275
|
return { error: `render failed: ${(renderErr as Error).message}` };
|
|
277
276
|
}
|
|
@@ -292,9 +291,7 @@ export async function handlePlanMilestone(
|
|
|
292
291
|
trigger_reason: params.triggerReason,
|
|
293
292
|
});
|
|
294
293
|
} catch (hookErr) {
|
|
295
|
-
|
|
296
|
-
`gsd: plan-milestone post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
297
|
-
);
|
|
294
|
+
logWarning("tool", `plan-milestone post-mutation hook warning: ${(hookErr as Error).message}`);
|
|
298
295
|
}
|
|
299
296
|
|
|
300
297
|
return {
|
|
@@ -16,6 +16,7 @@ import { renderPlanFromDb } from "../markdown-renderer.js";
|
|
|
16
16
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
17
17
|
import { writeManifest } from "../workflow-manifest.js";
|
|
18
18
|
import { appendEvent } from "../workflow-events.js";
|
|
19
|
+
import { logWarning } from "../workflow-logger.js";
|
|
19
20
|
|
|
20
21
|
export interface PlanSliceTaskInput {
|
|
21
22
|
taskId: string;
|
|
@@ -229,9 +230,7 @@ export async function handlePlanSlice(
|
|
|
229
230
|
trigger_reason: params.triggerReason,
|
|
230
231
|
});
|
|
231
232
|
} catch (hookErr) {
|
|
232
|
-
|
|
233
|
-
`gsd: plan-slice post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
234
|
-
);
|
|
233
|
+
logWarning("tool", `plan-slice post-mutation hook warning: ${(hookErr as Error).message}`);
|
|
235
234
|
}
|
|
236
235
|
|
|
237
236
|
return {
|
|
@@ -241,9 +240,7 @@ export async function handlePlanSlice(
|
|
|
241
240
|
taskPlanPaths: renderResult.taskPlanPaths,
|
|
242
241
|
};
|
|
243
242
|
} catch (renderErr) {
|
|
244
|
-
|
|
245
|
-
`gsd-db: plan_slice — render failed (DB rows preserved for debugging): ${(renderErr as Error).message}\n`,
|
|
246
|
-
);
|
|
243
|
+
logWarning("tool", `plan_slice — render failed (DB rows preserved for debugging): ${(renderErr as Error).message}`);
|
|
247
244
|
invalidateStateCache();
|
|
248
245
|
return { error: `render failed: ${(renderErr as Error).message}` };
|
|
249
246
|
}
|
|
@@ -7,6 +7,7 @@ import { renderTaskPlanFromDb } from "../markdown-renderer.js";
|
|
|
7
7
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
8
8
|
import { writeManifest } from "../workflow-manifest.js";
|
|
9
9
|
import { appendEvent } from "../workflow-events.js";
|
|
10
|
+
import { logWarning } from "../workflow-logger.js";
|
|
10
11
|
|
|
11
12
|
export interface PlanTaskParams {
|
|
12
13
|
milestoneId: string;
|
|
@@ -135,9 +136,7 @@ export async function handlePlanTask(
|
|
|
135
136
|
trigger_reason: params.triggerReason,
|
|
136
137
|
});
|
|
137
138
|
} catch (hookErr) {
|
|
138
|
-
|
|
139
|
-
`gsd: plan-task post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
140
|
-
);
|
|
139
|
+
logWarning("tool", `plan-task post-mutation hook warning: ${(hookErr as Error).message}`);
|
|
141
140
|
}
|
|
142
141
|
|
|
143
142
|
return {
|
|
@@ -19,6 +19,7 @@ import { renderRoadmapFromDb, renderAssessmentFromDb } from "../markdown-rendere
|
|
|
19
19
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
20
20
|
import { writeManifest } from "../workflow-manifest.js";
|
|
21
21
|
import { appendEvent } from "../workflow-events.js";
|
|
22
|
+
import { logWarning } from "../workflow-logger.js";
|
|
22
23
|
|
|
23
24
|
export interface SliceChangeInput {
|
|
24
25
|
sliceId: string;
|
|
@@ -248,9 +249,8 @@ export async function handleReassessRoadmap(
|
|
|
248
249
|
);
|
|
249
250
|
try {
|
|
250
251
|
if (existsSync(validationFile)) unlinkSync(validationFile);
|
|
251
|
-
} catch {
|
|
252
|
-
|
|
253
|
-
// will not see the file-based verdict as authoritative.
|
|
252
|
+
} catch (e) {
|
|
253
|
+
logWarning("tool", `validation file cleanup failed: ${(e as Error).message}`);
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
|
|
@@ -271,9 +271,7 @@ export async function handleReassessRoadmap(
|
|
|
271
271
|
trigger_reason: params.triggerReason,
|
|
272
272
|
});
|
|
273
273
|
} catch (hookErr) {
|
|
274
|
-
|
|
275
|
-
`gsd: reassess-roadmap post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
276
|
-
);
|
|
274
|
+
logWarning("tool", `reassess-roadmap post-mutation hook warning: ${(hookErr as Error).message}`);
|
|
277
275
|
}
|
|
278
276
|
|
|
279
277
|
return {
|
|
@@ -24,6 +24,7 @@ import { isClosedStatus } from "../status-guards.js";
|
|
|
24
24
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
25
25
|
import { writeManifest } from "../workflow-manifest.js";
|
|
26
26
|
import { appendEvent } from "../workflow-events.js";
|
|
27
|
+
import { logWarning } from "../workflow-logger.js";
|
|
27
28
|
|
|
28
29
|
export interface ReopenSliceParams {
|
|
29
30
|
milestoneId: string;
|
|
@@ -113,9 +114,7 @@ export async function handleReopenSlice(
|
|
|
113
114
|
trigger_reason: params.triggerReason,
|
|
114
115
|
});
|
|
115
116
|
} catch (hookErr) {
|
|
116
|
-
|
|
117
|
-
`gsd: reopen-slice post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
118
|
-
);
|
|
117
|
+
logWarning("tool", `reopen-slice post-mutation hook warning: ${(hookErr as Error).message}`);
|
|
119
118
|
}
|
|
120
119
|
|
|
121
120
|
return {
|
|
@@ -22,6 +22,7 @@ import { isClosedStatus } from "../status-guards.js";
|
|
|
22
22
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
23
23
|
import { writeManifest } from "../workflow-manifest.js";
|
|
24
24
|
import { appendEvent } from "../workflow-events.js";
|
|
25
|
+
import { logWarning } from "../workflow-logger.js";
|
|
25
26
|
|
|
26
27
|
export interface ReopenTaskParams {
|
|
27
28
|
milestoneId: string;
|
|
@@ -117,9 +118,7 @@ export async function handleReopenTask(
|
|
|
117
118
|
trigger_reason: params.triggerReason,
|
|
118
119
|
});
|
|
119
120
|
} catch (hookErr) {
|
|
120
|
-
|
|
121
|
-
`gsd: reopen-task post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
122
|
-
);
|
|
121
|
+
logWarning("tool", `reopen-task post-mutation hook warning: ${(hookErr as Error).message}`);
|
|
123
122
|
}
|
|
124
123
|
|
|
125
124
|
return {
|
|
@@ -16,6 +16,7 @@ import { renderPlanFromDb, renderReplanFromDb } from "../markdown-renderer.js";
|
|
|
16
16
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
17
17
|
import { writeManifest } from "../workflow-manifest.js";
|
|
18
18
|
import { appendEvent } from "../workflow-events.js";
|
|
19
|
+
import { logWarning } from "../workflow-logger.js";
|
|
19
20
|
|
|
20
21
|
export interface ReplanSliceTaskInput {
|
|
21
22
|
taskId: string;
|
|
@@ -226,9 +227,7 @@ export async function handleReplanSlice(
|
|
|
226
227
|
trigger_reason: params.triggerReason,
|
|
227
228
|
});
|
|
228
229
|
} catch (hookErr) {
|
|
229
|
-
|
|
230
|
-
`gsd: replan-slice post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
231
|
-
);
|
|
230
|
+
logWarning("tool", `replan-slice post-mutation hook warning: ${(hookErr as Error).message}`);
|
|
232
231
|
}
|
|
233
232
|
|
|
234
233
|
return {
|
|
@@ -22,6 +22,7 @@ import { saveFile, clearParseCache } from "../files.js";
|
|
|
22
22
|
import { invalidateStateCache } from "../state.js";
|
|
23
23
|
import { VALIDATION_VERDICTS, isValidMilestoneVerdict } from "../verdict-parser.js";
|
|
24
24
|
import { insertMilestoneValidationGates } from "../milestone-validation-gates.js";
|
|
25
|
+
import { logWarning } from "../workflow-logger.js";
|
|
25
26
|
|
|
26
27
|
export interface ValidateMilestoneParams {
|
|
27
28
|
milestoneId: string;
|
|
@@ -137,9 +138,7 @@ export async function handleValidateMilestone(
|
|
|
137
138
|
try {
|
|
138
139
|
await saveFile(validationPath, validationMd);
|
|
139
140
|
} catch (renderErr) {
|
|
140
|
-
|
|
141
|
-
`gsd-db: validate_milestone — disk render failed, rolling back DB row: ${(renderErr as Error).message}\n`,
|
|
142
|
-
);
|
|
141
|
+
logWarning("tool", `validate_milestone — disk render failed, rolling back DB row: ${(renderErr as Error).message}`);
|
|
143
142
|
deleteAssessmentByScope(params.milestoneId, 'milestone-validation');
|
|
144
143
|
return { error: `disk render failed: ${(renderErr as Error).message}` };
|
|
145
144
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* Also provides detectFileOverlap() for surfacing downstream impact on quick tasks.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
import { createRequire } from "node:module";
|
|
16
16
|
import { gsdRoot, milestonesDir } from "./paths.js";
|
|
@@ -129,6 +129,136 @@ export function executeReplan(
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
// ─── Backtrack (Milestone Regression) ────────────────────────────────────────
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Execute a backtrack directive — user wants to abandon current milestone
|
|
136
|
+
* and return to a previous one (milestone regression).
|
|
137
|
+
*
|
|
138
|
+
* Writes a BACKTRACK-TRIGGER.md marker at `.gsd/BACKTRACK-TRIGGER.md` with
|
|
139
|
+
* the target milestone, reason, and timestamp. The state machine (deriveState)
|
|
140
|
+
* detects this and transitions the project to the target milestone, resetting
|
|
141
|
+
* its slices to allow re-planning.
|
|
142
|
+
*
|
|
143
|
+
* Returns the extracted target milestone ID, or null if extraction failed.
|
|
144
|
+
*/
|
|
145
|
+
export function executeBacktrack(
|
|
146
|
+
basePath: string,
|
|
147
|
+
currentMilestoneId: string,
|
|
148
|
+
capture: CaptureEntry,
|
|
149
|
+
): string | null {
|
|
150
|
+
try {
|
|
151
|
+
// Extract target milestone from capture text or resolution.
|
|
152
|
+
// Filter out the current milestone ID to avoid picking it as the backtrack target
|
|
153
|
+
// when the text mentions both current and target milestones (e.g. "backtrack from M004 to M003").
|
|
154
|
+
const sourceText = capture.resolution ?? capture.text;
|
|
155
|
+
const allMatches = [...sourceText.matchAll(/\b(M\d{3}(?:-[a-z0-9]{6})?)\b/g)]
|
|
156
|
+
.map(m => m[1])
|
|
157
|
+
.filter(id => id !== currentMilestoneId);
|
|
158
|
+
// Reject ambiguous multi-target strings — if more than one distinct target remains,
|
|
159
|
+
// don't guess; let the user clarify.
|
|
160
|
+
const uniqueTargets = [...new Set(allMatches)];
|
|
161
|
+
const targetMilestoneId = uniqueTargets.length === 1 ? uniqueTargets[0] : null;
|
|
162
|
+
|
|
163
|
+
const ts = new Date().toISOString();
|
|
164
|
+
const triggerPath = join(gsdRoot(basePath), "BACKTRACK-TRIGGER.md");
|
|
165
|
+
const content = [
|
|
166
|
+
`# Backtrack Trigger`,
|
|
167
|
+
``,
|
|
168
|
+
`**Source:** Capture ${capture.id}`,
|
|
169
|
+
`**Capture:** ${capture.text}`,
|
|
170
|
+
`**Rationale:** ${capture.rationale ?? "User-initiated milestone backtrack"}`,
|
|
171
|
+
`**From:** ${currentMilestoneId}`,
|
|
172
|
+
`**Target:** ${targetMilestoneId ?? "(user to specify)"}`,
|
|
173
|
+
`**Triggered:** ${ts}`,
|
|
174
|
+
``,
|
|
175
|
+
`Auto-mode was paused by this backtrack directive. The user directed`,
|
|
176
|
+
`that the current milestone (${currentMilestoneId}) be abandoned and work`,
|
|
177
|
+
`should return to ${targetMilestoneId ?? "a previous milestone"}.`,
|
|
178
|
+
``,
|
|
179
|
+
`## Recovery Steps`,
|
|
180
|
+
``,
|
|
181
|
+
`1. Review what went wrong in ${currentMilestoneId}`,
|
|
182
|
+
`2. Identify missing features/requirements from the target milestone`,
|
|
183
|
+
`3. Resume auto-mode — the state machine will re-enter discussion for the target`,
|
|
184
|
+
].join("\n");
|
|
185
|
+
|
|
186
|
+
writeFileSync(triggerPath, content, "utf-8");
|
|
187
|
+
|
|
188
|
+
// If we have a valid target, also reset that milestone's completion status
|
|
189
|
+
// so deriveState() will re-enter it as the active milestone.
|
|
190
|
+
if (targetMilestoneId) {
|
|
191
|
+
try {
|
|
192
|
+
const targetDir = join(milestonesDir(basePath), targetMilestoneId);
|
|
193
|
+
if (existsSync(targetDir)) {
|
|
194
|
+
// Write a regression marker so the state machine knows this milestone
|
|
195
|
+
// needs re-discussion, not just re-execution
|
|
196
|
+
const regressionPath = join(targetDir, `${targetMilestoneId}-REGRESSION.md`);
|
|
197
|
+
writeFileSync(regressionPath, [
|
|
198
|
+
`# Milestone Regression`,
|
|
199
|
+
``,
|
|
200
|
+
`**From:** ${currentMilestoneId}`,
|
|
201
|
+
`**Reason:** ${capture.text}`,
|
|
202
|
+
`**Triggered:** ${ts}`,
|
|
203
|
+
``,
|
|
204
|
+
`This milestone is being revisited because downstream milestone`,
|
|
205
|
+
`${currentMilestoneId} failed or missed critical features that should`,
|
|
206
|
+
`have been part of this milestone's scope.`,
|
|
207
|
+
``,
|
|
208
|
+
`The discuss phase should re-evaluate requirements and identify gaps.`,
|
|
209
|
+
].join("\n"), "utf-8");
|
|
210
|
+
}
|
|
211
|
+
} catch { /* best-effort */ }
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return targetMilestoneId;
|
|
215
|
+
} catch {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Read the backtrack trigger file if it exists.
|
|
222
|
+
* Returns the parsed target milestone and metadata, or null.
|
|
223
|
+
*/
|
|
224
|
+
export function readBacktrackTrigger(basePath: string): {
|
|
225
|
+
target: string | null;
|
|
226
|
+
from: string | null;
|
|
227
|
+
capture: string;
|
|
228
|
+
triggeredAt: string;
|
|
229
|
+
} | null {
|
|
230
|
+
const triggerPath = join(gsdRoot(basePath), "BACKTRACK-TRIGGER.md");
|
|
231
|
+
if (!existsSync(triggerPath)) return null;
|
|
232
|
+
|
|
233
|
+
try {
|
|
234
|
+
const content = readFileSync(triggerPath, "utf-8");
|
|
235
|
+
const target = content.match(/\*\*Target:\*\*\s*(.+)/)?.[1]?.trim() ?? null;
|
|
236
|
+
const from = content.match(/\*\*From:\*\*\s*(.+)/)?.[1]?.trim() ?? null;
|
|
237
|
+
const capture = content.match(/\*\*Capture:\*\*\s*(.+)/)?.[1]?.trim() ?? "";
|
|
238
|
+
const triggeredAt = content.match(/\*\*Triggered:\*\*\s*(.+)/)?.[1]?.trim() ?? "";
|
|
239
|
+
return {
|
|
240
|
+
target: target === "(user to specify)" ? null : target,
|
|
241
|
+
from,
|
|
242
|
+
capture,
|
|
243
|
+
triggeredAt,
|
|
244
|
+
};
|
|
245
|
+
} catch {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Remove the backtrack trigger after it has been processed.
|
|
252
|
+
*/
|
|
253
|
+
export function clearBacktrackTrigger(basePath: string): void {
|
|
254
|
+
const triggerPath = join(gsdRoot(basePath), "BACKTRACK-TRIGGER.md");
|
|
255
|
+
try {
|
|
256
|
+
if (existsSync(triggerPath)) {
|
|
257
|
+
unlinkSync(triggerPath);
|
|
258
|
+
}
|
|
259
|
+
} catch { /* best-effort */ }
|
|
260
|
+
}
|
|
261
|
+
|
|
132
262
|
// ─── File Overlap Detection ───────────────────────────────────────────────────
|
|
133
263
|
|
|
134
264
|
/**
|
|
@@ -298,6 +428,10 @@ export interface TriageExecutionResult {
|
|
|
298
428
|
deferredMilestones: number;
|
|
299
429
|
/** Captures classified as quick-task that need dispatch */
|
|
300
430
|
quickTasks: CaptureEntry[];
|
|
431
|
+
/** Number of stop directives (will pause auto-mode via guard) */
|
|
432
|
+
stopped: number;
|
|
433
|
+
/** Backtrack captures (will trigger milestone regression via guard) */
|
|
434
|
+
backtracks: CaptureEntry[];
|
|
301
435
|
/** Details of each action taken, for logging */
|
|
302
436
|
actions: string[];
|
|
303
437
|
}
|
|
@@ -326,6 +460,8 @@ export function executeTriageResolutions(
|
|
|
326
460
|
replanned: 0,
|
|
327
461
|
deferredMilestones: 0,
|
|
328
462
|
quickTasks: [],
|
|
463
|
+
stopped: 0,
|
|
464
|
+
backtracks: [],
|
|
329
465
|
actions: [],
|
|
330
466
|
};
|
|
331
467
|
|
|
@@ -409,5 +545,19 @@ export function executeTriageResolutions(
|
|
|
409
545
|
}
|
|
410
546
|
}
|
|
411
547
|
|
|
548
|
+
// Count stop/backtrack captures — these are handled by the pre-dispatch guard
|
|
549
|
+
// in runGuards(), not here. We just report them for logging purposes.
|
|
550
|
+
const allCaptures = loadAllCaptures(basePath);
|
|
551
|
+
for (const cap of allCaptures) {
|
|
552
|
+
if (cap.status !== "resolved" || cap.executed) continue;
|
|
553
|
+
if (cap.classification === "stop") {
|
|
554
|
+
result.stopped++;
|
|
555
|
+
result.actions.push(`Stop directive from ${cap.id}: "${cap.text}" — will pause on next dispatch`);
|
|
556
|
+
} else if (cap.classification === "backtrack") {
|
|
557
|
+
result.backtracks.push(cap);
|
|
558
|
+
result.actions.push(`Backtrack directive from ${cap.id}: "${cap.text}" — will trigger milestone regression on next dispatch`);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
412
562
|
return result;
|
|
413
563
|
}
|
|
@@ -49,10 +49,18 @@ const CLASSIFICATION_LABELS: Record<Classification, { label: string; description
|
|
|
49
49
|
label: "Note",
|
|
50
50
|
description: "Informational only — no action needed.",
|
|
51
51
|
},
|
|
52
|
+
"stop": {
|
|
53
|
+
label: "Stop",
|
|
54
|
+
description: "Halt auto-mode immediately — user directive to cease execution.",
|
|
55
|
+
},
|
|
56
|
+
"backtrack": {
|
|
57
|
+
label: "Backtrack",
|
|
58
|
+
description: "Abandon current milestone and return to a previous one.",
|
|
59
|
+
},
|
|
52
60
|
};
|
|
53
61
|
|
|
54
62
|
const ALL_CLASSIFICATIONS: Classification[] = [
|
|
55
|
-
"quick-task", "inject", "defer", "replan", "note",
|
|
63
|
+
"quick-task", "inject", "defer", "replan", "note", "stop", "backtrack",
|
|
56
64
|
];
|
|
57
65
|
|
|
58
66
|
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
@@ -83,8 +91,9 @@ export async function showTriageConfirmation(
|
|
|
83
91
|
const capture = captureMap.get(result.captureId);
|
|
84
92
|
if (!capture) continue;
|
|
85
93
|
|
|
86
|
-
// Auto-confirm note and
|
|
87
|
-
if (result.classification === "note" || result.classification === "defer"
|
|
94
|
+
// Auto-confirm note, defer, stop, and backtrack — low-impact or urgent directives
|
|
95
|
+
if (result.classification === "note" || result.classification === "defer"
|
|
96
|
+
|| result.classification === "stop" || result.classification === "backtrack") {
|
|
88
97
|
const resolution = result.classification === "note"
|
|
89
98
|
? "acknowledged as note"
|
|
90
99
|
: `deferred${result.targetSlice ? ` to ${result.targetSlice}` : ""}`;
|
|
@@ -2,6 +2,7 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { appendFileSync, readFileSync, existsSync, mkdirSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
5
|
+
import { logWarning } from "./workflow-logger.js";
|
|
5
6
|
|
|
6
7
|
// ─── Session ID ───────────────────────────────────────────────────────────
|
|
7
8
|
|
|
@@ -74,7 +75,7 @@ export function readEvents(logPath: string): WorkflowEvent[] {
|
|
|
74
75
|
try {
|
|
75
76
|
events.push(JSON.parse(line) as WorkflowEvent);
|
|
76
77
|
} catch {
|
|
77
|
-
|
|
78
|
+
logWarning("event-log", `skipping corrupted event line (${line.length} bytes)`);
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
// Centralized warning/error accumulator for the workflow engine pipeline.
|
|
3
3
|
// Captures structured entries that the auto-loop can drain after each unit
|
|
4
4
|
// to surface root causes for stuck loops, silent degradation, and blocked writes.
|
|
5
|
-
//
|
|
5
|
+
// Error-severity entries are persisted to .gsd/audit-log.jsonl (sanitized) for
|
|
6
|
+
// post-mortem analysis. Warnings are ephemeral (stderr + buffer only) to avoid
|
|
7
|
+
// log amplification from expected-control-flow catch paths.
|
|
6
8
|
//
|
|
7
9
|
// Stderr policy: every logWarning/logError call writes immediately to stderr
|
|
8
10
|
// for terminal visibility. This is intentional — unlike debug-logger (which is
|
|
@@ -33,7 +35,20 @@ export type LogComponent =
|
|
|
33
35
|
| "compaction" // Event compaction
|
|
34
36
|
| "reconcile" // Worktree reconciliation
|
|
35
37
|
| "db" // Database operations (gsd-db)
|
|
36
|
-
| "dispatch"
|
|
38
|
+
| "dispatch" // Auto-dispatch rule evaluation
|
|
39
|
+
| "recovery" // Auto-recovery and timeout recovery
|
|
40
|
+
| "session" // Session lock and session state I/O
|
|
41
|
+
| "prompt" // Prompt construction and context injection
|
|
42
|
+
| "dashboard" // Auto-dashboard rendering
|
|
43
|
+
| "timer" // Auto-timers (idle watchdog, hard timeout)
|
|
44
|
+
| "worktree" // Worktree lifecycle (create, sync, merge)
|
|
45
|
+
| "command" // Slash command execution and maintenance
|
|
46
|
+
| "parallel" // Parallel orchestrator and merge
|
|
47
|
+
| "fs" // Safe filesystem operations
|
|
48
|
+
| "bootstrap" // Extension bootstrap (system-context, agent-end)
|
|
49
|
+
| "guided" // Guided flow (discuss, plan wizards)
|
|
50
|
+
| "registry" // Rule registry hook state
|
|
51
|
+
| "renderer"; // Markdown renderer and projections
|
|
37
52
|
|
|
38
53
|
export interface LogEntry {
|
|
39
54
|
ts: string;
|
|
@@ -230,15 +245,47 @@ function _push(
|
|
|
230
245
|
_buffer.shift();
|
|
231
246
|
}
|
|
232
247
|
|
|
233
|
-
// Persist to .gsd/audit-log.jsonl so
|
|
234
|
-
|
|
248
|
+
// Persist errors to .gsd/audit-log.jsonl so they survive context resets.
|
|
249
|
+
// Only error-severity entries are persisted — warnings are ephemeral (stderr + buffer)
|
|
250
|
+
// to avoid log amplification from expected-control-flow catch paths.
|
|
251
|
+
if (_auditBasePath && severity === "error") {
|
|
235
252
|
try {
|
|
236
253
|
const auditDir = join(_auditBasePath, ".gsd");
|
|
237
254
|
mkdirSync(auditDir, { recursive: true });
|
|
238
|
-
|
|
255
|
+
const sanitized = _sanitizeForAudit(entry);
|
|
256
|
+
appendFileSync(join(auditDir, "audit-log.jsonl"), JSON.stringify(sanitized) + "\n", "utf-8");
|
|
239
257
|
} catch (auditErr) {
|
|
240
258
|
// Best-effort — never let audit write failures bubble up
|
|
241
259
|
process.stderr.write(`[gsd:audit] failed to persist log entry: ${(auditErr as Error).message}\n`);
|
|
242
260
|
}
|
|
243
261
|
}
|
|
244
262
|
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Sanitize a log entry before persisting to the audit JSONL file.
|
|
266
|
+
* Strips potentially sensitive context (raw paths, cwd, full error text)
|
|
267
|
+
* to avoid leaking local environment details into durable telemetry.
|
|
268
|
+
*/
|
|
269
|
+
function _sanitizeForAudit(entry: LogEntry): LogEntry {
|
|
270
|
+
const sanitized: LogEntry = {
|
|
271
|
+
ts: entry.ts,
|
|
272
|
+
severity: entry.severity,
|
|
273
|
+
component: entry.component,
|
|
274
|
+
// Truncate message to avoid persisting oversized raw error dumps
|
|
275
|
+
message: entry.message.length > 200 ? entry.message.slice(0, 200) + "…[truncated]" : entry.message,
|
|
276
|
+
};
|
|
277
|
+
if (entry.context) {
|
|
278
|
+
// Allowlist: only persist known-safe structured keys
|
|
279
|
+
const SAFE_KEYS = new Set(["fn", "tool", "mid", "sid", "tid", "worktree"]);
|
|
280
|
+
const filtered: Record<string, string> = {};
|
|
281
|
+
for (const [k, v] of Object.entries(entry.context)) {
|
|
282
|
+
if (SAFE_KEYS.has(k)) {
|
|
283
|
+
filtered[k] = v;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (Object.keys(filtered).length > 0) {
|
|
287
|
+
sanitized.context = filtered;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return sanitized;
|
|
291
|
+
}
|