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
package/dist/headless-ui.js
CHANGED
|
@@ -13,9 +13,19 @@ export function handleExtensionUIRequest(event, writeToStdin) {
|
|
|
13
13
|
const { id, method } = event;
|
|
14
14
|
let response;
|
|
15
15
|
switch (method) {
|
|
16
|
-
case 'select':
|
|
17
|
-
|
|
16
|
+
case 'select': {
|
|
17
|
+
// Lock-guard prompts list "View status" first, but headless needs "Force start"
|
|
18
|
+
// to proceed. Detect by title and pick the force option.
|
|
19
|
+
const title = String(event.title ?? '');
|
|
20
|
+
let selected = event.options?.[0] ?? '';
|
|
21
|
+
if (title.includes('Auto-mode is running') && event.options) {
|
|
22
|
+
const forceOption = event.options.find(o => o.toLowerCase().includes('force start'));
|
|
23
|
+
if (forceOption)
|
|
24
|
+
selected = forceOption;
|
|
25
|
+
}
|
|
26
|
+
response = { type: 'extension_ui_response', id, value: selected };
|
|
18
27
|
break;
|
|
28
|
+
}
|
|
19
29
|
case 'confirm':
|
|
20
30
|
response = { type: 'extension_ui_response', id, confirmed: true };
|
|
21
31
|
break;
|
package/dist/headless.js
CHANGED
|
@@ -37,8 +37,8 @@ export function parseHeadlessArgs(argv) {
|
|
|
37
37
|
if (!positionalStarted && arg.startsWith('--')) {
|
|
38
38
|
if (arg === '--timeout' && i + 1 < args.length) {
|
|
39
39
|
options.timeout = parseInt(args[++i], 10);
|
|
40
|
-
if (Number.isNaN(options.timeout) || options.timeout
|
|
41
|
-
process.stderr.write('[headless] Error: --timeout must be a
|
|
40
|
+
if (Number.isNaN(options.timeout) || options.timeout < 0) {
|
|
41
|
+
process.stderr.write('[headless] Error: --timeout must be a non-negative integer (milliseconds, 0 to disable)\n');
|
|
42
42
|
process.exit(1);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -132,6 +132,13 @@ async function runHeadlessOnce(options, restartCount) {
|
|
|
132
132
|
if (isNewMilestone && options.timeout === 300_000) {
|
|
133
133
|
options.timeout = 600_000; // 10 minutes
|
|
134
134
|
}
|
|
135
|
+
// auto-mode sessions are long-running (minutes to hours) with their own internal
|
|
136
|
+
// per-unit timeout via auto-supervisor. Disable the overall timeout unless the
|
|
137
|
+
// user explicitly set --timeout.
|
|
138
|
+
const isAutoMode = options.command === 'auto';
|
|
139
|
+
if (isAutoMode && options.timeout === 300_000) {
|
|
140
|
+
options.timeout = 0;
|
|
141
|
+
}
|
|
135
142
|
// Supervised mode cannot share stdin with --context -
|
|
136
143
|
if (options.supervised && options.context === '-') {
|
|
137
144
|
process.stderr.write('[headless] Error: --supervised cannot be used with --context - (both require stdin)\n');
|
|
@@ -267,12 +274,14 @@ async function runHeadlessOnce(options, restartCount) {
|
|
|
267
274
|
}
|
|
268
275
|
// Precompute supervised response timeout
|
|
269
276
|
const responseTimeout = options.responseTimeout ?? 30_000;
|
|
270
|
-
// Overall timeout
|
|
271
|
-
const timeoutTimer =
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
277
|
+
// Overall timeout (disabled when options.timeout === 0, e.g. auto-mode)
|
|
278
|
+
const timeoutTimer = options.timeout > 0
|
|
279
|
+
? setTimeout(() => {
|
|
280
|
+
process.stderr.write(`[headless] Timeout after ${options.timeout / 1000}s\n`);
|
|
281
|
+
exitCode = 1;
|
|
282
|
+
resolveCompletion();
|
|
283
|
+
}, options.timeout)
|
|
284
|
+
: null;
|
|
276
285
|
// Event handler
|
|
277
286
|
client.onEvent((event) => {
|
|
278
287
|
const eventObj = event;
|
|
@@ -354,7 +363,8 @@ async function runHeadlessOnce(options, restartCount) {
|
|
|
354
363
|
interrupted = true;
|
|
355
364
|
exitCode = 1;
|
|
356
365
|
client.stop().finally(() => {
|
|
357
|
-
|
|
366
|
+
if (timeoutTimer)
|
|
367
|
+
clearTimeout(timeoutTimer);
|
|
358
368
|
if (idleTimer)
|
|
359
369
|
clearTimeout(idleTimer);
|
|
360
370
|
process.exit(exitCode);
|
|
@@ -368,7 +378,8 @@ async function runHeadlessOnce(options, restartCount) {
|
|
|
368
378
|
}
|
|
369
379
|
catch (err) {
|
|
370
380
|
process.stderr.write(`[headless] Error: Failed to start RPC session: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
371
|
-
|
|
381
|
+
if (timeoutTimer)
|
|
382
|
+
clearTimeout(timeoutTimer);
|
|
372
383
|
process.exit(1);
|
|
373
384
|
}
|
|
374
385
|
// Access stdin writer from the internal process
|
|
@@ -376,7 +387,8 @@ async function runHeadlessOnce(options, restartCount) {
|
|
|
376
387
|
if (!internalProcess?.stdin) {
|
|
377
388
|
process.stderr.write('[headless] Error: Cannot access child process stdin\n');
|
|
378
389
|
await client.stop();
|
|
379
|
-
|
|
390
|
+
if (timeoutTimer)
|
|
391
|
+
clearTimeout(timeoutTimer);
|
|
380
392
|
process.exit(1);
|
|
381
393
|
}
|
|
382
394
|
stdinWriter = (data) => {
|
|
@@ -424,7 +436,10 @@ async function runHeadlessOnce(options, restartCount) {
|
|
|
424
436
|
if (!options.json) {
|
|
425
437
|
process.stderr.write('[headless] Milestone ready — chaining into auto-mode...\n');
|
|
426
438
|
}
|
|
427
|
-
// Reset completion state for the auto-mode phase
|
|
439
|
+
// Reset completion state for the auto-mode phase.
|
|
440
|
+
// Disable the overall timeout — auto-mode has its own internal supervisor.
|
|
441
|
+
if (timeoutTimer)
|
|
442
|
+
clearTimeout(timeoutTimer);
|
|
428
443
|
completed = false;
|
|
429
444
|
milestoneReady = false;
|
|
430
445
|
blocked = false;
|
|
@@ -443,7 +458,8 @@ async function runHeadlessOnce(options, restartCount) {
|
|
|
443
458
|
}
|
|
444
459
|
}
|
|
445
460
|
// Cleanup
|
|
446
|
-
|
|
461
|
+
if (timeoutTimer)
|
|
462
|
+
clearTimeout(timeoutTimer);
|
|
447
463
|
if (idleTimer)
|
|
448
464
|
clearTimeout(idleTimer);
|
|
449
465
|
pendingResponseTimers.forEach((timer) => clearTimeout(timer));
|
|
@@ -17,6 +17,7 @@ export const INFRA_ERROR_CODES = new Set([
|
|
|
17
17
|
"EDQUOT", // disk quota exceeded
|
|
18
18
|
"EMFILE", // too many open files (process)
|
|
19
19
|
"ENFILE", // too many open files (system)
|
|
20
|
+
"EAGAIN", // resource temporarily unavailable (resource exhaustion)
|
|
20
21
|
"ECONNREFUSED", // connection refused (offline / local server down)
|
|
21
22
|
"ENOTFOUND", // DNS lookup failed (offline / no network)
|
|
22
23
|
"ENETUNREACH", // network unreachable (offline / no route)
|
|
@@ -721,18 +721,18 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
721
721
|
deps.updateSessionLock(deps.lockBase(), unitType, unitId, sessionFile);
|
|
722
722
|
deps.writeLock(deps.lockBase(), unitType, unitId, sessionFile);
|
|
723
723
|
// Tag the most recent window entry with error info for stuck detection
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
if (
|
|
724
|
+
const lastEntry = loopState.recentUnits[loopState.recentUnits.length - 1];
|
|
725
|
+
if (lastEntry) {
|
|
726
|
+
if (unitResult.errorContext) {
|
|
727
|
+
lastEntry.error = `${unitResult.errorContext.category}:${unitResult.errorContext.message}`.slice(0, 200);
|
|
728
|
+
}
|
|
729
|
+
else if (unitResult.status === "error" || unitResult.status === "cancelled") {
|
|
727
730
|
lastEntry.error = `${unitResult.status}:${unitType}/${unitId}`;
|
|
728
731
|
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
if (/error|fail|exception/i.test(msgStr)) {
|
|
734
|
-
const lastEntry = loopState.recentUnits[loopState.recentUnits.length - 1];
|
|
735
|
-
if (lastEntry) {
|
|
732
|
+
else if (unitResult.event?.messages?.length) {
|
|
733
|
+
const lastMsg = unitResult.event.messages[unitResult.event.messages.length - 1];
|
|
734
|
+
const msgStr = typeof lastMsg === "string" ? lastMsg : JSON.stringify(lastMsg);
|
|
735
|
+
if (/error|fail|exception/i.test(msgStr)) {
|
|
736
736
|
lastEntry.error = msgStr.slice(0, 200);
|
|
737
737
|
}
|
|
738
738
|
}
|
|
@@ -779,7 +779,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
779
779
|
s.unitDispatchCount.delete(`${unitType}/${unitId}`);
|
|
780
780
|
s.unitRecoveryCount.delete(`${unitType}/${unitId}`);
|
|
781
781
|
}
|
|
782
|
-
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: ic.nextSeq(), eventType: "unit-end", data: { unitType, unitId, status: unitResult.status, artifactVerified }, causedBy: { flowId: ic.flowId, seq: unitStartSeq } });
|
|
782
|
+
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: ic.nextSeq(), eventType: "unit-end", data: { unitType, unitId, status: unitResult.status, artifactVerified, ...(unitResult.errorContext ? { errorContext: unitResult.errorContext } : {}) }, causedBy: { flowId: ic.flowId, seq: unitStartSeq } });
|
|
783
783
|
return { action: "next", data: { unitStartedAt: s.currentUnit.startedAt } };
|
|
784
784
|
}
|
|
785
785
|
// ─── runFinalize ──────────────────────────────────────────────────────────────
|
|
@@ -64,12 +64,12 @@ export function isSessionSwitchInFlight() {
|
|
|
64
64
|
* blocks to ensure the autoLoop is never stuck awaiting a promise that
|
|
65
65
|
* will never resolve. Safe to call when no resolver is pending (no-op).
|
|
66
66
|
*/
|
|
67
|
-
export function resolveAgentEndCancelled() {
|
|
67
|
+
export function resolveAgentEndCancelled(errorContext) {
|
|
68
68
|
if (_currentResolve) {
|
|
69
69
|
debugLog("resolveAgentEndCancelled", { status: "resolving-cancelled" });
|
|
70
70
|
const r = _currentResolve;
|
|
71
71
|
_currentResolve = null;
|
|
72
|
-
r({ status: "cancelled" });
|
|
72
|
+
r({ status: "cancelled", ...(errorContext ? { errorContext } : {}) });
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
// ─── resetPendingResolve (test helper) ───────────────────────────────────────
|
|
@@ -41,13 +41,13 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
|
|
|
41
41
|
unitId,
|
|
42
42
|
error: msg,
|
|
43
43
|
});
|
|
44
|
-
return { status: "cancelled" };
|
|
44
|
+
return { status: "cancelled", errorContext: { message: `Session creation failed: ${msg}`, category: "session-failed", isTransient: true } };
|
|
45
45
|
}
|
|
46
46
|
if (sessionTimeoutHandle)
|
|
47
47
|
clearTimeout(sessionTimeoutHandle);
|
|
48
48
|
if (sessionResult.cancelled) {
|
|
49
49
|
debugLog("runUnit-session-timeout", { unitType, unitId });
|
|
50
|
-
return { status: "cancelled" };
|
|
50
|
+
return { status: "cancelled", errorContext: { message: "Session creation timed out", category: "timeout", isTransient: true } };
|
|
51
51
|
}
|
|
52
52
|
if (!s.active) {
|
|
53
53
|
return { status: "cancelled" };
|
|
@@ -61,6 +61,9 @@ export class AutoSession {
|
|
|
61
61
|
lastStateRebuildAt = 0;
|
|
62
62
|
// ── Sidecar queue ─────────────────────────────────────────────────────
|
|
63
63
|
sidecarQueue = [];
|
|
64
|
+
// ── Isolation degradation ────────────────────────────────────────────
|
|
65
|
+
/** Set to true when worktree creation fails; prevents merge of nonexistent branch. */
|
|
66
|
+
isolationDegraded = false;
|
|
64
67
|
// ── Dispatch circuit breakers ──────────────────────────────────────
|
|
65
68
|
rewriteAttemptCount = 0;
|
|
66
69
|
// ── Metrics ──────────────────────────────────────────────────────────────
|
|
@@ -140,6 +143,7 @@ export class AutoSession {
|
|
|
140
143
|
this.pendingQuickTasks = [];
|
|
141
144
|
this.sidecarQueue = [];
|
|
142
145
|
this.rewriteAttemptCount = 0;
|
|
146
|
+
this.isolationDegraded = false;
|
|
143
147
|
// Signal handler
|
|
144
148
|
this.sigtermHandler = null;
|
|
145
149
|
// Loop promise state lives in auto-loop.ts module scope
|
|
@@ -4,14 +4,13 @@
|
|
|
4
4
|
// auto-recovery.ts (Phase 5 dead-code cleanup). The artifact verification
|
|
5
5
|
// function was removed entirely — callers now query WorkflowEngine directly.
|
|
6
6
|
import { resolveMilestonePath, resolveSlicePath, relMilestoneFile, relSliceFile, buildMilestoneFileName, buildSliceFileName, buildTaskFileName, } from "./paths.js";
|
|
7
|
+
import { parseUnitId } from "./unit-id.js";
|
|
7
8
|
import { join } from "node:path";
|
|
8
9
|
/**
|
|
9
10
|
* Resolve the expected artifact for a unit to an absolute path.
|
|
10
11
|
*/
|
|
11
12
|
export function resolveExpectedArtifactPath(unitType, unitId, base) {
|
|
12
|
-
const
|
|
13
|
-
const mid = parts[0];
|
|
14
|
-
const sid = parts[1];
|
|
13
|
+
const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
|
|
15
14
|
switch (unitType) {
|
|
16
15
|
case "discuss-milestone": {
|
|
17
16
|
const dir = resolveMilestonePath(base, mid);
|
|
@@ -39,10 +38,9 @@ export function resolveExpectedArtifactPath(unitType, unitId, base) {
|
|
|
39
38
|
}
|
|
40
39
|
case "run-uat": {
|
|
41
40
|
const dir = resolveSlicePath(base, mid, sid);
|
|
42
|
-
return dir ? join(dir, buildSliceFileName(sid, "UAT
|
|
41
|
+
return dir ? join(dir, buildSliceFileName(sid, "UAT")) : null;
|
|
43
42
|
}
|
|
44
43
|
case "execute-task": {
|
|
45
|
-
const tid = parts[2];
|
|
46
44
|
const dir = resolveSlicePath(base, mid, sid);
|
|
47
45
|
return dir && tid
|
|
48
46
|
? join(dir, "tasks", buildTaskFileName(tid, "SUMMARY"))
|
|
@@ -66,6 +64,9 @@ export function resolveExpectedArtifactPath(unitType, unitId, base) {
|
|
|
66
64
|
}
|
|
67
65
|
case "rewrite-docs":
|
|
68
66
|
return null;
|
|
67
|
+
case "gate-evaluate":
|
|
68
|
+
// Gate evaluate writes to DB quality_gates table — verified via state derivation
|
|
69
|
+
return null;
|
|
69
70
|
case "reactive-execute":
|
|
70
71
|
// Reactive execute produces multiple task summaries — verified separately
|
|
71
72
|
return null;
|
|
@@ -74,9 +75,7 @@ export function resolveExpectedArtifactPath(unitType, unitId, base) {
|
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
export function diagnoseExpectedArtifact(unitType, unitId, base) {
|
|
77
|
-
const
|
|
78
|
-
const mid = parts[0];
|
|
79
|
-
const sid = parts[1];
|
|
78
|
+
const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
|
|
80
79
|
switch (unitType) {
|
|
81
80
|
case "discuss-milestone":
|
|
82
81
|
return `${relMilestoneFile(base, mid, "CONTEXT")} (milestone context from discussion)`;
|
|
@@ -89,7 +88,6 @@ export function diagnoseExpectedArtifact(unitType, unitId, base) {
|
|
|
89
88
|
case "plan-slice":
|
|
90
89
|
return `${relSliceFile(base, mid, sid, "PLAN")} (slice plan)`;
|
|
91
90
|
case "execute-task": {
|
|
92
|
-
const tid = parts[2];
|
|
93
91
|
return `Task ${tid} marked [x] in ${relSliceFile(base, mid, sid, "PLAN")} + summary written`;
|
|
94
92
|
}
|
|
95
93
|
case "complete-slice":
|
|
@@ -101,7 +99,7 @@ export function diagnoseExpectedArtifact(unitType, unitId, base) {
|
|
|
101
99
|
case "reassess-roadmap":
|
|
102
100
|
return `${relSliceFile(base, mid, sid, "ASSESSMENT")} (roadmap reassessment)`;
|
|
103
101
|
case "run-uat":
|
|
104
|
-
return `${relSliceFile(base, mid, sid, "UAT
|
|
102
|
+
return `${relSliceFile(base, mid, sid, "UAT")} (UAT result)`;
|
|
105
103
|
case "validate-milestone":
|
|
106
104
|
return `${relMilestoneFile(base, mid, "VALIDATION")} (milestone validation report)`;
|
|
107
105
|
case "complete-milestone":
|
|
@@ -18,15 +18,16 @@ import { computeProgressScore } from "./progress-score.js";
|
|
|
18
18
|
import { getActiveWorktreeName } from "./worktree-command.js";
|
|
19
19
|
import { loadEffectiveGSDPreferences, getGlobalGSDPreferencesPath } from "./preferences.js";
|
|
20
20
|
import { resolveServiceTierIcon, getEffectiveServiceTier } from "./service-tier.js";
|
|
21
|
+
import { parseUnitId } from "./unit-id.js";
|
|
21
22
|
// ─── UAT Slice Extraction ─────────────────────────────────────────────────────
|
|
22
23
|
/**
|
|
23
24
|
* Extract the target slice ID from a run-uat unit ID (e.g. "M001/S01" → "S01").
|
|
24
25
|
* Returns null if the format doesn't match.
|
|
25
26
|
*/
|
|
26
27
|
export function extractUatSliceId(unitId) {
|
|
27
|
-
const
|
|
28
|
-
if (
|
|
29
|
-
return
|
|
28
|
+
const { slice } = parseUnitId(unitId);
|
|
29
|
+
if (slice?.startsWith("S"))
|
|
30
|
+
return slice;
|
|
30
31
|
return null;
|
|
31
32
|
}
|
|
32
33
|
// ─── Unit Description Helpers ─────────────────────────────────────────────────
|
|
@@ -115,6 +116,8 @@ export function describeNextUnit(state) {
|
|
|
115
116
|
return { label: `Replan ${sid}: ${sTitle}`, description: "Blocker found — replan the slice." };
|
|
116
117
|
case "completing-milestone":
|
|
117
118
|
return { label: "Complete milestone", description: "Write milestone summary." };
|
|
119
|
+
case "evaluating-gates":
|
|
120
|
+
return { label: `Evaluate gates for ${sid}: ${sTitle}`, description: "Parallel quality gate assessment before execution." };
|
|
118
121
|
default:
|
|
119
122
|
return { label: "Continue", description: "Execute the next step." };
|
|
120
123
|
}
|
|
@@ -8,13 +8,14 @@
|
|
|
8
8
|
* data structure that is inspectable, testable per-rule, and extensible
|
|
9
9
|
* without modifying orchestration code.
|
|
10
10
|
*/
|
|
11
|
-
import { loadFile, loadActiveOverrides } from "./files.js";
|
|
12
|
-
import { isDbAvailable, getMilestoneSlices } from "./gsd-db.js";
|
|
11
|
+
import { loadFile, extractUatType, loadActiveOverrides } from "./files.js";
|
|
12
|
+
import { isDbAvailable, getMilestoneSlices, getPendingGates, markAllGatesOmitted } from "./gsd-db.js";
|
|
13
|
+
import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
|
|
13
14
|
import { resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveTaskFile, relSliceFile, buildMilestoneFileName, } from "./paths.js";
|
|
14
15
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
15
16
|
import { join } from "node:path";
|
|
16
17
|
import { hasImplementationArtifacts } from "./auto-recovery.js";
|
|
17
|
-
import { buildDiscussMilestonePrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
|
|
18
|
+
import { buildDiscussMilestonePrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, buildGateEvaluatePrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
|
|
18
19
|
function missingSliceStop(mid, phase) {
|
|
19
20
|
return {
|
|
20
21
|
action: "stop",
|
|
@@ -104,15 +105,15 @@ export const DISPATCH_RULES = [
|
|
|
104
105
|
return null;
|
|
105
106
|
}
|
|
106
107
|
for (const sliceId of completedSliceIds) {
|
|
107
|
-
const resultFile = resolveSliceFile(basePath, mid, sliceId, "UAT
|
|
108
|
+
const resultFile = resolveSliceFile(basePath, mid, sliceId, "UAT");
|
|
108
109
|
if (!resultFile)
|
|
109
110
|
continue;
|
|
110
111
|
const content = await loadFile(resultFile);
|
|
111
112
|
if (!content)
|
|
112
113
|
continue;
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
if (verdict && verdict
|
|
114
|
+
const verdict = extractVerdict(content);
|
|
115
|
+
const uatType = extractUatType(content);
|
|
116
|
+
if (verdict && !isAcceptableUatVerdict(verdict, uatType)) {
|
|
116
117
|
return {
|
|
117
118
|
action: "stop",
|
|
118
119
|
reason: `UAT verdict for ${sliceId} is "${verdict}" — blocking progression until resolved.\nReview the UAT result and update the verdict to PASS, or re-run /gsd auto after fixing.`,
|
|
@@ -246,6 +247,32 @@ export const DISPATCH_RULES = [
|
|
|
246
247
|
};
|
|
247
248
|
},
|
|
248
249
|
},
|
|
250
|
+
{
|
|
251
|
+
name: "evaluating-gates → gate-evaluate",
|
|
252
|
+
match: async ({ state, mid, midTitle, basePath, prefs }) => {
|
|
253
|
+
if (state.phase !== "evaluating-gates")
|
|
254
|
+
return null;
|
|
255
|
+
if (!state.activeSlice)
|
|
256
|
+
return missingSliceStop(mid, state.phase);
|
|
257
|
+
const sid = state.activeSlice.id;
|
|
258
|
+
const sTitle = state.activeSlice.title;
|
|
259
|
+
// Gate evaluation is opt-in via preferences
|
|
260
|
+
const gateConfig = prefs?.gate_evaluation;
|
|
261
|
+
if (!gateConfig?.enabled) {
|
|
262
|
+
markAllGatesOmitted(mid, sid);
|
|
263
|
+
return { action: "skip" };
|
|
264
|
+
}
|
|
265
|
+
const pending = getPendingGates(mid, sid, "slice");
|
|
266
|
+
if (pending.length === 0)
|
|
267
|
+
return { action: "skip" };
|
|
268
|
+
return {
|
|
269
|
+
action: "dispatch",
|
|
270
|
+
unitType: "gate-evaluate",
|
|
271
|
+
unitId: `${mid}/${sid}/gates+${pending.map(g => g.gate_id).join(",")}`,
|
|
272
|
+
prompt: await buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, basePath),
|
|
273
|
+
};
|
|
274
|
+
},
|
|
275
|
+
},
|
|
249
276
|
{
|
|
250
277
|
name: "replanning-slice → replan-slice",
|
|
251
278
|
match: async ({ state, mid, midTitle, basePath }) => {
|
|
@@ -15,17 +15,27 @@ import { loadFile, parseSummary, resolveAllOverrides } from "./files.js";
|
|
|
15
15
|
import { loadPrompt } from "./prompt-loader.js";
|
|
16
16
|
import { resolveSliceFile, resolveTaskFile, resolveMilestoneFile, resolveTasksDir, buildTaskFileName, } from "./paths.js";
|
|
17
17
|
import { invalidateAllCaches } from "./cache.js";
|
|
18
|
+
import { parseUnitId } from "./unit-id.js";
|
|
18
19
|
import { closeoutUnit } from "./auto-unit-closeout.js";
|
|
19
20
|
import { autoCommitCurrentBranch, } from "./worktree.js";
|
|
20
21
|
import { verifyExpectedArtifact, resolveExpectedArtifactPath, } from "./auto-recovery.js";
|
|
21
22
|
import { regenerateIfMissing } from "./workflow-projections.js";
|
|
22
|
-
import { syncStateToProjectRoot } from "./auto-worktree
|
|
23
|
+
import { syncStateToProjectRoot } from "./auto-worktree.js";
|
|
23
24
|
import { isDbAvailable, getTask, getSlice, getMilestone, updateTaskStatus, _getAdapter } from "./gsd-db.js";
|
|
24
25
|
import { renderPlanCheckboxes } from "./markdown-renderer.js";
|
|
25
26
|
import { consumeSignal } from "./session-status-io.js";
|
|
26
27
|
import { checkPostUnitHooks, isRetryPending, consumeRetryTrigger, persistHookState, resolveHookArtifactPath, } from "./post-unit-hooks.js";
|
|
27
28
|
import { hasPendingCaptures, loadPendingCaptures } from "./captures.js";
|
|
28
29
|
import { debugLog } from "./debug-logger.js";
|
|
30
|
+
/** Unit types that only touch `.gsd/` internal state files (no code changes).
|
|
31
|
+
* Auto-commit is skipped for these — their state files are picked up by the
|
|
32
|
+
* next actual task commit via `smartStage()`. */
|
|
33
|
+
const LIFECYCLE_ONLY_UNITS = new Set([
|
|
34
|
+
"research-milestone", "discuss-milestone", "plan-milestone",
|
|
35
|
+
"validate-milestone", "research-slice", "plan-slice",
|
|
36
|
+
"replan-slice", "complete-slice", "run-uat",
|
|
37
|
+
"reassess-roadmap", "rewrite-docs",
|
|
38
|
+
]);
|
|
29
39
|
import { existsSync, unlinkSync } from "node:fs";
|
|
30
40
|
import { join } from "node:path";
|
|
31
41
|
import { _resetHasChangesCache } from "./native-git-bridge.js";
|
|
@@ -38,13 +48,20 @@ import { _resetHasChangesCache } from "./native-git-bridge.js";
|
|
|
38
48
|
* in postUnitPostVerification() eventually ingests rogue files, but explicit
|
|
39
49
|
* detection provides immediate diagnostics so operators know the prompt failed.
|
|
40
50
|
*/
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
52
|
+
function hasNonEmptyFields(row, fields) {
|
|
53
|
+
if (!row)
|
|
54
|
+
return false;
|
|
55
|
+
return fields.some(f => String(row[f] || "").trim().length > 0);
|
|
56
|
+
}
|
|
57
|
+
const MILESTONE_PLANNING_FIELDS = ["title", "vision", "requirement_coverage", "boundary_map_markdown"];
|
|
58
|
+
const SLICE_PLANNING_FIELDS = ["title", "demo", "risk", "depends"];
|
|
41
59
|
export function detectRogueFileWrites(unitType, unitId, basePath) {
|
|
42
60
|
if (!isDbAvailable())
|
|
43
61
|
return [];
|
|
44
|
-
const
|
|
62
|
+
const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
|
|
45
63
|
const rogues = [];
|
|
46
64
|
if (unitType === "execute-task") {
|
|
47
|
-
const [mid, sid, tid] = parts;
|
|
48
65
|
if (!mid || !sid || !tid)
|
|
49
66
|
return [];
|
|
50
67
|
const summaryPath = resolveTaskFile(basePath, mid, sid, tid, "SUMMARY");
|
|
@@ -56,7 +73,6 @@ export function detectRogueFileWrites(unitType, unitId, basePath) {
|
|
|
56
73
|
}
|
|
57
74
|
}
|
|
58
75
|
else if (unitType === "complete-slice") {
|
|
59
|
-
const [mid, sid] = parts;
|
|
60
76
|
if (!mid || !sid)
|
|
61
77
|
return [];
|
|
62
78
|
const summaryPath = resolveSliceFile(basePath, mid, sid, "SUMMARY");
|
|
@@ -68,33 +84,25 @@ export function detectRogueFileWrites(unitType, unitId, basePath) {
|
|
|
68
84
|
}
|
|
69
85
|
}
|
|
70
86
|
else if (unitType === "plan-milestone") {
|
|
71
|
-
const [mid] = parts;
|
|
72
87
|
if (!mid)
|
|
73
88
|
return [];
|
|
74
89
|
const roadmapPath = resolveMilestoneFile(basePath, mid, "ROADMAP");
|
|
75
90
|
if (!roadmapPath || !existsSync(roadmapPath))
|
|
76
91
|
return [];
|
|
77
92
|
const dbRow = getMilestone(mid);
|
|
78
|
-
const hasPlanningState =
|
|
79
|
-
String(dbRow.vision || "").trim().length > 0 ||
|
|
80
|
-
String(dbRow.requirement_coverage || "").trim().length > 0 ||
|
|
81
|
-
String(dbRow.boundary_map_markdown || "").trim().length > 0);
|
|
93
|
+
const hasPlanningState = hasNonEmptyFields(dbRow, MILESTONE_PLANNING_FIELDS);
|
|
82
94
|
if (!hasPlanningState) {
|
|
83
95
|
rogues.push({ path: roadmapPath, unitType, unitId });
|
|
84
96
|
}
|
|
85
97
|
}
|
|
86
98
|
else if (unitType === "plan-slice" || unitType === "replan-slice") {
|
|
87
|
-
const [mid, sid] = parts;
|
|
88
99
|
if (!mid || !sid)
|
|
89
100
|
return [];
|
|
90
101
|
const planPath = resolveSliceFile(basePath, mid, sid, "PLAN");
|
|
91
102
|
if (!planPath || !existsSync(planPath))
|
|
92
103
|
return [];
|
|
93
104
|
const dbRow = getSlice(mid, sid);
|
|
94
|
-
const hasPlanningState =
|
|
95
|
-
String(dbRow.demo || "").trim().length > 0 ||
|
|
96
|
-
String(dbRow.risk || "").trim().length > 0 ||
|
|
97
|
-
String(dbRow.depends || "").trim().length > 0);
|
|
105
|
+
const hasPlanningState = hasNonEmptyFields(dbRow, SLICE_PLANNING_FIELDS);
|
|
98
106
|
if (!hasPlanningState) {
|
|
99
107
|
rogues.push({ path: planPath, unitType, unitId });
|
|
100
108
|
}
|
|
@@ -105,7 +113,6 @@ export function detectRogueFileWrites(unitType, unitId, basePath) {
|
|
|
105
113
|
}
|
|
106
114
|
}
|
|
107
115
|
else if (unitType === "reassess-roadmap") {
|
|
108
|
-
const [mid, sid] = parts;
|
|
109
116
|
if (!mid || !sid)
|
|
110
117
|
return [];
|
|
111
118
|
const assessPath = resolveSliceFile(basePath, mid, sid, "ASSESSMENT");
|
|
@@ -121,7 +128,6 @@ export function detectRogueFileWrites(unitType, unitId, basePath) {
|
|
|
121
128
|
}
|
|
122
129
|
}
|
|
123
130
|
else if (unitType === "plan-task") {
|
|
124
|
-
const [mid, sid, tid] = parts;
|
|
125
131
|
if (!mid || !sid || !tid)
|
|
126
132
|
return [];
|
|
127
133
|
const taskPlanPath = resolveTaskFile(basePath, mid, sid, tid, "PLAN");
|
|
@@ -171,8 +177,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
171
177
|
try {
|
|
172
178
|
let taskContext;
|
|
173
179
|
if (s.currentUnit.type === "execute-task") {
|
|
174
|
-
const
|
|
175
|
-
const [mid, sid, tid] = parts;
|
|
180
|
+
const { milestone: mid, slice: sid, task: tid } = parseUnitId(s.currentUnit.id);
|
|
176
181
|
if (mid && sid && tid) {
|
|
177
182
|
const summaryPath = resolveTaskFile(s.basePath, mid, sid, tid, "SUMMARY");
|
|
178
183
|
if (summaryPath) {
|
|
@@ -210,9 +215,14 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
210
215
|
// code files only in the working tree where they are destroyed by
|
|
211
216
|
// `git worktree remove --force` during teardown.
|
|
212
217
|
_resetHasChangesCache();
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
218
|
+
// Skip auto-commit for lifecycle-only units (#2553) — they only touch
|
|
219
|
+
// `.gsd/` internal state files. Those files are picked up by the next
|
|
220
|
+
// actual task commit via smartStage().
|
|
221
|
+
if (!LIFECYCLE_ONLY_UNITS.has(s.currentUnit.type)) {
|
|
222
|
+
const commitMsg = autoCommitCurrentBranch(s.basePath, s.currentUnit.type, s.currentUnit.id, taskContext);
|
|
223
|
+
if (commitMsg) {
|
|
224
|
+
ctx.ui.notify(`Committed: ${commitMsg.split("\n")[0]}`, "info");
|
|
225
|
+
}
|
|
216
226
|
}
|
|
217
227
|
}
|
|
218
228
|
catch (e) {
|
|
@@ -270,8 +280,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
270
280
|
// Reactive state cleanup on slice completion
|
|
271
281
|
if (s.currentUnit.type === "complete-slice") {
|
|
272
282
|
try {
|
|
273
|
-
const
|
|
274
|
-
const [mid, sid] = parts;
|
|
283
|
+
const { milestone: mid, slice: sid } = parseUnitId(s.currentUnit.id);
|
|
275
284
|
if (mid && sid) {
|
|
276
285
|
const { clearReactiveState } = await import("./reactive-graph.js");
|
|
277
286
|
clearReactiveState(s.basePath, mid, sid);
|
|
@@ -342,8 +351,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
342
351
|
// from DB data before giving up (e.g. research-slice produces PLAN from engine).
|
|
343
352
|
if (!triggerArtifactVerified) {
|
|
344
353
|
try {
|
|
345
|
-
const
|
|
346
|
-
const [mid, sid] = parts;
|
|
354
|
+
const { milestone: mid, slice: sid } = parseUnitId(s.currentUnit.id);
|
|
347
355
|
if (mid && sid) {
|
|
348
356
|
const regenerated = regenerateIfMissing(s.basePath, mid, sid, "PLAN");
|
|
349
357
|
if (regenerated) {
|
|
@@ -430,8 +438,7 @@ export async function postUnitPostVerification(pctx) {
|
|
|
430
438
|
ctx.ui.notify(`Hook requested retry of ${trigger.unitType} ${trigger.unitId} — resetting task state.`, "info");
|
|
431
439
|
// ── State reset: undo the completion so deriveState re-derives the unit ──
|
|
432
440
|
try {
|
|
433
|
-
const
|
|
434
|
-
const [mid, sid, tid] = parts;
|
|
441
|
+
const { milestone: mid, slice: sid, task: tid } = parseUnitId(trigger.unitId);
|
|
435
442
|
// 1. Reset task status in DB and re-render plan checkboxes
|
|
436
443
|
if (mid && sid && tid) {
|
|
437
444
|
try {
|