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
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* worktree-sync-overwrite-loop.test.ts — Regression tests for #1886.
|
|
3
|
+
*
|
|
4
|
+
* Reproduces the infinite validate-milestone loop caused by two bugs
|
|
5
|
+
* in syncProjectRootToWorktree:
|
|
6
|
+
*
|
|
7
|
+
* 1. safeCopyRecursive overwrites worktree-authoritative files (e.g.
|
|
8
|
+
* VALIDATION.md written by validate-milestone gets clobbered by the
|
|
9
|
+
* stale project root copy that lacks the file).
|
|
10
|
+
*
|
|
11
|
+
* 2. completed-units.json is not forward-synced from project root to
|
|
12
|
+
* worktree, so the worktree never learns about already-completed units.
|
|
13
|
+
*
|
|
14
|
+
* Covers:
|
|
15
|
+
* - syncProjectRootToWorktree does NOT overwrite existing worktree files
|
|
16
|
+
* - syncProjectRootToWorktree copies files missing from the worktree
|
|
17
|
+
* - completed-units.json is forward-synced from project root to worktree
|
|
18
|
+
* - completed-units.json sync uses force:true (project root is authoritative)
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
mkdtempSync,
|
|
23
|
+
mkdirSync,
|
|
24
|
+
writeFileSync,
|
|
25
|
+
rmSync,
|
|
26
|
+
existsSync,
|
|
27
|
+
readFileSync,
|
|
28
|
+
} from "node:fs";
|
|
29
|
+
import { join } from "node:path";
|
|
30
|
+
import { tmpdir } from "node:os";
|
|
31
|
+
|
|
32
|
+
import { syncProjectRootToWorktree } from "../auto-worktree.ts";
|
|
33
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
34
|
+
|
|
35
|
+
const { assertTrue, assertEq, report } = createTestContext();
|
|
36
|
+
|
|
37
|
+
function createBase(name: string): string {
|
|
38
|
+
const base = mkdtempSync(join(tmpdir(), `gsd-wt-1886-${name}-`));
|
|
39
|
+
mkdirSync(join(base, ".gsd", "milestones"), { recursive: true });
|
|
40
|
+
return base;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function cleanup(base: string): void {
|
|
44
|
+
rmSync(base, { recursive: true, force: true });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function main(): Promise<void> {
|
|
48
|
+
// ─── 1. Worktree VALIDATION.md must NOT be overwritten by project root ──
|
|
49
|
+
console.log(
|
|
50
|
+
"\n=== 1. #1886: worktree VALIDATION.md preserved (not overwritten) ===",
|
|
51
|
+
);
|
|
52
|
+
{
|
|
53
|
+
const mainBase = createBase("main");
|
|
54
|
+
const wtBase = createBase("wt");
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
// Project root has an older CONTEXT but no VALIDATION
|
|
58
|
+
const prM004 = join(mainBase, ".gsd", "milestones", "M004");
|
|
59
|
+
mkdirSync(prM004, { recursive: true });
|
|
60
|
+
writeFileSync(join(prM004, "M004-CONTEXT.md"), "# old context");
|
|
61
|
+
|
|
62
|
+
// Worktree has CONTEXT + VALIDATION (written by validate-milestone)
|
|
63
|
+
const wtM004 = join(wtBase, ".gsd", "milestones", "M004");
|
|
64
|
+
mkdirSync(wtM004, { recursive: true });
|
|
65
|
+
writeFileSync(join(wtM004, "M004-CONTEXT.md"), "# worktree context");
|
|
66
|
+
writeFileSync(
|
|
67
|
+
join(wtM004, "M004-VALIDATION.md"),
|
|
68
|
+
"verdict: pass\nremediation_round: 1",
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
syncProjectRootToWorktree(mainBase, wtBase, "M004");
|
|
72
|
+
|
|
73
|
+
// VALIDATION.md must still exist in worktree
|
|
74
|
+
assertTrue(
|
|
75
|
+
existsSync(join(wtM004, "M004-VALIDATION.md")),
|
|
76
|
+
"#1886: VALIDATION.md still exists after sync",
|
|
77
|
+
);
|
|
78
|
+
assertEq(
|
|
79
|
+
readFileSync(join(wtM004, "M004-VALIDATION.md"), "utf-8"),
|
|
80
|
+
"verdict: pass\nremediation_round: 1",
|
|
81
|
+
"#1886: VALIDATION.md content preserved",
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// CONTEXT.md should NOT be overwritten — worktree version is authoritative
|
|
85
|
+
assertEq(
|
|
86
|
+
readFileSync(join(wtM004, "M004-CONTEXT.md"), "utf-8"),
|
|
87
|
+
"# worktree context",
|
|
88
|
+
"#1886: existing worktree CONTEXT.md not overwritten",
|
|
89
|
+
);
|
|
90
|
+
} finally {
|
|
91
|
+
cleanup(mainBase);
|
|
92
|
+
cleanup(wtBase);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ─── 2. Missing files ARE still copied from project root ────────────────
|
|
97
|
+
console.log("\n=== 2. #1886: missing worktree files still copied ===");
|
|
98
|
+
{
|
|
99
|
+
const mainBase = createBase("main");
|
|
100
|
+
const wtBase = createBase("wt");
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
const prM004 = join(mainBase, ".gsd", "milestones", "M004");
|
|
104
|
+
mkdirSync(prM004, { recursive: true });
|
|
105
|
+
writeFileSync(join(prM004, "M004-CONTEXT.md"), "# from project root");
|
|
106
|
+
writeFileSync(join(prM004, "M004-ROADMAP.md"), "# roadmap");
|
|
107
|
+
|
|
108
|
+
// Worktree has no M004 directory at all
|
|
109
|
+
syncProjectRootToWorktree(mainBase, wtBase, "M004");
|
|
110
|
+
|
|
111
|
+
assertTrue(
|
|
112
|
+
existsSync(join(wtBase, ".gsd", "milestones", "M004", "M004-CONTEXT.md")),
|
|
113
|
+
"#1886: missing CONTEXT.md copied from project root",
|
|
114
|
+
);
|
|
115
|
+
assertTrue(
|
|
116
|
+
existsSync(join(wtBase, ".gsd", "milestones", "M004", "M004-ROADMAP.md")),
|
|
117
|
+
"#1886: missing ROADMAP.md copied from project root",
|
|
118
|
+
);
|
|
119
|
+
} finally {
|
|
120
|
+
cleanup(mainBase);
|
|
121
|
+
cleanup(wtBase);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ─── 3. completed-units.json forward-synced from project root ───────────
|
|
126
|
+
console.log(
|
|
127
|
+
"\n=== 3. #1886: completed-units.json forward-synced to worktree ===",
|
|
128
|
+
);
|
|
129
|
+
{
|
|
130
|
+
const mainBase = createBase("main");
|
|
131
|
+
const wtBase = createBase("wt");
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
// Project root has completed units (authoritative after crash recovery)
|
|
135
|
+
writeFileSync(
|
|
136
|
+
join(mainBase, ".gsd", "completed-units.json"),
|
|
137
|
+
JSON.stringify(["validate-milestone/M004"]),
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
// Worktree has empty completed-units
|
|
141
|
+
writeFileSync(
|
|
142
|
+
join(wtBase, ".gsd", "completed-units.json"),
|
|
143
|
+
JSON.stringify([]),
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
syncProjectRootToWorktree(mainBase, wtBase, "M004");
|
|
147
|
+
|
|
148
|
+
const wtCompleted = JSON.parse(
|
|
149
|
+
readFileSync(join(wtBase, ".gsd", "completed-units.json"), "utf-8"),
|
|
150
|
+
);
|
|
151
|
+
assertEq(
|
|
152
|
+
wtCompleted,
|
|
153
|
+
["validate-milestone/M004"],
|
|
154
|
+
"#1886: completed-units.json synced from project root (force:true)",
|
|
155
|
+
);
|
|
156
|
+
} finally {
|
|
157
|
+
cleanup(mainBase);
|
|
158
|
+
cleanup(wtBase);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ─── 4. completed-units.json: no-op when project root has no file ───────
|
|
163
|
+
console.log(
|
|
164
|
+
"\n=== 4. #1886: completed-units.json no-op when missing in project root ===",
|
|
165
|
+
);
|
|
166
|
+
{
|
|
167
|
+
const mainBase = createBase("main");
|
|
168
|
+
const wtBase = createBase("wt");
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
// Project root milestone dir must exist for sync to run
|
|
172
|
+
const prM004 = join(mainBase, ".gsd", "milestones", "M004");
|
|
173
|
+
mkdirSync(prM004, { recursive: true });
|
|
174
|
+
|
|
175
|
+
// No completed-units.json in project root
|
|
176
|
+
// Worktree has its own
|
|
177
|
+
writeFileSync(
|
|
178
|
+
join(wtBase, ".gsd", "completed-units.json"),
|
|
179
|
+
JSON.stringify(["some-unit/M001"]),
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
syncProjectRootToWorktree(mainBase, wtBase, "M004");
|
|
183
|
+
|
|
184
|
+
const wtCompleted = JSON.parse(
|
|
185
|
+
readFileSync(join(wtBase, ".gsd", "completed-units.json"), "utf-8"),
|
|
186
|
+
);
|
|
187
|
+
assertEq(
|
|
188
|
+
wtCompleted,
|
|
189
|
+
["some-unit/M001"],
|
|
190
|
+
"#1886: worktree completed-units.json untouched when project root has none",
|
|
191
|
+
);
|
|
192
|
+
} finally {
|
|
193
|
+
cleanup(mainBase);
|
|
194
|
+
cleanup(wtBase);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
report();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
main().catch((error) => {
|
|
202
|
+
console.error(error);
|
|
203
|
+
process.exit(1);
|
|
204
|
+
});
|
|
@@ -6,8 +6,10 @@ import {
|
|
|
6
6
|
insertTask,
|
|
7
7
|
upsertSlicePlanning,
|
|
8
8
|
upsertTaskPlanning,
|
|
9
|
+
insertGateRow,
|
|
9
10
|
_getAdapter,
|
|
10
11
|
} from "../gsd-db.js";
|
|
12
|
+
import type { GateId } from "../types.js";
|
|
11
13
|
import { invalidateStateCache } from "../state.js";
|
|
12
14
|
import { renderPlanFromDb } from "../markdown-renderer.js";
|
|
13
15
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
@@ -190,6 +192,20 @@ export async function handlePlanSlice(
|
|
|
190
192
|
fullPlanMd: task.fullPlanMd,
|
|
191
193
|
});
|
|
192
194
|
}
|
|
195
|
+
|
|
196
|
+
// Seed quality gate rows inside the transaction — all-or-nothing with
|
|
197
|
+
// the plan data so a crash can't leave orphaned gates without tasks.
|
|
198
|
+
const sliceGates: GateId[] = ["Q3", "Q4"];
|
|
199
|
+
for (const gid of sliceGates) {
|
|
200
|
+
insertGateRow({ milestoneId: params.milestoneId, sliceId: params.sliceId, gateId: gid, scope: "slice" });
|
|
201
|
+
}
|
|
202
|
+
const taskGates: GateId[] = ["Q5", "Q6", "Q7"];
|
|
203
|
+
for (const task of params.tasks) {
|
|
204
|
+
for (const gid of taskGates) {
|
|
205
|
+
insertGateRow({ milestoneId: params.milestoneId, sliceId: params.sliceId, gateId: gid, scope: "task", taskId: task.taskId });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
insertGateRow({ milestoneId: params.milestoneId, sliceId: params.sliceId, gateId: "Q8", scope: "slice" });
|
|
193
209
|
});
|
|
194
210
|
} catch (err) {
|
|
195
211
|
return { error: `db write failed: ${(err as Error).message}` };
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import { resolveMilestonePath, clearPathCache } from "../paths.js";
|
|
15
15
|
import { saveFile, clearParseCache } from "../files.js";
|
|
16
16
|
import { invalidateStateCache } from "../state.js";
|
|
17
|
+
import { VALIDATION_VERDICTS, isValidMilestoneVerdict } from "../verdict-parser.js";
|
|
17
18
|
|
|
18
19
|
export interface ValidateMilestoneParams {
|
|
19
20
|
milestoneId: string;
|
|
@@ -71,9 +72,8 @@ export async function handleValidateMilestone(
|
|
|
71
72
|
if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
|
|
72
73
|
return { error: "milestoneId is required and must be a non-empty string" };
|
|
73
74
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return { error: `verdict must be one of: ${validVerdicts.join(", ")}` };
|
|
75
|
+
if (!isValidMilestoneVerdict(params.verdict)) {
|
|
76
|
+
return { error: `verdict must be one of: ${VALIDATION_VERDICTS.join(", ")}` };
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
// ── Filesystem render ──────────────────────────────────────────────────
|
|
@@ -11,6 +11,7 @@ export type Phase =
|
|
|
11
11
|
| "discussing"
|
|
12
12
|
| "researching"
|
|
13
13
|
| "planning"
|
|
14
|
+
| "evaluating-gates"
|
|
14
15
|
| "executing"
|
|
15
16
|
| "verifying"
|
|
16
17
|
| "summarizing"
|
|
@@ -557,3 +558,32 @@ export interface CompleteSliceParams {
|
|
|
557
558
|
/** Optional caller-provided reason this action was triggered */
|
|
558
559
|
triggerReason?: string;
|
|
559
560
|
}
|
|
561
|
+
|
|
562
|
+
// ─── Quality Gates ───────────────────────────────────────────────────────
|
|
563
|
+
|
|
564
|
+
export type GateId = "Q3" | "Q4" | "Q5" | "Q6" | "Q7" | "Q8";
|
|
565
|
+
export type GateScope = "slice" | "task";
|
|
566
|
+
export type GateStatus = "pending" | "complete" | "omitted";
|
|
567
|
+
export type GateVerdict = "pass" | "flag" | "omitted" | "";
|
|
568
|
+
|
|
569
|
+
export interface GateRow {
|
|
570
|
+
milestone_id: string;
|
|
571
|
+
slice_id: string;
|
|
572
|
+
gate_id: GateId;
|
|
573
|
+
scope: GateScope;
|
|
574
|
+
task_id: string;
|
|
575
|
+
status: GateStatus;
|
|
576
|
+
verdict: GateVerdict;
|
|
577
|
+
rationale: string;
|
|
578
|
+
findings: string;
|
|
579
|
+
evaluated_at: string | null;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/** Configuration for parallel quality gate evaluation during slice planning. */
|
|
583
|
+
export interface GateEvaluationConfig {
|
|
584
|
+
enabled: boolean;
|
|
585
|
+
/** Which slice-scoped gates to evaluate in parallel. Default: ['Q3', 'Q4']. */
|
|
586
|
+
slice_gates?: string[];
|
|
587
|
+
/** Whether to evaluate task-level gates (Q5/Q6/Q7) via reactive-execute. Default: true when enabled. */
|
|
588
|
+
task_gates?: boolean;
|
|
589
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized verdict extraction, normalization, and schema validation.
|
|
3
|
+
*
|
|
4
|
+
* All verdict-related logic lives here so that normalization rules
|
|
5
|
+
* (e.g. `passed` → `pass`) are applied consistently across the codebase.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { extractUatType } from "./files.js";
|
|
9
|
+
import type { UatType } from "./files.js";
|
|
10
|
+
|
|
11
|
+
// ── Verdict extraction ──────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Extract and normalize the `verdict` value from YAML frontmatter.
|
|
15
|
+
*
|
|
16
|
+
* Normalization:
|
|
17
|
+
* - lowercased
|
|
18
|
+
* - `passed` → `pass`
|
|
19
|
+
*
|
|
20
|
+
* Returns `undefined` when frontmatter is absent or has no `verdict` field.
|
|
21
|
+
*/
|
|
22
|
+
export function extractVerdict(content: string): string | undefined {
|
|
23
|
+
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
24
|
+
if (!fmMatch) return undefined;
|
|
25
|
+
const verdictMatch = fmMatch[1].match(/verdict:\s*([\w-]+)/i);
|
|
26
|
+
if (!verdictMatch) return undefined;
|
|
27
|
+
let v = verdictMatch[1].toLowerCase();
|
|
28
|
+
if (v === "passed") v = "pass";
|
|
29
|
+
return v;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Returns `true` when the content's frontmatter contains a `verdict` field.
|
|
34
|
+
*/
|
|
35
|
+
export function hasVerdict(content: string): boolean {
|
|
36
|
+
return /verdict:\s*[\w-]+/i.test(content);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ── UAT verdict schema ──────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Base verdicts that are always acceptable for UAT results.
|
|
43
|
+
*/
|
|
44
|
+
export const UAT_ACCEPTABLE_VERDICTS: readonly string[] = ["pass", "passed"];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* UAT types whose results may legitimately produce a `partial` verdict
|
|
48
|
+
* when all automatable checks pass but human-only checks remain.
|
|
49
|
+
*/
|
|
50
|
+
const PARTIAL_ELIGIBLE_UAT_TYPES: readonly UatType[] = [
|
|
51
|
+
"mixed",
|
|
52
|
+
"human-experience",
|
|
53
|
+
"live-runtime",
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Check whether a verdict is acceptable for a given UAT type.
|
|
58
|
+
*
|
|
59
|
+
* `pass` / `passed` are always acceptable. `partial` is acceptable only for
|
|
60
|
+
* UAT types that include non-automatable human checks.
|
|
61
|
+
*/
|
|
62
|
+
export function isAcceptableUatVerdict(verdict: string, uatType: UatType | undefined): boolean {
|
|
63
|
+
if (UAT_ACCEPTABLE_VERDICTS.includes(verdict)) return true;
|
|
64
|
+
if (verdict === "partial" && uatType && (PARTIAL_ELIGIBLE_UAT_TYPES as readonly string[]).includes(uatType)) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ── Milestone validation verdict schema ─────────────────────────────────
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Valid verdicts for the `validate-milestone` tool.
|
|
74
|
+
*/
|
|
75
|
+
export const VALIDATION_VERDICTS = ["pass", "needs-attention", "needs-remediation"] as const;
|
|
76
|
+
export type ValidationVerdict = (typeof VALIDATION_VERDICTS)[number];
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Check whether a string is a valid milestone validation verdict.
|
|
80
|
+
*/
|
|
81
|
+
export function isValidMilestoneVerdict(verdict: string): verdict is ValidationVerdict {
|
|
82
|
+
return (VALIDATION_VERDICTS as readonly string[]).includes(verdict);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ── UAT type helper ─────────────────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Extract the UAT type from content, defaulting to `"artifact-driven"`.
|
|
89
|
+
*
|
|
90
|
+
* The `"artifact-driven"` fallback is the original default used throughout
|
|
91
|
+
* the codebase when a UAT file lacks an explicit `## UAT Type` section.
|
|
92
|
+
*/
|
|
93
|
+
export function getUatType(content: string): UatType {
|
|
94
|
+
return extractUatType(content) ?? "artifact-driven";
|
|
95
|
+
}
|
|
@@ -661,7 +661,7 @@ async function handleMerge(
|
|
|
661
661
|
// --- Deterministic merge path (preferred) ---
|
|
662
662
|
// Try a direct squash-merge first. Only fall back to LLM on conflict.
|
|
663
663
|
const commitType = inferCommitType(name);
|
|
664
|
-
const commitMessage = `${commitType}
|
|
664
|
+
const commitMessage = `${commitType}: merge worktree ${name}\n\nGSD-Worktree: ${name}`;
|
|
665
665
|
|
|
666
666
|
// Reconcile worktree DB into main DB before squash merge
|
|
667
667
|
const wtDbPath = join(worktreePath(basePath, name), ".gsd", "gsd.db");
|
|
@@ -150,6 +150,18 @@ export class WorktreeResolver {
|
|
|
150
150
|
*/
|
|
151
151
|
enterMilestone(milestoneId: string, ctx: NotifyCtx): void {
|
|
152
152
|
this.validateMilestoneId(milestoneId);
|
|
153
|
+
|
|
154
|
+
// If worktree creation failed earlier this session, skip all future attempts
|
|
155
|
+
if (this.s.isolationDegraded) {
|
|
156
|
+
debugLog("WorktreeResolver", {
|
|
157
|
+
action: "enterMilestone",
|
|
158
|
+
milestoneId,
|
|
159
|
+
skipped: true,
|
|
160
|
+
reason: "isolation-degraded",
|
|
161
|
+
});
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
153
165
|
if (!this.deps.shouldUseWorktreeIsolation()) {
|
|
154
166
|
debugLog("WorktreeResolver", {
|
|
155
167
|
action: "enterMilestone",
|
|
@@ -220,6 +232,9 @@ export class WorktreeResolver {
|
|
|
220
232
|
`Auto-worktree creation for ${milestoneId} failed: ${msg}. Continuing in project root.`,
|
|
221
233
|
"warning",
|
|
222
234
|
);
|
|
235
|
+
// Degrade isolation for the rest of this session so mergeAndExit
|
|
236
|
+
// doesn't try to merge a nonexistent worktree branch (#2483)
|
|
237
|
+
this.s.isolationDegraded = true;
|
|
223
238
|
// Do NOT update s.basePath — stay in project root
|
|
224
239
|
}
|
|
225
240
|
}
|
|
@@ -304,6 +319,22 @@ export class WorktreeResolver {
|
|
|
304
319
|
*/
|
|
305
320
|
mergeAndExit(milestoneId: string, ctx: NotifyCtx): void {
|
|
306
321
|
this.validateMilestoneId(milestoneId);
|
|
322
|
+
|
|
323
|
+
// If worktree creation failed earlier, skip merge — work is on current branch (#2483)
|
|
324
|
+
if (this.s.isolationDegraded) {
|
|
325
|
+
debugLog("WorktreeResolver", {
|
|
326
|
+
action: "mergeAndExit",
|
|
327
|
+
milestoneId,
|
|
328
|
+
skipped: true,
|
|
329
|
+
reason: "isolation-degraded",
|
|
330
|
+
});
|
|
331
|
+
ctx.notify(
|
|
332
|
+
`Skipping worktree merge for ${milestoneId} — isolation was degraded (worktree creation failed earlier). Work is on the current branch.`,
|
|
333
|
+
"info",
|
|
334
|
+
);
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
|
|
307
338
|
const mode = this.deps.getIsolationMode();
|
|
308
339
|
debugLog("WorktreeResolver", {
|
|
309
340
|
action: "mergeAndExit",
|
|
@@ -235,8 +235,9 @@ export function getSliceBranchName(milestoneId: string, sliceId: string, worktre
|
|
|
235
235
|
return `gsd/${milestoneId}/${sliceId}`;
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
/**
|
|
239
|
-
export
|
|
238
|
+
/** Re-export for backward compatibility — canonical definition in branch-patterns.ts */
|
|
239
|
+
export { SLICE_BRANCH_RE } from "./branch-patterns.js";
|
|
240
|
+
import { SLICE_BRANCH_RE } from "./branch-patterns.js";
|
|
240
241
|
|
|
241
242
|
/**
|
|
242
243
|
* Parse a slice branch name into its components.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Remote Questions — configuration resolution and validation
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { AuthStorage } from "@gsd/pi-coding-agent";
|
|
6
6
|
import { loadEffectiveGSDPreferences, type RemoteQuestionsConfig } from "../gsd/preferences.js";
|
|
7
7
|
import type { RemoteChannel } from "./types.js";
|
|
8
8
|
|
|
@@ -54,9 +54,7 @@ function hydrateRemoteTokensFromAuth(): void {
|
|
|
54
54
|
if (needed.length === 0) return;
|
|
55
55
|
|
|
56
56
|
try {
|
|
57
|
-
const
|
|
58
|
-
const authPath = join(process.env.HOME ?? "~", ".gsd", "agent", "auth.json");
|
|
59
|
-
const auth = AuthStorage.create(authPath);
|
|
57
|
+
const auth = AuthStorage.create();
|
|
60
58
|
|
|
61
59
|
for (const [providerId, envVar] of needed) {
|
|
62
60
|
try {
|
|
@@ -72,7 +70,7 @@ function hydrateRemoteTokensFromAuth(): void {
|
|
|
72
70
|
}
|
|
73
71
|
}
|
|
74
72
|
} catch {
|
|
75
|
-
// AuthStorage unavailable
|
|
73
|
+
// AuthStorage unavailable or auth.json missing/unreadable — skip silently.
|
|
76
74
|
}
|
|
77
75
|
}
|
|
78
76
|
|
|
@@ -176,11 +176,15 @@ export function registerNativeSearchHooks(pi: NativeSearchPI): { getIsAnthropic:
|
|
|
176
176
|
);
|
|
177
177
|
payload.tools = tools;
|
|
178
178
|
|
|
179
|
-
// ── Session-level search budget (#1309)
|
|
179
|
+
// ── Session-level search budget (#1309, #compaction-safe) ─────────────
|
|
180
180
|
// Count web_search_tool_result blocks in the conversation history to
|
|
181
181
|
// determine how many native searches have already been used this session.
|
|
182
182
|
// The Anthropic API's max_uses resets per request, so without this guard,
|
|
183
183
|
// pause_turn → resubmit cycles allow unlimited total searches.
|
|
184
|
+
//
|
|
185
|
+
// Use the monotonic high-water mark: take the max of the history count
|
|
186
|
+
// and the running counter. This prevents budget resets when context
|
|
187
|
+
// compaction removes web_search_tool_result blocks from history.
|
|
184
188
|
if (Array.isArray(messages)) {
|
|
185
189
|
let historySearchCount = 0;
|
|
186
190
|
for (const msg of messages) {
|
|
@@ -192,8 +196,9 @@ export function registerNativeSearchHooks(pi: NativeSearchPI): { getIsAnthropic:
|
|
|
192
196
|
}
|
|
193
197
|
}
|
|
194
198
|
}
|
|
195
|
-
//
|
|
196
|
-
|
|
199
|
+
// High-water mark: never decrease the counter, even if compaction
|
|
200
|
+
// removes web_search_tool_result blocks from the visible history.
|
|
201
|
+
sessionSearchCount = Math.max(sessionSearchCount, historySearchCount);
|
|
197
202
|
}
|
|
198
203
|
|
|
199
204
|
const remaining = Math.max(0, MAX_NATIVE_SEARCHES_PER_SESSION - sessionSearchCount);
|
|
@@ -106,14 +106,20 @@ searchCache.startPurgeInterval(60_000);
|
|
|
106
106
|
|
|
107
107
|
// Consecutive duplicate search guard (#949)
|
|
108
108
|
// Tracks recent query keys to detect and break search loops.
|
|
109
|
-
const MAX_CONSECUTIVE_DUPES =
|
|
109
|
+
const MAX_CONSECUTIVE_DUPES = 1;
|
|
110
110
|
let lastSearchKey = "";
|
|
111
111
|
let consecutiveDupeCount = 0;
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
// Session-level total search budget (all queries, not just duplicates).
|
|
114
|
+
// Prevents unbounded search accumulation across varied queries.
|
|
115
|
+
const MAX_SEARCHES_PER_SESSION = 15;
|
|
116
|
+
let sessionTotalSearches = 0;
|
|
117
|
+
|
|
118
|
+
/** Reset session-scoped search guard state (both duplicate and budget). */
|
|
114
119
|
export function resetSearchLoopGuardState(): void {
|
|
115
120
|
lastSearchKey = "";
|
|
116
121
|
consecutiveDupeCount = 0;
|
|
122
|
+
sessionTotalSearches = 0;
|
|
117
123
|
}
|
|
118
124
|
|
|
119
125
|
// Summarizer responses: max 50 entries, 15-minute TTL
|
|
@@ -357,6 +363,17 @@ export function registerSearchTool(pi: ExtensionAPI) {
|
|
|
357
363
|
};
|
|
358
364
|
}
|
|
359
365
|
|
|
366
|
+
// ------------------------------------------------------------------
|
|
367
|
+
// Session-level search budget
|
|
368
|
+
// ------------------------------------------------------------------
|
|
369
|
+
if (sessionTotalSearches >= MAX_SEARCHES_PER_SESSION) {
|
|
370
|
+
return {
|
|
371
|
+
content: [{ type: "text" as const, text: `⚠️ Search budget exhausted: ${sessionTotalSearches}/${MAX_SEARCHES_PER_SESSION} searches used this session. The information you need should already be in previous search results. Stop searching and use those results to proceed with your task.` }],
|
|
372
|
+
isError: true,
|
|
373
|
+
details: { errorKind: "budget_exhausted", error: `Session search budget exhausted (${MAX_SEARCHES_PER_SESSION})` } satisfies Partial<SearchDetails>,
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
|
|
360
377
|
const count = params.count ?? 5;
|
|
361
378
|
const wantSummary = params.summary ?? false;
|
|
362
379
|
|
|
@@ -410,6 +427,9 @@ export function registerSearchTool(pi: ExtensionAPI) {
|
|
|
410
427
|
consecutiveDupeCount = 1;
|
|
411
428
|
}
|
|
412
429
|
|
|
430
|
+
// Count every search that passes the guards toward the session budget.
|
|
431
|
+
sessionTotalSearches++;
|
|
432
|
+
|
|
413
433
|
const cached = searchCache.get(cacheKey);
|
|
414
434
|
|
|
415
435
|
if (cached) {
|
|
@@ -103,9 +103,12 @@ gh issue list -R gsd-build/gsd-2
|
|
|
103
103
|
gh issue list -R gsd-build/gsd-2 --label "priority:p1" --state open
|
|
104
104
|
|
|
105
105
|
# Create issue with labels and milestone
|
|
106
|
+
# NOTE: Do NOT use labels for issue classification (bug, feature, etc.)
|
|
107
|
+
# Use labels for metadata (priority, status, auto-generated) only.
|
|
108
|
+
# Issue classification uses GitHub Issue Types, set via GraphQL after creation.
|
|
106
109
|
gh issue create -R gsd-build/gsd-2 \
|
|
107
110
|
--title "feat: add feature X" \
|
|
108
|
-
--label "priority:p1"
|
|
111
|
+
--label "priority:p1" \
|
|
109
112
|
--milestone "v1.0"
|
|
110
113
|
|
|
111
114
|
# View issue
|
|
@@ -120,6 +123,24 @@ gh issue edit <number> -R gsd-build/gsd-2 \
|
|
|
120
123
|
--remove-label "status:needs-grooming"
|
|
121
124
|
```
|
|
122
125
|
|
|
126
|
+
### Issue Types (Classification)
|
|
127
|
+
|
|
128
|
+
`gh issue create` has no `--type` flag. Issue types (Bug, Feature Request, etc.) are set via GraphQL after creation:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# Step 1: Create the issue (returns URL)
|
|
132
|
+
ISSUE_URL=$(gh issue create -R gsd-build/gsd-2 \
|
|
133
|
+
--title "..." --body "...")
|
|
134
|
+
|
|
135
|
+
# Step 2: Set the issue type via GraphQL
|
|
136
|
+
ISSUE_NUM=$(echo "$ISSUE_URL" | grep -oE '[0-9]+$')
|
|
137
|
+
ISSUE_ID=$(gh api graphql -f query='{ repository(owner:"gsd-build",name:"gsd-2") { issue(number:'"$ISSUE_NUM"') { id } } }' --jq '.data.repository.issue.id')
|
|
138
|
+
TYPE_ID=$(gh api graphql -f query='{ repository(owner:"gsd-build",name:"gsd-2") { issueTypes(first:20) { nodes { id name } } } }' --jq '.data.repository.issueTypes.nodes[] | select(.name=="Bug") | .id')
|
|
139
|
+
gh api graphql -f query='mutation { updateIssue(input:{id:"'"$ISSUE_ID"'",issueTypeId:"'"$TYPE_ID"'"}) { issue { number } } }'
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Replace `"Bug"` with the appropriate type name (`"Feature Request"`, `"Task"`, etc.).
|
|
143
|
+
|
|
123
144
|
### Labels
|
|
124
145
|
|
|
125
146
|
```bash
|