gsd-pi 2.73.1 → 2.74.0-dev.b741afb
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/cli-web-branch.d.ts +4 -3
- package/dist/cli-web-branch.js +10 -7
- package/dist/cli.js +184 -206
- package/dist/headless-query.js +4 -1
- package/dist/help-text.js +23 -0
- package/dist/logo.d.ts +1 -1
- package/dist/logo.js +1 -1
- package/dist/onboarding.js +59 -53
- package/dist/resource-loader.js +2 -2
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +68 -4
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +11 -4
- package/dist/resources/extensions/gsd/auto/phases.js +60 -10
- package/dist/resources/extensions/gsd/auto-dispatch.js +11 -3
- package/dist/resources/extensions/gsd/auto-model-selection.js +54 -11
- package/dist/resources/extensions/gsd/auto-post-unit.js +93 -57
- package/dist/resources/extensions/gsd/auto-prompts.js +12 -0
- package/dist/resources/extensions/gsd/auto-start.js +23 -6
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +13 -0
- package/dist/resources/extensions/gsd/auto-verification.js +88 -3
- package/dist/resources/extensions/gsd/auto.js +37 -10
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +21 -8
- package/dist/resources/extensions/gsd/commands/catalog.js +26 -1
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +20 -0
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +68 -9
- package/dist/resources/extensions/gsd/commands-add-tests.js +111 -0
- package/dist/resources/extensions/gsd/commands-backlog.js +140 -0
- package/dist/resources/extensions/gsd/commands-do.js +79 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +8 -2
- package/dist/resources/extensions/gsd/commands-maintenance.js +6 -6
- package/dist/resources/extensions/gsd/commands-pr-branch.js +180 -0
- package/dist/resources/extensions/gsd/commands-session-report.js +82 -0
- package/dist/resources/extensions/gsd/commands-ship.js +187 -0
- package/dist/resources/extensions/gsd/db-writer.js +3 -5
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/graph-context.js +66 -0
- package/dist/resources/extensions/gsd/gsd-db.js +321 -0
- package/dist/resources/extensions/gsd/index.js +15 -2
- package/dist/resources/extensions/gsd/md-importer.js +3 -4
- package/dist/resources/extensions/gsd/memory-store.js +19 -51
- package/dist/resources/extensions/gsd/milestone-validation-gates.js +13 -12
- package/dist/resources/extensions/gsd/native-git-bridge.js +7 -4
- package/dist/resources/extensions/gsd/notification-widget.js +2 -2
- package/dist/resources/extensions/gsd/preferences-models.js +43 -0
- package/dist/resources/extensions/gsd/preferences-types.js +1 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +22 -0
- package/dist/resources/extensions/gsd/prompts/add-tests.md +35 -0
- package/dist/resources/extensions/gsd/state.js +66 -15
- package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +3 -14
- package/dist/resources/extensions/gsd/triage-resolution.js +2 -5
- package/dist/resources/extensions/gsd/workflow-manifest.js +8 -69
- package/dist/resources/extensions/gsd/workflow-migration.js +21 -22
- package/dist/resources/extensions/gsd/workflow-projections.js +4 -1
- package/dist/resources/extensions/gsd/workflow-reconcile.js +14 -11
- package/dist/tsconfig.extensions.tsbuildinfo +1 -0
- package/dist/update-check.d.ts +1 -0
- package/dist/update-check.js +13 -5
- package/dist/update-cmd.js +4 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
- 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 +1 -1
- 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/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/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 +9 -9
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- 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 +1 -1
- 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-f1e30ab6bb269149.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 +3 -3
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/dist/index.d.ts +3 -0
- package/packages/mcp-server/dist/index.d.ts.map +1 -1
- package/packages/mcp-server/dist/index.js +3 -0
- package/packages/mcp-server/dist/index.js.map +1 -1
- package/packages/mcp-server/dist/readers/graph.d.ts +87 -0
- package/packages/mcp-server/dist/readers/graph.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/graph.js +548 -0
- package/packages/mcp-server/dist/readers/graph.js.map +1 -0
- package/packages/mcp-server/dist/readers/index.d.ts +2 -0
- package/packages/mcp-server/dist/readers/index.d.ts.map +1 -1
- package/packages/mcp-server/dist/readers/index.js +1 -0
- package/packages/mcp-server/dist/readers/index.js.map +1 -1
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +65 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/index.ts +15 -0
- package/packages/mcp-server/src/readers/graph.test.ts +426 -0
- package/packages/mcp-server/src/readers/graph.ts +708 -0
- package/packages/mcp-server/src/readers/index.ts +12 -0
- package/packages/mcp-server/src/server.ts +83 -0
- package/packages/mcp-server/tsconfig.json +1 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -0
- package/packages/native/package.json +2 -2
- package/packages/native/tsconfig.tsbuildinfo +1 -0
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.json +1 -0
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -0
- package/packages/pi-ai/dist/index.d.ts +1 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/utils/overflow.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/overflow.js +12 -0
- package/packages/pi-ai/dist/utils/overflow.js.map +1 -1
- package/packages/pi-ai/dist/utils/tests/overflow.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/tests/overflow.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/tests/overflow.test.js +50 -0
- package/packages/pi-ai/dist/utils/tests/overflow.test.js.map +1 -0
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/index.ts +4 -0
- package/packages/pi-ai/src/utils/overflow.ts +14 -1
- package/packages/pi-ai/src/utils/tests/overflow.test.ts +58 -0
- package/packages/pi-ai/tsconfig.json +1 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +313 -8
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/utils.js +5 -5
- package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.js +45 -0
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +12 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +61 -28
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts +2 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +9 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +52 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +94 -16
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- 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 +11 -3
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +355 -8
- package/packages/pi-coding-agent/src/core/compaction/utils.ts +5 -5
- package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +50 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +74 -32
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +73 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +9 -3
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +113 -21
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +11 -3
- package/packages/pi-coding-agent/tsconfig.json +1 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -0
- package/packages/pi-tui/dist/__tests__/tui.test.js +60 -1
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts +8 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +32 -3
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/tui.test.ts +76 -1
- package/packages/pi-tui/src/tui.ts +31 -3
- package/packages/pi-tui/tsconfig.json +1 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -0
- package/packages/rpc-client/package.json +1 -1
- package/packages/rpc-client/tsconfig.json +1 -0
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -0
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +107 -5
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +111 -2
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +12 -4
- package/src/resources/extensions/gsd/auto/loop-deps.ts +6 -0
- package/src/resources/extensions/gsd/auto/phases.ts +90 -10
- package/src/resources/extensions/gsd/auto-dispatch.ts +10 -4
- package/src/resources/extensions/gsd/auto-model-selection.ts +85 -11
- package/src/resources/extensions/gsd/auto-post-unit.ts +107 -58
- package/src/resources/extensions/gsd/auto-prompts.ts +13 -0
- package/src/resources/extensions/gsd/auto-start.ts +30 -6
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +17 -0
- package/src/resources/extensions/gsd/auto-verification.ts +98 -3
- package/src/resources/extensions/gsd/auto.ts +38 -14
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -8
- package/src/resources/extensions/gsd/commands/catalog.ts +26 -1
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +20 -0
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +74 -9
- package/src/resources/extensions/gsd/commands-add-tests.ts +137 -0
- package/src/resources/extensions/gsd/commands-backlog.ts +182 -0
- package/src/resources/extensions/gsd/commands-do.ts +109 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +8 -2
- package/src/resources/extensions/gsd/commands-maintenance.ts +6 -6
- package/src/resources/extensions/gsd/commands-pr-branch.ts +234 -0
- package/src/resources/extensions/gsd/commands-session-report.ts +101 -0
- package/src/resources/extensions/gsd/commands-ship.ts +219 -0
- package/src/resources/extensions/gsd/db-writer.ts +3 -5
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/graph-context.ts +85 -0
- package/src/resources/extensions/gsd/gsd-db.ts +467 -0
- package/src/resources/extensions/gsd/index.ts +18 -2
- package/src/resources/extensions/gsd/md-importer.ts +3 -5
- package/src/resources/extensions/gsd/memory-store.ts +31 -62
- package/src/resources/extensions/gsd/milestone-validation-gates.ts +13 -14
- package/src/resources/extensions/gsd/native-git-bridge.ts +11 -12
- package/src/resources/extensions/gsd/notification-widget.ts +2 -2
- package/src/resources/extensions/gsd/preferences-models.ts +41 -0
- package/src/resources/extensions/gsd/preferences-types.ts +12 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +23 -0
- package/src/resources/extensions/gsd/prompts/add-tests.md +35 -0
- package/src/resources/extensions/gsd/state.ts +80 -17
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +51 -2
- package/src/resources/extensions/gsd/tests/commands-backlog.test.ts +158 -0
- package/src/resources/extensions/gsd/tests/commands-do.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/commands-pr-branch.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/commands-session-report.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/commands-ship.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +68 -8
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +154 -0
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +137 -1
- package/src/resources/extensions/gsd/tests/graph-context.test.ts +337 -0
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +68 -1
- package/src/resources/extensions/gsd/tests/model-isolation.test.ts +91 -2
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +180 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +223 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +19 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +3 -11
- package/src/resources/extensions/gsd/triage-resolution.ts +2 -7
- package/src/resources/extensions/gsd/workflow-manifest.ts +9 -104
- package/src/resources/extensions/gsd/workflow-migration.ts +21 -29
- package/src/resources/extensions/gsd/workflow-projections.ts +8 -1
- package/src/resources/extensions/gsd/workflow-reconcile.ts +15 -15
- package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.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/{Qr27MOHx0lxRGnJvlhxxu → XnHY5eXUsTCFmNodWHetD}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Qr27MOHx0lxRGnJvlhxxu → XnHY5eXUsTCFmNodWHetD}/_ssgManifest.js +0 -0
|
@@ -67,6 +67,7 @@ const LIFECYCLE_ONLY_UNITS = new Set([
|
|
|
67
67
|
"replan-slice", "complete-slice", "run-uat",
|
|
68
68
|
"reassess-roadmap", "rewrite-docs",
|
|
69
69
|
]);
|
|
70
|
+
import { describeNextUnit, } from "./auto-dashboard.js";
|
|
70
71
|
import { existsSync, unlinkSync } from "node:fs";
|
|
71
72
|
import { join } from "node:path";
|
|
72
73
|
import { _resetHasChangesCache } from "./native-git-bridge.js";
|
|
@@ -179,6 +180,66 @@ export function detectRogueFileWrites(unitType, unitId, basePath) {
|
|
|
179
180
|
}
|
|
180
181
|
return rogues;
|
|
181
182
|
}
|
|
183
|
+
export const STEP_COMPLETE_FALLBACK_MESSAGE = "Step complete. Run /clear, then /gsd to continue (or /gsd auto to run continuously).";
|
|
184
|
+
export function buildStepCompleteMessage(nextState) {
|
|
185
|
+
if (nextState.phase === "complete") {
|
|
186
|
+
return "Step complete — milestone finished. Run /gsd status to review, or start the next milestone.";
|
|
187
|
+
}
|
|
188
|
+
const next = describeNextUnit(nextState);
|
|
189
|
+
return `Step complete. Next: ${next.label}\n`
|
|
190
|
+
+ `Run /clear, then /gsd to continue (or /gsd auto to run continuously).`;
|
|
191
|
+
}
|
|
192
|
+
export async function autoCommitUnit(basePath, unitType, unitId, ctx) {
|
|
193
|
+
try {
|
|
194
|
+
let taskContext;
|
|
195
|
+
if (unitType === "execute-task") {
|
|
196
|
+
const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
|
|
197
|
+
if (mid && sid && tid) {
|
|
198
|
+
const summaryPath = resolveTaskFile(basePath, mid, sid, tid, "SUMMARY");
|
|
199
|
+
if (summaryPath) {
|
|
200
|
+
try {
|
|
201
|
+
const summaryContent = await loadFile(summaryPath);
|
|
202
|
+
if (summaryContent) {
|
|
203
|
+
const summary = parseSummary(summaryContent);
|
|
204
|
+
let ghIssueNumber;
|
|
205
|
+
try {
|
|
206
|
+
const { getTaskIssueNumberForCommit } = await import("../github-sync/sync.js");
|
|
207
|
+
ghIssueNumber = getTaskIssueNumberForCommit(basePath, mid, sid, tid) ?? undefined;
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
logWarning("engine", `GitHub issue lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
211
|
+
}
|
|
212
|
+
taskContext = {
|
|
213
|
+
taskId: `${sid}/${tid}`,
|
|
214
|
+
taskTitle: summary.title?.replace(/^T\d+:\s*/, "") || tid,
|
|
215
|
+
oneLiner: summary.oneLiner || undefined,
|
|
216
|
+
keyFiles: summary.frontmatter.key_files?.filter(f => !f.includes("{{")) || undefined,
|
|
217
|
+
issueNumber: ghIssueNumber,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (e) {
|
|
222
|
+
debugLog("postUnit", { phase: "task-summary-parse", error: String(e) });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
_resetHasChangesCache();
|
|
228
|
+
if (LIFECYCLE_ONLY_UNITS.has(unitType)) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
const commitMsg = autoCommitCurrentBranch(basePath, unitType, unitId, taskContext);
|
|
232
|
+
if (commitMsg) {
|
|
233
|
+
ctx?.ui.notify(`Committed: ${commitMsg.split("\n")[0]}`, "info");
|
|
234
|
+
}
|
|
235
|
+
return commitMsg;
|
|
236
|
+
}
|
|
237
|
+
catch (e) {
|
|
238
|
+
debugLog("postUnit", { phase: "auto-commit", error: String(e) });
|
|
239
|
+
ctx?.ui.notify(`Auto-commit failed: ${String(e).split("\n")[0]}`, "warning");
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
182
243
|
/**
|
|
183
244
|
* Pre-verification processing: parallel worker signal check, cache invalidation,
|
|
184
245
|
* auto-commit, doctor run, state rebuild, worktree sync, artifact verification.
|
|
@@ -214,62 +275,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
214
275
|
// Auto-commit
|
|
215
276
|
if (s.currentUnit) {
|
|
216
277
|
const unit = s.currentUnit;
|
|
217
|
-
|
|
218
|
-
let taskContext;
|
|
219
|
-
if (s.currentUnit.type === "execute-task") {
|
|
220
|
-
const { milestone: mid, slice: sid, task: tid } = parseUnitId(s.currentUnit.id);
|
|
221
|
-
if (mid && sid && tid) {
|
|
222
|
-
const summaryPath = resolveTaskFile(s.basePath, mid, sid, tid, "SUMMARY");
|
|
223
|
-
if (summaryPath) {
|
|
224
|
-
try {
|
|
225
|
-
const summaryContent = await loadFile(summaryPath);
|
|
226
|
-
if (summaryContent) {
|
|
227
|
-
const summary = parseSummary(summaryContent);
|
|
228
|
-
// Look up GitHub issue number for commit linking
|
|
229
|
-
let ghIssueNumber;
|
|
230
|
-
try {
|
|
231
|
-
const { getTaskIssueNumberForCommit } = await import("../github-sync/sync.js");
|
|
232
|
-
ghIssueNumber = getTaskIssueNumberForCommit(s.basePath, mid, sid, tid) ?? undefined;
|
|
233
|
-
}
|
|
234
|
-
catch (err) {
|
|
235
|
-
// GitHub sync not available — skip
|
|
236
|
-
logWarning("engine", `GitHub issue lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
237
|
-
}
|
|
238
|
-
taskContext = {
|
|
239
|
-
taskId: `${sid}/${tid}`,
|
|
240
|
-
taskTitle: summary.title?.replace(/^T\d+:\s*/, "") || tid,
|
|
241
|
-
oneLiner: summary.oneLiner || undefined,
|
|
242
|
-
keyFiles: summary.frontmatter.key_files?.filter(f => !f.includes("{{")) || undefined,
|
|
243
|
-
issueNumber: ghIssueNumber,
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
catch (e) {
|
|
248
|
-
debugLog("postUnit", { phase: "task-summary-parse", error: String(e) });
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
// Invalidate the nativeHasChanges cache before auto-commit (#1853).
|
|
254
|
-
// The cache has a 10-second TTL and is keyed by basePath. A stale
|
|
255
|
-
// `false` result causes autoCommit to skip staging entirely, leaving
|
|
256
|
-
// code files only in the working tree where they are destroyed by
|
|
257
|
-
// `git worktree remove --force` during teardown.
|
|
258
|
-
_resetHasChangesCache();
|
|
259
|
-
// Skip auto-commit for lifecycle-only units (#2553) — they only touch
|
|
260
|
-
// `.gsd/` internal state files. Those files are picked up by the next
|
|
261
|
-
// actual task commit via smartStage().
|
|
262
|
-
if (!LIFECYCLE_ONLY_UNITS.has(s.currentUnit.type)) {
|
|
263
|
-
const commitMsg = autoCommitCurrentBranch(s.basePath, s.currentUnit.type, s.currentUnit.id, taskContext);
|
|
264
|
-
if (commitMsg) {
|
|
265
|
-
ctx.ui.notify(`Committed: ${commitMsg.split("\n")[0]}`, "info");
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
catch (e) {
|
|
270
|
-
debugLog("postUnit", { phase: "auto-commit", error: String(e) });
|
|
271
|
-
ctx.ui.notify(`Auto-commit failed: ${String(e).split("\n")[0]}`, "warning");
|
|
272
|
-
}
|
|
278
|
+
await autoCommitUnit(s.basePath, unit.type, unit.id, ctx);
|
|
273
279
|
// GitHub sync (non-blocking, opt-in)
|
|
274
280
|
await runSafely("postUnit", "github-sync", async () => {
|
|
275
281
|
const { runGitHubSync } = await import("../github-sync/sync.js");
|
|
@@ -509,6 +515,26 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
509
515
|
const attempt = (s.verificationRetryCount.get(retryKey) ?? 0) + 1;
|
|
510
516
|
s.verificationRetryCount.set(retryKey, attempt);
|
|
511
517
|
if (attempt > MAX_VERIFICATION_RETRIES) {
|
|
518
|
+
// #4175: For complete-milestone, a blocker placeholder is harmful —
|
|
519
|
+
// the stub SUMMARY has no recovery value (milestone is terminal),
|
|
520
|
+
// it does not update DB status (so deriveState never advances),
|
|
521
|
+
// and it fools stopAuto's presence check into merging a milestone
|
|
522
|
+
// that was never legitimately completed. Pause auto-mode with a
|
|
523
|
+
// clear single failure signal and preserve the worktree branch.
|
|
524
|
+
if (s.currentUnit.type === "complete-milestone") {
|
|
525
|
+
debugLog("postUnit", {
|
|
526
|
+
phase: "artifact-verify-pause-complete-milestone",
|
|
527
|
+
unitType: s.currentUnit.type,
|
|
528
|
+
unitId: s.currentUnit.id,
|
|
529
|
+
attempt,
|
|
530
|
+
maxRetries: MAX_VERIFICATION_RETRIES,
|
|
531
|
+
});
|
|
532
|
+
s.verificationRetryCount.delete(retryKey);
|
|
533
|
+
s.pendingVerificationRetry = null;
|
|
534
|
+
ctx.ui.notify(`Milestone ${s.currentUnit.id} verification failed after ${MAX_VERIFICATION_RETRIES} retries — worktree branch preserved. Re-run /gsd auto once blockers are resolved.`, "error");
|
|
535
|
+
await pauseAuto(ctx, pi);
|
|
536
|
+
return "dispatched";
|
|
537
|
+
}
|
|
512
538
|
// Retries exhausted — write a blocker placeholder so the pipeline
|
|
513
539
|
// can advance past this stuck unit (#2653).
|
|
514
540
|
debugLog("postUnit", {
|
|
@@ -836,8 +862,18 @@ export async function postUnitPostVerification(pctx) {
|
|
|
836
862
|
debugLog("postUnit", { phase: "quick-task-dispatch", error: String(e) });
|
|
837
863
|
}
|
|
838
864
|
}
|
|
839
|
-
// Step mode → show wizard instead of dispatch
|
|
865
|
+
// Step mode → show wizard instead of dispatch.
|
|
866
|
+
// Without this notify(), /gsd in step mode finishes a unit and silently
|
|
867
|
+
// exits the loop, leaving the user with no hint to /clear and /gsd again.
|
|
840
868
|
if (s.stepMode) {
|
|
869
|
+
try {
|
|
870
|
+
const nextState = await deriveState(s.basePath);
|
|
871
|
+
ctx.ui.notify(buildStepCompleteMessage(nextState), "info");
|
|
872
|
+
}
|
|
873
|
+
catch (e) {
|
|
874
|
+
debugLog("postUnit", { phase: "step-wizard-notify", error: String(e) });
|
|
875
|
+
ctx.ui.notify(STEP_COMPLETE_FALLBACK_MESSAGE, "info");
|
|
876
|
+
}
|
|
841
877
|
return "step-wizard";
|
|
842
878
|
}
|
|
843
879
|
return "continue";
|
|
@@ -20,6 +20,7 @@ import { assertGateCoverage, getGatesForTurn, } from "./gate-registry.js";
|
|
|
20
20
|
import { formatDecisionsCompact, formatRequirementsCompact } from "./structured-data-formatter.js";
|
|
21
21
|
import { readPhaseAnchor, formatAnchorForPrompt } from "./phase-anchor.js";
|
|
22
22
|
import { logWarning } from "./workflow-logger.js";
|
|
23
|
+
import { inlineGraphSubgraph } from "./graph-context.js";
|
|
23
24
|
// ─── Preamble Cap ─────────────────────────────────────────────────────────────
|
|
24
25
|
const MAX_PREAMBLE_CHARS = 30_000;
|
|
25
26
|
function capPreamble(preamble) {
|
|
@@ -1040,6 +1041,10 @@ export async function buildResearchSlicePrompt(mid, _midTitle, sid, sTitle, base
|
|
|
1040
1041
|
const knowledgeInlineRS = await inlineKnowledgeScoped(base, keywords);
|
|
1041
1042
|
if (knowledgeInlineRS)
|
|
1042
1043
|
inlined.push(knowledgeInlineRS);
|
|
1044
|
+
// Knowledge graph: subgraph for this slice (graceful — skipped if no graph.json)
|
|
1045
|
+
const graphBlockRS = await inlineGraphSubgraph(base, `${sid} ${sTitle}`, { budget: 3000 });
|
|
1046
|
+
if (graphBlockRS)
|
|
1047
|
+
inlined.push(graphBlockRS);
|
|
1043
1048
|
inlined.push(inlineTemplate("research", "Research"));
|
|
1044
1049
|
const depContent = await inlineDependencySummaries(mid, sid, base);
|
|
1045
1050
|
const activeOverrides = await loadActiveOverrides(base);
|
|
@@ -1111,6 +1116,10 @@ export async function buildPlanSlicePrompt(mid, _midTitle, sid, sTitle, base, le
|
|
|
1111
1116
|
const knowledgeInlinePS = await inlineKnowledgeScoped(base, keywordsPS);
|
|
1112
1117
|
if (knowledgeInlinePS)
|
|
1113
1118
|
inlined.push(knowledgeInlinePS);
|
|
1119
|
+
// Knowledge graph: subgraph for this slice (graceful — skipped if no graph.json)
|
|
1120
|
+
const graphBlockPS = await inlineGraphSubgraph(base, `${sid} ${sTitle}`, { budget: 3000 });
|
|
1121
|
+
if (graphBlockPS)
|
|
1122
|
+
inlined.push(graphBlockPS);
|
|
1114
1123
|
inlined.push(inlineTemplate("plan", "Slice Plan"));
|
|
1115
1124
|
if (inlineLevel === "full") {
|
|
1116
1125
|
inlined.push(inlineTemplate("task-plan", "Task Plan"));
|
|
@@ -1194,12 +1203,15 @@ export async function buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle, base
|
|
|
1194
1203
|
: null;
|
|
1195
1204
|
// Only include if it has content (not a "not found" result)
|
|
1196
1205
|
const knowledgeContent = knowledgeInlineET && !knowledgeInlineET.includes("not found") ? knowledgeInlineET : null;
|
|
1206
|
+
// Knowledge graph: tight subgraph for this task (graceful — skipped if no graph.json)
|
|
1207
|
+
const graphBlockET = await inlineGraphSubgraph(base, `${tid} ${tTitle}`, { budget: 2000 });
|
|
1197
1208
|
const inlinedTemplates = inlineLevel === "minimal"
|
|
1198
1209
|
? inlineTemplate("task-summary", "Task Summary")
|
|
1199
1210
|
: [
|
|
1200
1211
|
inlineTemplate("task-summary", "Task Summary"),
|
|
1201
1212
|
inlineTemplate("decisions", "Decisions"),
|
|
1202
1213
|
...(knowledgeContent ? [knowledgeContent] : []),
|
|
1214
|
+
...(graphBlockET ? [graphBlockET] : []),
|
|
1203
1215
|
].join("\n\n---\n\n");
|
|
1204
1216
|
const taskSummaryPath = join(base, `${relSlicePath(base, mid, sid)}/tasks/${tid}-SUMMARY.md`);
|
|
1205
1217
|
const activeOverrides = await loadActiveOverrides(base);
|
|
@@ -38,7 +38,7 @@ import { existsSync, mkdirSync, readdirSync, rmSync, statSync, unlinkSync, } fro
|
|
|
38
38
|
import { join } from "node:path";
|
|
39
39
|
import { sep as pathSep } from "node:path";
|
|
40
40
|
import { resolveProjectRootDbPath } from "./bootstrap/dynamic-tools.js";
|
|
41
|
-
import { resolveDefaultSessionModel, resolveDynamicRoutingConfig } from "./preferences-models.js";
|
|
41
|
+
import { isCustomProvider, resolveDefaultSessionModel, resolveDynamicRoutingConfig, } from "./preferences-models.js";
|
|
42
42
|
import { getSessionModelOverride } from "./session-model-override.js";
|
|
43
43
|
/**
|
|
44
44
|
* Bootstrap a fresh auto-mode session. Handles everything from git init
|
|
@@ -195,8 +195,18 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
195
195
|
//
|
|
196
196
|
// This preserves #3517 defaults while honoring explicit runtime model
|
|
197
197
|
// selection for subsequent /gsd runs in the same session.
|
|
198
|
+
//
|
|
199
|
+
// Exception (#4122): when the session provider is a custom provider declared
|
|
200
|
+
// in ~/.gsd/agent/models.json (Ollama, vLLM, OpenAI-compatible proxy, etc.),
|
|
201
|
+
// PREFERENCES.md is skipped entirely. PREFERENCES.md cannot reference custom
|
|
202
|
+
// providers, so honoring it would silently reroute auto-mode to a built-in
|
|
203
|
+
// provider the user is not logged into and surface as "Not logged in · Please
|
|
204
|
+
// run /login" before pausing and resetting to claude-code/claude-sonnet-4-6.
|
|
198
205
|
const manualSessionOverride = getSessionModelOverride(ctx.sessionManager.getSessionId());
|
|
199
|
-
const
|
|
206
|
+
const sessionProviderIsCustom = isCustomProvider(ctx.model?.provider);
|
|
207
|
+
const preferredModel = sessionProviderIsCustom
|
|
208
|
+
? null
|
|
209
|
+
: resolveDefaultSessionModel(ctx.model?.provider);
|
|
200
210
|
// Validate the preferred model against the live registry + provider auth so
|
|
201
211
|
// an unconfigured PREFERENCES.md entry (no API key / OAuth) can't become the
|
|
202
212
|
// start-model snapshot. Without this, every subsequent unit would try to
|
|
@@ -622,6 +632,9 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
622
632
|
}
|
|
623
633
|
ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
|
|
624
634
|
ctx.ui.setFooter(hideFooter);
|
|
635
|
+
// Hide gsd-health during AUTO — gsd-progress is the single source of truth
|
|
636
|
+
// for last-commit / cost / health signal while auto is running.
|
|
637
|
+
ctx.ui.setWidget("gsd-health", undefined);
|
|
625
638
|
const modeLabel = s.stepMode ? "Step-mode" : "Auto-mode";
|
|
626
639
|
const pendingCount = (state.registry ?? []).filter((m) => m.status !== "complete" && m.status !== "parked").length;
|
|
627
640
|
const scopeMsg = pendingCount > 1
|
|
@@ -636,12 +649,16 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
636
649
|
const startModelLabel = s.autoModeStartModel
|
|
637
650
|
? `${s.autoModeStartModel.provider}/${s.autoModeStartModel.id}`
|
|
638
651
|
: ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : "default";
|
|
639
|
-
// Flat-rate providers (e.g. GitHub Copilot, claude-code
|
|
640
|
-
//
|
|
641
|
-
|
|
652
|
+
// Flat-rate providers (e.g. GitHub Copilot, claude-code, user-declared
|
|
653
|
+
// subscription proxies, externalCli CLIs) suppress routing at dispatch
|
|
654
|
+
// time (#3453) — reflect that in the banner. Thread the same
|
|
655
|
+
// FlatRateContext used by selectAndApplyModel so user-declared
|
|
656
|
+
// flat-rate providers and externalCli auto-detection are respected.
|
|
657
|
+
const { isFlatRateProvider, buildFlatRateContext } = await import("./auto-model-selection.js");
|
|
658
|
+
const bannerPrefs = loadEffectiveGSDPreferences()?.preferences;
|
|
642
659
|
const effectiveProvider = s.autoModeStartModel?.provider ?? ctx.model?.provider;
|
|
643
660
|
const effectivelyEnabled = routingConfig.enabled
|
|
644
|
-
&& !(effectiveProvider && isFlatRateProvider(effectiveProvider));
|
|
661
|
+
&& !(effectiveProvider && isFlatRateProvider(effectiveProvider, buildFlatRateContext(effectiveProvider, ctx, bannerPrefs)));
|
|
645
662
|
// The actual ceiling may come from tier_models.heavy, not the start model.
|
|
646
663
|
const effectiveCeiling = (routingConfig.enabled && routingConfig.tier_models?.heavy)
|
|
647
664
|
? routingConfig.tier_models.heavy
|
|
@@ -156,6 +156,19 @@ export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rct
|
|
|
156
156
|
ctx.ui.notify(`${reason === "idle" ? "Idle" : "Timeout"} recovery: steering ${unitType} ${unitId} to produce ${expected} (attempt ${attemptNumber}, session ${recoveryAttempts + 1}/${maxRecoveryAttempts}).`, "warning");
|
|
157
157
|
return "recovered";
|
|
158
158
|
}
|
|
159
|
+
// #4175: For complete-milestone, never write a blocker placeholder — a stub
|
|
160
|
+
// SUMMARY has no recovery value (milestone is terminal), it does not update
|
|
161
|
+
// DB status, and downstream merge paths can treat the stub as a legitimate
|
|
162
|
+
// completion signal. Pause instead so the worktree branch is preserved.
|
|
163
|
+
if (unitType === "complete-milestone") {
|
|
164
|
+
writeUnitRuntimeRecord(basePath, unitType, unitId, currentUnitStartedAt, {
|
|
165
|
+
phase: "paused",
|
|
166
|
+
recoveryAttempts: recoveryAttempts + 1,
|
|
167
|
+
lastRecoveryReason: reason,
|
|
168
|
+
});
|
|
169
|
+
ctx.ui.notify(`Milestone ${unitId} ${reason}-recovery exhausted ${maxRecoveryAttempts} attempt(s) — worktree branch preserved. Re-run /gsd auto once blockers are resolved.`, "error");
|
|
170
|
+
return "paused";
|
|
171
|
+
}
|
|
159
172
|
// Retries exhausted — write a blocker placeholder and advance the pipeline
|
|
160
173
|
// instead of silently stalling.
|
|
161
174
|
const placeholder = writeBlockerPlaceholder(unitType, unitId, basePath, `${reason} recovery exhausted ${maxRecoveryAttempts} attempts without producing the artifact.`);
|
|
@@ -10,10 +10,15 @@
|
|
|
10
10
|
* checks the result and handles control flow.
|
|
11
11
|
*/
|
|
12
12
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
13
|
-
import { resolveSlicePath } from "./paths.js";
|
|
13
|
+
import { resolveSlicePath, resolveMilestoneFile } from "./paths.js";
|
|
14
14
|
import { parseUnitId } from "./unit-id.js";
|
|
15
|
-
import { isDbAvailable, getTask, getSliceTasks } from "./gsd-db.js";
|
|
15
|
+
import { isDbAvailable, getTask, getSliceTasks, getMilestoneSlices } from "./gsd-db.js";
|
|
16
16
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
17
|
+
import { extractVerdict } from "./verdict-parser.js";
|
|
18
|
+
import { isClosedStatus } from "./status-guards.js";
|
|
19
|
+
import { loadFile } from "./files.js";
|
|
20
|
+
import { parseRoadmap } from "./parsers-legacy.js";
|
|
21
|
+
import { isMilestoneComplete } from "./state.js";
|
|
17
22
|
import { runVerificationGate, formatFailureContext, captureRuntimeErrors, runDependencyAudit, } from "./verification-gate.js";
|
|
18
23
|
import { writeVerificationJSON } from "./verification-evidence.js";
|
|
19
24
|
import { logWarning } from "./workflow-logger.js";
|
|
@@ -22,6 +27,80 @@ import { join } from "node:path";
|
|
|
22
27
|
function isInfraVerificationFailure(stderr) {
|
|
23
28
|
return /\b(ENOENT|ENOTFOUND|ETIMEDOUT|ECONNRESET|EAI_AGAIN|spawn\s+\S+\s+ENOENT|command not found)\b/i.test(stderr);
|
|
24
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Post-unit guard for `validate-milestone` units (#4094).
|
|
32
|
+
*
|
|
33
|
+
* When validate-milestone writes verdict=needs-remediation, the agent is
|
|
34
|
+
* expected to also call gsd_reassess_roadmap in the same turn to add
|
|
35
|
+
* remediation slices. If they don't, the state machine re-derives
|
|
36
|
+
* `phase: validating-milestone` indefinitely (all slices still complete +
|
|
37
|
+
* verdict still needs-remediation), wasting ~3 dispatches before the stuck
|
|
38
|
+
* detector fires.
|
|
39
|
+
*
|
|
40
|
+
* This guard fires immediately on the first occurrence: if VALIDATION.md
|
|
41
|
+
* verdict is needs-remediation and no incomplete slices exist for the
|
|
42
|
+
* milestone, pause the auto-loop with a clear blocker.
|
|
43
|
+
*/
|
|
44
|
+
async function runValidateMilestonePostCheck(vctx, pauseAuto) {
|
|
45
|
+
const { s, ctx, pi } = vctx;
|
|
46
|
+
if (!s.currentUnit)
|
|
47
|
+
return "continue";
|
|
48
|
+
const { milestone: mid } = parseUnitId(s.currentUnit.id);
|
|
49
|
+
if (!mid)
|
|
50
|
+
return "continue";
|
|
51
|
+
const validationFile = resolveMilestoneFile(s.basePath, mid, "VALIDATION");
|
|
52
|
+
if (!validationFile)
|
|
53
|
+
return "continue";
|
|
54
|
+
const validationContent = await loadFile(validationFile);
|
|
55
|
+
if (!validationContent)
|
|
56
|
+
return "continue";
|
|
57
|
+
const verdict = extractVerdict(validationContent);
|
|
58
|
+
if (verdict !== "needs-remediation")
|
|
59
|
+
return "continue";
|
|
60
|
+
const incompleteSliceCount = await countIncompleteSlices(s.basePath, mid);
|
|
61
|
+
// If any non-closed slices exist, the agent successfully queued remediation
|
|
62
|
+
// work — proceed normally. The state machine will execute those slices and
|
|
63
|
+
// re-validate per the #3596/#3670 fix.
|
|
64
|
+
if (incompleteSliceCount > 0)
|
|
65
|
+
return "continue";
|
|
66
|
+
ctx.ui.notify(`Milestone ${mid} validation returned verdict=needs-remediation but no remediation slices were added. Pausing for human review.`, "error");
|
|
67
|
+
process.stderr.write(`validate-milestone: pausing — verdict=needs-remediation with no incomplete slices for ${mid}. ` +
|
|
68
|
+
`The agent must call gsd_reassess_roadmap to add remediation slices before re-validation.\n`);
|
|
69
|
+
await pauseAuto(ctx, pi);
|
|
70
|
+
return "pause";
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Count slices for a milestone that are not in a closed status.
|
|
74
|
+
* DB-backed projects are authoritative (#4094 peer review); falls back to
|
|
75
|
+
* roadmap parsing only when the DB is unavailable.
|
|
76
|
+
*/
|
|
77
|
+
async function countIncompleteSlices(basePath, milestoneId) {
|
|
78
|
+
if (isDbAvailable()) {
|
|
79
|
+
const slices = getMilestoneSlices(milestoneId);
|
|
80
|
+
if (slices.length === 0) {
|
|
81
|
+
// No DB rows — treat as "unknown", do not pause.
|
|
82
|
+
return 1;
|
|
83
|
+
}
|
|
84
|
+
return slices.filter((slice) => !isClosedStatus(slice.status)).length;
|
|
85
|
+
}
|
|
86
|
+
// Filesystem fallback: parse the roadmap markdown.
|
|
87
|
+
try {
|
|
88
|
+
const roadmapFile = resolveMilestoneFile(basePath, milestoneId, "ROADMAP");
|
|
89
|
+
if (!roadmapFile)
|
|
90
|
+
return 1;
|
|
91
|
+
const roadmapContent = await loadFile(roadmapFile);
|
|
92
|
+
if (!roadmapContent)
|
|
93
|
+
return 1;
|
|
94
|
+
const roadmap = parseRoadmap(roadmapContent);
|
|
95
|
+
if (roadmap.slices.length === 0)
|
|
96
|
+
return 1;
|
|
97
|
+
return isMilestoneComplete(roadmap) ? 0 : 1;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// Parsing failures should not cause false-positive pauses.
|
|
101
|
+
return 1;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
25
104
|
/**
|
|
26
105
|
* Run the verification gate for the current execute-task unit.
|
|
27
106
|
* Returns:
|
|
@@ -31,7 +110,13 @@ function isInfraVerificationFailure(stderr) {
|
|
|
31
110
|
*/
|
|
32
111
|
export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
33
112
|
const { s, ctx, pi } = vctx;
|
|
34
|
-
if (!s.currentUnit
|
|
113
|
+
if (!s.currentUnit) {
|
|
114
|
+
return "continue";
|
|
115
|
+
}
|
|
116
|
+
if (s.currentUnit.type === "validate-milestone") {
|
|
117
|
+
return await runValidateMilestonePostCheck(vctx, pauseAuto);
|
|
118
|
+
}
|
|
119
|
+
if (s.currentUnit.type !== "execute-task") {
|
|
35
120
|
return "continue";
|
|
36
121
|
}
|
|
37
122
|
try {
|
|
@@ -36,7 +36,7 @@ import { captureAvailableSkills, resetSkillTelemetry, } from "./skill-telemetry.
|
|
|
36
36
|
import { getRtkSessionSavings } from "../shared/rtk-session-stats.js";
|
|
37
37
|
import { deactivateGSD } from "../shared/gsd-phase-state.js";
|
|
38
38
|
import { initMetrics, resetMetrics, getLedger, getProjectTotals, formatCost, formatTokenCount, } from "./metrics.js";
|
|
39
|
-
import { logWarning } from "./workflow-logger.js";
|
|
39
|
+
import { setLogBasePath, logWarning } from "./workflow-logger.js";
|
|
40
40
|
import { homedir } from "node:os";
|
|
41
41
|
import { join } from "node:path";
|
|
42
42
|
import { pathToFileURL } from "node:url";
|
|
@@ -55,14 +55,15 @@ import { initRegistry, convertDispatchRules } from "./rule-registry.js";
|
|
|
55
55
|
import { emitJournalEvent as _emitJournalEvent } from "./journal.js";
|
|
56
56
|
import { updateProgressWidget as _updateProgressWidget, updateSliceProgressCache, clearSliceProgressCache, hideFooter, } from "./auto-dashboard.js";
|
|
57
57
|
import { registerSigtermHandler as _registerSigtermHandler, deregisterSigtermHandler as _deregisterSigtermHandler, } from "./auto-supervisor.js";
|
|
58
|
-
import { isDbAvailable } from "./gsd-db.js";
|
|
58
|
+
import { isDbAvailable, getMilestone } from "./gsd-db.js";
|
|
59
59
|
import { countPendingCaptures } from "./captures.js";
|
|
60
60
|
import { clearCmuxSidebar, logCmuxEvent, syncCmuxSidebar } from "../cmux/index.js";
|
|
61
61
|
// ── Extracted modules ──────────────────────────────────────────────────────
|
|
62
62
|
import { startUnitSupervision } from "./auto-timers.js";
|
|
63
63
|
import { runPostUnitVerification } from "./auto-verification.js";
|
|
64
|
-
import { postUnitPreVerification, postUnitPostVerification, } from "./auto-post-unit.js";
|
|
64
|
+
import { autoCommitUnit, postUnitPreVerification, postUnitPostVerification, } from "./auto-post-unit.js";
|
|
65
65
|
import { bootstrapAutoSession, openProjectDbIfPresent } from "./auto-start.js";
|
|
66
|
+
import { initHealthWidget } from "./health-widget.js";
|
|
66
67
|
import { autoLoop, resolveAgentEnd, resolveAgentEndCancelled, _resetPendingResolve, isSessionSwitchInFlight } from "./auto-loop.js";
|
|
67
68
|
import { WorktreeResolver, } from "./worktree-resolver.js";
|
|
68
69
|
import { reorderForCaching } from "./prompt-ordering.js";
|
|
@@ -397,6 +398,8 @@ function handleLostSessionLock(ctx, lockStatus) {
|
|
|
397
398
|
ctx?.ui.setStatus("gsd-auto", undefined);
|
|
398
399
|
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
399
400
|
ctx?.ui.setFooter(undefined);
|
|
401
|
+
if (ctx)
|
|
402
|
+
initHealthWidget(ctx);
|
|
400
403
|
}
|
|
401
404
|
/**
|
|
402
405
|
* Lightweight cleanup after autoLoop exits via step-wizard break.
|
|
@@ -431,6 +434,7 @@ function cleanupAfterLoopExit(ctx) {
|
|
|
431
434
|
ctx.ui.setStatus("gsd-auto", undefined);
|
|
432
435
|
ctx.ui.setWidget("gsd-progress", undefined);
|
|
433
436
|
ctx.ui.setFooter(undefined);
|
|
437
|
+
initHealthWidget(ctx);
|
|
434
438
|
}
|
|
435
439
|
// Restore CWD out of worktree back to original project root
|
|
436
440
|
if (s.originalBasePath) {
|
|
@@ -501,17 +505,30 @@ export async function stopAuto(ctx, pi, reason) {
|
|
|
501
505
|
? { notify: ctx.ui.notify.bind(ctx.ui) }
|
|
502
506
|
: { notify: () => { } };
|
|
503
507
|
const resolver = buildResolver();
|
|
504
|
-
// Check if the milestone is complete
|
|
508
|
+
// Check if the milestone is complete. DB status is the authoritative
|
|
509
|
+
// signal — only a successful gsd_complete_milestone call flips it to
|
|
510
|
+
// "complete" (tools/complete-milestone.ts). SUMMARY file presence is
|
|
511
|
+
// NOT sufficient: a blocker placeholder stub or a partial write can
|
|
512
|
+
// leave a file behind without the milestone actually being done,
|
|
513
|
+
// which previously caused stopAuto to merge a failed milestone and
|
|
514
|
+
// emit a misleading metadata-only merge warning (#4175).
|
|
515
|
+
// DB-unavailable projects fall back to SUMMARY-file presence.
|
|
505
516
|
let milestoneComplete = false;
|
|
506
517
|
try {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
const wtSummaryPath = resolveMilestoneFile(s.basePath, s.currentMilestoneId, "SUMMARY");
|
|
511
|
-
milestoneComplete = wtSummaryPath !== null;
|
|
518
|
+
if (isDbAvailable()) {
|
|
519
|
+
const dbRow = getMilestone(s.currentMilestoneId);
|
|
520
|
+
milestoneComplete = dbRow?.status === "complete";
|
|
512
521
|
}
|
|
513
522
|
else {
|
|
514
|
-
|
|
523
|
+
const summaryPath = resolveMilestoneFile(s.originalBasePath || s.basePath, s.currentMilestoneId, "SUMMARY");
|
|
524
|
+
if (!summaryPath) {
|
|
525
|
+
// Also check in the worktree path (SUMMARY may not be synced yet)
|
|
526
|
+
const wtSummaryPath = resolveMilestoneFile(s.basePath, s.currentMilestoneId, "SUMMARY");
|
|
527
|
+
milestoneComplete = wtSummaryPath !== null;
|
|
528
|
+
}
|
|
529
|
+
else {
|
|
530
|
+
milestoneComplete = true;
|
|
531
|
+
}
|
|
515
532
|
}
|
|
516
533
|
}
|
|
517
534
|
catch (err) {
|
|
@@ -676,6 +693,8 @@ export async function stopAuto(ctx, pi, reason) {
|
|
|
676
693
|
ctx?.ui.setStatus("gsd-auto", undefined);
|
|
677
694
|
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
678
695
|
ctx?.ui.setFooter(undefined);
|
|
696
|
+
if (ctx)
|
|
697
|
+
initHealthWidget(ctx);
|
|
679
698
|
restoreProjectRootEnv();
|
|
680
699
|
restoreMilestoneLockEnv();
|
|
681
700
|
// Reset all session state in one call
|
|
@@ -762,6 +781,8 @@ export async function pauseAuto(ctx, _pi, _errorContext) {
|
|
|
762
781
|
ctx?.ui.setStatus("gsd-auto", "paused");
|
|
763
782
|
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
764
783
|
ctx?.ui.setFooter(undefined);
|
|
784
|
+
if (ctx)
|
|
785
|
+
initHealthWidget(ctx);
|
|
765
786
|
const resumeCmd = s.stepMode ? "/gsd next" : "/gsd auto";
|
|
766
787
|
ctx?.ui.notify(`${s.stepMode ? "Step" : "Auto"}-mode paused (Escape). Type to interact, or ${resumeCmd} to resume.`, "info");
|
|
767
788
|
}
|
|
@@ -863,6 +884,7 @@ function buildLoopDeps() {
|
|
|
863
884
|
getMainBranch,
|
|
864
885
|
// Unit closeout + runtime records
|
|
865
886
|
closeoutUnit,
|
|
887
|
+
autoCommitUnit,
|
|
866
888
|
recordOutcome,
|
|
867
889
|
writeLock,
|
|
868
890
|
captureAvailableSkills,
|
|
@@ -1060,6 +1082,11 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1060
1082
|
s.stepMode = requestedStepMode;
|
|
1061
1083
|
s.cmdCtx = ctx;
|
|
1062
1084
|
s.basePath = base;
|
|
1085
|
+
// Ensure the workflow-logger audit log is pinned to the project root
|
|
1086
|
+
// even when auto-mode is entered via a path that bypasses the
|
|
1087
|
+
// bootstrap/dynamic-tools ensureDbOpen() → setLogBasePath() chain
|
|
1088
|
+
// (e.g. /clear resume, hot-reload).
|
|
1089
|
+
setLogBasePath(base);
|
|
1063
1090
|
s.unitDispatchCount.clear();
|
|
1064
1091
|
s.unitLifetimeDispatches.clear();
|
|
1065
1092
|
if (!getLedger())
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// GSD2 — Extension registration: wires all GSD tools, commands, and hooks into pi
|
|
2
|
-
import { registerGSDCommand } from "../commands.js";
|
|
3
2
|
import { registerExitCommand } from "../exit-command.js";
|
|
4
3
|
import { registerWorktreeCommand } from "../worktree-command.js";
|
|
5
4
|
import { registerDbTools } from "./db-tools.js";
|
|
@@ -9,6 +8,7 @@ import { registerQueryTools } from "./query-tools.js";
|
|
|
9
8
|
import { registerHooks } from "./register-hooks.js";
|
|
10
9
|
import { registerShortcuts } from "./register-shortcuts.js";
|
|
11
10
|
import { writeCrashLog } from "./crash-log.js";
|
|
11
|
+
import { logWarning } from "../workflow-logger.js";
|
|
12
12
|
export { writeCrashLog } from "./crash-log.js";
|
|
13
13
|
export function handleRecoverableExtensionProcessError(err) {
|
|
14
14
|
if (err.code === "EPIPE") {
|
|
@@ -52,7 +52,8 @@ function installEpipeGuard() {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
export function registerGsdExtension(pi) {
|
|
55
|
-
registerGSDCommand
|
|
55
|
+
// Note: registerGSDCommand is called by index.ts before this function,
|
|
56
|
+
// so we intentionally skip it here to avoid double-registration.
|
|
56
57
|
registerWorktreeCommand(pi);
|
|
57
58
|
registerExitCommand(pi);
|
|
58
59
|
installEpipeGuard();
|
|
@@ -62,10 +63,22 @@ export function registerGsdExtension(pi) {
|
|
|
62
63
|
process.exit(0);
|
|
63
64
|
},
|
|
64
65
|
});
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
// Wrap non-critical registrations individually so one failure
|
|
67
|
+
// doesn't prevent the others from loading.
|
|
68
|
+
const nonCriticalRegistrations = [
|
|
69
|
+
["dynamic-tools", () => registerDynamicTools(pi)],
|
|
70
|
+
["db-tools", () => registerDbTools(pi)],
|
|
71
|
+
["journal-tools", () => registerJournalTools(pi)],
|
|
72
|
+
["query-tools", () => registerQueryTools(pi)],
|
|
73
|
+
["shortcuts", () => registerShortcuts(pi)],
|
|
74
|
+
["hooks", () => registerHooks(pi)],
|
|
75
|
+
];
|
|
76
|
+
for (const [name, register] of nonCriticalRegistrations) {
|
|
77
|
+
try {
|
|
78
|
+
register();
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
logWarning("bootstrap", `Failed to register ${name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
71
84
|
}
|
|
@@ -4,7 +4,7 @@ import { join } from "node:path";
|
|
|
4
4
|
import { loadRegistry } from "../workflow-templates.js";
|
|
5
5
|
import { resolveProjectRoot } from "../worktree.js";
|
|
6
6
|
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
7
|
-
export const GSD_COMMAND_DESCRIPTION = "GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|widget|visualize|queue|quick|discuss|capture|triage|dispatch|history|undo|undo-task|reset-slice|rate|skip|export|cleanup|model|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|logs|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|parallel|cmux|park|unpark|init|setup|inspect|extensions|update|fast|mcp|rethink|codebase|notifications";
|
|
7
|
+
export const GSD_COMMAND_DESCRIPTION = "GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|widget|visualize|queue|quick|discuss|capture|triage|dispatch|history|undo|undo-task|reset-slice|rate|skip|export|cleanup|model|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|logs|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|parallel|cmux|park|unpark|init|setup|inspect|extensions|update|fast|mcp|rethink|codebase|notifications|ship|do|session-report|backlog|pr-branch|add-tests";
|
|
8
8
|
export const TOP_LEVEL_SUBCOMMANDS = [
|
|
9
9
|
{ cmd: "help", desc: "Categorized command reference with descriptions" },
|
|
10
10
|
{ cmd: "next", desc: "Explicit step mode (same as /gsd)" },
|
|
@@ -62,6 +62,12 @@ export const TOP_LEVEL_SUBCOMMANDS = [
|
|
|
62
62
|
{ cmd: "rethink", desc: "Conversational project reorganization — reorder, park, discard, add milestones" },
|
|
63
63
|
{ cmd: "workflow", desc: "Custom workflow lifecycle (new, run, list, validate, pause, resume)" },
|
|
64
64
|
{ cmd: "codebase", desc: "Generate, refresh, and inspect the codebase map cache (.gsd/CODEBASE.md)" },
|
|
65
|
+
{ cmd: "ship", desc: "Create PR from milestone artifacts and open for review" },
|
|
66
|
+
{ cmd: "do", desc: "Route freeform text to the right GSD command" },
|
|
67
|
+
{ cmd: "session-report", desc: "Session cost, tokens, and work summary" },
|
|
68
|
+
{ cmd: "backlog", desc: "Manage backlog items (add, promote, remove, list)" },
|
|
69
|
+
{ cmd: "pr-branch", desc: "Create clean PR branch filtering .gsd/ commits" },
|
|
70
|
+
{ cmd: "add-tests", desc: "Generate tests for completed slices" },
|
|
65
71
|
];
|
|
66
72
|
const NESTED_COMPLETIONS = {
|
|
67
73
|
auto: [
|
|
@@ -231,6 +237,25 @@ const NESTED_COMPLETIONS = {
|
|
|
231
237
|
{ cmd: "stats", desc: "Show file count, description coverage, and generation time" },
|
|
232
238
|
{ cmd: "help", desc: "Show usage and available subcommands" },
|
|
233
239
|
],
|
|
240
|
+
ship: [
|
|
241
|
+
{ cmd: "--dry-run", desc: "Preview PR without creating" },
|
|
242
|
+
{ cmd: "--draft", desc: "Open as draft PR" },
|
|
243
|
+
{ cmd: "--base", desc: "Override target branch (default: main)" },
|
|
244
|
+
{ cmd: "--force", desc: "Ship even with pending tasks" },
|
|
245
|
+
],
|
|
246
|
+
"session-report": [
|
|
247
|
+
{ cmd: "--json", desc: "Machine-readable JSON output" },
|
|
248
|
+
{ cmd: "--save", desc: "Save report to .gsd/reports/" },
|
|
249
|
+
],
|
|
250
|
+
backlog: [
|
|
251
|
+
{ cmd: "add", desc: "Add item to backlog" },
|
|
252
|
+
{ cmd: "promote", desc: "Promote backlog item to active slice" },
|
|
253
|
+
{ cmd: "remove", desc: "Remove backlog item" },
|
|
254
|
+
],
|
|
255
|
+
"pr-branch": [
|
|
256
|
+
{ cmd: "--dry-run", desc: "Preview what would be filtered" },
|
|
257
|
+
{ cmd: "--name", desc: "Custom branch name" },
|
|
258
|
+
],
|
|
234
259
|
};
|
|
235
260
|
function filterOptions(partial, options, prefix = "") {
|
|
236
261
|
const normalizedPrefix = prefix ? `${prefix} ` : "";
|