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
|
@@ -14,6 +14,7 @@ import { isClosedStatus } from "../status-guards.js";
|
|
|
14
14
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
15
15
|
import { writeManifest } from "../workflow-manifest.js";
|
|
16
16
|
import { appendEvent } from "../workflow-events.js";
|
|
17
|
+
import { logWarning } from "../workflow-logger.js";
|
|
17
18
|
export async function handleReopenTask(params, basePath) {
|
|
18
19
|
// ── Validate required fields ────────────────────────────────────────────
|
|
19
20
|
if (!params.taskId || typeof params.taskId !== "string" || params.taskId.trim() === "") {
|
|
@@ -81,7 +82,7 @@ export async function handleReopenTask(params, basePath) {
|
|
|
81
82
|
});
|
|
82
83
|
}
|
|
83
84
|
catch (hookErr) {
|
|
84
|
-
|
|
85
|
+
logWarning("tool", `reopen-task post-mutation hook warning: ${hookErr.message}`);
|
|
85
86
|
}
|
|
86
87
|
return {
|
|
87
88
|
milestoneId: params.milestoneId,
|
|
@@ -7,6 +7,7 @@ import { renderPlanFromDb, renderReplanFromDb } 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
|
function validateParams(params) {
|
|
11
12
|
if (!isNonEmptyString(params?.milestoneId))
|
|
12
13
|
throw new Error("milestoneId is required");
|
|
@@ -173,7 +174,7 @@ export async function handleReplanSlice(rawParams, basePath) {
|
|
|
173
174
|
});
|
|
174
175
|
}
|
|
175
176
|
catch (hookErr) {
|
|
176
|
-
|
|
177
|
+
logWarning("tool", `replan-slice post-mutation hook warning: ${hookErr.message}`);
|
|
177
178
|
}
|
|
178
179
|
return {
|
|
179
180
|
milestoneId: params.milestoneId,
|
|
@@ -15,6 +15,7 @@ import { saveFile, clearParseCache } from "../files.js";
|
|
|
15
15
|
import { invalidateStateCache } from "../state.js";
|
|
16
16
|
import { VALIDATION_VERDICTS, isValidMilestoneVerdict } from "../verdict-parser.js";
|
|
17
17
|
import { insertMilestoneValidationGates } from "../milestone-validation-gates.js";
|
|
18
|
+
import { logWarning } from "../workflow-logger.js";
|
|
18
19
|
function renderValidationMarkdown(params) {
|
|
19
20
|
let md = `---
|
|
20
21
|
verdict: ${params.verdict}
|
|
@@ -95,7 +96,7 @@ export async function handleValidateMilestone(params, basePath) {
|
|
|
95
96
|
await saveFile(validationPath, validationMd);
|
|
96
97
|
}
|
|
97
98
|
catch (renderErr) {
|
|
98
|
-
|
|
99
|
+
logWarning("tool", `validate_milestone — disk render failed, rolling back DB row: ${renderErr.message}`);
|
|
99
100
|
deleteAssessmentByScope(params.milestoneId, 'milestone-validation');
|
|
100
101
|
return { error: `disk render failed: ${renderErr.message}` };
|
|
101
102
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Also provides detectFileOverlap() for surfacing downstream impact on quick tasks.
|
|
11
11
|
*/
|
|
12
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
|
|
13
13
|
import { join } from "node:path";
|
|
14
14
|
import { createRequire } from "node:module";
|
|
15
15
|
import { gsdRoot, milestonesDir } from "./paths.js";
|
|
@@ -99,6 +99,123 @@ export function executeReplan(basePath, mid, sid, capture) {
|
|
|
99
99
|
return false;
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
|
+
// ─── Backtrack (Milestone Regression) ────────────────────────────────────────
|
|
103
|
+
/**
|
|
104
|
+
* Execute a backtrack directive — user wants to abandon current milestone
|
|
105
|
+
* and return to a previous one (milestone regression).
|
|
106
|
+
*
|
|
107
|
+
* Writes a BACKTRACK-TRIGGER.md marker at `.gsd/BACKTRACK-TRIGGER.md` with
|
|
108
|
+
* the target milestone, reason, and timestamp. The state machine (deriveState)
|
|
109
|
+
* detects this and transitions the project to the target milestone, resetting
|
|
110
|
+
* its slices to allow re-planning.
|
|
111
|
+
*
|
|
112
|
+
* Returns the extracted target milestone ID, or null if extraction failed.
|
|
113
|
+
*/
|
|
114
|
+
export function executeBacktrack(basePath, currentMilestoneId, capture) {
|
|
115
|
+
try {
|
|
116
|
+
// Extract target milestone from capture text or resolution.
|
|
117
|
+
// Filter out the current milestone ID to avoid picking it as the backtrack target
|
|
118
|
+
// when the text mentions both current and target milestones (e.g. "backtrack from M004 to M003").
|
|
119
|
+
const sourceText = capture.resolution ?? capture.text;
|
|
120
|
+
const allMatches = [...sourceText.matchAll(/\b(M\d{3}(?:-[a-z0-9]{6})?)\b/g)]
|
|
121
|
+
.map(m => m[1])
|
|
122
|
+
.filter(id => id !== currentMilestoneId);
|
|
123
|
+
// Reject ambiguous multi-target strings — if more than one distinct target remains,
|
|
124
|
+
// don't guess; let the user clarify.
|
|
125
|
+
const uniqueTargets = [...new Set(allMatches)];
|
|
126
|
+
const targetMilestoneId = uniqueTargets.length === 1 ? uniqueTargets[0] : null;
|
|
127
|
+
const ts = new Date().toISOString();
|
|
128
|
+
const triggerPath = join(gsdRoot(basePath), "BACKTRACK-TRIGGER.md");
|
|
129
|
+
const content = [
|
|
130
|
+
`# Backtrack Trigger`,
|
|
131
|
+
``,
|
|
132
|
+
`**Source:** Capture ${capture.id}`,
|
|
133
|
+
`**Capture:** ${capture.text}`,
|
|
134
|
+
`**Rationale:** ${capture.rationale ?? "User-initiated milestone backtrack"}`,
|
|
135
|
+
`**From:** ${currentMilestoneId}`,
|
|
136
|
+
`**Target:** ${targetMilestoneId ?? "(user to specify)"}`,
|
|
137
|
+
`**Triggered:** ${ts}`,
|
|
138
|
+
``,
|
|
139
|
+
`Auto-mode was paused by this backtrack directive. The user directed`,
|
|
140
|
+
`that the current milestone (${currentMilestoneId}) be abandoned and work`,
|
|
141
|
+
`should return to ${targetMilestoneId ?? "a previous milestone"}.`,
|
|
142
|
+
``,
|
|
143
|
+
`## Recovery Steps`,
|
|
144
|
+
``,
|
|
145
|
+
`1. Review what went wrong in ${currentMilestoneId}`,
|
|
146
|
+
`2. Identify missing features/requirements from the target milestone`,
|
|
147
|
+
`3. Resume auto-mode — the state machine will re-enter discussion for the target`,
|
|
148
|
+
].join("\n");
|
|
149
|
+
writeFileSync(triggerPath, content, "utf-8");
|
|
150
|
+
// If we have a valid target, also reset that milestone's completion status
|
|
151
|
+
// so deriveState() will re-enter it as the active milestone.
|
|
152
|
+
if (targetMilestoneId) {
|
|
153
|
+
try {
|
|
154
|
+
const targetDir = join(milestonesDir(basePath), targetMilestoneId);
|
|
155
|
+
if (existsSync(targetDir)) {
|
|
156
|
+
// Write a regression marker so the state machine knows this milestone
|
|
157
|
+
// needs re-discussion, not just re-execution
|
|
158
|
+
const regressionPath = join(targetDir, `${targetMilestoneId}-REGRESSION.md`);
|
|
159
|
+
writeFileSync(regressionPath, [
|
|
160
|
+
`# Milestone Regression`,
|
|
161
|
+
``,
|
|
162
|
+
`**From:** ${currentMilestoneId}`,
|
|
163
|
+
`**Reason:** ${capture.text}`,
|
|
164
|
+
`**Triggered:** ${ts}`,
|
|
165
|
+
``,
|
|
166
|
+
`This milestone is being revisited because downstream milestone`,
|
|
167
|
+
`${currentMilestoneId} failed or missed critical features that should`,
|
|
168
|
+
`have been part of this milestone's scope.`,
|
|
169
|
+
``,
|
|
170
|
+
`The discuss phase should re-evaluate requirements and identify gaps.`,
|
|
171
|
+
].join("\n"), "utf-8");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch { /* best-effort */ }
|
|
175
|
+
}
|
|
176
|
+
return targetMilestoneId;
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Read the backtrack trigger file if it exists.
|
|
184
|
+
* Returns the parsed target milestone and metadata, or null.
|
|
185
|
+
*/
|
|
186
|
+
export function readBacktrackTrigger(basePath) {
|
|
187
|
+
const triggerPath = join(gsdRoot(basePath), "BACKTRACK-TRIGGER.md");
|
|
188
|
+
if (!existsSync(triggerPath))
|
|
189
|
+
return null;
|
|
190
|
+
try {
|
|
191
|
+
const content = readFileSync(triggerPath, "utf-8");
|
|
192
|
+
const target = content.match(/\*\*Target:\*\*\s*(.+)/)?.[1]?.trim() ?? null;
|
|
193
|
+
const from = content.match(/\*\*From:\*\*\s*(.+)/)?.[1]?.trim() ?? null;
|
|
194
|
+
const capture = content.match(/\*\*Capture:\*\*\s*(.+)/)?.[1]?.trim() ?? "";
|
|
195
|
+
const triggeredAt = content.match(/\*\*Triggered:\*\*\s*(.+)/)?.[1]?.trim() ?? "";
|
|
196
|
+
return {
|
|
197
|
+
target: target === "(user to specify)" ? null : target,
|
|
198
|
+
from,
|
|
199
|
+
capture,
|
|
200
|
+
triggeredAt,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Remove the backtrack trigger after it has been processed.
|
|
209
|
+
*/
|
|
210
|
+
export function clearBacktrackTrigger(basePath) {
|
|
211
|
+
const triggerPath = join(gsdRoot(basePath), "BACKTRACK-TRIGGER.md");
|
|
212
|
+
try {
|
|
213
|
+
if (existsSync(triggerPath)) {
|
|
214
|
+
unlinkSync(triggerPath);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
catch { /* best-effort */ }
|
|
218
|
+
}
|
|
102
219
|
// ─── File Overlap Detection ───────────────────────────────────────────────────
|
|
103
220
|
/**
|
|
104
221
|
* Detect file overlap between a capture's affected files and planned tasks.
|
|
@@ -240,6 +357,8 @@ export function executeTriageResolutions(basePath, mid, sid) {
|
|
|
240
357
|
replanned: 0,
|
|
241
358
|
deferredMilestones: 0,
|
|
242
359
|
quickTasks: [],
|
|
360
|
+
stopped: 0,
|
|
361
|
+
backtracks: [],
|
|
243
362
|
actions: [],
|
|
244
363
|
};
|
|
245
364
|
const actionable = loadActionableCaptures(basePath, mid || undefined);
|
|
@@ -318,5 +437,20 @@ export function executeTriageResolutions(basePath, mid, sid) {
|
|
|
318
437
|
}
|
|
319
438
|
}
|
|
320
439
|
}
|
|
440
|
+
// Count stop/backtrack captures — these are handled by the pre-dispatch guard
|
|
441
|
+
// in runGuards(), not here. We just report them for logging purposes.
|
|
442
|
+
const allCaptures = loadAllCaptures(basePath);
|
|
443
|
+
for (const cap of allCaptures) {
|
|
444
|
+
if (cap.status !== "resolved" || cap.executed)
|
|
445
|
+
continue;
|
|
446
|
+
if (cap.classification === "stop") {
|
|
447
|
+
result.stopped++;
|
|
448
|
+
result.actions.push(`Stop directive from ${cap.id}: "${cap.text}" — will pause on next dispatch`);
|
|
449
|
+
}
|
|
450
|
+
else if (cap.classification === "backtrack") {
|
|
451
|
+
result.backtracks.push(cap);
|
|
452
|
+
result.actions.push(`Backtrack directive from ${cap.id}: "${cap.text}" — will trigger milestone regression on next dispatch`);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
321
455
|
return result;
|
|
322
456
|
}
|
|
@@ -33,9 +33,17 @@ const CLASSIFICATION_LABELS = {
|
|
|
33
33
|
label: "Note",
|
|
34
34
|
description: "Informational only — no action needed.",
|
|
35
35
|
},
|
|
36
|
+
"stop": {
|
|
37
|
+
label: "Stop",
|
|
38
|
+
description: "Halt auto-mode immediately — user directive to cease execution.",
|
|
39
|
+
},
|
|
40
|
+
"backtrack": {
|
|
41
|
+
label: "Backtrack",
|
|
42
|
+
description: "Abandon current milestone and return to a previous one.",
|
|
43
|
+
},
|
|
36
44
|
};
|
|
37
45
|
const ALL_CLASSIFICATIONS = [
|
|
38
|
-
"quick-task", "inject", "defer", "replan", "note",
|
|
46
|
+
"quick-task", "inject", "defer", "replan", "note", "stop", "backtrack",
|
|
39
47
|
];
|
|
40
48
|
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
41
49
|
/**
|
|
@@ -57,8 +65,9 @@ export async function showTriageConfirmation(ctx, triageResults, captures, baseP
|
|
|
57
65
|
const capture = captureMap.get(result.captureId);
|
|
58
66
|
if (!capture)
|
|
59
67
|
continue;
|
|
60
|
-
// Auto-confirm note and
|
|
61
|
-
if (result.classification === "note" || result.classification === "defer"
|
|
68
|
+
// Auto-confirm note, defer, stop, and backtrack — low-impact or urgent directives
|
|
69
|
+
if (result.classification === "note" || result.classification === "defer"
|
|
70
|
+
|| result.classification === "stop" || result.classification === "backtrack") {
|
|
62
71
|
const resolution = result.classification === "note"
|
|
63
72
|
? "acknowledged as note"
|
|
64
73
|
: `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
|
// ─── Session ID ───────────────────────────────────────────────────────────
|
|
6
7
|
/**
|
|
7
8
|
* Engine-generated session ID — stable for the lifetime of this process.
|
|
@@ -49,7 +50,7 @@ export function readEvents(logPath) {
|
|
|
49
50
|
events.push(JSON.parse(line));
|
|
50
51
|
}
|
|
51
52
|
catch {
|
|
52
|
-
|
|
53
|
+
logWarning("event-log", `skipping corrupted event line (${line.length} bytes)`);
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
return events;
|
|
@@ -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
|
|
@@ -177,12 +179,15 @@ function _push(severity, component, message, context) {
|
|
|
177
179
|
if (_buffer.length > MAX_BUFFER) {
|
|
178
180
|
_buffer.shift();
|
|
179
181
|
}
|
|
180
|
-
// Persist to .gsd/audit-log.jsonl so
|
|
181
|
-
|
|
182
|
+
// Persist errors to .gsd/audit-log.jsonl so they survive context resets.
|
|
183
|
+
// Only error-severity entries are persisted — warnings are ephemeral (stderr + buffer)
|
|
184
|
+
// to avoid log amplification from expected-control-flow catch paths.
|
|
185
|
+
if (_auditBasePath && severity === "error") {
|
|
182
186
|
try {
|
|
183
187
|
const auditDir = join(_auditBasePath, ".gsd");
|
|
184
188
|
mkdirSync(auditDir, { recursive: true });
|
|
185
|
-
|
|
189
|
+
const sanitized = _sanitizeForAudit(entry);
|
|
190
|
+
appendFileSync(join(auditDir, "audit-log.jsonl"), JSON.stringify(sanitized) + "\n", "utf-8");
|
|
186
191
|
}
|
|
187
192
|
catch (auditErr) {
|
|
188
193
|
// Best-effort — never let audit write failures bubble up
|
|
@@ -190,3 +195,31 @@ function _push(severity, component, message, context) {
|
|
|
190
195
|
}
|
|
191
196
|
}
|
|
192
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* Sanitize a log entry before persisting to the audit JSONL file.
|
|
200
|
+
* Strips potentially sensitive context (raw paths, cwd, full error text)
|
|
201
|
+
* to avoid leaking local environment details into durable telemetry.
|
|
202
|
+
*/
|
|
203
|
+
function _sanitizeForAudit(entry) {
|
|
204
|
+
const sanitized = {
|
|
205
|
+
ts: entry.ts,
|
|
206
|
+
severity: entry.severity,
|
|
207
|
+
component: entry.component,
|
|
208
|
+
// Truncate message to avoid persisting oversized raw error dumps
|
|
209
|
+
message: entry.message.length > 200 ? entry.message.slice(0, 200) + "…[truncated]" : entry.message,
|
|
210
|
+
};
|
|
211
|
+
if (entry.context) {
|
|
212
|
+
// Allowlist: only persist known-safe structured keys
|
|
213
|
+
const SAFE_KEYS = new Set(["fn", "tool", "mid", "sid", "tid", "worktree"]);
|
|
214
|
+
const filtered = {};
|
|
215
|
+
for (const [k, v] of Object.entries(entry.context)) {
|
|
216
|
+
if (SAFE_KEYS.has(k)) {
|
|
217
|
+
filtered[k] = v;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (Object.keys(filtered).length > 0) {
|
|
221
|
+
sanitized.context = filtered;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return sanitized;
|
|
225
|
+
}
|
|
@@ -6,6 +6,7 @@ import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
import { _getAdapter, transaction } from "./gsd-db.js";
|
|
8
8
|
import { parseRoadmap, parsePlan } from "./parsers-legacy.js";
|
|
9
|
+
import { logWarning } from "./workflow-logger.js";
|
|
9
10
|
// ─── needsAutoMigration ───────────────────────────────────────────────────
|
|
10
11
|
/**
|
|
11
12
|
* Returns true when engine tables are empty AND a .gsd/milestones/ directory
|
|
@@ -22,8 +23,8 @@ export function needsAutoMigration(basePath) {
|
|
|
22
23
|
if (row && row["cnt"] > 0)
|
|
23
24
|
return false;
|
|
24
25
|
}
|
|
25
|
-
catch {
|
|
26
|
-
|
|
26
|
+
catch (e) {
|
|
27
|
+
logWarning("migration", `DB probe failed: ${e.message}`);
|
|
27
28
|
return false;
|
|
28
29
|
}
|
|
29
30
|
// Check if .gsd/milestones/ directory exists
|
|
@@ -66,7 +67,7 @@ export function migrateFromMarkdown(basePath) {
|
|
|
66
67
|
.map(e => e.name);
|
|
67
68
|
}
|
|
68
69
|
catch {
|
|
69
|
-
|
|
70
|
+
logWarning("migration", "failed to read milestones directory");
|
|
70
71
|
return;
|
|
71
72
|
}
|
|
72
73
|
if (milestoneDirs.length === 0) {
|
|
@@ -102,7 +103,7 @@ export function migrateFromMarkdown(basePath) {
|
|
|
102
103
|
}));
|
|
103
104
|
}
|
|
104
105
|
catch (err) {
|
|
105
|
-
|
|
106
|
+
logWarning("migration", `failed to parse ROADMAP.md for ${mId}: ${err.message}`);
|
|
106
107
|
// Still add milestone with ID as title
|
|
107
108
|
milestoneInserts.push({ id: mId, title: mId, status: milestoneStatus });
|
|
108
109
|
}
|
|
@@ -148,7 +149,7 @@ export function migrateFromMarkdown(basePath) {
|
|
|
148
149
|
}
|
|
149
150
|
}
|
|
150
151
|
catch (err) {
|
|
151
|
-
|
|
152
|
+
logWarning("migration", `failed to parse ${slice.id}-PLAN.md for ${mId}: ${err.message}`);
|
|
152
153
|
}
|
|
153
154
|
}
|
|
154
155
|
}
|
|
@@ -163,8 +164,8 @@ export function migrateFromMarkdown(basePath) {
|
|
|
163
164
|
}
|
|
164
165
|
}
|
|
165
166
|
}
|
|
166
|
-
catch {
|
|
167
|
-
|
|
167
|
+
catch (e) {
|
|
168
|
+
logWarning("migration", `Orphaned summary check failed for ${mId}: ${e.message}`);
|
|
168
169
|
}
|
|
169
170
|
}
|
|
170
171
|
// Execute all inserts atomically
|
|
@@ -245,19 +246,20 @@ export function validateMigration(basePath) {
|
|
|
245
246
|
const plan = parsePlan(planContent);
|
|
246
247
|
mdTaskCount += plan.tasks.length;
|
|
247
248
|
}
|
|
248
|
-
catch {
|
|
249
|
-
|
|
249
|
+
catch (e) {
|
|
250
|
+
logWarning("migration", `Failed to read plan ${slice.id}-PLAN.md: ${e.message}`);
|
|
250
251
|
}
|
|
251
252
|
}
|
|
252
253
|
}
|
|
253
254
|
}
|
|
254
|
-
catch {
|
|
255
|
-
|
|
255
|
+
catch (e) {
|
|
256
|
+
logWarning("migration", `Failed to read roadmap for ${mId}: ${e.message}`);
|
|
256
257
|
}
|
|
257
258
|
}
|
|
258
259
|
}
|
|
259
260
|
}
|
|
260
|
-
catch {
|
|
261
|
+
catch (e) {
|
|
262
|
+
logWarning("migration", `Validation failed to read markdown: ${e.message}`);
|
|
261
263
|
return { discrepancies: ["Failed to read markdown for validation"] };
|
|
262
264
|
}
|
|
263
265
|
// Compare counts
|
|
@@ -371,7 +371,7 @@ export function regenerateIfMissing(basePath, milestoneId, sliceId, fileType) {
|
|
|
371
371
|
regenerated++;
|
|
372
372
|
}
|
|
373
373
|
catch (err) {
|
|
374
|
-
|
|
374
|
+
logWarning("projection", `regenerateIfMissing SUMMARY failed for ${task.id}: ${err.message}`);
|
|
375
375
|
}
|
|
376
376
|
}
|
|
377
377
|
}
|
|
@@ -399,7 +399,7 @@ export function regenerateIfMissing(basePath, milestoneId, sliceId, fileType) {
|
|
|
399
399
|
return true;
|
|
400
400
|
}
|
|
401
401
|
catch (err) {
|
|
402
|
-
|
|
402
|
+
logWarning("projection", `regenerateIfMissing ${fileType} failed: ${err.message}`);
|
|
403
403
|
return false;
|
|
404
404
|
}
|
|
405
405
|
}
|
|
@@ -375,8 +375,8 @@ function parseEventBlock(block) {
|
|
|
375
375
|
try {
|
|
376
376
|
params = JSON.parse(paramsMatch[1]);
|
|
377
377
|
}
|
|
378
|
-
catch {
|
|
379
|
-
|
|
378
|
+
catch (e) {
|
|
379
|
+
logWarning("reconcile", `tool call params parse failed: ${e.message}`);
|
|
380
380
|
}
|
|
381
381
|
i++; // consume params line
|
|
382
382
|
}
|
|
@@ -51,8 +51,8 @@ export function resolveGitDir(basePath) {
|
|
|
51
51
|
return resolve(basePath, content.slice(8));
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
catch {
|
|
55
|
-
|
|
54
|
+
catch (e) {
|
|
55
|
+
logWarning("worktree", `.git file read failed: ${e.message}`);
|
|
56
56
|
}
|
|
57
57
|
return join(basePath, ".git");
|
|
58
58
|
}
|
|
@@ -232,8 +232,9 @@ export function findNestedGitDirs(rootPath) {
|
|
|
232
232
|
try {
|
|
233
233
|
entries = readdirSync(dir);
|
|
234
234
|
}
|
|
235
|
-
catch {
|
|
236
|
-
|
|
235
|
+
catch (e) {
|
|
236
|
+
logWarning("worktree", `readdirSync failed: ${e.message}`);
|
|
237
|
+
return;
|
|
237
238
|
}
|
|
238
239
|
for (const entry of entries) {
|
|
239
240
|
if (NESTED_GIT_SKIP_DIRS.has(entry))
|
|
@@ -244,7 +245,8 @@ export function findNestedGitDirs(rootPath) {
|
|
|
244
245
|
try {
|
|
245
246
|
stat = lstatSync(fullPath);
|
|
246
247
|
}
|
|
247
|
-
catch {
|
|
248
|
+
catch (e) {
|
|
249
|
+
logWarning("worktree", `lstatSync failed for ${fullPath}: ${e.message}`);
|
|
248
250
|
continue;
|
|
249
251
|
}
|
|
250
252
|
if (!stat.isDirectory())
|
|
@@ -261,8 +263,8 @@ export function findNestedGitDirs(rootPath) {
|
|
|
261
263
|
continue;
|
|
262
264
|
}
|
|
263
265
|
}
|
|
264
|
-
catch {
|
|
265
|
-
|
|
266
|
+
catch (e) {
|
|
267
|
+
logWarning("worktree", `existsSync/.git check failed for ${fullPath}: ${e.message}`);
|
|
266
268
|
}
|
|
267
269
|
walk(fullPath, depth + 1);
|
|
268
270
|
}
|
|
@@ -291,7 +293,9 @@ export function removeWorktree(basePath, name, opts = {}) {
|
|
|
291
293
|
wtPath = entry.path;
|
|
292
294
|
}
|
|
293
295
|
}
|
|
294
|
-
catch {
|
|
296
|
+
catch (e) {
|
|
297
|
+
logWarning("worktree", `nativeWorktreeList parse failed: ${e.message}`);
|
|
298
|
+
}
|
|
295
299
|
const resolvedWtPath = existsSync(wtPath) ? realpathSync(wtPath) : wtPath;
|
|
296
300
|
// If we're inside the worktree, move out first — git can't remove an in-use directory
|
|
297
301
|
const cwd = process.cwd();
|
|
@@ -305,7 +309,9 @@ export function removeWorktree(basePath, name, opts = {}) {
|
|
|
305
309
|
try {
|
|
306
310
|
nativeBranchDelete(basePath, branch, true);
|
|
307
311
|
}
|
|
308
|
-
catch {
|
|
312
|
+
catch (e) {
|
|
313
|
+
logWarning("worktree", `nativeBranchDelete failed: ${e.message}`);
|
|
314
|
+
}
|
|
309
315
|
}
|
|
310
316
|
return;
|
|
311
317
|
}
|
|
@@ -332,8 +338,8 @@ export function removeWorktree(basePath, name, opts = {}) {
|
|
|
332
338
|
}
|
|
333
339
|
}
|
|
334
340
|
}
|
|
335
|
-
catch {
|
|
336
|
-
|
|
341
|
+
catch (e) {
|
|
342
|
+
logWarning("worktree", `submodule status check failed: ${e.message}`);
|
|
337
343
|
}
|
|
338
344
|
}
|
|
339
345
|
// Nested .git safety (#2616): detect nested .git directories created by
|
|
@@ -360,13 +366,17 @@ export function removeWorktree(basePath, name, opts = {}) {
|
|
|
360
366
|
try {
|
|
361
367
|
nativeWorktreeRemove(basePath, resolvedWtPath, useForce);
|
|
362
368
|
}
|
|
363
|
-
catch {
|
|
369
|
+
catch (e) {
|
|
370
|
+
logWarning("worktree", `nativeWorktreeRemove failed: ${e.message}`);
|
|
371
|
+
}
|
|
364
372
|
// If the directory is still there (e.g. locked), try harder with force
|
|
365
373
|
if (existsSync(resolvedWtPath)) {
|
|
366
374
|
try {
|
|
367
375
|
nativeWorktreeRemove(basePath, resolvedWtPath, true);
|
|
368
376
|
}
|
|
369
|
-
catch {
|
|
377
|
+
catch (e) {
|
|
378
|
+
logWarning("worktree", `nativeWorktreeRemove (force) failed: ${e.message}`);
|
|
379
|
+
}
|
|
370
380
|
}
|
|
371
381
|
// (#2821) If the worktree directory STILL exists after both native removal
|
|
372
382
|
// attempts (e.g. untracked files like ASSESSMENT/UAT-RESULT prevent git
|
|
@@ -393,7 +403,9 @@ export function removeWorktree(basePath, name, opts = {}) {
|
|
|
393
403
|
try {
|
|
394
404
|
nativeBranchDelete(basePath, branch, true);
|
|
395
405
|
}
|
|
396
|
-
catch {
|
|
406
|
+
catch (e) {
|
|
407
|
+
logWarning("worktree", `final branch delete failed: ${e.message}`);
|
|
408
|
+
}
|
|
397
409
|
}
|
|
398
410
|
}
|
|
399
411
|
/** Paths to skip in all worktree diffs (internal/runtime artifacts). */
|
|
@@ -202,7 +202,9 @@ export async function showInterviewRound(questions, opts, ctx) {
|
|
|
202
202
|
// Auto-open the notes field when "None of the above" is selected
|
|
203
203
|
// so the user can immediately provide a free-text explanation
|
|
204
204
|
// instead of being trapped in a re-asking loop (bug #2715).
|
|
205
|
-
if
|
|
205
|
+
// Only auto-open if the user hasn't already provided notes —
|
|
206
|
+
// otherwise Enter from notes mode loops back here endlessly.
|
|
207
|
+
if (!isMultiSelect(currentIdx) && states[currentIdx].cursorIndex === noneOrDoneIdx(currentIdx) && !states[currentIdx].notes) {
|
|
206
208
|
states[currentIdx].notesVisible = true;
|
|
207
209
|
focusNotes = true;
|
|
208
210
|
loadStateToEditor();
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: btw
|
|
3
|
+
description: Ask a quick side question about your current work without derailing the main task. Answers from existing conversation context only — no tool calls, no file reads, single concise response. Use when you need a fast answer from what is already in this session.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<objective>
|
|
7
|
+
Answer a quick side question using only what is already present in the current conversation context. Do not read files, run commands, search, or use any tools. Give a single, concise response and return focus to the main work.
|
|
8
|
+
</objective>
|
|
9
|
+
|
|
10
|
+
<behavior>
|
|
11
|
+
**This is a side question, not a task.**
|
|
12
|
+
|
|
13
|
+
- Answer only from information already in the conversation (files read, decisions made, code seen, context established)
|
|
14
|
+
- Do NOT use any tools — no Read, no Bash, no Grep, no Search
|
|
15
|
+
- If the answer requires reading something new, say so briefly and suggest the user ask as a normal prompt instead
|
|
16
|
+
- Keep the response short and direct — one to a few sentences unless the question genuinely needs more
|
|
17
|
+
- Do not summarize the main work, ask follow-up questions, or offer to do anything else
|
|
18
|
+
- After answering, stop — do not prompt for next steps
|
|
19
|
+
</behavior>
|
|
20
|
+
|
|
21
|
+
<quick_start>
|
|
22
|
+
Parse the argument after `/btw` as the question. Answer it directly from context.
|
|
23
|
+
|
|
24
|
+
If no argument is provided, ask: "What did you want to know?"
|
|
25
|
+
|
|
26
|
+
If the question cannot be answered from current context (requires reading a file, running a command, or information not yet in the session), respond with:
|
|
27
|
+
"I'd need to [read X / run Y / look up Z] to answer that — ask it as a normal prompt when you're ready."
|
|
28
|
+
</quick_start>
|
|
29
|
+
|
|
30
|
+
<examples>
|
|
31
|
+
**Good uses of /btw:**
|
|
32
|
+
- `/btw what was the name of that config file again?` → answers from files already read in session
|
|
33
|
+
- `/btw which branch are we on?` → answers from git context already established
|
|
34
|
+
- `/btw did we already handle the null case in that function?` → answers from code already reviewed
|
|
35
|
+
- `/btw what model does this use?` → answers from code or config already in context
|
|
36
|
+
|
|
37
|
+
**Not a good fit for /btw (suggest normal prompt):**
|
|
38
|
+
- Questions requiring reading a file not yet seen
|
|
39
|
+
- Questions requiring running a command
|
|
40
|
+
- Questions needing a multi-step answer or follow-up
|
|
41
|
+
- Starting a new task or changing direction
|
|
42
|
+
</examples>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
ogyMN7M-3bGGuRY08L5HR
|