gsd-pi 2.48.0 → 2.49.0-dev.9e177e9
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/headless-ui.js +12 -2
- package/dist/headless.js +29 -13
- package/dist/resources/extensions/gsd/auto/infra-errors.js +1 -0
- package/dist/resources/extensions/gsd/auto/phases.js +11 -11
- package/dist/resources/extensions/gsd/auto/resolve.js +2 -2
- package/dist/resources/extensions/gsd/auto/run-unit.js +2 -2
- package/dist/resources/extensions/gsd/auto/session.js +4 -0
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +8 -10
- package/dist/resources/extensions/gsd/auto-dashboard.js +6 -3
- package/dist/resources/extensions/gsd/auto-dispatch.js +34 -7
- package/dist/resources/extensions/gsd/auto-post-unit.js +34 -27
- package/dist/resources/extensions/gsd/auto-prompts.js +102 -21
- package/dist/resources/extensions/gsd/auto-recovery.js +62 -184
- package/dist/resources/extensions/gsd/auto-start.js +4 -31
- package/dist/resources/extensions/gsd/auto-timers.js +2 -2
- package/dist/resources/extensions/gsd/auto-verification.js +4 -7
- package/dist/resources/extensions/gsd/auto-worktree.js +262 -115
- package/dist/resources/extensions/gsd/auto.js +7 -5
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +89 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +8 -1
- package/dist/resources/extensions/gsd/branch-patterns.js +13 -0
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +43 -3
- package/dist/resources/extensions/gsd/doctor-checks.js +5 -1234
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +168 -0
- package/dist/resources/extensions/gsd/doctor-environment.js +28 -7
- package/dist/resources/extensions/gsd/doctor-git-checks.js +405 -0
- package/dist/resources/extensions/gsd/doctor-global-checks.js +74 -0
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +600 -0
- package/dist/resources/extensions/gsd/doctor.js +9 -1
- package/dist/resources/extensions/gsd/extension-manifest.json +1 -1
- package/dist/resources/extensions/gsd/git-service.js +20 -20
- package/dist/resources/extensions/gsd/gsd-db.js +124 -1
- package/dist/resources/extensions/gsd/guided-flow-queue.js +10 -11
- package/dist/resources/extensions/gsd/markdown-renderer.js +33 -5
- package/dist/resources/extensions/gsd/preferences-types.js +2 -1
- package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +27 -8
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +9 -8
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +223 -56
- package/dist/resources/extensions/gsd/prompts/execute-task.md +16 -13
- package/dist/resources/extensions/gsd/prompts/forensics.md +12 -5
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +32 -0
- package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +8 -3
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +3 -0
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +4 -4
- package/dist/resources/extensions/gsd/repo-identity.js +29 -0
- package/dist/resources/extensions/gsd/roadmap-slices.js +2 -2
- package/dist/resources/extensions/gsd/session-forensics.js +6 -11
- package/dist/resources/extensions/gsd/session-lock.js +67 -56
- package/dist/resources/extensions/gsd/state.js +34 -7
- package/dist/resources/extensions/gsd/templates/milestone-summary.md +8 -0
- package/dist/resources/extensions/gsd/templates/plan.md +16 -0
- package/dist/resources/extensions/gsd/templates/roadmap.md +13 -0
- package/dist/resources/extensions/gsd/templates/slice-summary.md +9 -0
- package/dist/resources/extensions/gsd/templates/task-plan.md +24 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -1
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +3 -3
- package/dist/resources/extensions/gsd/verdict-parser.js +84 -0
- package/dist/resources/extensions/gsd/worktree-command.js +1 -1
- package/dist/resources/extensions/gsd/worktree-resolver.js +24 -0
- package/dist/resources/extensions/gsd/worktree.js +3 -2
- package/dist/resources/extensions/remote-questions/config.js +3 -5
- package/dist/resources/extensions/search-the-web/native-search.js +8 -3
- package/dist/resources/extensions/search-the-web/tool-search.js +19 -2
- package/dist/resources/skills/github-workflows/references/gh/SKILL.md +22 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
- package/dist/web/standalone/.next/build-manifest.json +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 +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
- package/dist/web/standalone/.next/server/chunks/229.js +2 -2
- package/dist/web/standalone/.next/server/chunks/471.js +3 -3
- 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 +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/4024.7c75ac378de0f2b5.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-6654a8cca61a3d1c.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-0a4cd455ec4197d2.js → webpack-2473ce2c3879fff4.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/dist/worktree-cli.js +1 -1
- package/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +4 -1
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.ts +4 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +39 -10
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/src/providers/openai-codex-responses.ts +39 -8
- package/packages/pi-coding-agent/dist/core/blob-store.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/blob-store.js +8 -3
- package/packages/pi-coding-agent/dist/core/blob-store.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/discovery-cache.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/discovery-cache.js +9 -2
- package/packages/pi-coding-agent/dist/core/discovery-cache.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.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 +7 -32
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/jsonl.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/jsonl.js +5 -0
- package/packages/pi-coding-agent/dist/modes/rpc/jsonl.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js +0 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.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/package.json +1 -1
- package/packages/pi-coding-agent/src/core/blob-store.ts +6 -3
- package/packages/pi-coding-agent/src/core/discovery-cache.ts +9 -2
- package/packages/pi-coding-agent/src/core/retry-handler.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +7 -32
- package/packages/pi-coding-agent/src/modes/rpc/jsonl.ts +6 -0
- package/packages/pi-coding-agent/src/modes/rpc/rpc-client.ts +0 -2
- package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/github-sync/tests/commit-linking.test.ts +8 -4
- package/src/resources/extensions/gsd/auto/infra-errors.ts +1 -0
- package/src/resources/extensions/gsd/auto/phases.ts +10 -11
- package/src/resources/extensions/gsd/auto/resolve.ts +3 -3
- package/src/resources/extensions/gsd/auto/run-unit.ts +2 -2
- package/src/resources/extensions/gsd/auto/session.ts +5 -0
- package/src/resources/extensions/gsd/auto/types.ts +13 -0
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +19 -21
- package/src/resources/extensions/gsd/auto-dashboard.ts +5 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +40 -5
- package/src/resources/extensions/gsd/auto-loop.ts +1 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +36 -31
- package/src/resources/extensions/gsd/auto-prompts.ts +113 -19
- package/src/resources/extensions/gsd/auto-recovery.ts +65 -199
- package/src/resources/extensions/gsd/auto-start.ts +7 -27
- package/src/resources/extensions/gsd/auto-timers.ts +2 -2
- package/src/resources/extensions/gsd/auto-verification.ts +4 -7
- package/src/resources/extensions/gsd/auto-worktree.ts +309 -110
- package/src/resources/extensions/gsd/auto.ts +11 -10
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +93 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +8 -0
- package/src/resources/extensions/gsd/branch-patterns.ts +16 -0
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +46 -3
- package/src/resources/extensions/gsd/doctor-checks.ts +5 -1291
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +182 -0
- package/src/resources/extensions/gsd/doctor-environment.ts +30 -7
- package/src/resources/extensions/gsd/doctor-git-checks.ts +415 -0
- package/src/resources/extensions/gsd/doctor-global-checks.ts +84 -0
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +626 -0
- package/src/resources/extensions/gsd/doctor.ts +9 -1
- package/src/resources/extensions/gsd/extension-manifest.json +1 -1
- package/src/resources/extensions/gsd/git-service.ts +19 -26
- package/src/resources/extensions/gsd/gsd-db.ts +150 -2
- package/src/resources/extensions/gsd/guided-flow-queue.ts +11 -12
- package/src/resources/extensions/gsd/markdown-renderer.ts +37 -4
- package/src/resources/extensions/gsd/preferences-types.ts +5 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +37 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +27 -8
- package/src/resources/extensions/gsd/prompts/complete-slice.md +9 -8
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +223 -56
- package/src/resources/extensions/gsd/prompts/execute-task.md +16 -13
- package/src/resources/extensions/gsd/prompts/forensics.md +12 -5
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +32 -0
- package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +8 -3
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +3 -0
- package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +4 -4
- package/src/resources/extensions/gsd/repo-identity.ts +28 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +2 -2
- package/src/resources/extensions/gsd/session-forensics.ts +6 -11
- package/src/resources/extensions/gsd/session-lock.ts +92 -64
- package/src/resources/extensions/gsd/state.ts +38 -5
- package/src/resources/extensions/gsd/templates/milestone-summary.md +8 -0
- package/src/resources/extensions/gsd/templates/plan.md +16 -0
- package/src/resources/extensions/gsd/templates/roadmap.md +13 -0
- package/src/resources/extensions/gsd/templates/slice-summary.md +9 -0
- package/src/resources/extensions/gsd/templates/task-plan.md +24 -0
- package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +1 -81
- package/src/resources/extensions/gsd/tests/auto-stash-merge.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +14 -12
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +9 -12
- package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +115 -1
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +65 -1
- package/src/resources/extensions/gsd/tests/doctor-git.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +189 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/git-service.test.ts +68 -9
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/parallel-merge.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/quality-gates.test.ts +347 -0
- package/src/resources/extensions/gsd/tests/queue-completed-milestone-perf.test.ts +155 -0
- package/src/resources/extensions/gsd/tests/replan-slice.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +87 -15
- package/src/resources/extensions/gsd/tests/session-lock-transient-read.test.ts +223 -0
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +44 -4
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +0 -16
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +204 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +16 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +3 -3
- package/src/resources/extensions/gsd/types.ts +30 -0
- package/src/resources/extensions/gsd/verdict-parser.ts +95 -0
- package/src/resources/extensions/gsd/verification-gate.ts +0 -2
- package/src/resources/extensions/gsd/worktree-command.ts +1 -1
- package/src/resources/extensions/gsd/worktree-resolver.ts +31 -0
- package/src/resources/extensions/gsd/worktree.ts +3 -2
- package/src/resources/extensions/remote-questions/config.ts +3 -5
- package/src/resources/extensions/search-the-web/native-search.ts +8 -3
- package/src/resources/extensions/search-the-web/tool-search.ts +22 -2
- package/src/resources/skills/github-workflows/references/gh/SKILL.md +22 -1
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +0 -191
- package/dist/resources/extensions/gsd/resource-version.js +0 -97
- package/dist/web/standalone/.next/static/chunks/4024.11ca5c01938e5948.js +0 -9
- package/dist/web/standalone/.next/static/chunks/app/page-12dd5ece0df4badc.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/src/resources/extensions/gsd/auto-worktree-sync.ts +0 -234
- package/src/resources/extensions/gsd/resource-version.ts +0 -101
- /package/dist/web/standalone/.next/static/{zGWUKFTfjCQerNgsPpAbF → vNN0h0emdEi8l_npi8poE}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{zGWUKFTfjCQerNgsPpAbF → vNN0h0emdEi8l_npi8poE}/_ssgManifest.js +0 -0
|
@@ -18,8 +18,8 @@ import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
|
18
18
|
|
|
19
19
|
import {
|
|
20
20
|
detectWorktreeName,
|
|
21
|
-
SLICE_BRANCH_RE,
|
|
22
21
|
} from "./worktree.js";
|
|
22
|
+
import { SLICE_BRANCH_RE, QUICK_BRANCH_RE, WORKFLOW_BRANCH_RE } from "./branch-patterns.js";
|
|
23
23
|
import {
|
|
24
24
|
nativeGetCurrentBranch,
|
|
25
25
|
nativeDetectMainBranch,
|
|
@@ -102,23 +102,25 @@ export interface TaskCommitContext {
|
|
|
102
102
|
|
|
103
103
|
/**
|
|
104
104
|
* Build a meaningful conventional commit message from task execution context.
|
|
105
|
-
* Format: `{type}
|
|
105
|
+
* Format: `{type}: {description}` (clean conventional commit — no GSD IDs in subject).
|
|
106
|
+
*
|
|
107
|
+
* GSD metadata is placed in a `GSD-Task:` git trailer at the end of the body,
|
|
108
|
+
* following the same convention as `Signed-off-by:` or `Co-Authored-By:`.
|
|
106
109
|
*
|
|
107
110
|
* The description is the task summary one-liner if available (it describes
|
|
108
111
|
* what was actually built), falling back to the task title (what was planned).
|
|
109
112
|
*/
|
|
110
113
|
export function buildTaskCommitMessage(ctx: TaskCommitContext): string {
|
|
111
|
-
const scope = ctx.taskId; // e.g. "S01/T02" or just "T02"
|
|
112
114
|
const description = ctx.oneLiner || ctx.taskTitle;
|
|
113
115
|
const type = inferCommitType(ctx.taskTitle, ctx.oneLiner);
|
|
114
116
|
|
|
115
|
-
// Truncate description to ~72 chars for subject line
|
|
116
|
-
const maxDescLen =
|
|
117
|
+
// Truncate description to ~72 chars for subject line (full budget without scope)
|
|
118
|
+
const maxDescLen = 70 - type.length;
|
|
117
119
|
const truncated = description.length > maxDescLen
|
|
118
120
|
? description.slice(0, maxDescLen - 1).trimEnd() + "…"
|
|
119
121
|
: description;
|
|
120
122
|
|
|
121
|
-
const subject = `${type}
|
|
123
|
+
const subject = `${type}: ${truncated}`;
|
|
122
124
|
|
|
123
125
|
// Build body with key files if available
|
|
124
126
|
const bodyParts: string[] = [];
|
|
@@ -131,15 +133,14 @@ export function buildTaskCommitMessage(ctx: TaskCommitContext): string {
|
|
|
131
133
|
bodyParts.push(fileLines);
|
|
132
134
|
}
|
|
133
135
|
|
|
136
|
+
// Trailers: GSD-Task first, then Resolves
|
|
137
|
+
bodyParts.push(`GSD-Task: ${ctx.taskId}`);
|
|
138
|
+
|
|
134
139
|
if (ctx.issueNumber) {
|
|
135
140
|
bodyParts.push(`Resolves #${ctx.issueNumber}`);
|
|
136
141
|
}
|
|
137
142
|
|
|
138
|
-
|
|
139
|
-
return `${subject}\n\n${bodyParts.join("\n\n")}`;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return subject;
|
|
143
|
+
return `${subject}\n\n${bodyParts.join("\n\n")}`;
|
|
143
144
|
}
|
|
144
145
|
|
|
145
146
|
/**
|
|
@@ -242,8 +243,8 @@ export function readIntegrationBranch(basePath: string, milestoneId: string): st
|
|
|
242
243
|
*
|
|
243
244
|
* The file is committed immediately so the metadata is persisted in git.
|
|
244
245
|
*/
|
|
245
|
-
/**
|
|
246
|
-
export
|
|
246
|
+
/** Re-export for backward compatibility — canonical definitions in branch-patterns.ts */
|
|
247
|
+
export { QUICK_BRANCH_RE, WORKFLOW_BRANCH_RE } from "./branch-patterns.js";
|
|
247
248
|
|
|
248
249
|
export function writeIntegrationBranch(
|
|
249
250
|
basePath: string,
|
|
@@ -256,6 +257,10 @@ export function writeIntegrationBranch(
|
|
|
256
257
|
// to their origin branch on completion. Recording one as the integration
|
|
257
258
|
// target causes milestone merges to land on the wrong branch (#1293).
|
|
258
259
|
if (QUICK_BRANCH_RE.test(branch)) return;
|
|
260
|
+
// Don't record workflow-template branches (hotfix, bugfix, spike, etc.) —
|
|
261
|
+
// same root cause as quick-task branches (#2498). All templates create
|
|
262
|
+
// gsd/<templateId>/<slug> branches that are ephemeral.
|
|
263
|
+
if (WORKFLOW_BRANCH_RE.test(branch)) return;
|
|
259
264
|
// Validate
|
|
260
265
|
if (!VALID_BRANCH_NAME.test(branch)) return;
|
|
261
266
|
// Skip if already recorded with the same branch (idempotent across restarts).
|
|
@@ -440,11 +445,6 @@ export class GitServiceImpl {
|
|
|
440
445
|
this._milestoneId = milestoneId;
|
|
441
446
|
}
|
|
442
447
|
|
|
443
|
-
/** Convenience wrapper: run git in this repo's basePath. */
|
|
444
|
-
private git(args: string[], options: { allowFailure?: boolean; input?: string } = {}): string {
|
|
445
|
-
return runGit(this.basePath, args, options);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
448
|
/**
|
|
449
449
|
* Smart staging: `git add -A` excluding GSD runtime paths via pathspec.
|
|
450
450
|
* Falls back to plain `git add -A` if the exclusion pathspec fails.
|
|
@@ -538,7 +538,7 @@ export class GitServiceImpl {
|
|
|
538
538
|
|
|
539
539
|
const message = taskContext
|
|
540
540
|
? buildTaskCommitMessage(taskContext)
|
|
541
|
-
: `chore
|
|
541
|
+
: `chore: auto-commit after ${unitType}\n\nGSD-Unit: ${unitId}`;
|
|
542
542
|
nativeCommit(this.basePath, message, { allowEmpty: false });
|
|
543
543
|
return message;
|
|
544
544
|
}
|
|
@@ -603,11 +603,6 @@ export class GitServiceImpl {
|
|
|
603
603
|
return nativeGetCurrentBranch(this.basePath);
|
|
604
604
|
}
|
|
605
605
|
|
|
606
|
-
/** True if currently on a GSD slice branch. */
|
|
607
|
-
// ─── Branch Lifecycle ──────────────────────────────────────────────────
|
|
608
|
-
|
|
609
|
-
// ─── S05 Features ─────────────────────────────────────────────────────
|
|
610
|
-
|
|
611
606
|
/**
|
|
612
607
|
* Create a snapshot ref for the given label (typically a slice branch name).
|
|
613
608
|
* Gated on prefs.snapshots === true. Ref path: refs/gsd/snapshots/<label>/<timestamp>
|
|
@@ -668,8 +663,6 @@ export class GitServiceImpl {
|
|
|
668
663
|
}
|
|
669
664
|
}
|
|
670
665
|
|
|
671
|
-
// ─── Merge ─────────────────────────────────────────────────────────────
|
|
672
|
-
|
|
673
666
|
}
|
|
674
667
|
|
|
675
668
|
// ─── Draft PR Creation ─────────────────────────────────────────────────────
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { createRequire } from "node:module";
|
|
9
9
|
import { existsSync, copyFileSync, mkdirSync } from "node:fs";
|
|
10
10
|
import { dirname } from "node:path";
|
|
11
|
-
import type { Decision, Requirement } from "./types.js";
|
|
11
|
+
import type { Decision, Requirement, GateRow, GateId, GateScope, GateStatus, GateVerdict } from "./types.js";
|
|
12
12
|
import { GSDError, GSD_STALE_STATE } from "./errors.js";
|
|
13
13
|
|
|
14
14
|
const _require = createRequire(import.meta.url);
|
|
@@ -149,7 +149,7 @@ function openRawDb(path: string): unknown {
|
|
|
149
149
|
return new Database(path);
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
const SCHEMA_VERSION =
|
|
152
|
+
const SCHEMA_VERSION = 12;
|
|
153
153
|
|
|
154
154
|
function initSchema(db: DbAdapter, fileBacked: boolean): void {
|
|
155
155
|
if (fileBacked) db.exec("PRAGMA journal_mode=WAL");
|
|
@@ -355,6 +355,23 @@ function initSchema(db: DbAdapter, fileBacked: boolean): void {
|
|
|
355
355
|
)
|
|
356
356
|
`);
|
|
357
357
|
|
|
358
|
+
db.exec(`
|
|
359
|
+
CREATE TABLE IF NOT EXISTS quality_gates (
|
|
360
|
+
milestone_id TEXT NOT NULL,
|
|
361
|
+
slice_id TEXT NOT NULL,
|
|
362
|
+
gate_id TEXT NOT NULL,
|
|
363
|
+
scope TEXT NOT NULL DEFAULT 'slice',
|
|
364
|
+
task_id TEXT NOT NULL DEFAULT '',
|
|
365
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
366
|
+
verdict TEXT NOT NULL DEFAULT '',
|
|
367
|
+
rationale TEXT NOT NULL DEFAULT '',
|
|
368
|
+
findings TEXT NOT NULL DEFAULT '',
|
|
369
|
+
evaluated_at TEXT DEFAULT NULL,
|
|
370
|
+
PRIMARY KEY (milestone_id, slice_id, gate_id, task_id),
|
|
371
|
+
FOREIGN KEY (milestone_id, slice_id) REFERENCES slices(milestone_id, id)
|
|
372
|
+
)
|
|
373
|
+
`);
|
|
374
|
+
|
|
358
375
|
db.exec("CREATE INDEX IF NOT EXISTS idx_memories_active ON memories(superseded_by)");
|
|
359
376
|
db.exec("CREATE INDEX IF NOT EXISTS idx_replan_history_milestone ON replan_history(milestone_id, created_at)");
|
|
360
377
|
|
|
@@ -637,6 +654,29 @@ function migrateSchema(db: DbAdapter): void {
|
|
|
637
654
|
});
|
|
638
655
|
}
|
|
639
656
|
|
|
657
|
+
if (currentVersion < 12) {
|
|
658
|
+
db.exec(`
|
|
659
|
+
CREATE TABLE IF NOT EXISTS quality_gates (
|
|
660
|
+
milestone_id TEXT NOT NULL,
|
|
661
|
+
slice_id TEXT NOT NULL,
|
|
662
|
+
gate_id TEXT NOT NULL,
|
|
663
|
+
scope TEXT NOT NULL DEFAULT 'slice',
|
|
664
|
+
task_id TEXT DEFAULT NULL,
|
|
665
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
666
|
+
verdict TEXT NOT NULL DEFAULT '',
|
|
667
|
+
rationale TEXT NOT NULL DEFAULT '',
|
|
668
|
+
findings TEXT NOT NULL DEFAULT '',
|
|
669
|
+
evaluated_at TEXT DEFAULT NULL,
|
|
670
|
+
PRIMARY KEY (milestone_id, slice_id, gate_id, COALESCE(task_id, '')),
|
|
671
|
+
FOREIGN KEY (milestone_id, slice_id) REFERENCES slices(milestone_id, id)
|
|
672
|
+
)
|
|
673
|
+
`);
|
|
674
|
+
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
675
|
+
":version": 12,
|
|
676
|
+
":applied_at": new Date().toISOString(),
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
|
|
640
680
|
db.exec("COMMIT");
|
|
641
681
|
} catch (err) {
|
|
642
682
|
db.exec("ROLLBACK");
|
|
@@ -1722,3 +1762,111 @@ export function getAssessment(path: string): Record<string, unknown> | null {
|
|
|
1722
1762
|
).get({ ":path": path });
|
|
1723
1763
|
return row ?? null;
|
|
1724
1764
|
}
|
|
1765
|
+
|
|
1766
|
+
// ─── Quality Gates ───────────────────────────────────────────────────────
|
|
1767
|
+
|
|
1768
|
+
function rowToGate(row: Record<string, unknown>): GateRow {
|
|
1769
|
+
return {
|
|
1770
|
+
milestone_id: row["milestone_id"] as string,
|
|
1771
|
+
slice_id: row["slice_id"] as string,
|
|
1772
|
+
gate_id: row["gate_id"] as GateId,
|
|
1773
|
+
scope: row["scope"] as GateScope,
|
|
1774
|
+
task_id: (row["task_id"] as string) ?? "",
|
|
1775
|
+
status: row["status"] as GateStatus,
|
|
1776
|
+
verdict: (row["verdict"] as GateVerdict) || "",
|
|
1777
|
+
rationale: (row["rationale"] as string) || "",
|
|
1778
|
+
findings: (row["findings"] as string) || "",
|
|
1779
|
+
evaluated_at: (row["evaluated_at"] as string) ?? null,
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
export function insertGateRow(g: {
|
|
1784
|
+
milestoneId: string;
|
|
1785
|
+
sliceId: string;
|
|
1786
|
+
gateId: GateId;
|
|
1787
|
+
scope: GateScope;
|
|
1788
|
+
taskId?: string | null;
|
|
1789
|
+
status?: GateStatus;
|
|
1790
|
+
}): void {
|
|
1791
|
+
if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1792
|
+
currentDb.prepare(
|
|
1793
|
+
`INSERT OR IGNORE INTO quality_gates (milestone_id, slice_id, gate_id, scope, task_id, status)
|
|
1794
|
+
VALUES (:mid, :sid, :gid, :scope, :tid, :status)`,
|
|
1795
|
+
).run({
|
|
1796
|
+
":mid": g.milestoneId,
|
|
1797
|
+
":sid": g.sliceId,
|
|
1798
|
+
":gid": g.gateId,
|
|
1799
|
+
":scope": g.scope,
|
|
1800
|
+
":tid": g.taskId ?? "",
|
|
1801
|
+
":status": g.status ?? "pending",
|
|
1802
|
+
});
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
export function saveGateResult(g: {
|
|
1806
|
+
milestoneId: string;
|
|
1807
|
+
sliceId: string;
|
|
1808
|
+
gateId: string;
|
|
1809
|
+
taskId?: string | null;
|
|
1810
|
+
verdict: GateVerdict;
|
|
1811
|
+
rationale: string;
|
|
1812
|
+
findings: string;
|
|
1813
|
+
}): void {
|
|
1814
|
+
if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1815
|
+
currentDb.prepare(
|
|
1816
|
+
`UPDATE quality_gates
|
|
1817
|
+
SET status = 'complete', verdict = :verdict, rationale = :rationale,
|
|
1818
|
+
findings = :findings, evaluated_at = :evaluated_at
|
|
1819
|
+
WHERE milestone_id = :mid AND slice_id = :sid AND gate_id = :gid
|
|
1820
|
+
AND task_id = :tid`,
|
|
1821
|
+
).run({
|
|
1822
|
+
":mid": g.milestoneId,
|
|
1823
|
+
":sid": g.sliceId,
|
|
1824
|
+
":gid": g.gateId,
|
|
1825
|
+
":tid": g.taskId ?? "",
|
|
1826
|
+
":verdict": g.verdict,
|
|
1827
|
+
":rationale": g.rationale,
|
|
1828
|
+
":findings": g.findings,
|
|
1829
|
+
":evaluated_at": new Date().toISOString(),
|
|
1830
|
+
});
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
export function getPendingGates(milestoneId: string, sliceId: string, scope?: GateScope): GateRow[] {
|
|
1834
|
+
if (!currentDb) return [];
|
|
1835
|
+
const sql = scope
|
|
1836
|
+
? `SELECT * FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid AND scope = :scope AND status = 'pending'`
|
|
1837
|
+
: `SELECT * FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid AND status = 'pending'`;
|
|
1838
|
+
const params: Record<string, unknown> = { ":mid": milestoneId, ":sid": sliceId };
|
|
1839
|
+
if (scope) params[":scope"] = scope;
|
|
1840
|
+
return currentDb.prepare(sql).all(params).map(rowToGate);
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
export function getGateResults(milestoneId: string, sliceId: string, scope?: GateScope): GateRow[] {
|
|
1844
|
+
if (!currentDb) return [];
|
|
1845
|
+
const sql = scope
|
|
1846
|
+
? `SELECT * FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid AND scope = :scope`
|
|
1847
|
+
: `SELECT * FROM quality_gates WHERE milestone_id = :mid AND slice_id = :sid`;
|
|
1848
|
+
const params: Record<string, unknown> = { ":mid": milestoneId, ":sid": sliceId };
|
|
1849
|
+
if (scope) params[":scope"] = scope;
|
|
1850
|
+
return currentDb.prepare(sql).all(params).map(rowToGate);
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
export function markAllGatesOmitted(milestoneId: string, sliceId: string): void {
|
|
1854
|
+
if (!currentDb) return;
|
|
1855
|
+
currentDb.prepare(
|
|
1856
|
+
`UPDATE quality_gates SET status = 'omitted', verdict = 'omitted', evaluated_at = :now
|
|
1857
|
+
WHERE milestone_id = :mid AND slice_id = :sid AND status = 'pending'`,
|
|
1858
|
+
).run({
|
|
1859
|
+
":mid": milestoneId,
|
|
1860
|
+
":sid": sliceId,
|
|
1861
|
+
":now": new Date().toISOString(),
|
|
1862
|
+
});
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
export function getPendingSliceGateCount(milestoneId: string, sliceId: string): number {
|
|
1866
|
+
if (!currentDb) return 0;
|
|
1867
|
+
const row = currentDb.prepare(
|
|
1868
|
+
`SELECT COUNT(*) as cnt FROM quality_gates
|
|
1869
|
+
WHERE milestone_id = :mid AND slice_id = :sid AND scope = 'slice' AND status = 'pending'`,
|
|
1870
|
+
).get({ ":mid": milestoneId, ":sid": sliceId });
|
|
1871
|
+
return row ? (row["cnt"] as number) : 0;
|
|
1872
|
+
}
|
|
@@ -244,12 +244,22 @@ export async function buildExistingMilestonesContext(
|
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
// For each milestone, include context and status
|
|
247
|
+
// For each milestone, include context and status.
|
|
248
|
+
// Completed milestones get a compact summary line only — loading their full
|
|
249
|
+
// CONTEXT.md + SUMMARY.md files is expensive and triggers 429 rate limits on
|
|
250
|
+
// projects with many completed milestones (#2379).
|
|
248
251
|
for (const mid of milestoneIds) {
|
|
249
252
|
const registryEntry = state.registry.find(m => m.id === mid);
|
|
250
253
|
const status = registryEntry?.status ?? "unknown";
|
|
251
254
|
const title = registryEntry?.title ?? mid;
|
|
252
255
|
|
|
256
|
+
// Completed milestones: emit a one-liner — the LLM only needs to know
|
|
257
|
+
// they exist for dedup/dependency purposes, not their full content.
|
|
258
|
+
if (status === "complete") {
|
|
259
|
+
sections.push(`### ${mid}: ${title}\n**Status:** complete`);
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
|
|
253
263
|
const parts: string[] = [];
|
|
254
264
|
parts.push(`### ${mid}: ${title}\n**Status:** ${status}`);
|
|
255
265
|
|
|
@@ -271,17 +281,6 @@ export async function buildExistingMilestonesContext(
|
|
|
271
281
|
}
|
|
272
282
|
}
|
|
273
283
|
|
|
274
|
-
// For completed milestones, include the summary if it exists
|
|
275
|
-
if (status === "complete") {
|
|
276
|
-
const summaryFile = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
277
|
-
if (summaryFile) {
|
|
278
|
-
const content = await loadFile(summaryFile);
|
|
279
|
-
if (content) {
|
|
280
|
-
parts.push(`\n**Summary:**\n${content.trim()}`);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
284
|
// For active/pending/parked milestones, include the roadmap if it exists
|
|
286
285
|
// (shows what's planned but not yet built)
|
|
287
286
|
if (status === "active" || status === "pending" || status === "parked") {
|
|
@@ -20,8 +20,10 @@ import {
|
|
|
20
20
|
getSlice,
|
|
21
21
|
getArtifact,
|
|
22
22
|
insertArtifact,
|
|
23
|
+
getGateResults,
|
|
23
24
|
} from "./gsd-db.js";
|
|
24
25
|
import type { MilestoneRow, SliceRow, TaskRow, ArtifactRow } from "./gsd-db.js";
|
|
26
|
+
import type { GateRow } from "./types.js";
|
|
25
27
|
import {
|
|
26
28
|
resolveMilestoneFile,
|
|
27
29
|
resolveSliceFile,
|
|
@@ -188,7 +190,7 @@ function renderRoadmapMarkdown(milestone: MilestoneRow, slices: SliceRow[]): str
|
|
|
188
190
|
return `${lines.join("\n").trimEnd()}\n`;
|
|
189
191
|
}
|
|
190
192
|
|
|
191
|
-
function renderTaskPlanMarkdown(task: TaskRow): string {
|
|
193
|
+
function renderTaskPlanMarkdown(task: TaskRow, taskGates: GateRow[] = []): string {
|
|
192
194
|
const estimatedSteps = Math.max(1, task.description.trim().split(/\n+/).filter(Boolean).length || 1);
|
|
193
195
|
const estimatedFiles = task.files.length > 0
|
|
194
196
|
? task.files.length
|
|
@@ -251,10 +253,22 @@ function renderTaskPlanMarkdown(task: TaskRow): string {
|
|
|
251
253
|
lines.push("");
|
|
252
254
|
}
|
|
253
255
|
|
|
256
|
+
// ── Quality Gate Sections (Q5/Q6/Q7) ──────────────────────────────────
|
|
257
|
+
const gateLabels: Record<string, string> = { Q5: "Failure Modes", Q6: "Load Profile", Q7: "Negative Tests" };
|
|
258
|
+
for (const [gid, label] of Object.entries(gateLabels)) {
|
|
259
|
+
const gate = taskGates.find(g => g.gate_id === gid && g.status === "complete");
|
|
260
|
+
if (gate && gate.verdict !== "omitted") {
|
|
261
|
+
lines.push(`## ${label}`);
|
|
262
|
+
lines.push("");
|
|
263
|
+
lines.push(gate.findings.trim() || `- **Verdict:** ${gate.verdict}\n- **Rationale:** ${gate.rationale}`);
|
|
264
|
+
lines.push("");
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
254
268
|
return `${lines.join("\n").trimEnd()}\n`;
|
|
255
269
|
}
|
|
256
270
|
|
|
257
|
-
function renderSlicePlanMarkdown(slice: SliceRow, tasks: TaskRow[]): string {
|
|
271
|
+
function renderSlicePlanMarkdown(slice: SliceRow, tasks: TaskRow[], gates: GateRow[] = []): string {
|
|
258
272
|
const lines: string[] = [];
|
|
259
273
|
|
|
260
274
|
lines.push(`# ${slice.id}: ${slice.title || slice.id}`);
|
|
@@ -274,6 +288,23 @@ function renderSlicePlanMarkdown(slice: SliceRow, tasks: TaskRow[]): string {
|
|
|
274
288
|
}
|
|
275
289
|
lines.push("");
|
|
276
290
|
|
|
291
|
+
// ── Quality Gate Sections (Q3/Q4) ────────────────────────────────────
|
|
292
|
+
const q3 = gates.find(g => g.gate_id === "Q3" && g.status === "complete");
|
|
293
|
+
if (q3 && q3.verdict !== "omitted") {
|
|
294
|
+
lines.push("## Threat Surface");
|
|
295
|
+
lines.push("");
|
|
296
|
+
lines.push(q3.findings.trim() || `- **Verdict:** ${q3.verdict}\n- **Rationale:** ${q3.rationale}`);
|
|
297
|
+
lines.push("");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const q4 = gates.find(g => g.gate_id === "Q4" && g.status === "complete");
|
|
301
|
+
if (q4 && q4.verdict !== "omitted") {
|
|
302
|
+
lines.push("## Requirement Impact");
|
|
303
|
+
lines.push("");
|
|
304
|
+
lines.push(q4.findings.trim() || `- **Verdict:** ${q4.verdict}\n- **Rationale:** ${q4.rationale}`);
|
|
305
|
+
lines.push("");
|
|
306
|
+
}
|
|
307
|
+
|
|
277
308
|
if (slice.proof_level.trim()) {
|
|
278
309
|
lines.push("## Proof Level");
|
|
279
310
|
lines.push("");
|
|
@@ -354,7 +385,8 @@ export async function renderPlanFromDb(
|
|
|
354
385
|
const absPath = resolveSliceFile(basePath, milestoneId, sliceId, "PLAN")
|
|
355
386
|
?? join(slicePath, `${sliceId}-PLAN.md`);
|
|
356
387
|
const artifactPath = toArtifactPath(absPath, basePath);
|
|
357
|
-
const
|
|
388
|
+
const sliceGates = getGateResults(milestoneId, sliceId, "slice");
|
|
389
|
+
const content = renderSlicePlanMarkdown(slice, tasks, sliceGates);
|
|
358
390
|
|
|
359
391
|
await writeAndStore(absPath, artifactPath, content, {
|
|
360
392
|
artifact_type: "PLAN",
|
|
@@ -387,7 +419,8 @@ export async function renderTaskPlanFromDb(
|
|
|
387
419
|
mkdirSync(tasksDir, { recursive: true });
|
|
388
420
|
const absPath = join(tasksDir, buildTaskFileName(taskId, "PLAN"));
|
|
389
421
|
const artifactPath = toArtifactPath(absPath, basePath);
|
|
390
|
-
const
|
|
422
|
+
const taskGates = getGateResults(milestoneId, sliceId, "task").filter(g => g.task_id === taskId);
|
|
423
|
+
const content = task.full_plan_md.trim() ? task.full_plan_md : renderTaskPlanMarkdown(task, taskGates);
|
|
391
424
|
|
|
392
425
|
await writeAndStore(absPath, artifactPath, content, {
|
|
393
426
|
artifact_type: "PLAN",
|
|
@@ -18,6 +18,7 @@ import type {
|
|
|
18
18
|
ParallelConfig,
|
|
19
19
|
ContextSelectionMode,
|
|
20
20
|
ReactiveExecutionConfig,
|
|
21
|
+
GateEvaluationConfig,
|
|
21
22
|
} from "./types.js";
|
|
22
23
|
import type { DynamicRoutingConfig } from "./model-router.js";
|
|
23
24
|
import type { GitHubSyncConfig } from "../github-sync/types.js";
|
|
@@ -87,6 +88,7 @@ export const KNOWN_PREFERENCE_KEYS = new Set<string>([
|
|
|
87
88
|
"context_selection",
|
|
88
89
|
"widget_mode",
|
|
89
90
|
"reactive_execution",
|
|
91
|
+
"gate_evaluation",
|
|
90
92
|
"github",
|
|
91
93
|
"service_tier",
|
|
92
94
|
"forensics_dedup",
|
|
@@ -96,7 +98,7 @@ export const KNOWN_PREFERENCE_KEYS = new Set<string>([
|
|
|
96
98
|
/** Canonical list of all dispatch unit types. */
|
|
97
99
|
export const KNOWN_UNIT_TYPES = [
|
|
98
100
|
"research-milestone", "plan-milestone", "research-slice", "plan-slice",
|
|
99
|
-
"execute-task", "reactive-execute", "complete-slice", "replan-slice", "reassess-roadmap",
|
|
101
|
+
"execute-task", "reactive-execute", "gate-evaluate", "complete-slice", "replan-slice", "reassess-roadmap",
|
|
100
102
|
"run-uat", "complete-milestone",
|
|
101
103
|
] as const;
|
|
102
104
|
export type UnitType = (typeof KNOWN_UNIT_TYPES)[number];
|
|
@@ -221,6 +223,8 @@ export interface GSDPreferences {
|
|
|
221
223
|
widget_mode?: "full" | "small" | "min" | "off";
|
|
222
224
|
/** Reactive (graph-derived parallel) task execution within slices. Disabled by default. */
|
|
223
225
|
reactive_execution?: ReactiveExecutionConfig;
|
|
226
|
+
/** Parallel quality gate evaluation during slice planning. Disabled by default. */
|
|
227
|
+
gate_evaluation?: GateEvaluationConfig;
|
|
224
228
|
/** GitHub sync configuration. Opt-in: syncs GSD events to GitHub Issues, Milestones, and PRs. */
|
|
225
229
|
github?: GitHubSyncConfig;
|
|
226
230
|
/** OpenAI service tier preference. "priority" = 2x cost, faster. "flex" = 0.5x cost, slower. Only affects gpt-5.4 models. */
|
|
@@ -538,6 +538,43 @@ export function validatePreferences(preferences: GSDPreferences): {
|
|
|
538
538
|
}
|
|
539
539
|
}
|
|
540
540
|
|
|
541
|
+
// ─── Gate Evaluation ─────────────────────────────────────────────────────
|
|
542
|
+
if (preferences.gate_evaluation !== undefined) {
|
|
543
|
+
if (typeof preferences.gate_evaluation === "object" && preferences.gate_evaluation !== null) {
|
|
544
|
+
const ge = preferences.gate_evaluation as unknown as Record<string, unknown>;
|
|
545
|
+
const validGe: Record<string, unknown> = {};
|
|
546
|
+
|
|
547
|
+
if (ge.enabled !== undefined) {
|
|
548
|
+
if (typeof ge.enabled === "boolean") validGe.enabled = ge.enabled;
|
|
549
|
+
else errors.push("gate_evaluation.enabled must be a boolean");
|
|
550
|
+
}
|
|
551
|
+
if (ge.slice_gates !== undefined) {
|
|
552
|
+
if (Array.isArray(ge.slice_gates) && ge.slice_gates.every((g: unknown) => typeof g === "string")) {
|
|
553
|
+
validGe.slice_gates = ge.slice_gates;
|
|
554
|
+
} else {
|
|
555
|
+
errors.push("gate_evaluation.slice_gates must be an array of strings");
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
if (ge.task_gates !== undefined) {
|
|
559
|
+
if (typeof ge.task_gates === "boolean") validGe.task_gates = ge.task_gates;
|
|
560
|
+
else errors.push("gate_evaluation.task_gates must be a boolean");
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const knownGeKeys = new Set(["enabled", "slice_gates", "task_gates"]);
|
|
564
|
+
for (const key of Object.keys(ge)) {
|
|
565
|
+
if (!knownGeKeys.has(key)) {
|
|
566
|
+
warnings.push(`unknown gate_evaluation key "${key}" — ignored`);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
if (Object.keys(validGe).length > 0) {
|
|
571
|
+
validated.gate_evaluation = validGe as unknown as import("./types.js").GateEvaluationConfig;
|
|
572
|
+
}
|
|
573
|
+
} else {
|
|
574
|
+
errors.push("gate_evaluation must be an object");
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
541
578
|
// ─── Verification Preferences ───────────────────────────────────────────
|
|
542
579
|
if (preferences.verification_commands !== undefined) {
|
|
543
580
|
if (Array.isArray(preferences.verification_commands)) {
|
|
@@ -20,11 +20,13 @@ Then:
|
|
|
20
20
|
3. **Verify code changes exist.** Run `git diff --stat HEAD $(git merge-base HEAD main) -- ':!.gsd/'` (or the equivalent for the integration branch). If no non-`.gsd/` files appear in the diff, the milestone produced only planning artifacts and no actual code. Record this as a **verification failure**.
|
|
21
21
|
4. Verify each **success criterion** from the milestone definition in `{{roadmapPath}}`. For each criterion, confirm it was met with specific evidence from slice summaries, test results, or observable behavior. Record any criterion that was NOT met as a **verification failure**.
|
|
22
22
|
5. Verify the milestone's **definition of done** — all slices are `[x]`, all slice summaries exist, and any cross-slice integration points work correctly. Record any unmet items as a **verification failure**.
|
|
23
|
-
6.
|
|
23
|
+
6. If the roadmap includes a **Horizontal Checklist**, verify each item was addressed during the milestone. Note unchecked items in the milestone summary.
|
|
24
|
+
7. Fill the **Decision Re-evaluation** table in the milestone summary. For each key decision from `.gsd/DECISIONS.md` made during this milestone, evaluate whether it is still valid given what was actually built. Flag decisions that should be revisited next milestone.
|
|
25
|
+
8. Validate **requirement status transitions**. For each requirement that changed status during this milestone, confirm the transition is supported by evidence. Requirements can move between Active, Validated, Deferred, Blocked, or Out of Scope — but only with proof.
|
|
24
26
|
|
|
25
27
|
### Verification Gate — STOP if verification failed
|
|
26
28
|
|
|
27
|
-
**If ANY verification failure was recorded in steps 3, 4, or 5, you MUST follow the failure path below. Do NOT proceed to step
|
|
29
|
+
**If ANY verification failure was recorded in steps 3, 4, or 5, you MUST follow the failure path below. Do NOT proceed to step 9.**
|
|
28
30
|
|
|
29
31
|
**Failure path** (verification failed):
|
|
30
32
|
- Do NOT call `gsd_complete_milestone` — the milestone must not be marked as complete.
|
|
@@ -33,13 +35,30 @@ Then:
|
|
|
33
35
|
- Write a clear summary of what failed and why to help the next attempt.
|
|
34
36
|
- Say: "Milestone {{milestoneId}} verification FAILED — not complete." and stop.
|
|
35
37
|
|
|
36
|
-
**Success path** (all verifications passed — continue with steps
|
|
38
|
+
**Success path** (all verifications passed — continue with steps 9–13):
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
9. **Persist completion through `gsd_complete_milestone`.** Call it with the parameters below. The tool updates the milestone status in the DB, renders `{{milestoneSummaryPath}}`, and validates all slices are complete before proceeding.
|
|
41
|
+
|
|
42
|
+
**Required parameters:**
|
|
43
|
+
- `milestoneId` (string) — Milestone ID (e.g. M001)
|
|
44
|
+
- `title` (string) — Milestone title
|
|
45
|
+
- `oneLiner` (string) — One-sentence summary of what the milestone achieved
|
|
46
|
+
- `narrative` (string) — Detailed narrative of what happened during the milestone
|
|
47
|
+
- `successCriteriaResults` (string) — Markdown detailing how each success criterion was met or not met
|
|
48
|
+
- `definitionOfDoneResults` (string) — Markdown detailing how each definition-of-done item was met
|
|
49
|
+
- `requirementOutcomes` (string) — Markdown detailing requirement status transitions with evidence
|
|
50
|
+
- `keyDecisions` (array of strings) — Key architectural/pattern decisions made during the milestone
|
|
51
|
+
- `keyFiles` (array of strings) — Key files created or modified during the milestone
|
|
52
|
+
- `lessonsLearned` (array of strings) — Lessons learned during the milestone
|
|
53
|
+
- `verificationPassed` (boolean) — Must be `true` — confirms that code change verification, success criteria, and definition of done checks all passed before completion
|
|
54
|
+
|
|
55
|
+
**Optional parameters:**
|
|
56
|
+
- `followUps` (string) — Follow-up items for future milestones
|
|
57
|
+
- `deviations` (string) — Deviations from the original plan
|
|
58
|
+
10. For each requirement whose status changed in step 8, call `gsd_requirement_update` with the requirement ID and updated `status` and `validation` fields — the tool regenerates `.gsd/REQUIREMENTS.md` automatically.
|
|
59
|
+
11. Update `.gsd/PROJECT.md` to reflect milestone completion and current project state.
|
|
60
|
+
12. Review all slice summaries for cross-cutting lessons, patterns, or gotchas that emerged during this milestone. Append any non-obvious, reusable insights to `.gsd/KNOWLEDGE.md`.
|
|
61
|
+
13. Do not commit manually — the system auto-commits your changes after this unit completes.
|
|
43
62
|
- Say: "Milestone {{milestoneId}} complete."
|
|
44
63
|
|
|
45
64
|
**Important:** Do NOT skip the code change verification, success criteria, or definition of done verification (steps 3-5). The milestone summary must reflect actual verified outcomes, not assumed success. Verification failures BLOCK completion — there is no override. The milestone stays in its current state until issues are resolved and verification is re-run.
|
|
@@ -23,14 +23,15 @@ Then:
|
|
|
23
23
|
2. {{skillActivation}}
|
|
24
24
|
3. Run all slice-level verification checks defined in the slice plan. All must pass before marking the slice done. If any fail, fix them first.
|
|
25
25
|
4. If the slice plan includes observability/diagnostic surfaces, confirm they work. Skip this for simple slices that don't have observability sections.
|
|
26
|
-
5. If
|
|
27
|
-
6.
|
|
28
|
-
7. Write `{{
|
|
29
|
-
8.
|
|
30
|
-
9. Review task summaries for
|
|
31
|
-
10.
|
|
32
|
-
11. Do
|
|
33
|
-
12.
|
|
26
|
+
5. If the slice involved runtime behavior, fill the **Operational Readiness** section (Q8) in the slice summary: health signal, failure signal, recovery procedure, and monitoring gaps. Omit entirely for simple slices with no runtime concerns.
|
|
27
|
+
6. If this slice produced evidence that a requirement changed status (Active → Validated, Active → Deferred, etc.), call `gsd_save_decision` with scope="requirement", decision="{requirement-id}", choice="{new-status}", rationale="{evidence}". Do NOT write `.gsd/REQUIREMENTS.md` directly — the engine renders it from the database.
|
|
28
|
+
7. Write `{{sliceSummaryPath}}` (compress all task summaries).
|
|
29
|
+
8. Write `{{sliceUatPath}}` — a concrete UAT script with real test cases derived from the slice plan and task summaries. Include preconditions, numbered steps with expected outcomes, and edge cases. This must NOT be a placeholder or generic template — tailor every test case to what this slice actually built.
|
|
30
|
+
9. Review task summaries for `key_decisions`. Append any significant decisions to `.gsd/DECISIONS.md` if missing.
|
|
31
|
+
10. Review task summaries for patterns, gotchas, or non-obvious lessons learned. If any would save future agents from repeating investigation or hitting the same issues, append them to `.gsd/KNOWLEDGE.md`. Only add entries that are genuinely useful — don't pad with obvious observations.
|
|
32
|
+
11. Call `gsd_complete_slice` with milestone_id, slice_id, the slice summary, and the UAT result. Do NOT manually mark the roadmap checkbox — the tool writes to the DB and renders the ROADMAP.md projection automatically.
|
|
33
|
+
12. Do not run git commands — the system commits your changes and handles any merge after this unit succeeds.
|
|
34
|
+
13. Update `.gsd/PROJECT.md` if it exists — refresh current state if needed.
|
|
34
35
|
|
|
35
36
|
**You MUST call `gsd_complete_slice` with the slice summary and UAT content before finishing. The tool persists to both DB and disk and renders `{{sliceSummaryPath}}` and `{{sliceUatPath}}` automatically.**
|
|
36
37
|
|