gsd-pi 2.70.1 → 2.71.0-dev.246c32d
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/README.md +57 -17
- package/dist/cli.js +29 -3
- package/dist/headless-events.d.ts +2 -0
- package/dist/headless-events.js +7 -0
- package/dist/headless.js +16 -3
- package/dist/mcp-server.js +40 -17
- package/dist/provider-migrations.d.ts +10 -0
- package/dist/provider-migrations.js +12 -0
- package/dist/resource-loader.js +139 -13
- package/dist/resources/GSD-WORKFLOW.md +1 -1
- package/dist/resources/agents/debugger.md +58 -0
- package/dist/resources/agents/doc-writer.md +43 -0
- package/dist/resources/agents/git-ops.md +56 -0
- package/dist/resources/agents/javascript-pro.md +46 -271
- package/dist/resources/agents/planner.md +55 -0
- package/dist/resources/agents/refactorer.md +47 -0
- package/dist/resources/agents/reviewer.md +48 -0
- package/dist/resources/agents/security.md +59 -0
- package/dist/resources/agents/tester.md +50 -0
- package/dist/resources/agents/typescript-pro.md +41 -235
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +242 -40
- package/dist/resources/extensions/get-secrets-from-user.js +17 -1
- package/dist/resources/extensions/gsd/auto/infra-errors.js +34 -0
- package/dist/resources/extensions/gsd/auto/loop.js +32 -1
- package/dist/resources/extensions/gsd/auto/phases.js +5 -1
- package/dist/resources/extensions/gsd/auto/session.js +11 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +22 -16
- package/dist/resources/extensions/gsd/auto-model-selection.js +10 -2
- package/dist/resources/extensions/gsd/auto-prompts.js +88 -33
- package/dist/resources/extensions/gsd/auto-start.js +37 -18
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
- package/dist/resources/extensions/gsd/auto-worktree.js +1 -1
- package/dist/resources/extensions/gsd/auto.js +56 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +6 -0
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +63 -51
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -0
- package/dist/resources/extensions/gsd/commands/context.js +15 -6
- package/dist/resources/extensions/gsd/commands/dispatcher.js +12 -2
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +10 -33
- package/dist/resources/extensions/gsd/commands/handlers/core.js +56 -11
- package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +15 -6
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +4 -10
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +16 -12
- package/dist/resources/extensions/gsd/dashboard-overlay.js +8 -3
- package/dist/resources/extensions/gsd/dispatch-guard.js +18 -1
- package/dist/resources/extensions/gsd/doctor-providers.js +23 -0
- package/dist/resources/extensions/gsd/error-classifier.js +5 -2
- package/dist/resources/extensions/gsd/file-lock.js +60 -0
- package/dist/resources/extensions/gsd/forensics.js +19 -6
- package/dist/resources/extensions/gsd/gate-registry.js +208 -0
- package/dist/resources/extensions/gsd/gsd-db.js +41 -0
- package/dist/resources/extensions/gsd/guided-flow.js +17 -20
- package/dist/resources/extensions/gsd/init-wizard.js +3 -11
- package/dist/resources/extensions/gsd/metrics.js +1 -0
- package/dist/resources/extensions/gsd/milestone-actions.js +10 -4
- package/dist/resources/extensions/gsd/milestone-validation-gates.js +11 -12
- package/dist/resources/extensions/gsd/notification-overlay.js +42 -13
- package/dist/resources/extensions/gsd/notification-store.js +56 -5
- package/dist/resources/extensions/gsd/notification-widget.js +5 -13
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +8 -3
- package/dist/resources/extensions/gsd/pre-execution-checks.js +35 -2
- package/dist/resources/extensions/gsd/prompt-validation.js +126 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +5 -3
- package/dist/resources/extensions/gsd/prompts/discuss.md +33 -13
- package/dist/resources/extensions/gsd/prompts/execute-task.md +22 -19
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/queue.md +3 -2
- package/dist/resources/extensions/gsd/prompts/system.md +1 -0
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
- package/dist/resources/extensions/gsd/session-model-override.js +25 -0
- package/dist/resources/extensions/gsd/shortcut-defs.js +40 -0
- package/dist/resources/extensions/gsd/state.js +241 -332
- package/dist/resources/extensions/gsd/tools/complete-slice.js +52 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +51 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +38 -1
- package/dist/resources/extensions/gsd/workflow-events.js +25 -13
- package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +56 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +1 -1
- package/dist/resources/extensions/ollama/index.js +13 -5
- package/dist/resources/extensions/shared/gsd-phase-state.js +35 -0
- package/dist/resources/extensions/subagent/agents.js +8 -0
- package/dist/resources/extensions/subagent/index.js +17 -0
- package/dist/resources/skills/create-skill/SKILL.md +2 -0
- package/dist/startup-model-validation.d.ts +0 -1
- package/dist/startup-model-validation.js +6 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +19 -19
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/required-server-files.json +4 -4
- 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 +1 -1
- 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 +1 -1
- 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 +2 -2
- 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 +19 -19
- 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-react-loadable-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 +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/2826.dd3dc8bbd3025fa5.js +9 -0
- 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/.next/static/chunks/{webpack-6e4d7e9a4f57bed4.js → webpack-b868033a5834586d.js} +1 -1
- 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/mcp-server/dist/env-writer.d.ts +39 -0
- package/packages/mcp-server/dist/env-writer.d.ts.map +1 -0
- package/packages/mcp-server/dist/env-writer.js +158 -0
- package/packages/mcp-server/dist/env-writer.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts +23 -3
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +192 -44
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +22 -12
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/env-writer.test.ts +280 -0
- package/packages/mcp-server/src/env-writer.ts +183 -0
- package/packages/mcp-server/src/secure-env-collect.test.ts +265 -0
- package/packages/mcp-server/src/server.ts +247 -41
- package/packages/mcp-server/src/workflow-tools.test.ts +110 -0
- package/packages/mcp-server/src/workflow-tools.ts +32 -12
- package/packages/pi-ai/dist/providers/amazon-bedrock.js +11 -2
- package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js +20 -0
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +4 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +8 -3
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js +44 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts +2 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +7 -4
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +11 -0
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/src/providers/amazon-bedrock.ts +13 -1
- package/packages/pi-ai/src/providers/anthropic-auth.test.ts +32 -0
- package/packages/pi-ai/src/providers/anthropic-shared.test.ts +55 -1
- package/packages/pi-ai/src/providers/anthropic-shared.ts +14 -3
- package/packages/pi-ai/src/providers/anthropic.ts +8 -4
- package/packages/pi-ai/src/providers/openai-completions.ts +14 -0
- package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js +61 -0
- package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +2 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +27 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +85 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +388 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -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/model-resolver-initial-model-auth.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js +64 -0
- package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +22 -18
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts +8 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.test.js +75 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +55 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +57 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +38 -5
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/sdk.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.test.js +71 -0
- package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js +13 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts +19 -2
- 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 +50 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +24 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +9 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +43 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- 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 +175 -25
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js +6 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -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 +62 -5
- 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.js +4 -2
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-renderable-tools.test.ts +70 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +108 -0
- package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -0
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +468 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -0
- package/packages/pi-coding-agent/src/core/model-resolver-initial-model-auth.test.ts +78 -0
- package/packages/pi-coding-agent/src/core/model-resolver.test.ts +85 -0
- package/packages/pi-coding-agent/src/core/model-resolver.ts +22 -18
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +83 -0
- package/packages/pi-coding-agent/src/core/retry-handler.ts +60 -1
- package/packages/pi-coding-agent/src/core/sdk.test.ts +89 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +45 -9
- package/packages/pi-coding-agent/src/index.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/login-dialog.test.ts +24 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +58 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/extension-input.ts +2 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +30 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +15 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +47 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +205 -31
- package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +6 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +70 -5
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +4 -2
- package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +1 -1
- package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +1 -0
- package/packages/pi-tui/dist/components/__tests__/input.test.js +9 -0
- package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +66 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -0
- package/packages/pi-tui/dist/components/input.d.ts +2 -0
- package/packages/pi-tui/dist/components/input.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/input.js +7 -4
- package/packages/pi-tui/dist/components/input.js.map +1 -1
- package/packages/pi-tui/dist/components/markdown.d.ts +3 -0
- package/packages/pi-tui/dist/components/markdown.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/markdown.js +17 -1
- package/packages/pi-tui/dist/components/markdown.js.map +1 -1
- package/packages/pi-tui/src/components/__tests__/input.test.ts +11 -0
- package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +75 -0
- package/packages/pi-tui/src/components/input.ts +7 -4
- package/packages/pi-tui/src/components/markdown.ts +22 -1
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +1 -1
- package/src/resources/agents/debugger.md +58 -0
- package/src/resources/agents/doc-writer.md +43 -0
- package/src/resources/agents/git-ops.md +56 -0
- package/src/resources/agents/javascript-pro.md +46 -271
- package/src/resources/agents/planner.md +55 -0
- package/src/resources/agents/refactorer.md +47 -0
- package/src/resources/agents/reviewer.md +48 -0
- package/src/resources/agents/security.md +59 -0
- package/src/resources/agents/tester.md +50 -0
- package/src/resources/agents/typescript-pro.md +41 -235
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +288 -39
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +330 -2
- package/src/resources/extensions/get-secrets-from-user.ts +24 -1
- package/src/resources/extensions/gsd/auto/infra-errors.ts +38 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
- package/src/resources/extensions/gsd/auto/loop.ts +45 -1
- package/src/resources/extensions/gsd/auto/phases.ts +6 -0
- package/src/resources/extensions/gsd/auto/session.ts +11 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +29 -18
- package/src/resources/extensions/gsd/auto-model-selection.ts +9 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +111 -33
- package/src/resources/extensions/gsd/auto-start.ts +44 -20
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
- package/src/resources/extensions/gsd/auto-worktree.ts +1 -1
- package/src/resources/extensions/gsd/auto.ts +72 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +6 -0
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +79 -60
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +7 -0
- package/src/resources/extensions/gsd/commands/context.ts +16 -5
- package/src/resources/extensions/gsd/commands/dispatcher.ts +14 -2
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +10 -36
- package/src/resources/extensions/gsd/commands/handlers/core.ts +58 -11
- package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +17 -7
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +4 -10
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +19 -14
- package/src/resources/extensions/gsd/dashboard-overlay.ts +10 -3
- package/src/resources/extensions/gsd/dispatch-guard.ts +18 -1
- package/src/resources/extensions/gsd/doctor-providers.ts +24 -0
- package/src/resources/extensions/gsd/error-classifier.ts +5 -2
- package/src/resources/extensions/gsd/file-lock.ts +59 -0
- package/src/resources/extensions/gsd/forensics.ts +23 -7
- package/src/resources/extensions/gsd/gate-registry.ts +251 -0
- package/src/resources/extensions/gsd/gsd-db.ts +51 -0
- package/src/resources/extensions/gsd/guided-flow.ts +17 -19
- package/src/resources/extensions/gsd/init-wizard.ts +3 -13
- package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
- package/src/resources/extensions/gsd/metrics.ts +12 -1
- package/src/resources/extensions/gsd/milestone-actions.ts +10 -3
- package/src/resources/extensions/gsd/milestone-validation-gates.ts +11 -13
- package/src/resources/extensions/gsd/notification-overlay.ts +47 -14
- package/src/resources/extensions/gsd/notification-store.ts +54 -5
- package/src/resources/extensions/gsd/notification-widget.ts +5 -14
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -3
- package/src/resources/extensions/gsd/pre-execution-checks.ts +39 -2
- package/src/resources/extensions/gsd/prompt-validation.ts +157 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +5 -3
- package/src/resources/extensions/gsd/prompts/discuss.md +33 -13
- package/src/resources/extensions/gsd/prompts/execute-task.md +22 -19
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/queue.md +3 -2
- package/src/resources/extensions/gsd/prompts/system.md +1 -0
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
- package/src/resources/extensions/gsd/session-model-override.ts +36 -0
- package/src/resources/extensions/gsd/shortcut-defs.ts +56 -0
- package/src/resources/extensions/gsd/state.ts +285 -344
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +25 -9
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/complete-slice-gate-closure.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/complete-slice-prompt-task-summary-layout.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +436 -0
- package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/execute-task-prompt-existing-artifact-guard.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/file-lock.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/gate-registry.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +180 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +66 -1
- package/src/resources/extensions/gsd/tests/model-isolation.test.ts +36 -51
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/prompt-system-gate-coverage.test.ts +208 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +63 -5
- package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/session-model-override.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +155 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +22 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +63 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +63 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +64 -26
- package/src/resources/extensions/gsd/types.ts +26 -0
- package/src/resources/extensions/gsd/workflow-events.ts +34 -25
- package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +76 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +1 -1
- package/src/resources/extensions/ollama/index.ts +13 -3
- package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +28 -0
- package/src/resources/extensions/shared/gsd-phase-state.ts +42 -0
- package/src/resources/extensions/shared/tests/gsd-phase-state.test.ts +48 -0
- package/src/resources/extensions/subagent/agents.ts +10 -0
- package/src/resources/extensions/subagent/index.ts +18 -0
- package/src/resources/extensions/subagent/tests/agents-conflicts.test.ts +33 -0
- package/src/resources/skills/create-skill/SKILL.md +2 -0
- package/dist/web/standalone/.next/static/chunks/2826.821e01b07d92e948.js +0 -9
- 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/{9pw9EXtXjdM7EFrCXUEPf → hnGGkVMxIGGpxSJkf5jIV}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{9pw9EXtXjdM7EFrCXUEPf → hnGGkVMxIGGpxSJkf5jIV}/_ssgManifest.js +0 -0
|
@@ -20,10 +20,13 @@ export function resetRetryState(state) {
|
|
|
20
20
|
// ── Classification ──────────────────────────────────────────────────────────
|
|
21
21
|
const PERMANENT_RE = /auth|unauthorized|forbidden|invalid.*key|invalid.*api|billing|quota exceeded|account/i;
|
|
22
22
|
const RATE_LIMIT_RE = /rate.?limit|too many requests|429/i;
|
|
23
|
+
// OpenRouter affordability-style quota errors should be treated as transient
|
|
24
|
+
// so core retry logic can lower maxTokens and continue in-session.
|
|
25
|
+
const AFFORDABILITY_RE = /requires more credits|can only afford|insufficient credits|not enough credits|fewer max_tokens/i;
|
|
23
26
|
const NETWORK_RE = /network|ECONNRESET|ETIMEDOUT|ECONNREFUSED|socket hang up|fetch failed|connection.*reset|dns/i;
|
|
24
27
|
const SERVER_RE = /internal server error|500|502|503|overloaded|server_error|api_error|service.?unavailable/i;
|
|
25
28
|
// ECONNRESET/ECONNREFUSED are in NETWORK_RE (same-model retry first).
|
|
26
|
-
const CONNECTION_RE = /terminated|connection.?refused|other side closed|EPIPE|network.?(?:is\s+)?unavailable|stream_exhausted(?:_without_result)?/i;
|
|
29
|
+
const CONNECTION_RE = /terminated|connection.?(?:refused|error)|other side closed|EPIPE|network.?(?:is\s+)?unavailable|stream_exhausted(?:_without_result)?/i;
|
|
27
30
|
// Catch-all for V8 JSON.parse errors: all modern variants end with "in JSON at position \d+".
|
|
28
31
|
// This eliminates the need to enumerate every error message variant individually.
|
|
29
32
|
const STREAM_RE = /in JSON at position \d+|Unexpected end of JSON|SyntaxError.*JSON/i;
|
|
@@ -42,7 +45,7 @@ const RESET_DELAY_RE = /reset in (\d+)s/i;
|
|
|
42
45
|
*/
|
|
43
46
|
export function classifyError(errorMsg, retryAfterMs) {
|
|
44
47
|
const isPermanent = PERMANENT_RE.test(errorMsg);
|
|
45
|
-
const isRateLimit = RATE_LIMIT_RE.test(errorMsg);
|
|
48
|
+
const isRateLimit = RATE_LIMIT_RE.test(errorMsg) || AFFORDABILITY_RE.test(errorMsg);
|
|
46
49
|
// 1. Permanent — but rate limit takes precedence
|
|
47
50
|
if (isPermanent && !isRateLimit) {
|
|
48
51
|
return { kind: "permanent" };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
function _require(name) {
|
|
3
|
+
try {
|
|
4
|
+
return require(name);
|
|
5
|
+
}
|
|
6
|
+
catch {
|
|
7
|
+
try {
|
|
8
|
+
const gsdPiRequire = require("module").createRequire(require("path").join(process.cwd(), "node_modules", "gsd-pi", "index.js"));
|
|
9
|
+
return gsdPiRequire(name);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function withFileLockSync(filePath, fn) {
|
|
17
|
+
const lockfile = _require("proper-lockfile");
|
|
18
|
+
if (!lockfile)
|
|
19
|
+
return fn();
|
|
20
|
+
if (!existsSync(filePath))
|
|
21
|
+
return fn();
|
|
22
|
+
try {
|
|
23
|
+
const release = lockfile.lockSync(filePath, { retries: 5, stale: 10000 });
|
|
24
|
+
try {
|
|
25
|
+
return fn();
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
release();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
if (err.code === "ELOCKED") {
|
|
33
|
+
// Could not get lock after retries, let's fallback to un-locked instead of crashing the whole state machine
|
|
34
|
+
return fn();
|
|
35
|
+
}
|
|
36
|
+
throw err;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export async function withFileLock(filePath, fn) {
|
|
40
|
+
const lockfile = _require("proper-lockfile");
|
|
41
|
+
if (!lockfile)
|
|
42
|
+
return await fn();
|
|
43
|
+
if (!existsSync(filePath))
|
|
44
|
+
return await fn();
|
|
45
|
+
try {
|
|
46
|
+
const release = await lockfile.lock(filePath, { retries: 5, stale: 10000 });
|
|
47
|
+
try {
|
|
48
|
+
return await fn();
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
await release();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
if (err.code === "ELOCKED") {
|
|
56
|
+
return await fn();
|
|
57
|
+
}
|
|
58
|
+
throw err;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -508,19 +508,30 @@ function getDbCompletionCounts() {
|
|
|
508
508
|
* Exported for testability.
|
|
509
509
|
*/
|
|
510
510
|
export function detectStuckLoops(units, anomalies) {
|
|
511
|
-
// First, collect unique startedAt values per type/id key
|
|
511
|
+
// First, collect unique startedAt values per type/id key, bucketed by
|
|
512
|
+
// autoSessionKey when available so cross-session recovery does not look
|
|
513
|
+
// like a within-session stuck loop.
|
|
512
514
|
const dispatchMap = new Map();
|
|
513
515
|
for (const u of units) {
|
|
514
516
|
const key = `${u.type}/${u.id}`;
|
|
515
|
-
let
|
|
517
|
+
let sessionBuckets = dispatchMap.get(key);
|
|
518
|
+
if (!sessionBuckets) {
|
|
519
|
+
sessionBuckets = new Map();
|
|
520
|
+
dispatchMap.set(key, sessionBuckets);
|
|
521
|
+
}
|
|
522
|
+
const sessionKey = u.autoSessionKey ?? "__legacy__";
|
|
523
|
+
let starts = sessionBuckets.get(sessionKey);
|
|
516
524
|
if (!starts) {
|
|
517
525
|
starts = new Set();
|
|
518
|
-
|
|
526
|
+
sessionBuckets.set(sessionKey, starts);
|
|
519
527
|
}
|
|
520
528
|
starts.add(u.startedAt);
|
|
521
529
|
}
|
|
522
|
-
for (const [key,
|
|
523
|
-
const
|
|
530
|
+
for (const [key, sessionBuckets] of dispatchMap) {
|
|
531
|
+
const hasSessionAwareData = Array.from(sessionBuckets.keys()).some((sessionKey) => sessionKey !== "__legacy__");
|
|
532
|
+
const count = hasSessionAwareData
|
|
533
|
+
? Math.max(...Array.from(sessionBuckets.values(), (starts) => starts.size))
|
|
534
|
+
: (sessionBuckets.get("__legacy__")?.size ?? 0);
|
|
524
535
|
if (count > 1) {
|
|
525
536
|
const [unitType, ...idParts] = key.split("/");
|
|
526
537
|
anomalies.push({
|
|
@@ -529,7 +540,9 @@ export function detectStuckLoops(units, anomalies) {
|
|
|
529
540
|
unitType,
|
|
530
541
|
unitId: idParts.join("/"),
|
|
531
542
|
summary: `Unit ${key} was dispatched ${count} times`,
|
|
532
|
-
details:
|
|
543
|
+
details: hasSessionAwareData
|
|
544
|
+
? `Repeated dispatch within the same auto session suggests the unit completed but its artifacts were not verified, or the state machine kept returning it. Cross-session recovery runs are ignored.`
|
|
545
|
+
: `Repeated dispatch suggests the unit completed but its artifacts weren't verified, or the state machine kept returning it.`,
|
|
533
546
|
});
|
|
534
547
|
}
|
|
535
548
|
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GSD Gate Registry — single source of truth for quality-gate ownership.
|
|
3
|
+
*
|
|
4
|
+
* Each gate declares which workflow turn owns it, the scope at which it is
|
|
5
|
+
* persisted in the `quality_gates` table, and the question/guidance text used
|
|
6
|
+
* in the prompt that turn sends. The registry replaces the ad-hoc
|
|
7
|
+
* `GATE_QUESTIONS` table that used to live in `auto-prompts.ts`, and every
|
|
8
|
+
* layer of the prompt system (prompt builders, dispatch rules, state
|
|
9
|
+
* derivation, tool handlers) consults it so a pending gate can never be
|
|
10
|
+
* silently dropped.
|
|
11
|
+
*
|
|
12
|
+
* Design notes:
|
|
13
|
+
* - `GATE_REGISTRY` is exhaustiveness-checked against `GateId` via
|
|
14
|
+
* `satisfies Record<GateId, GateDefinition>`, so adding a new GateId
|
|
15
|
+
* without a registry entry is a compile error.
|
|
16
|
+
* - `getGatesForTurn(turn)` returns the definitions a turn owns.
|
|
17
|
+
* - `assertGateCoverage(pending, turn)` throws a GSDError if the pending
|
|
18
|
+
* list for a turn contains unknown gates, or if any gate owned by the
|
|
19
|
+
* turn is missing from the pending list.
|
|
20
|
+
*/
|
|
21
|
+
import { GSDError, GSD_PARSE_ERROR } from "./errors.js";
|
|
22
|
+
export const GATE_REGISTRY = {
|
|
23
|
+
Q3: {
|
|
24
|
+
id: "Q3",
|
|
25
|
+
scope: "slice",
|
|
26
|
+
ownerTurn: "gate-evaluate",
|
|
27
|
+
question: "How can this be exploited?",
|
|
28
|
+
guidance: [
|
|
29
|
+
"Identify abuse scenarios: parameter tampering, replay attacks, privilege escalation.",
|
|
30
|
+
"Map data exposure risks: PII, tokens, secrets accessible through this slice.",
|
|
31
|
+
"Define input trust boundaries: untrusted user input reaching DB, API, or filesystem.",
|
|
32
|
+
"If none apply, return verdict 'omitted' with rationale explaining why.",
|
|
33
|
+
].join("\n"),
|
|
34
|
+
promptSection: "Abuse Surface",
|
|
35
|
+
},
|
|
36
|
+
Q4: {
|
|
37
|
+
id: "Q4",
|
|
38
|
+
scope: "slice",
|
|
39
|
+
ownerTurn: "gate-evaluate",
|
|
40
|
+
question: "What existing promises does this break?",
|
|
41
|
+
guidance: [
|
|
42
|
+
"List which existing requirements (R001, R003, etc.) are touched by this slice.",
|
|
43
|
+
"Identify what must be re-tested after shipping.",
|
|
44
|
+
"Flag decisions that should be revisited given the new scope.",
|
|
45
|
+
"If no existing requirements are affected, return verdict 'omitted'.",
|
|
46
|
+
].join("\n"),
|
|
47
|
+
promptSection: "Broken Promises",
|
|
48
|
+
},
|
|
49
|
+
Q5: {
|
|
50
|
+
id: "Q5",
|
|
51
|
+
scope: "task",
|
|
52
|
+
ownerTurn: "execute-task",
|
|
53
|
+
question: "What breaks when dependencies fail?",
|
|
54
|
+
guidance: [
|
|
55
|
+
"Enumerate the task's external dependencies (APIs, filesystem, network, subprocesses).",
|
|
56
|
+
"Describe the failure path for each: timeout, malformed response, connection loss.",
|
|
57
|
+
"Verify the implementation handles each failure or explicitly bubbles the error.",
|
|
58
|
+
"Return verdict 'omitted' only if the task has no external dependencies.",
|
|
59
|
+
].join("\n"),
|
|
60
|
+
promptSection: "Failure Modes",
|
|
61
|
+
},
|
|
62
|
+
Q6: {
|
|
63
|
+
id: "Q6",
|
|
64
|
+
scope: "task",
|
|
65
|
+
ownerTurn: "execute-task",
|
|
66
|
+
question: "What is the 10x load breakpoint?",
|
|
67
|
+
guidance: [
|
|
68
|
+
"Identify the resource that saturates first at 10x the expected load.",
|
|
69
|
+
"Describe the protection applied (pool sizing, rate limiting, pagination, caching).",
|
|
70
|
+
"Return verdict 'omitted' if the task has no runtime load dimension.",
|
|
71
|
+
].join("\n"),
|
|
72
|
+
promptSection: "Load Profile",
|
|
73
|
+
},
|
|
74
|
+
Q7: {
|
|
75
|
+
id: "Q7",
|
|
76
|
+
scope: "task",
|
|
77
|
+
ownerTurn: "execute-task",
|
|
78
|
+
question: "What negative tests protect this task?",
|
|
79
|
+
guidance: [
|
|
80
|
+
"List malformed inputs, error paths, and boundary conditions the tests cover.",
|
|
81
|
+
"Point to the specific test files or cases that assert each negative scenario.",
|
|
82
|
+
"Return verdict 'omitted' only if the task has no meaningful negative surface.",
|
|
83
|
+
].join("\n"),
|
|
84
|
+
promptSection: "Negative Tests",
|
|
85
|
+
},
|
|
86
|
+
Q8: {
|
|
87
|
+
id: "Q8",
|
|
88
|
+
scope: "slice",
|
|
89
|
+
ownerTurn: "complete-slice",
|
|
90
|
+
question: "How will ops know this slice is healthy or broken?",
|
|
91
|
+
guidance: [
|
|
92
|
+
"Describe the health signal (metric, log line, dashboard) that proves the slice works.",
|
|
93
|
+
"Describe the failure signal that triggers an alert or paging.",
|
|
94
|
+
"Document the recovery procedure and any monitoring gaps.",
|
|
95
|
+
"Return verdict 'omitted' only for slices with no runtime behavior at all.",
|
|
96
|
+
].join("\n"),
|
|
97
|
+
promptSection: "Operational Readiness",
|
|
98
|
+
},
|
|
99
|
+
MV01: {
|
|
100
|
+
id: "MV01",
|
|
101
|
+
scope: "milestone",
|
|
102
|
+
ownerTurn: "validate-milestone",
|
|
103
|
+
question: "Is every success criterion in the milestone roadmap satisfied?",
|
|
104
|
+
guidance: [
|
|
105
|
+
"Walk the success-criteria checklist from the milestone roadmap.",
|
|
106
|
+
"For each criterion, point to the slice / assessment / verification evidence that proves it.",
|
|
107
|
+
"Return verdict 'flag' if any criterion is unmet or unverifiable.",
|
|
108
|
+
].join("\n"),
|
|
109
|
+
promptSection: "Success Criteria Checklist",
|
|
110
|
+
},
|
|
111
|
+
MV02: {
|
|
112
|
+
id: "MV02",
|
|
113
|
+
scope: "milestone",
|
|
114
|
+
ownerTurn: "validate-milestone",
|
|
115
|
+
question: "Does every slice have a SUMMARY.md and a passing assessment?",
|
|
116
|
+
guidance: [
|
|
117
|
+
"Confirm every slice listed in the roadmap has a SUMMARY.md.",
|
|
118
|
+
"Confirm each slice has an ASSESSMENT verdict of 'pass' (or justified 'omitted').",
|
|
119
|
+
"Flag missing artifacts and slices with outstanding follow-ups or known limitations.",
|
|
120
|
+
].join("\n"),
|
|
121
|
+
promptSection: "Slice Delivery Audit",
|
|
122
|
+
},
|
|
123
|
+
MV03: {
|
|
124
|
+
id: "MV03",
|
|
125
|
+
scope: "milestone",
|
|
126
|
+
ownerTurn: "validate-milestone",
|
|
127
|
+
question: "Do the slices integrate end-to-end?",
|
|
128
|
+
guidance: [
|
|
129
|
+
"Trace at least one cross-slice flow proving the pieces compose.",
|
|
130
|
+
"Flag gaps where two slices were built in isolation with no integration evidence.",
|
|
131
|
+
].join("\n"),
|
|
132
|
+
promptSection: "Cross-Slice Integration",
|
|
133
|
+
},
|
|
134
|
+
MV04: {
|
|
135
|
+
id: "MV04",
|
|
136
|
+
scope: "milestone",
|
|
137
|
+
ownerTurn: "validate-milestone",
|
|
138
|
+
question: "Are all touched requirements covered and still coherent?",
|
|
139
|
+
guidance: [
|
|
140
|
+
"For each requirement advanced, validated, surfaced, or invalidated across the milestone's slices, confirm the milestone-level evidence matches.",
|
|
141
|
+
"Flag requirements that slices claim to advance but no artifact proves.",
|
|
142
|
+
].join("\n"),
|
|
143
|
+
promptSection: "Requirement Coverage",
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
/** Stable ordered lists per owner turn — iteration order matches declaration. */
|
|
147
|
+
const ORDERED_GATES = Object.values(GATE_REGISTRY);
|
|
148
|
+
/** Return every gate owned by a turn, in stable declaration order. */
|
|
149
|
+
export function getGatesForTurn(turn) {
|
|
150
|
+
return ORDERED_GATES.filter((g) => g.ownerTurn === turn);
|
|
151
|
+
}
|
|
152
|
+
/** Return the set of gate ids a turn owns. */
|
|
153
|
+
export function getGateIdsForTurn(turn) {
|
|
154
|
+
return new Set(getGatesForTurn(turn).map((g) => g.id));
|
|
155
|
+
}
|
|
156
|
+
/** Look up a definition by gate id, or undefined if unknown. */
|
|
157
|
+
export function getGateDefinition(id) {
|
|
158
|
+
return GATE_REGISTRY[id];
|
|
159
|
+
}
|
|
160
|
+
/** Look up the owner turn for a gate id. Throws if the gate is unknown. */
|
|
161
|
+
export function getOwnerTurn(id) {
|
|
162
|
+
const def = GATE_REGISTRY[id];
|
|
163
|
+
if (!def) {
|
|
164
|
+
throw new GSDError(GSD_PARSE_ERROR, `gate-registry: unknown gate id "${id}"`);
|
|
165
|
+
}
|
|
166
|
+
return def.ownerTurn;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Assert that the pending gate rows for a turn match what the registry says
|
|
170
|
+
* the turn owns. Fails loudly rather than silently skipping.
|
|
171
|
+
*
|
|
172
|
+
* - Every row in `pending` must have a definition whose `ownerTurn` matches `turn`.
|
|
173
|
+
* (The caller is responsible for scoping the pending list — e.g. filtering
|
|
174
|
+
* by slice scope before passing it in.)
|
|
175
|
+
* - `options.requireAll` (default true): every gate the turn owns must appear
|
|
176
|
+
* in `pending`. Set to false for turns like `execute-task` that only need
|
|
177
|
+
* coverage for the subset of gates that were seeded (e.g. tasks with no
|
|
178
|
+
* external dependencies have no Q5 row).
|
|
179
|
+
*/
|
|
180
|
+
export function assertGateCoverage(pending, turn, options = {}) {
|
|
181
|
+
const requireAll = options.requireAll ?? true;
|
|
182
|
+
const expected = getGateIdsForTurn(turn);
|
|
183
|
+
const pendingIds = new Set(pending.map((g) => g.gate_id));
|
|
184
|
+
const unknown = [];
|
|
185
|
+
for (const id of pendingIds) {
|
|
186
|
+
const def = getGateDefinition(id);
|
|
187
|
+
if (!def) {
|
|
188
|
+
unknown.push(id);
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (def.ownerTurn !== turn) {
|
|
192
|
+
unknown.push(`${id} (owned by ${def.ownerTurn}, not ${turn})`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (unknown.length > 0) {
|
|
196
|
+
throw new GSDError(GSD_PARSE_ERROR, `assertGateCoverage: turn "${turn}" received pending gates it does not own: ${unknown.join(", ")}`);
|
|
197
|
+
}
|
|
198
|
+
if (requireAll) {
|
|
199
|
+
const missing = [];
|
|
200
|
+
for (const id of expected) {
|
|
201
|
+
if (!pendingIds.has(id))
|
|
202
|
+
missing.push(id);
|
|
203
|
+
}
|
|
204
|
+
if (missing.length > 0) {
|
|
205
|
+
throw new GSDError(GSD_PARSE_ERROR, `assertGateCoverage: turn "${turn}" is missing required gates: ${missing.join(", ")}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -8,6 +8,7 @@ import { createRequire } from "node:module";
|
|
|
8
8
|
import { existsSync, copyFileSync, mkdirSync, realpathSync } from "node:fs";
|
|
9
9
|
import { dirname } from "node:path";
|
|
10
10
|
import { GSDError, GSD_STALE_STATE } from "./errors.js";
|
|
11
|
+
import { getGateIdsForTurn } from "./gate-registry.js";
|
|
11
12
|
import { logError, logWarning } from "./workflow-logger.js";
|
|
12
13
|
const _require = createRequire(import.meta.url);
|
|
13
14
|
let providerName = null;
|
|
@@ -1927,3 +1928,43 @@ export function getPendingSliceGateCount(milestoneId, sliceId) {
|
|
|
1927
1928
|
WHERE milestone_id = :mid AND slice_id = :sid AND scope = 'slice' AND status = 'pending'`).get({ ":mid": milestoneId, ":sid": sliceId });
|
|
1928
1929
|
return row ? row["cnt"] : 0;
|
|
1929
1930
|
}
|
|
1931
|
+
/**
|
|
1932
|
+
* Return pending gate rows owned by a specific workflow turn.
|
|
1933
|
+
*
|
|
1934
|
+
* Unlike `getPendingGates(..., scope)`, this filters by the registry's
|
|
1935
|
+
* `ownerTurn` metadata so callers can distinguish Q3/Q4 (owned by
|
|
1936
|
+
* gate-evaluate) from Q8 (owned by complete-slice) even though both are
|
|
1937
|
+
* scope:"slice". Pass `taskId` to narrow task-scoped results to one task.
|
|
1938
|
+
*/
|
|
1939
|
+
export function getPendingGatesForTurn(milestoneId, sliceId, turn, taskId) {
|
|
1940
|
+
if (!currentDb)
|
|
1941
|
+
return [];
|
|
1942
|
+
const ids = getGateIdsForTurn(turn);
|
|
1943
|
+
if (ids.size === 0)
|
|
1944
|
+
return [];
|
|
1945
|
+
const idList = [...ids];
|
|
1946
|
+
const placeholders = idList.map((_, i) => `:gid${i}`).join(",");
|
|
1947
|
+
const params = {
|
|
1948
|
+
":mid": milestoneId,
|
|
1949
|
+
":sid": sliceId,
|
|
1950
|
+
};
|
|
1951
|
+
idList.forEach((id, i) => {
|
|
1952
|
+
params[`:gid${i}`] = id;
|
|
1953
|
+
});
|
|
1954
|
+
let sql = `SELECT * FROM quality_gates
|
|
1955
|
+
WHERE milestone_id = :mid AND slice_id = :sid
|
|
1956
|
+
AND status = 'pending'
|
|
1957
|
+
AND gate_id IN (${placeholders})`;
|
|
1958
|
+
if (taskId !== undefined) {
|
|
1959
|
+
sql += ` AND task_id = :tid`;
|
|
1960
|
+
params[":tid"] = taskId;
|
|
1961
|
+
}
|
|
1962
|
+
return currentDb.prepare(sql).all(params).map(rowToGate);
|
|
1963
|
+
}
|
|
1964
|
+
/**
|
|
1965
|
+
* Count pending gates for a turn. Convenience wrapper used by state
|
|
1966
|
+
* derivation to decide whether a phase transition should pause.
|
|
1967
|
+
*/
|
|
1968
|
+
export function getPendingGateCountForTurn(milestoneId, sliceId, turn) {
|
|
1969
|
+
return getPendingGatesForTurn(milestoneId, sliceId, turn).length;
|
|
1970
|
+
}
|
|
@@ -13,7 +13,7 @@ import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
|
|
|
13
13
|
import { buildSkillActivationBlock } from "./auto-prompts.js";
|
|
14
14
|
import { deriveState } from "./state.js";
|
|
15
15
|
import { invalidateAllCaches } from "./cache.js";
|
|
16
|
-
import {
|
|
16
|
+
import { startAutoDetached } from "./auto.js";
|
|
17
17
|
import { clearLock } from "./crash-recovery.js";
|
|
18
18
|
import { assessInterruptedSession, formatInterruptedSessionRunningMessage, formatInterruptedSessionSummary, } from "./interrupted-session.js";
|
|
19
19
|
import { listUnitRuntimeRecords, clearUnitRuntimeRecord } from "./unit-runtime.js";
|
|
@@ -40,7 +40,6 @@ import { runPreparation, formatCodebaseBrief, formatPriorContextBrief, } from ".
|
|
|
40
40
|
// ─── Re-exports (preserve public API for existing importers) ────────────────
|
|
41
41
|
export { MILESTONE_ID_RE, generateMilestoneSuffix, nextMilestoneId, extractMilestoneSeq, parseMilestoneId, milestoneIdSort, maxMilestoneNum, findMilestoneIds, reserveMilestoneId, claimReservedId, getReservedMilestoneIds, clearReservedMilestoneIds, } from "./milestone-ids.js";
|
|
42
42
|
export { showQueue, handleQueueReorder, showQueueAdd, buildExistingMilestonesContext, } from "./guided-flow-queue.js";
|
|
43
|
-
import { getErrorMessage } from "./error-utils.js";
|
|
44
43
|
import { logWarning } from "./workflow-logger.js";
|
|
45
44
|
// ─── ID Generation with Reservation ─────────────────────────────────────────
|
|
46
45
|
/**
|
|
@@ -200,11 +199,7 @@ export function checkAutoStartAfterDiscuss() {
|
|
|
200
199
|
}
|
|
201
200
|
pendingAutoStartMap.delete(basePath);
|
|
202
201
|
ctx.ui.notify(`Milestone ${milestoneId} ready.`, "info");
|
|
203
|
-
|
|
204
|
-
ctx.ui.notify(`Auto-start failed: ${getErrorMessage(err)}`, "error");
|
|
205
|
-
logWarning("guided", `auto start error: ${getErrorMessage(err)}`);
|
|
206
|
-
debugLog("auto-start-failed", { error: getErrorMessage(err) });
|
|
207
|
-
});
|
|
202
|
+
startAutoDetached(ctx, pi, basePath, false, { step });
|
|
208
203
|
return true;
|
|
209
204
|
}
|
|
210
205
|
/**
|
|
@@ -334,8 +329,9 @@ function resolveAvailableModel(modelId, availableModels, currentProvider) {
|
|
|
334
329
|
* Build the discuss-and-plan prompt for a new milestone.
|
|
335
330
|
* Used by all three "new milestone" paths (first ever, no active, all complete).
|
|
336
331
|
*/
|
|
337
|
-
function buildDiscussPrompt(nextId, preamble, _basePath, preparationContext) {
|
|
332
|
+
function buildDiscussPrompt(nextId, preamble, _basePath, pi, ctx, preparationContext) {
|
|
338
333
|
const milestoneRel = `.gsd/milestones/${nextId}`;
|
|
334
|
+
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
339
335
|
const inlinedTemplates = [
|
|
340
336
|
inlineTemplate("project", "Project"),
|
|
341
337
|
inlineTemplate("requirements", "Requirements"),
|
|
@@ -347,6 +343,7 @@ function buildDiscussPrompt(nextId, preamble, _basePath, preparationContext) {
|
|
|
347
343
|
milestoneId: nextId,
|
|
348
344
|
preamble,
|
|
349
345
|
preparationContext: preparationContext ?? "",
|
|
346
|
+
structuredQuestionsAvailable,
|
|
350
347
|
contextPath: `${milestoneRel}/${nextId}-CONTEXT.md`,
|
|
351
348
|
roadmapPath: `${milestoneRel}/${nextId}-ROADMAP.md`,
|
|
352
349
|
inlinedTemplates,
|
|
@@ -390,7 +387,7 @@ function buildHeadlessDiscussPrompt(nextId, seedContext, _basePath) {
|
|
|
390
387
|
* @param basePath - Root directory of the project
|
|
391
388
|
* @returns The discuss prompt string
|
|
392
389
|
*/
|
|
393
|
-
async function prepareAndBuildDiscussPrompt(ctx, nextId, preamble, basePath) {
|
|
390
|
+
async function prepareAndBuildDiscussPrompt(ctx, pi, nextId, preamble, basePath) {
|
|
394
391
|
const prefs = loadEffectiveGSDPreferences()?.preferences ?? {};
|
|
395
392
|
// Run preparation if enabled (default: true) — results are injected as
|
|
396
393
|
// supplementary context into the standard discuss prompt, NOT as a
|
|
@@ -421,7 +418,7 @@ async function prepareAndBuildDiscussPrompt(ctx, nextId, preamble, basePath) {
|
|
|
421
418
|
logWarning("guided", `preparation failed, proceeding without context: ${err.message}`);
|
|
422
419
|
}
|
|
423
420
|
}
|
|
424
|
-
return buildDiscussPrompt(nextId, preamble, basePath, preparationContext);
|
|
421
|
+
return buildDiscussPrompt(nextId, preamble, basePath, pi, ctx, preparationContext);
|
|
425
422
|
}
|
|
426
423
|
/**
|
|
427
424
|
* Bootstrap a .gsd/ project from scratch for headless use.
|
|
@@ -638,7 +635,7 @@ export async function showDiscuss(ctx, pi, basePath) {
|
|
|
638
635
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
639
636
|
const nextId = nextMilestoneIdReserved(milestoneIds, uniqueMilestoneIds);
|
|
640
637
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: false, createdAt: Date.now() });
|
|
641
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
638
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
642
639
|
}
|
|
643
640
|
return;
|
|
644
641
|
}
|
|
@@ -994,7 +991,7 @@ async function handleMilestoneActions(ctx, pi, basePath, milestoneId, milestoneT
|
|
|
994
991
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
995
992
|
const nextId = nextMilestoneIdReserved(milestoneIds, uniqueMilestoneIds);
|
|
996
993
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode, createdAt: Date.now() });
|
|
997
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
994
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
998
995
|
return true;
|
|
999
996
|
}
|
|
1000
997
|
// "back" or null
|
|
@@ -1095,7 +1092,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1095
1092
|
],
|
|
1096
1093
|
});
|
|
1097
1094
|
if (resume === "resume") {
|
|
1098
|
-
|
|
1095
|
+
startAutoDetached(ctx, pi, basePath, false, {
|
|
1099
1096
|
interrupted,
|
|
1100
1097
|
step: interrupted.pausedSession?.stepMode ?? false,
|
|
1101
1098
|
});
|
|
@@ -1161,7 +1158,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1161
1158
|
if (isFirst) {
|
|
1162
1159
|
// First ever — skip wizard, just ask directly
|
|
1163
1160
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode, createdAt: Date.now() });
|
|
1164
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId, `New project, milestone ${nextId}. Do NOT read or explore .gsd/ — it's empty scaffolding.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
1161
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId, `New project, milestone ${nextId}. Do NOT read or explore .gsd/ — it's empty scaffolding.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
1165
1162
|
}
|
|
1166
1163
|
else {
|
|
1167
1164
|
const choice = await showNextAction(ctx, {
|
|
@@ -1179,7 +1176,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1179
1176
|
});
|
|
1180
1177
|
if (choice === "new_milestone") {
|
|
1181
1178
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode, createdAt: Date.now() });
|
|
1182
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
1179
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
1183
1180
|
}
|
|
1184
1181
|
}
|
|
1185
1182
|
return;
|
|
@@ -1211,7 +1208,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1211
1208
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
1212
1209
|
const nextId = nextMilestoneIdReserved(milestoneIds, uniqueMilestoneIds);
|
|
1213
1210
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode, createdAt: Date.now() });
|
|
1214
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
1211
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
1215
1212
|
}
|
|
1216
1213
|
else if (choice === "status") {
|
|
1217
1214
|
const { fireStatusViaCommand } = await import("./commands.js");
|
|
@@ -1275,7 +1272,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1275
1272
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
1276
1273
|
const nextId = nextMilestoneIdReserved(milestoneIds, uniqueMilestoneIds);
|
|
1277
1274
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode, createdAt: Date.now() });
|
|
1278
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
1275
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
1279
1276
|
}
|
|
1280
1277
|
return;
|
|
1281
1278
|
}
|
|
@@ -1365,7 +1362,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1365
1362
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
1366
1363
|
const nextId = nextMilestoneIdReserved(milestoneIds, uniqueMilestoneIds);
|
|
1367
1364
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode, createdAt: Date.now() });
|
|
1368
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
1365
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
1369
1366
|
}
|
|
1370
1367
|
else if (choice === "discard_milestone") {
|
|
1371
1368
|
const confirmed = await showConfirm(ctx, {
|
|
@@ -1407,7 +1404,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1407
1404
|
notYetMessage: "Run /gsd status for details.",
|
|
1408
1405
|
});
|
|
1409
1406
|
if (choice === "auto") {
|
|
1410
|
-
|
|
1407
|
+
startAutoDetached(ctx, pi, basePath, false);
|
|
1411
1408
|
}
|
|
1412
1409
|
else if (choice === "status") {
|
|
1413
1410
|
const { fireStatusViaCommand } = await import("./commands.js");
|
|
@@ -1620,7 +1617,7 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1620
1617
|
notYetMessage: "Run /gsd when ready.",
|
|
1621
1618
|
});
|
|
1622
1619
|
if (choice === "auto") {
|
|
1623
|
-
|
|
1620
|
+
startAutoDetached(ctx, pi, basePath, false);
|
|
1624
1621
|
return;
|
|
1625
1622
|
}
|
|
1626
1623
|
if (choice === "execute") {
|
|
@@ -225,17 +225,9 @@ export async function showProjectInit(ctx, pi, basePath, detection) {
|
|
|
225
225
|
catch {
|
|
226
226
|
// Non-fatal — STATE.md will be regenerated on next /gsd invocation
|
|
227
227
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const result = ensureProjectWorkflowMcpConfig(basePath);
|
|
232
|
-
if (result.status !== "unchanged") {
|
|
233
|
-
ctx.ui.notify(`Claude Code MCP prepared at ${result.configPath}`, "info");
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
catch (err) {
|
|
237
|
-
ctx.ui.notify(`Claude Code MCP prep failed: ${err instanceof Error ? err.message : String(err)}`, "warning");
|
|
238
|
-
}
|
|
228
|
+
{
|
|
229
|
+
const { prepareWorkflowMcpForProject } = await import("./workflow-mcp-auto-prep.js");
|
|
230
|
+
prepareWorkflowMcpForProject(ctx, basePath);
|
|
239
231
|
}
|
|
240
232
|
ctx.ui.notify("GSD initialized. Starting your first milestone...", "info");
|
|
241
233
|
return { completed: true, bootstrapped: true };
|
|
@@ -15,7 +15,7 @@ import { join } from "node:path";
|
|
|
15
15
|
import { resolveMilestonePath, resolveMilestoneFile, buildMilestoneFileName, } from "./paths.js";
|
|
16
16
|
import { invalidateAllCaches } from "./cache.js";
|
|
17
17
|
import { loadQueueOrder, saveQueueOrder } from "./queue-order.js";
|
|
18
|
-
import { isDbAvailable, updateMilestoneStatus } from "./gsd-db.js";
|
|
18
|
+
import { getMilestone, isDbAvailable, updateMilestoneStatus } from "./gsd-db.js";
|
|
19
19
|
import { logWarning } from "./workflow-logger.js";
|
|
20
20
|
// ─── Park ──────────────────────────────────────────────────────────────────
|
|
21
21
|
/**
|
|
@@ -68,9 +68,15 @@ export function unparkMilestone(basePath, milestoneId) {
|
|
|
68
68
|
if (!mDir || !existsSync(mDir))
|
|
69
69
|
return false;
|
|
70
70
|
const parkedPath = join(mDir, buildMilestoneFileName(milestoneId, "PARKED"));
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
const hadParkedFile = existsSync(parkedPath);
|
|
72
|
+
const dbThinksParked = isDbAvailable() && getMilestone(milestoneId)?.status === "parked";
|
|
73
|
+
// Recover the reverse desync too: DB can still say "parked" even when the
|
|
74
|
+
// PARKED marker was lost on disk, and /gsd unpark should repair that state.
|
|
75
|
+
if (!hadParkedFile && !dbThinksParked)
|
|
76
|
+
return false;
|
|
77
|
+
if (hadParkedFile) {
|
|
78
|
+
unlinkSync(parkedPath);
|
|
79
|
+
}
|
|
74
80
|
// Sync DB status so deriveStateFromDb picks up the unparked milestone (#2694)
|
|
75
81
|
if (isDbAvailable()) {
|
|
76
82
|
try {
|
|
@@ -6,17 +6,12 @@
|
|
|
6
6
|
* records in the DB. This module inserts milestone-level validation gates
|
|
7
7
|
* that correspond to the validation checks performed.
|
|
8
8
|
*
|
|
9
|
-
* Gate IDs for milestone validation
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* MV03 — Cross-slice integration
|
|
13
|
-
* MV04 — Requirement coverage
|
|
14
|
-
*
|
|
15
|
-
* These use the existing quality_gates table with scope "milestone".
|
|
9
|
+
* Gate IDs for milestone validation (MV01–MV04) are sourced from the
|
|
10
|
+
* gate registry so the definitions stay in lockstep with prompt builders,
|
|
11
|
+
* dispatch rules, and state derivation. See gate-registry.ts.
|
|
16
12
|
*/
|
|
17
13
|
import { _getAdapter } from "./gsd-db.js";
|
|
18
|
-
|
|
19
|
-
const MILESTONE_GATE_IDS = ["MV01", "MV02", "MV03", "MV04"];
|
|
14
|
+
import { getGatesForTurn } from "./gate-registry.js";
|
|
20
15
|
/**
|
|
21
16
|
* Insert milestone-level quality_gates records for a validation run.
|
|
22
17
|
*
|
|
@@ -24,21 +19,25 @@ const MILESTONE_GATE_IDS = ["MV01", "MV02", "MV03", "MV04"];
|
|
|
24
19
|
* from the overall milestone validation verdict. Individual gate-level
|
|
25
20
|
* verdicts are not available (the handler receives a single verdict),
|
|
26
21
|
* so all gates share the overall verdict.
|
|
22
|
+
*
|
|
23
|
+
* Gate IDs come from the registry — adding/removing an MV-scoped gate
|
|
24
|
+
* in gate-registry.ts automatically flows through here.
|
|
27
25
|
*/
|
|
28
26
|
export function insertMilestoneValidationGates(milestoneId, sliceId, verdict, evaluatedAt) {
|
|
29
27
|
const db = _getAdapter();
|
|
30
28
|
if (!db)
|
|
31
29
|
return;
|
|
32
30
|
const gateVerdict = verdict === "pass" ? "pass" : "flag";
|
|
33
|
-
|
|
31
|
+
const milestoneGates = getGatesForTurn("validate-milestone");
|
|
32
|
+
for (const def of milestoneGates) {
|
|
34
33
|
db.prepare(`INSERT OR REPLACE INTO quality_gates
|
|
35
34
|
(milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at)
|
|
36
35
|
VALUES (:mid, :sid, :gid, 'milestone', '', 'complete', :verdict, :rationale, '', :evaluated_at)`).run({
|
|
37
36
|
":mid": milestoneId,
|
|
38
37
|
":sid": sliceId,
|
|
39
|
-
":gid":
|
|
38
|
+
":gid": def.id,
|
|
40
39
|
":verdict": gateVerdict,
|
|
41
|
-
":rationale":
|
|
40
|
+
":rationale": `${def.promptSection} — milestone validation verdict: ${verdict}`,
|
|
42
41
|
":evaluated_at": evaluatedAt,
|
|
43
42
|
});
|
|
44
43
|
}
|