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,156 @@
|
|
|
1
|
+
// Quality gate DB storage tests
|
|
2
|
+
// Verifies CRUD operations on the quality_gates table.
|
|
3
|
+
|
|
4
|
+
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
openDatabase,
|
|
12
|
+
closeDatabase,
|
|
13
|
+
insertGateRow,
|
|
14
|
+
saveGateResult,
|
|
15
|
+
getPendingGates,
|
|
16
|
+
getGateResults,
|
|
17
|
+
markAllGatesOmitted,
|
|
18
|
+
getPendingSliceGateCount,
|
|
19
|
+
insertMilestone,
|
|
20
|
+
insertSlice,
|
|
21
|
+
} from "../gsd-db.ts";
|
|
22
|
+
|
|
23
|
+
describe("quality_gates CRUD", () => {
|
|
24
|
+
let tmpDir: string;
|
|
25
|
+
let dbPath: string;
|
|
26
|
+
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
tmpDir = mkdtempSync(join(tmpdir(), "gate-test-"));
|
|
29
|
+
dbPath = join(tmpDir, "gsd.db");
|
|
30
|
+
openDatabase(dbPath);
|
|
31
|
+
// Seed parent rows
|
|
32
|
+
insertMilestone({
|
|
33
|
+
id: "M001",
|
|
34
|
+
title: "Test Milestone",
|
|
35
|
+
status: "active",
|
|
36
|
+
});
|
|
37
|
+
insertSlice({
|
|
38
|
+
milestoneId: "M001",
|
|
39
|
+
id: "S01",
|
|
40
|
+
title: "Test Slice",
|
|
41
|
+
status: "pending",
|
|
42
|
+
risk: "medium",
|
|
43
|
+
depends: [],
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
afterEach(() => {
|
|
48
|
+
closeDatabase();
|
|
49
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("insertGateRow creates a pending gate", () => {
|
|
53
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
54
|
+
const pending = getPendingGates("M001", "S01");
|
|
55
|
+
assert.equal(pending.length, 1);
|
|
56
|
+
assert.equal(pending[0].gate_id, "Q3");
|
|
57
|
+
assert.equal(pending[0].status, "pending");
|
|
58
|
+
assert.equal(pending[0].scope, "slice");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("insertGateRow with INSERT OR IGNORE is idempotent", () => {
|
|
62
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
63
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
64
|
+
const all = getGateResults("M001", "S01");
|
|
65
|
+
assert.equal(all.length, 1);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("saveGateResult updates status and verdict", () => {
|
|
69
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
70
|
+
saveGateResult({
|
|
71
|
+
milestoneId: "M001",
|
|
72
|
+
sliceId: "S01",
|
|
73
|
+
gateId: "Q3",
|
|
74
|
+
verdict: "pass",
|
|
75
|
+
rationale: "No auth surface",
|
|
76
|
+
findings: "This slice has no user-facing endpoints.",
|
|
77
|
+
});
|
|
78
|
+
const results = getGateResults("M001", "S01");
|
|
79
|
+
assert.equal(results.length, 1);
|
|
80
|
+
assert.equal(results[0].status, "complete");
|
|
81
|
+
assert.equal(results[0].verdict, "pass");
|
|
82
|
+
assert.equal(results[0].rationale, "No auth surface");
|
|
83
|
+
assert.ok(results[0].evaluated_at);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("getPendingGates filters by scope", () => {
|
|
87
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
88
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q5", scope: "task", taskId: "T01" });
|
|
89
|
+
|
|
90
|
+
const sliceGates = getPendingGates("M001", "S01", "slice");
|
|
91
|
+
assert.equal(sliceGates.length, 1);
|
|
92
|
+
assert.equal(sliceGates[0].gate_id, "Q3");
|
|
93
|
+
|
|
94
|
+
const taskGates = getPendingGates("M001", "S01", "task");
|
|
95
|
+
assert.equal(taskGates.length, 1);
|
|
96
|
+
assert.equal(taskGates[0].gate_id, "Q5");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("markAllGatesOmitted marks all pending gates as omitted", () => {
|
|
100
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
101
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q4", scope: "slice" });
|
|
102
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q5", scope: "task", taskId: "T01" });
|
|
103
|
+
|
|
104
|
+
markAllGatesOmitted("M001", "S01");
|
|
105
|
+
|
|
106
|
+
const pending = getPendingGates("M001", "S01");
|
|
107
|
+
assert.equal(pending.length, 0);
|
|
108
|
+
|
|
109
|
+
const all = getGateResults("M001", "S01");
|
|
110
|
+
assert.equal(all.length, 3);
|
|
111
|
+
for (const g of all) {
|
|
112
|
+
assert.equal(g.status, "omitted");
|
|
113
|
+
assert.equal(g.verdict, "omitted");
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("getPendingSliceGateCount returns correct count", () => {
|
|
118
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
119
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q4", scope: "slice" });
|
|
120
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q5", scope: "task", taskId: "T01" });
|
|
121
|
+
|
|
122
|
+
assert.equal(getPendingSliceGateCount("M001", "S01"), 2);
|
|
123
|
+
|
|
124
|
+
saveGateResult({
|
|
125
|
+
milestoneId: "M001", sliceId: "S01", gateId: "Q3",
|
|
126
|
+
verdict: "pass", rationale: "OK", findings: "",
|
|
127
|
+
});
|
|
128
|
+
assert.equal(getPendingSliceGateCount("M001", "S01"), 1);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("task-scoped gates with different task_id are distinct", () => {
|
|
132
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q5", scope: "task", taskId: "T01" });
|
|
133
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q5", scope: "task", taskId: "T02" });
|
|
134
|
+
|
|
135
|
+
const all = getGateResults("M001", "S01", "task");
|
|
136
|
+
assert.equal(all.length, 2);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("getGateResults returns empty for nonexistent slice", () => {
|
|
140
|
+
const results = getGateResults("M001", "S99");
|
|
141
|
+
assert.equal(results.length, 0);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("saveGateResult with flag verdict preserves findings", () => {
|
|
145
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q4", scope: "slice" });
|
|
146
|
+
saveGateResult({
|
|
147
|
+
milestoneId: "M001", sliceId: "S01", gateId: "Q4",
|
|
148
|
+
verdict: "flag", rationale: "Breaks R003",
|
|
149
|
+
findings: "## R003 Impact\n\n- Login flow must be re-tested\n- Session token format changed",
|
|
150
|
+
});
|
|
151
|
+
const results = getGateResults("M001", "S01", "slice");
|
|
152
|
+
const q4 = results.find(g => g.gate_id === "Q4")!;
|
|
153
|
+
assert.equal(q4.verdict, "flag");
|
|
154
|
+
assert.ok(q4.findings.includes("R003 Impact"));
|
|
155
|
+
});
|
|
156
|
+
});
|
|
@@ -215,10 +215,12 @@ describe('git-service', async () => {
|
|
|
215
215
|
oneLiner: "Added JWT-based auth with refresh token rotation",
|
|
216
216
|
keyFiles: ["src/auth.ts", "src/middleware/jwt.ts"],
|
|
217
217
|
});
|
|
218
|
-
assert.ok(msg.startsWith("feat
|
|
218
|
+
assert.ok(msg.startsWith("feat:"), "message starts with type: (no scope)");
|
|
219
|
+
assert.ok(!msg.includes("(S01/T02)"), "no GSD ID in subject line");
|
|
219
220
|
assert.ok(msg.includes("JWT-based auth"), "message includes one-liner content");
|
|
220
221
|
assert.ok(msg.includes("- src/auth.ts"), "message body includes key files");
|
|
221
222
|
assert.ok(msg.includes("- src/middleware/jwt.ts"), "message body includes second key file");
|
|
223
|
+
assert.ok(msg.includes("GSD-Task: S01/T02"), "GSD-Task trailer in body");
|
|
222
224
|
});
|
|
223
225
|
|
|
224
226
|
{
|
|
@@ -226,9 +228,9 @@ describe('git-service', async () => {
|
|
|
226
228
|
taskId: "S02/T01",
|
|
227
229
|
taskTitle: "fix login redirect bug",
|
|
228
230
|
});
|
|
229
|
-
assert.ok(msg.startsWith("fix
|
|
231
|
+
assert.ok(msg.startsWith("fix:"), "infers fix type from title");
|
|
230
232
|
assert.ok(msg.includes("fix login redirect bug"), "uses task title when no one-liner");
|
|
231
|
-
assert.ok(
|
|
233
|
+
assert.ok(msg.includes("GSD-Task: S02/T01"), "GSD-Task trailer present");
|
|
232
234
|
}
|
|
233
235
|
|
|
234
236
|
{
|
|
@@ -237,7 +239,8 @@ describe('git-service', async () => {
|
|
|
237
239
|
taskTitle: "add tests",
|
|
238
240
|
oneLiner: "Unit tests for auth module with coverage",
|
|
239
241
|
});
|
|
240
|
-
assert.ok(msg.startsWith("test
|
|
242
|
+
assert.ok(msg.startsWith("test:"), "infers test type");
|
|
243
|
+
assert.ok(msg.includes("GSD-Task: S01/T03"), "GSD-Task trailer present");
|
|
241
244
|
}
|
|
242
245
|
|
|
243
246
|
// ─── RUNTIME_EXCLUSION_PATHS ───────────────────────────────────────────
|
|
@@ -478,10 +481,10 @@ describe('git-service', async () => {
|
|
|
478
481
|
|
|
479
482
|
// Without task context, autoCommit uses generic chore message
|
|
480
483
|
const msg = svc.autoCommit("task", "T01");
|
|
481
|
-
assert.deepStrictEqual(msg, "chore
|
|
484
|
+
assert.deepStrictEqual(msg, "chore: auto-commit after task\n\nGSD-Unit: T01", "autoCommit returns generic format with trailer");
|
|
482
485
|
|
|
483
486
|
const log = run("git log --oneline -1", repo);
|
|
484
|
-
assert.ok(log.includes("chore
|
|
487
|
+
assert.ok(log.includes("chore: auto-commit after task"), "generic commit message is in git log");
|
|
485
488
|
|
|
486
489
|
// With task context, autoCommit uses meaningful message
|
|
487
490
|
createFile(repo, "src/auth.ts", "export function login() {}");
|
|
@@ -492,8 +495,9 @@ describe('git-service', async () => {
|
|
|
492
495
|
keyFiles: ["src/auth.ts"],
|
|
493
496
|
});
|
|
494
497
|
assert.ok(msg2 !== null, "autoCommit with task context returns a message");
|
|
495
|
-
assert.ok(msg2!.startsWith("feat
|
|
498
|
+
assert.ok(msg2!.startsWith("feat:"), "meaningful commit uses feat type without scope");
|
|
496
499
|
assert.ok(msg2!.includes("JWT-based auth"), "meaningful commit includes one-liner content");
|
|
500
|
+
assert.ok(msg2!.includes("GSD-Task: S01/T02"), "meaningful commit has GSD-Task trailer");
|
|
497
501
|
|
|
498
502
|
rmSync(repo, { recursive: true, force: true });
|
|
499
503
|
});
|
|
@@ -529,7 +533,7 @@ describe('git-service', async () => {
|
|
|
529
533
|
|
|
530
534
|
// Auto-commit with .gsd/ excluded (simulates pre-switch)
|
|
531
535
|
const msg = svc.autoCommit("pre-switch", "main", [".gsd/"]);
|
|
532
|
-
assert.deepStrictEqual(msg, "chore
|
|
536
|
+
assert.deepStrictEqual(msg, "chore: auto-commit after pre-switch\n\nGSD-Unit: main", "pre-switch autoCommit with .gsd/ exclusion commits");
|
|
533
537
|
|
|
534
538
|
// Verify .gsd/ file was NOT committed
|
|
535
539
|
const show = run("git show --stat HEAD", repo);
|
|
@@ -864,6 +868,55 @@ describe('git-service', async () => {
|
|
|
864
868
|
rmSync(repo, { recursive: true, force: true });
|
|
865
869
|
});
|
|
866
870
|
|
|
871
|
+
// ─── writeIntegrationBranch: rejects workflow-template branches (#2498) ─
|
|
872
|
+
|
|
873
|
+
test('Integration branch: rejects workflow-template branches', () => {
|
|
874
|
+
const repo = initBranchTestRepo();
|
|
875
|
+
|
|
876
|
+
// All 8 registered workflow templates should be rejected
|
|
877
|
+
writeIntegrationBranch(repo, "M001", "gsd/hotfix/fix-login");
|
|
878
|
+
assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), null, "hotfix branch is not recorded");
|
|
879
|
+
|
|
880
|
+
writeIntegrationBranch(repo, "M001", "gsd/bugfix/null-pointer");
|
|
881
|
+
assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), null, "bugfix branch is not recorded");
|
|
882
|
+
|
|
883
|
+
writeIntegrationBranch(repo, "M001", "gsd/small-feature/add-button");
|
|
884
|
+
assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), null, "small-feature branch is not recorded");
|
|
885
|
+
|
|
886
|
+
writeIntegrationBranch(repo, "M001", "gsd/refactor/rename-module");
|
|
887
|
+
assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), null, "refactor branch is not recorded");
|
|
888
|
+
|
|
889
|
+
writeIntegrationBranch(repo, "M001", "gsd/spike/evaluate-lib");
|
|
890
|
+
assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), null, "spike branch is not recorded");
|
|
891
|
+
|
|
892
|
+
writeIntegrationBranch(repo, "M001", "gsd/security-audit/owasp-scan");
|
|
893
|
+
assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), null, "security-audit branch is not recorded");
|
|
894
|
+
|
|
895
|
+
writeIntegrationBranch(repo, "M001", "gsd/dep-upgrade/bump-react");
|
|
896
|
+
assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), null, "dep-upgrade branch is not recorded");
|
|
897
|
+
|
|
898
|
+
writeIntegrationBranch(repo, "M001", "gsd/full-project/new-app");
|
|
899
|
+
assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), null, "full-project branch is not recorded");
|
|
900
|
+
|
|
901
|
+
rmSync(repo, { recursive: true, force: true });
|
|
902
|
+
});
|
|
903
|
+
|
|
904
|
+
// ─── writeIntegrationBranch: still records legitimate branches ────────
|
|
905
|
+
|
|
906
|
+
test('Integration branch: records non-ephemeral gsd branches', () => {
|
|
907
|
+
const repo = initBranchTestRepo();
|
|
908
|
+
|
|
909
|
+
// A normal feature branch should still be recorded
|
|
910
|
+
writeIntegrationBranch(repo, "M001", "feature/new-thing");
|
|
911
|
+
assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), "feature/new-thing", "normal branches are recorded");
|
|
912
|
+
|
|
913
|
+
// The main branch should be recorded
|
|
914
|
+
writeIntegrationBranch(repo, "M002", "main");
|
|
915
|
+
assert.deepStrictEqual(readIntegrationBranch(repo, "M002"), "main", "main branch is recorded");
|
|
916
|
+
|
|
917
|
+
rmSync(repo, { recursive: true, force: true });
|
|
918
|
+
});
|
|
919
|
+
|
|
867
920
|
// ─── writeIntegrationBranch: rejects invalid branch names ─────────────
|
|
868
921
|
|
|
869
922
|
test('Integration branch: rejects invalid names', () => {
|
|
@@ -1295,7 +1348,12 @@ describe('git-service', async () => {
|
|
|
1295
1348
|
issueNumber: 42,
|
|
1296
1349
|
});
|
|
1297
1350
|
assert.ok(msg.includes("Resolves #42"), "buildTaskCommitMessage includes Resolves #N trailer when issueNumber is set");
|
|
1298
|
-
assert.ok(msg.startsWith("fix
|
|
1351
|
+
assert.ok(msg.startsWith("fix:"), "buildTaskCommitMessage infers fix type");
|
|
1352
|
+
assert.ok(msg.includes("GSD-Task: S01/T03"), "GSD-Task trailer present");
|
|
1353
|
+
// GSD-Task should come before Resolves
|
|
1354
|
+
const taskIdx = msg.indexOf("GSD-Task: S01/T03");
|
|
1355
|
+
const resolvesIdx = msg.indexOf("Resolves #42");
|
|
1356
|
+
assert.ok(taskIdx < resolvesIdx, "GSD-Task trailer before Resolves trailer");
|
|
1299
1357
|
});
|
|
1300
1358
|
|
|
1301
1359
|
{
|
|
@@ -1305,6 +1363,7 @@ describe('git-service', async () => {
|
|
|
1305
1363
|
taskTitle: "add dashboard widget",
|
|
1306
1364
|
});
|
|
1307
1365
|
assert.ok(!msg.includes("Resolves"), "buildTaskCommitMessage omits Resolves trailer when issueNumber is absent");
|
|
1366
|
+
assert.ok(msg.includes("GSD-Task: S01/T04"), "GSD-Task trailer still present");
|
|
1308
1367
|
}
|
|
1309
1368
|
|
|
1310
1369
|
// ─── runPreMergeCheck: skips when no package.json ────────────────────────
|
|
@@ -64,7 +64,7 @@ describe('gsd-db', () => {
|
|
|
64
64
|
// Check schema_version table
|
|
65
65
|
const adapter = _getAdapter()!;
|
|
66
66
|
const version = adapter.prepare('SELECT MAX(version) as version FROM schema_version').get();
|
|
67
|
-
assert.deepStrictEqual(version?.['version'],
|
|
67
|
+
assert.deepStrictEqual(version?.['version'], 12, 'schema version should be 12');
|
|
68
68
|
|
|
69
69
|
// Check tables exist by querying them
|
|
70
70
|
const dRows = adapter.prepare('SELECT count(*) as cnt FROM decisions').get();
|
|
@@ -9,11 +9,11 @@ import { isInfrastructureError, INFRA_ERROR_CODES } from "../auto/infra-errors.j
|
|
|
9
9
|
test("INFRA_ERROR_CODES contains the expected codes", () => {
|
|
10
10
|
for (const code of [
|
|
11
11
|
"ENOSPC", "ENOMEM", "EROFS", "EDQUOT", "EMFILE", "ENFILE",
|
|
12
|
-
"ECONNREFUSED", "ENOTFOUND", "ENETUNREACH",
|
|
12
|
+
"EAGAIN", "ECONNREFUSED", "ENOTFOUND", "ENETUNREACH",
|
|
13
13
|
]) {
|
|
14
14
|
assert.ok(INFRA_ERROR_CODES.has(code), `missing ${code}`);
|
|
15
15
|
}
|
|
16
|
-
assert.equal(INFRA_ERROR_CODES.size,
|
|
16
|
+
assert.equal(INFRA_ERROR_CODES.size, 10, "unexpected extra codes");
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
// ── isInfrastructureError: code property detection ───────────────────────────
|
|
@@ -48,6 +48,16 @@ test("detects ENFILE via code property", () => {
|
|
|
48
48
|
assert.equal(isInfrastructureError(err), "ENFILE");
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
+
test("detects EAGAIN via code property", () => {
|
|
52
|
+
const err = Object.assign(new Error("resource temporarily unavailable"), { code: "EAGAIN" });
|
|
53
|
+
assert.equal(isInfrastructureError(err), "EAGAIN");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("detects EAGAIN in error message fallback", () => {
|
|
57
|
+
const err = new Error("spawn failed: EAGAIN resource temporarily unavailable");
|
|
58
|
+
assert.equal(isInfrastructureError(err), "EAGAIN");
|
|
59
|
+
});
|
|
60
|
+
|
|
51
61
|
test("detects ECONNREFUSED via code property", () => {
|
|
52
62
|
const err = Object.assign(new Error("connect ECONNREFUSED 127.0.0.1:3000"), { code: "ECONNREFUSED" });
|
|
53
63
|
assert.equal(isInfrastructureError(err), "ECONNREFUSED");
|
|
@@ -505,3 +505,42 @@ test("milestone-transition event is emitted when milestone changes", async () =>
|
|
|
505
505
|
assert.equal((transitionEvents[0].data as any).to, "M002");
|
|
506
506
|
assert.equal(transitionEvents[0].flowId, ic.flowId);
|
|
507
507
|
});
|
|
508
|
+
|
|
509
|
+
test("unit-end event contains errorContext when unit is cancelled with structured error", async () => {
|
|
510
|
+
const capture = createEventCapture();
|
|
511
|
+
const { resolveAgentEndCancelled, _resetPendingResolve } = await import("../auto-loop.js");
|
|
512
|
+
_resetPendingResolve();
|
|
513
|
+
|
|
514
|
+
const deps = makeMockDeps(capture);
|
|
515
|
+
const ic = makeIC(deps);
|
|
516
|
+
const iterData: IterationData = {
|
|
517
|
+
unitType: "execute-task",
|
|
518
|
+
unitId: "M001/S01/T01",
|
|
519
|
+
prompt: "do stuff",
|
|
520
|
+
finalPrompt: "do stuff",
|
|
521
|
+
pauseAfterUatDispatch: false,
|
|
522
|
+
state: { phase: "executing", activeMilestone: { id: "M001" }, activeSlice: { id: "S01" }, registry: [], blockers: [] } as any,
|
|
523
|
+
mid: "M001",
|
|
524
|
+
midTitle: "Test",
|
|
525
|
+
isRetry: false,
|
|
526
|
+
previousTier: undefined,
|
|
527
|
+
};
|
|
528
|
+
const loopState: LoopState = { recentUnits: [{ key: "execute-task/M001/S01/T01" }], stuckRecoveryAttempts: 0 };
|
|
529
|
+
|
|
530
|
+
const unitPromise = runUnitPhase(ic, iterData, loopState);
|
|
531
|
+
await new Promise(r => setTimeout(r, 50));
|
|
532
|
+
|
|
533
|
+
// Resolve with errorContext (simulates a timeout cancel)
|
|
534
|
+
resolveAgentEndCancelled({ message: "Hard timeout error: exceeded limit", category: "timeout", isTransient: true });
|
|
535
|
+
|
|
536
|
+
const result = await unitPromise;
|
|
537
|
+
// Cancelled units break the loop before emitting unit-end
|
|
538
|
+
assert.equal(result.action, "break");
|
|
539
|
+
assert.equal((result as any).reason, "session-failed");
|
|
540
|
+
|
|
541
|
+
// Verify error classification used structured errorContext on the window entry
|
|
542
|
+
const entry = loopState.recentUnits[loopState.recentUnits.length - 1];
|
|
543
|
+
assert.ok(entry.error, "window entry must have error set");
|
|
544
|
+
assert.ok(entry.error!.startsWith("timeout:"), "error must start with category from errorContext");
|
|
545
|
+
assert.ok(entry.error!.includes("Hard timeout error"), "error must include the errorContext message");
|
|
546
|
+
});
|
|
@@ -363,7 +363,7 @@ test('md-importer: schema v1→v2 migration', () => {
|
|
|
363
363
|
openDatabase(':memory:');
|
|
364
364
|
const adapter = _getAdapter();
|
|
365
365
|
const version = adapter?.prepare('SELECT MAX(version) as v FROM schema_version').get();
|
|
366
|
-
assert.deepStrictEqual(version?.v,
|
|
366
|
+
assert.deepStrictEqual(version?.v, 12, 'new DB should be at schema version 12');
|
|
367
367
|
|
|
368
368
|
// Artifacts table should exist
|
|
369
369
|
const tableCheck = adapter?.prepare("SELECT count(*) as c FROM sqlite_master WHERE type='table' AND name='artifacts'").get();
|
|
@@ -323,9 +323,9 @@ test('memory-store: schema includes memories table', () => {
|
|
|
323
323
|
const viewCount = adapter.prepare('SELECT count(*) as cnt FROM active_memories').get();
|
|
324
324
|
assert.deepStrictEqual(viewCount?.['cnt'], 0, 'active_memories view should exist');
|
|
325
325
|
|
|
326
|
-
// Verify schema version is
|
|
326
|
+
// Verify schema version is 12 (after quality gates table)
|
|
327
327
|
const version = adapter.prepare('SELECT MAX(version) as v FROM schema_version').get();
|
|
328
|
-
assert.deepStrictEqual(version?.['v'],
|
|
328
|
+
assert.deepStrictEqual(version?.['v'], 12, 'schema version should be 12');
|
|
329
329
|
|
|
330
330
|
closeDatabase();
|
|
331
331
|
});
|
|
@@ -94,8 +94,8 @@ test("worktree swap on milestone transition: merge old, create new", () => {
|
|
|
94
94
|
assert.equal(process.cwd(), tempDir, "cwd restored to project root after merge");
|
|
95
95
|
assert.ok(!isInAutoWorktree(tempDir), "no longer in auto-worktree after merge");
|
|
96
96
|
|
|
97
|
-
// Verify M001 work was merged to main
|
|
98
|
-
const mainLog = run("git log
|
|
97
|
+
// Verify M001 work was merged to main (milestone ID is in trailer, not subject)
|
|
98
|
+
const mainLog = run("git log -3", tempDir);
|
|
99
99
|
assert.ok(mainLog.includes("M001"), "M001 squash commit should be on main");
|
|
100
100
|
|
|
101
101
|
// Phase 3: Create new worktree for M002 (simulates new milestone)
|
|
@@ -168,7 +168,7 @@ test("formatMergeResults — empty results", () => {
|
|
|
168
168
|
|
|
169
169
|
test("formatMergeResults — successful merge", () => {
|
|
170
170
|
const results: MergeResult[] = [
|
|
171
|
-
{ milestoneId: "M001", success: true, commitMessage: "feat
|
|
171
|
+
{ milestoneId: "M001", success: true, commitMessage: "feat: Auth\n\nGSD-Milestone: M001\nBranch: milestone/M001", pushed: true },
|
|
172
172
|
];
|
|
173
173
|
const output = formatMergeResults(results);
|
|
174
174
|
assert.ok(output.includes("M001"));
|
|
@@ -178,7 +178,7 @@ test("formatMergeResults — successful merge", () => {
|
|
|
178
178
|
|
|
179
179
|
test("formatMergeResults — successful merge without push", () => {
|
|
180
180
|
const results: MergeResult[] = [
|
|
181
|
-
{ milestoneId: "M001", success: true, commitMessage: "feat
|
|
181
|
+
{ milestoneId: "M001", success: true, commitMessage: "feat: Auth\n\nGSD-Milestone: M001\nBranch: milestone/M001", pushed: false },
|
|
182
182
|
];
|
|
183
183
|
const output = formatMergeResults(results);
|
|
184
184
|
assert.ok(output.includes("merged successfully"));
|
|
@@ -213,7 +213,7 @@ test("formatMergeResults — generic failure without conflict files", () => {
|
|
|
213
213
|
|
|
214
214
|
test("formatMergeResults — mixed results", () => {
|
|
215
215
|
const results: MergeResult[] = [
|
|
216
|
-
{ milestoneId: "M001", success: true, commitMessage: "feat
|
|
216
|
+
{ milestoneId: "M001", success: true, commitMessage: "feat: OK\n\nGSD-Milestone: M001\nBranch: milestone/M001", pushed: false },
|
|
217
217
|
{ milestoneId: "M002", success: false, error: "conflict", conflictFiles: ["a.ts"] },
|
|
218
218
|
];
|
|
219
219
|
const output = formatMergeResults(results);
|
|
@@ -281,9 +281,9 @@ test("mergeCompletedMilestone — clean merge, session status cleaned up", async
|
|
|
281
281
|
// Verify file merged to main
|
|
282
282
|
assert.ok(existsSync(join(repo, "auth.ts")), "auth.ts should be on main");
|
|
283
283
|
|
|
284
|
-
// Verify commit on main
|
|
285
|
-
const log = run("git log --
|
|
286
|
-
assert.ok(log.includes("M010"), "commit message should reference M010");
|
|
284
|
+
// Verify commit on main (M010 is now in the body as a GSD-Milestone trailer)
|
|
285
|
+
const log = run("git log -1 --format=%B main", repo);
|
|
286
|
+
assert.ok(log.includes("GSD-Milestone: M010"), "commit message should reference M010 in trailer");
|
|
287
287
|
|
|
288
288
|
// Verify session status cleaned up
|
|
289
289
|
const statusAfter = readSessionStatus(repo, "M010");
|