gsd-pi 2.64.0-dev.f8aad9b → 2.65.0-dev.16e10d7
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.js +3 -1
- package/dist/mcp-server.js +6 -2
- package/dist/resources/extensions/bg-shell/bg-shell-lifecycle.js +22 -7
- package/dist/resources/extensions/bg-shell/process-manager.js +6 -1
- package/dist/resources/extensions/browser-tools/capture.js +20 -1
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +13 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +94 -8
- package/dist/resources/extensions/gsd/auto-model-selection.js +7 -5
- package/dist/resources/extensions/gsd/auto-post-unit.js +115 -7
- package/dist/resources/extensions/gsd/auto-prompts.js +24 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +12 -8
- package/dist/resources/extensions/gsd/auto-start.js +35 -1
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +10 -0
- package/dist/resources/extensions/gsd/auto-verification.js +138 -1
- package/dist/resources/extensions/gsd/auto-worktree.js +29 -7
- package/dist/resources/extensions/gsd/auto.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -4
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +34 -13
- package/dist/resources/extensions/gsd/bootstrap/notify-interceptor.js +28 -0
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +6 -4
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +12 -1
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +16 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +20 -0
- package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
- package/dist/resources/extensions/gsd/commands/context.js +8 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +21 -0
- package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +104 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/commands-extensions.js +1 -1
- package/dist/resources/extensions/gsd/config-overlay.js +312 -0
- package/dist/resources/extensions/gsd/detection.js +1 -1
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -0
- package/dist/resources/extensions/gsd/doctor.js +2 -1
- package/dist/resources/extensions/gsd/gitignore.js +1 -0
- package/dist/resources/extensions/gsd/gsd-db.js +11 -2
- package/dist/resources/extensions/gsd/guided-flow.js +220 -29
- package/dist/resources/extensions/gsd/md-importer.js +14 -7
- package/dist/resources/extensions/gsd/notification-overlay.js +256 -0
- package/dist/resources/extensions/gsd/notification-store.js +273 -0
- package/dist/resources/extensions/gsd/notification-widget.js +56 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +17 -11
- package/dist/resources/extensions/gsd/post-execution-checks.js +407 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +471 -0
- package/dist/resources/extensions/gsd/preferences-types.js +7 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +78 -1
- package/dist/resources/extensions/gsd/preferences.js +13 -2
- package/dist/resources/extensions/gsd/preparation.js +1092 -0
- package/dist/resources/extensions/gsd/prompt-validation.js +67 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +4 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
- package/dist/resources/extensions/gsd/prompts/rethink.md +2 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
- package/dist/resources/extensions/gsd/quick.js +19 -15
- package/dist/resources/extensions/gsd/reactive-graph.js +12 -0
- package/dist/resources/extensions/gsd/roadmap-slices.js +24 -5
- package/dist/resources/extensions/gsd/safety/content-validator.js +3 -3
- package/dist/resources/extensions/gsd/session-lock.js +23 -1
- package/dist/resources/extensions/gsd/state.js +100 -12
- package/dist/resources/extensions/gsd/templates/context-enhanced.md +138 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +12 -3
- package/dist/resources/extensions/gsd/tools/complete-task.js +16 -4
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -5
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +5 -2
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +119 -0
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +30 -0
- package/dist/resources/extensions/gsd/tools/reopen-task.js +18 -0
- package/dist/resources/extensions/gsd/triage-resolution.js +25 -9
- package/dist/resources/extensions/gsd/verification-evidence.js +18 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +8 -0
- package/dist/resources/extensions/gsd/workflow-projections.js +4 -7
- package/dist/resources/extensions/gsd/workflow-reconcile.js +2 -4
- package/dist/resources/extensions/gsd/workflow-templates.js +11 -2
- package/dist/resources/extensions/gsd/worktree-manager.js +5 -2
- package/dist/resources/extensions/gsd/worktree.js +9 -0
- package/dist/resources/extensions/shared/interview-ui.js +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -17
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- 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/routes-manifest.json +6 -0
- 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.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- 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 +1 -1
- 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/notifications/route.js +3 -0
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -0
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -0
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -17
- package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
- 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/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/Z3TgDP0c7kG9j8CVQVGcl/_buildManifest.js +1 -0
- package/dist/web/standalone/.next/static/chunks/6502.8874bcae249c02e1.js +9 -0
- package/dist/web/standalone/.next/static/chunks/app/_global-error/page-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/boot/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/captures/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/files/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/git/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/history/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/notifications/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/projects/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/steer/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/undo/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/update/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-a1c1e452c6b32d04.js → webpack-9fed74684e1c5bb1.js} +1 -1
- package/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +26 -9
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +100 -4
- package/packages/pi-agent-core/src/agent-loop.ts +43 -12
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +38 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +11 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +24 -0
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +4 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +30 -19
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +51 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +9 -9
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +2 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +10 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +28 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +15 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +18 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +40 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +64 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +10 -0
- package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +42 -0
- package/packages/pi-coding-agent/src/core/resource-loader.ts +5 -1
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +80 -0
- package/packages/pi-coding-agent/src/core/retry-handler.ts +37 -25
- package/packages/pi-coding-agent/src/core/sdk.ts +9 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +10 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +29 -4
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +27 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +16 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +38 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +66 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -0
- package/packages/pi-tui/dist/components/image.d.ts +2 -0
- package/packages/pi-tui/dist/components/image.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/image.js +4 -0
- package/packages/pi-tui/dist/components/image.js.map +1 -1
- package/packages/pi-tui/dist/components/image.test.d.ts +6 -0
- package/packages/pi-tui/dist/components/image.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/image.test.js +32 -0
- package/packages/pi-tui/dist/components/image.test.js.map +1 -0
- package/packages/pi-tui/dist/components/loader.d.ts +4 -2
- package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/loader.js +27 -9
- package/packages/pi-tui/dist/components/loader.js.map +1 -1
- package/packages/pi-tui/dist/components/text.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/text.js +2 -0
- package/packages/pi-tui/dist/components/text.js.map +1 -1
- package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
- package/packages/pi-tui/dist/overlay-layout.js +12 -1
- package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts +4 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +35 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +82 -0
- package/packages/pi-tui/src/components/image.test.ts +36 -0
- package/packages/pi-tui/src/components/image.ts +5 -0
- package/packages/pi-tui/src/components/loader.ts +27 -10
- package/packages/pi-tui/src/components/text.ts +1 -0
- package/packages/pi-tui/src/overlay-layout.ts +13 -1
- package/packages/pi-tui/src/tui.ts +34 -0
- package/pkg/package.json +1 -1
- package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +19 -7
- package/src/resources/extensions/bg-shell/process-manager.ts +8 -2
- package/src/resources/extensions/browser-tools/capture.ts +19 -1
- package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
- package/src/resources/extensions/gsd/auto/run-unit.ts +12 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +105 -8
- package/src/resources/extensions/gsd/auto-model-selection.ts +7 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +138 -6
- package/src/resources/extensions/gsd/auto-prompts.ts +31 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
- package/src/resources/extensions/gsd/auto-start.ts +38 -0
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +10 -0
- package/src/resources/extensions/gsd/auto-verification.ts +190 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +28 -7
- package/src/resources/extensions/gsd/auto.ts +2 -1
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -4
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +35 -13
- package/src/resources/extensions/gsd/bootstrap/notify-interceptor.ts +34 -0
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +12 -1
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +20 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +28 -0
- package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
- package/src/resources/extensions/gsd/commands/context.ts +7 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +24 -0
- package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +140 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/commands-extensions.ts +1 -1
- package/src/resources/extensions/gsd/config-overlay.ts +331 -0
- package/src/resources/extensions/gsd/detection.ts +1 -1
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -0
- package/src/resources/extensions/gsd/doctor.ts +2 -1
- package/src/resources/extensions/gsd/gitignore.ts +1 -0
- package/src/resources/extensions/gsd/gsd-db.ts +13 -2
- package/src/resources/extensions/gsd/guided-flow.ts +254 -30
- package/src/resources/extensions/gsd/md-importer.ts +13 -6
- package/src/resources/extensions/gsd/notification-overlay.ts +295 -0
- package/src/resources/extensions/gsd/notification-store.ts +293 -0
- package/src/resources/extensions/gsd/notification-widget.ts +68 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +19 -11
- package/src/resources/extensions/gsd/post-execution-checks.ts +539 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +581 -0
- package/src/resources/extensions/gsd/preferences-types.ts +53 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +78 -1
- package/src/resources/extensions/gsd/preferences.ts +13 -2
- package/src/resources/extensions/gsd/preparation.ts +1419 -0
- package/src/resources/extensions/gsd/prompt-validation.ts +88 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +4 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
- package/src/resources/extensions/gsd/prompts/rethink.md +2 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
- package/src/resources/extensions/gsd/quick.ts +20 -15
- package/src/resources/extensions/gsd/reactive-graph.ts +18 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +21 -5
- package/src/resources/extensions/gsd/safety/content-validator.ts +3 -3
- package/src/resources/extensions/gsd/session-lock.ts +17 -1
- package/src/resources/extensions/gsd/state.ts +101 -11
- package/src/resources/extensions/gsd/templates/context-enhanced.md +138 -0
- package/src/resources/extensions/gsd/tests/adversarial-review-fixes.test.ts +223 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +33 -2
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/complete-slice-string-coercion.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +72 -0
- package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/defer-milestone-stamp.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +526 -0
- package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +28 -30
- package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +53 -0
- package/src/resources/extensions/gsd/tests/integration-prepared-discussion.test.ts +525 -0
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +282 -0
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +813 -0
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +1197 -0
- package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +266 -0
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +457 -0
- package/src/resources/extensions/gsd/tests/preparation.test.ts +1211 -0
- package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/prompt-builder.test.ts +669 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +7 -4
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +4 -5
- package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/skipped-validation-completion.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +147 -0
- package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +13 -0
- package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +6 -7
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/symlink-extension-discovery.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +163 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +3 -4
- package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +16 -17
- package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +13 -9
- package/src/resources/extensions/gsd/tests/worktree.test.ts +26 -9
- package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +13 -3
- package/src/resources/extensions/gsd/tools/complete-task.ts +16 -4
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +11 -9
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +5 -2
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +152 -0
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +27 -0
- package/src/resources/extensions/gsd/tools/reopen-task.ts +17 -0
- package/src/resources/extensions/gsd/triage-resolution.ts +29 -10
- package/src/resources/extensions/gsd/types.ts +4 -0
- package/src/resources/extensions/gsd/verification-evidence.ts +68 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +13 -0
- package/src/resources/extensions/gsd/workflow-projections.ts +4 -6
- package/src/resources/extensions/gsd/workflow-reconcile.ts +2 -3
- package/src/resources/extensions/gsd/workflow-templates.ts +11 -2
- package/src/resources/extensions/gsd/worktree-manager.ts +4 -2
- package/src/resources/extensions/gsd/worktree.ts +10 -0
- package/src/resources/extensions/shared/interview-ui.ts +1 -1
- package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +8 -10
- package/dist/web/standalone/.next/static/F1mOwzgCW9R8N3Pt1Et87/_buildManifest.js +0 -1
- package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
- package/dist/web/standalone/.next/static/chunks/app/_global-error/page-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/boot/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/captures/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/files/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/git/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/history/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/projects/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/steer/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/undo/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/update/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c4cc189e7b117ea2.js +0 -1
- /package/dist/web/standalone/.next/static/{F1mOwzgCW9R8N3Pt1Et87 → Z3TgDP0c7kG9j8CVQVGcl}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// GSD-2 — Regression test for #3615: unstructured "continue" must inject task context
|
|
2
|
+
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Bug #3615: When a user types "continue" (or any bare text) to resume
|
|
6
|
+
* an in-progress session, buildGuidedExecuteContextInjection() only
|
|
7
|
+
* matched two hardcoded regex patterns (auto-dispatch and guided-resume).
|
|
8
|
+
* The function returned null for any other input, so no task context was
|
|
9
|
+
* injected — causing the agent to rebuild everything from scratch and
|
|
10
|
+
* burn ~86k tokens.
|
|
11
|
+
*
|
|
12
|
+
* This test verifies:
|
|
13
|
+
* 1. Structural: the fallback exists with phase + intent guards
|
|
14
|
+
* 2. Behavioral: RESUME_INTENT_PATTERNS matches expected prompts and
|
|
15
|
+
* rejects non-resume prompts (control, help, diagnostic, etc.)
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { describe, test } from "node:test";
|
|
19
|
+
import assert from "node:assert/strict";
|
|
20
|
+
import { readFileSync } from "node:fs";
|
|
21
|
+
import { join, dirname } from "node:path";
|
|
22
|
+
import { fileURLToPath } from "node:url";
|
|
23
|
+
|
|
24
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
25
|
+
const systemContextSource = readFileSync(
|
|
26
|
+
join(__dirname, "..", "bootstrap", "system-context.ts"),
|
|
27
|
+
"utf-8",
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// ── Structural tests ────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
describe("#3615 — structural: fallback exists with correct guards", () => {
|
|
33
|
+
const fnStart = systemContextSource.indexOf("async function buildGuidedExecuteContextInjection(");
|
|
34
|
+
assert.ok(fnStart >= 0, "should find buildGuidedExecuteContextInjection");
|
|
35
|
+
const fnEnd = systemContextSource.indexOf("\nasync function ", fnStart + 1);
|
|
36
|
+
const fnBody = fnEnd >= 0
|
|
37
|
+
? systemContextSource.slice(fnStart, fnEnd)
|
|
38
|
+
: systemContextSource.slice(fnStart);
|
|
39
|
+
|
|
40
|
+
test("has a deriveState fallback after the two regex branches", () => {
|
|
41
|
+
const deriveStateCalls = fnBody.match(/deriveState\(basePath\)/g);
|
|
42
|
+
assert.ok(
|
|
43
|
+
deriveStateCalls && deriveStateCalls.length >= 2,
|
|
44
|
+
`expected >=2 deriveState(basePath) calls, got ${deriveStateCalls?.length ?? 0}`,
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("fallback is phase-gated to executing only", () => {
|
|
49
|
+
const afterFallback = fnBody.indexOf("// Fallback:");
|
|
50
|
+
assert.ok(afterFallback >= 0, "should have a fallback comment");
|
|
51
|
+
const fallbackSection = fnBody.slice(afterFallback);
|
|
52
|
+
assert.ok(
|
|
53
|
+
fallbackSection.includes('state.phase === "executing"'),
|
|
54
|
+
'fallback must be gated on state.phase === "executing"',
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("fallback is intent-gated via RESUME_INTENT_PATTERNS", () => {
|
|
59
|
+
const afterFallback = fnBody.indexOf("// Fallback:");
|
|
60
|
+
const fallbackSection = fnBody.slice(afterFallback);
|
|
61
|
+
assert.ok(
|
|
62
|
+
fallbackSection.includes("RESUME_INTENT_PATTERNS"),
|
|
63
|
+
"fallback must check RESUME_INTENT_PATTERNS before deriveState",
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("fallback calls buildTaskExecutionContextInjection with derived state", () => {
|
|
68
|
+
const afterFallback = fnBody.indexOf("// Fallback:");
|
|
69
|
+
const fallbackSection = fnBody.slice(afterFallback);
|
|
70
|
+
assert.ok(
|
|
71
|
+
fallbackSection.includes("buildTaskExecutionContextInjection") &&
|
|
72
|
+
fallbackSection.includes("state.activeMilestone.id") &&
|
|
73
|
+
fallbackSection.includes("state.activeSlice.id") &&
|
|
74
|
+
fallbackSection.includes("state.activeTask.id"),
|
|
75
|
+
"fallback must call buildTaskExecutionContextInjection with state-derived IDs",
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("only one return null at the end", () => {
|
|
80
|
+
const returnNulls = fnBody.match(/return null;/g);
|
|
81
|
+
assert.ok(
|
|
82
|
+
returnNulls && returnNulls.length === 1,
|
|
83
|
+
`expected exactly 1 'return null' (at end after fallback), got ${returnNulls?.length ?? 0}`,
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// ── Behavioral tests: RESUME_INTENT_PATTERNS ────────────────────────
|
|
89
|
+
|
|
90
|
+
describe("#3615 — behavioral: RESUME_INTENT_PATTERNS matches resume prompts", () => {
|
|
91
|
+
// Extract the regex from source so the test stays in sync
|
|
92
|
+
const patternMatch = systemContextSource.match(/const RESUME_INTENT_PATTERNS\s*=\s*\/(.+)\/;/);
|
|
93
|
+
assert.ok(patternMatch, "should find RESUME_INTENT_PATTERNS definition");
|
|
94
|
+
const pattern = new RegExp(patternMatch[1]);
|
|
95
|
+
|
|
96
|
+
// Helper: normalize prompt the same way the production code does
|
|
97
|
+
const normalize = (s: string) => s.trim().toLowerCase().replace(/[.!?,]+$/g, "");
|
|
98
|
+
|
|
99
|
+
const shouldMatch = [
|
|
100
|
+
"continue",
|
|
101
|
+
"Continue",
|
|
102
|
+
"CONTINUE",
|
|
103
|
+
"continue.",
|
|
104
|
+
"continue!",
|
|
105
|
+
"resume",
|
|
106
|
+
"ok",
|
|
107
|
+
"OK",
|
|
108
|
+
"Ok!",
|
|
109
|
+
"go",
|
|
110
|
+
"go ahead",
|
|
111
|
+
"Go ahead.",
|
|
112
|
+
"proceed",
|
|
113
|
+
"keep going",
|
|
114
|
+
"carry on",
|
|
115
|
+
"next",
|
|
116
|
+
"yes",
|
|
117
|
+
"yeah",
|
|
118
|
+
"yep",
|
|
119
|
+
"sure",
|
|
120
|
+
"do it",
|
|
121
|
+
"let's go",
|
|
122
|
+
"pick up where you left off",
|
|
123
|
+
" continue ", // whitespace padded
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
const shouldNotMatch = [
|
|
127
|
+
"help",
|
|
128
|
+
"status",
|
|
129
|
+
"/gsd auto",
|
|
130
|
+
"/gsd stats",
|
|
131
|
+
"what's the plan?",
|
|
132
|
+
"show me the logs",
|
|
133
|
+
"abort",
|
|
134
|
+
"stop",
|
|
135
|
+
"cancel",
|
|
136
|
+
"replan this slice",
|
|
137
|
+
"I think we should change the approach",
|
|
138
|
+
"can you explain what you just did?",
|
|
139
|
+
"run the tests",
|
|
140
|
+
"check the build",
|
|
141
|
+
"Execute the next task: T01",
|
|
142
|
+
"what files were changed",
|
|
143
|
+
"",
|
|
144
|
+
];
|
|
145
|
+
|
|
146
|
+
for (const prompt of shouldMatch) {
|
|
147
|
+
test(`matches resume prompt: "${prompt}"`, () => {
|
|
148
|
+
assert.ok(
|
|
149
|
+
pattern.test(normalize(prompt)),
|
|
150
|
+
`expected RESUME_INTENT_PATTERNS to match "${prompt}" (normalized: "${normalize(prompt)}")`,
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
for (const prompt of shouldNotMatch) {
|
|
156
|
+
test(`rejects non-resume prompt: "${prompt}"`, () => {
|
|
157
|
+
assert.ok(
|
|
158
|
+
!pattern.test(normalize(prompt)),
|
|
159
|
+
`expected RESUME_INTENT_PATTERNS to NOT match "${prompt}" (normalized: "${normalize(prompt)}")`,
|
|
160
|
+
);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
});
|
|
@@ -163,16 +163,15 @@ test("deriveState returns completing-milestone when VALIDATION exists with termi
|
|
|
163
163
|
}
|
|
164
164
|
});
|
|
165
165
|
|
|
166
|
-
test("deriveState treats needs-remediation as terminal —
|
|
166
|
+
test("deriveState treats needs-remediation as non-terminal — re-enters validating-milestone (#832)", async () => {
|
|
167
167
|
const base = makeTmpBase();
|
|
168
168
|
try {
|
|
169
169
|
writeRoadmap(base, "M001", ALL_DONE_ROADMAP);
|
|
170
170
|
writeValidation(base, "M001", "---\nverdict: needs-remediation\nremediation_round: 0\n---\n\n# Validation\nNeeds fixes.");
|
|
171
171
|
|
|
172
172
|
const state = await deriveState(base);
|
|
173
|
-
// needs-remediation
|
|
174
|
-
|
|
175
|
-
assert.notEqual(state.phase, "validating-milestone");
|
|
173
|
+
// needs-remediation routes back to validating-milestone for re-validation
|
|
174
|
+
assert.equal(state.phase, "validating-milestone");
|
|
176
175
|
assert.equal(state.activeMilestone?.id, "M001");
|
|
177
176
|
} finally {
|
|
178
177
|
cleanup(base);
|
|
@@ -80,3 +80,18 @@ test("isVerificationNotApplicable: 'Verify API response times under load' requir
|
|
|
80
80
|
test("isVerificationNotApplicable: 'Monitor error rates for 24h' requires verification", () => {
|
|
81
81
|
assert.equal(isVerificationNotApplicable("Monitor error rates for 24h"), false);
|
|
82
82
|
});
|
|
83
|
+
|
|
84
|
+
// Regression: #3634 — "Not provided." default from plan-milestone
|
|
85
|
+
test("isVerificationNotApplicable: 'Not provided.' is not applicable (#3634)", () => {
|
|
86
|
+
assert.equal(isVerificationNotApplicable("Not provided."), true);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("isVerificationNotApplicable: 'Not provided' (no period) is not applicable (#3634)", () => {
|
|
90
|
+
assert.equal(isVerificationNotApplicable("Not provided"), true);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("isVerificationNotApplicable: trailing period does not defeat match (#3634)", () => {
|
|
94
|
+
assert.equal(isVerificationNotApplicable("None required."), true);
|
|
95
|
+
assert.equal(isVerificationNotApplicable("N/A."), true);
|
|
96
|
+
assert.equal(isVerificationNotApplicable("Not applicable."), true);
|
|
97
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3607 — tighten verifyExpectedArtifact legacy branch
|
|
3
|
+
*
|
|
4
|
+
* The legacy (pre-migration) fallback in verifyExpectedArtifact previously
|
|
5
|
+
* accepted either a heading match (### T01 --) or a checked checkbox as proof
|
|
6
|
+
* that gsd_complete_task ran. A heading alone does not prove completion —
|
|
7
|
+
* it could result from a rogue write.
|
|
8
|
+
*
|
|
9
|
+
* The fix removes the hdRe heading regex and requires only a checked checkbox
|
|
10
|
+
* (cbRe) in the legacy branch, ensuring that only actual tool-completed tasks
|
|
11
|
+
* are treated as verified.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { describe, it } from 'node:test'
|
|
15
|
+
import assert from 'node:assert/strict'
|
|
16
|
+
import { readFileSync } from 'node:fs'
|
|
17
|
+
import { resolve } from 'node:path'
|
|
18
|
+
|
|
19
|
+
const src = readFileSync(
|
|
20
|
+
resolve(process.cwd(), 'src', 'resources', 'extensions', 'gsd', 'auto-recovery.ts'),
|
|
21
|
+
'utf-8',
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
describe('verifyExpectedArtifact legacy branch tightened (#3607)', () => {
|
|
25
|
+
it('legacy branch does NOT define hdRe heading regex', () => {
|
|
26
|
+
// Find the legacy fallback section
|
|
27
|
+
const legacyIdx = src.indexOf('LEGACY: Pre-migration fallback')
|
|
28
|
+
assert.ok(legacyIdx !== -1, 'LEGACY comment must exist')
|
|
29
|
+
|
|
30
|
+
// Check the code within a reasonable window after the LEGACY comment
|
|
31
|
+
const legacyBlock = src.slice(legacyIdx, legacyIdx + 600)
|
|
32
|
+
|
|
33
|
+
assert.ok(
|
|
34
|
+
!legacyBlock.includes('hdRe'),
|
|
35
|
+
'hdRe heading regex must NOT exist in legacy branch — heading alone is not proof of completion',
|
|
36
|
+
)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('legacy branch requires checked checkbox via cbRe', () => {
|
|
40
|
+
const legacyIdx = src.indexOf('LEGACY: Pre-migration fallback')
|
|
41
|
+
assert.ok(legacyIdx !== -1)
|
|
42
|
+
|
|
43
|
+
const legacyBlock = src.slice(legacyIdx, legacyIdx + 600)
|
|
44
|
+
|
|
45
|
+
assert.ok(
|
|
46
|
+
legacyBlock.includes('cbRe'),
|
|
47
|
+
'cbRe checked-checkbox regex must exist in legacy branch',
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
// cbRe must match checked checkboxes [x] or [X]
|
|
51
|
+
assert.ok(
|
|
52
|
+
legacyBlock.includes('[xX]'),
|
|
53
|
+
'cbRe must match both [x] and [X] checkbox variants',
|
|
54
|
+
)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('legacy branch returns false when no plan file exists', () => {
|
|
58
|
+
const legacyIdx = src.indexOf('LEGACY: Pre-migration fallback')
|
|
59
|
+
assert.ok(legacyIdx !== -1)
|
|
60
|
+
|
|
61
|
+
const legacyBlock = src.slice(legacyIdx, legacyIdx + 1000)
|
|
62
|
+
|
|
63
|
+
// The else branch: no plan file means cannot verify
|
|
64
|
+
assert.ok(
|
|
65
|
+
legacyBlock.includes('no plan file'),
|
|
66
|
+
'missing plan file must be handled with return false',
|
|
67
|
+
)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('DB available but task not found returns false', () => {
|
|
71
|
+
const legacyIdx = src.indexOf('LEGACY: Pre-migration fallback')
|
|
72
|
+
assert.ok(legacyIdx !== -1)
|
|
73
|
+
|
|
74
|
+
const legacyBlock = src.slice(legacyIdx, legacyIdx + 1000)
|
|
75
|
+
|
|
76
|
+
assert.ok(
|
|
77
|
+
legacyBlock.includes('DB available but task row not found'),
|
|
78
|
+
'must handle case where DB is available but task row is missing',
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
// The comment should be followed by a return false
|
|
82
|
+
const commentIdx = legacyBlock.indexOf('DB available but task row not found')
|
|
83
|
+
const afterComment = legacyBlock.slice(commentIdx, commentIdx + 200)
|
|
84
|
+
assert.ok(
|
|
85
|
+
afterComment.includes('return false'),
|
|
86
|
+
'missing task row when DB available must return false',
|
|
87
|
+
)
|
|
88
|
+
})
|
|
89
|
+
})
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker model override — tests for parallel.worker_model preference.
|
|
3
|
+
*
|
|
4
|
+
* Verifies validation, resolveParallelConfig pass-through, and type definitions.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import test from "node:test";
|
|
8
|
+
import assert from "node:assert/strict";
|
|
9
|
+
import { readFileSync } from "node:fs";
|
|
10
|
+
import { join, dirname } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
|
|
15
|
+
const typesSrc = readFileSync(join(__dirname, "..", "types.ts"), "utf-8");
|
|
16
|
+
const validationSrc = readFileSync(join(__dirname, "..", "preferences-validation.ts"), "utf-8");
|
|
17
|
+
const preferencesSrc = readFileSync(join(__dirname, "..", "preferences.ts"), "utf-8");
|
|
18
|
+
|
|
19
|
+
// ─── Type definition ──────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
test("ParallelConfig includes worker_model optional field", () => {
|
|
22
|
+
assert.ok(
|
|
23
|
+
typesSrc.includes("worker_model?: string"),
|
|
24
|
+
"ParallelConfig should have optional worker_model field",
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// ─── Validation ───────────────────────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
test("validatePreferences accepts valid worker_model string", () => {
|
|
31
|
+
assert.ok(
|
|
32
|
+
validationSrc.includes("p.worker_model"),
|
|
33
|
+
"validation should check parallel.worker_model",
|
|
34
|
+
);
|
|
35
|
+
assert.ok(
|
|
36
|
+
validationSrc.includes('parallel.worker_model must be a non-empty string'),
|
|
37
|
+
"validation should reject invalid worker_model",
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// ─── resolveParallelConfig ────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
test("resolveParallelConfig passes through worker_model", () => {
|
|
44
|
+
assert.ok(
|
|
45
|
+
preferencesSrc.includes("worker_model: prefs?.parallel?.worker_model"),
|
|
46
|
+
"resolveParallelConfig should pass through worker_model",
|
|
47
|
+
);
|
|
48
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* worktree-expected-warnings.test.ts — #3665
|
|
3
|
+
*
|
|
4
|
+
* Verify that auto-worktree.ts and worktree-manager.ts suppress expected
|
|
5
|
+
* ENOENT and EISDIR conditions instead of logging misleading warnings.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, test } from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
11
|
+
import { join, dirname } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const autoWorktreeFile = join(__dirname, "..", "auto-worktree.ts");
|
|
16
|
+
const worktreeManagerFile = join(__dirname, "..", "worktree-manager.ts");
|
|
17
|
+
|
|
18
|
+
describe("worktree expected-condition warning suppression (#3665)", () => {
|
|
19
|
+
const autoSource = readFileSync(autoWorktreeFile, "utf-8");
|
|
20
|
+
|
|
21
|
+
test("auto-worktree.ts checks for ENOENT before logging unlink warning", () => {
|
|
22
|
+
assert.match(autoSource, /code\s*!==\s*["']ENOENT["']/);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("auto-worktree.ts checks for EISDIR before logging unlink warning", () => {
|
|
26
|
+
assert.match(autoSource, /code\s*!==\s*["']EISDIR["']/);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("auto-worktree.ts references issue #3597", () => {
|
|
30
|
+
assert.match(autoSource, /#3597/);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const managerSource = readFileSync(worktreeManagerFile, "utf-8");
|
|
34
|
+
|
|
35
|
+
test("worktree-manager.ts checks isDirectory() before reading .git file", () => {
|
|
36
|
+
assert.match(managerSource, /lstatSync\(gitPath\)\.isDirectory\(\)/);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -26,9 +26,11 @@ import {
|
|
|
26
26
|
getSliceBranchName,
|
|
27
27
|
autoCommitCurrentBranch,
|
|
28
28
|
SLICE_BRANCH_RE,
|
|
29
|
+
_resetServiceCache,
|
|
29
30
|
} from "../worktree.ts";
|
|
30
31
|
|
|
31
32
|
import { deriveState } from "../state.ts";
|
|
33
|
+
import { _clearGsdRootCache } from "../paths.ts";
|
|
32
34
|
import { describe, test } from 'node:test';
|
|
33
35
|
import assert from 'node:assert/strict';
|
|
34
36
|
|
|
@@ -74,6 +76,14 @@ run("git add .", base);
|
|
|
74
76
|
run('git commit -m "chore: init"', base);
|
|
75
77
|
|
|
76
78
|
describe('worktree-integration', async () => {
|
|
79
|
+
// Isolate from user's global preferences (which may have git.main_branch set).
|
|
80
|
+
// Reset caches so getService() creates a fresh instance with empty preferences.
|
|
81
|
+
const originalHome = process.env.HOME;
|
|
82
|
+
const fakeHome = mkdtempSync(join(tmpdir(), "gsd-fake-home-"));
|
|
83
|
+
process.env.HOME = fakeHome;
|
|
84
|
+
_clearGsdRootCache();
|
|
85
|
+
_resetServiceCache();
|
|
86
|
+
|
|
77
87
|
// ── Verify main tree baseline ──────────────────────────────────────────────
|
|
78
88
|
|
|
79
89
|
console.log("\n=== Main tree baseline ===");
|
|
@@ -197,4 +207,10 @@ describe('worktree-integration', async () => {
|
|
|
197
207
|
assert.deepStrictEqual(listWorktrees(base).length, 0, "all worktrees removed");
|
|
198
208
|
|
|
199
209
|
rmSync(base, { recursive: true, force: true });
|
|
210
|
+
|
|
211
|
+
// Restore HOME and reset caches
|
|
212
|
+
process.env.HOME = originalHome;
|
|
213
|
+
_clearGsdRootCache();
|
|
214
|
+
_resetServiceCache();
|
|
215
|
+
rmSync(fakeHome, { recursive: true, force: true });
|
|
200
216
|
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3461: createAutoWorktree must use git.main_branch
|
|
3
|
+
* preference when META.json integration branch is absent.
|
|
4
|
+
*/
|
|
5
|
+
import { test } from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
|
|
10
|
+
test("auto-worktree.ts includes main_branch preference in startPoint fallback (#3461)", () => {
|
|
11
|
+
const src = readFileSync(
|
|
12
|
+
join(import.meta.dirname, "..", "auto-worktree.ts"),
|
|
13
|
+
"utf-8",
|
|
14
|
+
);
|
|
15
|
+
// The fix adds gitPrefs?.main_branch to the startPoint fallback chain
|
|
16
|
+
assert.ok(
|
|
17
|
+
src.includes("gitPrefs?.main_branch") || src.includes("prefs.main_branch"),
|
|
18
|
+
"createAutoWorktree must check git.main_branch preference before falling back to nativeDetectMainBranch",
|
|
19
|
+
);
|
|
20
|
+
});
|
|
@@ -221,7 +221,8 @@ describe('worktree-sync-milestones', async () => {
|
|
|
221
221
|
|
|
222
222
|
try {
|
|
223
223
|
// Build worktree milestone structure with slice-level and task-level files
|
|
224
|
-
|
|
224
|
+
// Use M002 as the milestone to sync, M001 as the "current" being merged (skipped)
|
|
225
|
+
const wtSliceDir = join(wtBase, '.gsd', 'milestones', 'M002', 'slices', 'S01');
|
|
225
226
|
const wtTasksDir = join(wtSliceDir, 'tasks');
|
|
226
227
|
mkdirSync(wtTasksDir, { recursive: true });
|
|
227
228
|
writeFileSync(join(wtSliceDir, 'S01-SUMMARY.md'), '# S01 Summary');
|
|
@@ -229,11 +230,12 @@ describe('worktree-sync-milestones', async () => {
|
|
|
229
230
|
writeFileSync(join(wtTasksDir, 'T02-SUMMARY.md'), '# T02 Summary');
|
|
230
231
|
|
|
231
232
|
// Main project root starts with only the milestone directory (no slices yet)
|
|
232
|
-
mkdirSync(join(mainBase, '.gsd', 'milestones', '
|
|
233
|
+
mkdirSync(join(mainBase, '.gsd', 'milestones', 'M002'), { recursive: true });
|
|
233
234
|
|
|
235
|
+
// Pass M001 as milestoneId (the one being merged/skipped), M002 should still sync
|
|
234
236
|
const { synced } = syncWorktreeStateBack(mainBase, wtBase, 'M001');
|
|
235
237
|
|
|
236
|
-
const mainSliceDir = join(mainBase, '.gsd', 'milestones', '
|
|
238
|
+
const mainSliceDir = join(mainBase, '.gsd', 'milestones', 'M002', 'slices', 'S01');
|
|
237
239
|
const mainTasksDir = join(mainSliceDir, 'tasks');
|
|
238
240
|
|
|
239
241
|
assert.ok(
|
|
@@ -341,16 +343,16 @@ describe('worktree-sync-milestones', async () => {
|
|
|
341
343
|
'M002 missing in main before sync',
|
|
342
344
|
);
|
|
343
345
|
|
|
344
|
-
// Sync with milestoneId = M001 (the current milestone)
|
|
346
|
+
// Sync with milestoneId = M001 (the current milestone being merged — skipped)
|
|
345
347
|
const { synced } = syncWorktreeStateBack(mainBase, wtBase, 'M001');
|
|
346
348
|
|
|
347
|
-
// M001 should be
|
|
349
|
+
// M001 should be SKIPPED (current milestone being merged — #3641)
|
|
348
350
|
assert.ok(
|
|
349
|
-
existsSync(join(mainBase, '.gsd', 'milestones', 'M001', 'M001-SUMMARY.md')),
|
|
350
|
-
'M001 SUMMARY synced to
|
|
351
|
+
!existsSync(join(mainBase, '.gsd', 'milestones', 'M001', 'M001-SUMMARY.md')),
|
|
352
|
+
'M001 SUMMARY NOT synced (current milestone skipped to prevent merge conflicts)',
|
|
351
353
|
);
|
|
352
354
|
|
|
353
|
-
// M002 should
|
|
355
|
+
// M002 should be synced (other milestone — not skipped)
|
|
354
356
|
assert.ok(
|
|
355
357
|
existsSync(join(mainBase, '.gsd', 'milestones', 'M002-abc123', 'M002-abc123-CONTEXT.md')),
|
|
356
358
|
'M002 CONTEXT synced to main (next-milestone fix)',
|
|
@@ -407,20 +409,17 @@ describe('worktree-sync-milestones', async () => {
|
|
|
407
409
|
writeFileSync(join(wtBase, '.gsd', 'REQUIREMENTS.md'), '# Requirements\n## R001-R089\n## R090 — SCIM\n## R091 — WebAuthn');
|
|
408
410
|
writeFileSync(join(wtBase, '.gsd', 'PROJECT.md'), '# Project\nMilestones: M001-M007');
|
|
409
411
|
|
|
410
|
-
// Sync with milestoneId = M006 (the completing milestone)
|
|
412
|
+
// Sync with milestoneId = M006 (the completing milestone — skipped by sync)
|
|
411
413
|
const { synced } = syncWorktreeStateBack(mainBase, wtBase, 'M006-589wvh');
|
|
412
414
|
|
|
413
|
-
//
|
|
414
|
-
|
|
415
|
-
existsSync(join(mainBase, '.gsd', 'milestones', 'M006-589wvh', 'M006-589wvh-SUMMARY.md')),
|
|
416
|
-
'M006 SUMMARY synced',
|
|
417
|
-
);
|
|
415
|
+
// M006 is the current milestone being merged — it should be SKIPPED (#3641)
|
|
416
|
+
// Its files are already in the milestone branch and would conflict with squash merge.
|
|
418
417
|
assert.ok(
|
|
419
|
-
existsSync(join(mainBase, '.gsd', 'milestones', 'M006-589wvh', '
|
|
420
|
-
'M006
|
|
418
|
+
!existsSync(join(mainBase, '.gsd', 'milestones', 'M006-589wvh', 'M006-589wvh-SUMMARY.md')),
|
|
419
|
+
'M006 SUMMARY NOT synced (current milestone skipped)',
|
|
421
420
|
);
|
|
422
421
|
|
|
423
|
-
// Verify M007 artifacts synced (the critical fix)
|
|
422
|
+
// Verify M007 artifacts synced (the critical fix — other milestones still sync)
|
|
424
423
|
assert.ok(
|
|
425
424
|
existsSync(join(mainBase, '.gsd', 'milestones', 'M007-wortc8', 'M007-wortc8-CONTEXT.md')),
|
|
426
425
|
'M007 CONTEXT synced to main (next-milestone)',
|
|
@@ -47,7 +47,8 @@ function writeFile(dir: string, relativePath: string, content: string): void {
|
|
|
47
47
|
test("syncWorktreeStateBack copies task summaries from tasks/ subdirectory (#1678)", () => {
|
|
48
48
|
const mainBase = makeTempDir("main");
|
|
49
49
|
const wtBase = makeTempDir("wt");
|
|
50
|
-
const
|
|
50
|
+
const currentMid = "M000"; // milestone being merged (skipped by sync)
|
|
51
|
+
const mid = "M001"; // other milestone that should be synced
|
|
51
52
|
|
|
52
53
|
try {
|
|
53
54
|
// Set up worktree with milestone, slice, and task files
|
|
@@ -64,8 +65,8 @@ test("syncWorktreeStateBack copies task summaries from tasks/ subdirectory (#167
|
|
|
64
65
|
// Set up main with empty .gsd
|
|
65
66
|
mkdirSync(join(mainBase, ".gsd"), { recursive: true });
|
|
66
67
|
|
|
67
|
-
// Run sync
|
|
68
|
-
const result = syncWorktreeStateBack(mainBase, wtBase,
|
|
68
|
+
// Run sync — currentMid is skipped, mid (M001) should be synced
|
|
69
|
+
const result = syncWorktreeStateBack(mainBase, wtBase, currentMid);
|
|
69
70
|
|
|
70
71
|
// Verify milestone-level files synced
|
|
71
72
|
assert.ok(
|
|
@@ -126,7 +127,8 @@ test("syncWorktreeStateBack copies task summaries from tasks/ subdirectory (#167
|
|
|
126
127
|
test("syncWorktreeStateBack handles multiple slices with tasks (#1678)", () => {
|
|
127
128
|
const mainBase = makeTempDir("main");
|
|
128
129
|
const wtBase = makeTempDir("wt");
|
|
129
|
-
const
|
|
130
|
+
const currentMid = "M000"; // milestone being merged (skipped)
|
|
131
|
+
const mid = "M002"; // other milestone that should be synced
|
|
130
132
|
|
|
131
133
|
try {
|
|
132
134
|
// Set up two slices with tasks
|
|
@@ -139,7 +141,7 @@ test("syncWorktreeStateBack handles multiple slices with tasks (#1678)", () => {
|
|
|
139
141
|
|
|
140
142
|
mkdirSync(join(mainBase, ".gsd"), { recursive: true });
|
|
141
143
|
|
|
142
|
-
const result = syncWorktreeStateBack(mainBase, wtBase,
|
|
144
|
+
const result = syncWorktreeStateBack(mainBase, wtBase, currentMid);
|
|
143
145
|
|
|
144
146
|
// All task summaries from both slices should be synced
|
|
145
147
|
assert.ok(existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/tasks/T01-SUMMARY.md`)));
|
|
@@ -160,7 +162,8 @@ test("syncWorktreeStateBack handles multiple slices with tasks (#1678)", () => {
|
|
|
160
162
|
test("syncWorktreeStateBack handles slices without tasks/ directory", () => {
|
|
161
163
|
const mainBase = makeTempDir("main");
|
|
162
164
|
const wtBase = makeTempDir("wt");
|
|
163
|
-
const
|
|
165
|
+
const currentMid = "M000"; // milestone being merged (skipped)
|
|
166
|
+
const mid = "M003"; // other milestone that should be synced
|
|
164
167
|
|
|
165
168
|
try {
|
|
166
169
|
// Slice with no tasks/ subdirectory (legitimate case: pre-planning)
|
|
@@ -168,7 +171,7 @@ test("syncWorktreeStateBack handles slices without tasks/ directory", () => {
|
|
|
168
171
|
|
|
169
172
|
mkdirSync(join(mainBase, ".gsd"), { recursive: true });
|
|
170
173
|
|
|
171
|
-
const result = syncWorktreeStateBack(mainBase, wtBase,
|
|
174
|
+
const result = syncWorktreeStateBack(mainBase, wtBase, currentMid);
|
|
172
175
|
|
|
173
176
|
// Should sync the slice file without errors
|
|
174
177
|
assert.ok(existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/S01-RESEARCH.md`)));
|
|
@@ -183,7 +186,8 @@ test("syncWorktreeStateBack handles slices without tasks/ directory", () => {
|
|
|
183
186
|
test("syncWorktreeStateBack ignores non-md files in tasks/", () => {
|
|
184
187
|
const mainBase = makeTempDir("main");
|
|
185
188
|
const wtBase = makeTempDir("wt");
|
|
186
|
-
const
|
|
189
|
+
const currentMid = "M000"; // milestone being merged (skipped)
|
|
190
|
+
const mid = "M004"; // other milestone that should be synced
|
|
187
191
|
|
|
188
192
|
try {
|
|
189
193
|
writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/S01-PLAN.md`, "# Plan\n");
|
|
@@ -194,7 +198,7 @@ test("syncWorktreeStateBack ignores non-md files in tasks/", () => {
|
|
|
194
198
|
|
|
195
199
|
mkdirSync(join(mainBase, ".gsd"), { recursive: true });
|
|
196
200
|
|
|
197
|
-
const result = syncWorktreeStateBack(mainBase, wtBase,
|
|
201
|
+
const result = syncWorktreeStateBack(mainBase, wtBase, currentMid);
|
|
198
202
|
|
|
199
203
|
// Only .md files should be synced
|
|
200
204
|
assert.ok(existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/tasks/T01-SUMMARY.md`)));
|
|
@@ -14,9 +14,11 @@ import {
|
|
|
14
14
|
resolveProjectRoot,
|
|
15
15
|
setActiveMilestoneId,
|
|
16
16
|
SLICE_BRANCH_RE,
|
|
17
|
+
_resetServiceCache,
|
|
17
18
|
} from "../worktree.ts";
|
|
18
19
|
import { readIntegrationBranch } from "../git-service.ts";
|
|
19
20
|
import { _resetHasChangesCache } from "../native-git-bridge.ts";
|
|
21
|
+
import { _clearGsdRootCache } from "../paths.ts";
|
|
20
22
|
import { describe, test } from 'node:test';
|
|
21
23
|
import assert from 'node:assert/strict';
|
|
22
24
|
|
|
@@ -165,15 +167,30 @@ describe('worktree', async () => {
|
|
|
165
167
|
run("git checkout -b my-feature", repo);
|
|
166
168
|
captureIntegrationBranch(repo, "M001");
|
|
167
169
|
|
|
168
|
-
//
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
170
|
+
// Isolate from user's global preferences (which may have git.main_branch set).
|
|
171
|
+
// Reset caches so getService() creates a fresh instance with empty preferences.
|
|
172
|
+
const originalHome = process.env.HOME;
|
|
173
|
+
const fakeHome = mkdtempSync(join(tmpdir(), "gsd-fake-home-"));
|
|
174
|
+
process.env.HOME = fakeHome;
|
|
175
|
+
_clearGsdRootCache();
|
|
176
|
+
_resetServiceCache();
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
// Without milestone set, getMainBranch returns "main"
|
|
180
|
+
setActiveMilestoneId(repo, null);
|
|
181
|
+
assert.deepStrictEqual(getMainBranch(repo), "main",
|
|
182
|
+
"getMainBranch returns main without milestone set");
|
|
183
|
+
|
|
184
|
+
// With milestone set, getMainBranch returns feature branch
|
|
185
|
+
setActiveMilestoneId(repo, "M001");
|
|
186
|
+
assert.deepStrictEqual(getMainBranch(repo), "my-feature",
|
|
187
|
+
"getMainBranch returns integration branch with milestone set");
|
|
188
|
+
} finally {
|
|
189
|
+
process.env.HOME = originalHome;
|
|
190
|
+
_clearGsdRootCache();
|
|
191
|
+
_resetServiceCache();
|
|
192
|
+
rmSync(fakeHome, { recursive: true, force: true });
|
|
193
|
+
}
|
|
177
194
|
|
|
178
195
|
rmSync(repo, { recursive: true, force: true });
|
|
179
196
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3441: guided flow must treat a roadmap with zero
|
|
3
|
+
* parseable slices the same as no roadmap — offer "Create roadmap" not "Go auto".
|
|
4
|
+
*/
|
|
5
|
+
import { test } from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
|
|
10
|
+
test("guided-flow checks roadmap slice count before offering auto (#3441)", () => {
|
|
11
|
+
const src = readFileSync(
|
|
12
|
+
join(import.meta.dirname, "..", "guided-flow.ts"),
|
|
13
|
+
"utf-8",
|
|
14
|
+
);
|
|
15
|
+
assert.ok(
|
|
16
|
+
src.includes("roadmapHasSlices") || src.includes("parseRoadmapSlices"),
|
|
17
|
+
"Guided flow must parse roadmap for slices before deciding which options to show",
|
|
18
|
+
);
|
|
19
|
+
});
|