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,525 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for the prepared discussion system.
|
|
3
|
+
*
|
|
4
|
+
* Exercises the full preparation pipeline against the real GSD-2 codebase:
|
|
5
|
+
* - runPreparation() produces valid briefs
|
|
6
|
+
* - TypeScript is detected as primary language
|
|
7
|
+
* - Module structure includes top-level directories
|
|
8
|
+
* - Completes within R112 timing requirement (<60s)
|
|
9
|
+
* - prepareAndBuildDiscussPrompt() uses discuss-prepared template when enabled
|
|
10
|
+
* - Fallback to standard prompt when preparation is disabled
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import test from "node:test";
|
|
14
|
+
import assert from "node:assert/strict";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import { existsSync } from "node:fs";
|
|
17
|
+
import {
|
|
18
|
+
runPreparation,
|
|
19
|
+
formatCodebaseBrief,
|
|
20
|
+
formatPriorContextBrief,
|
|
21
|
+
formatEcosystemBrief,
|
|
22
|
+
type PreparationUIContext,
|
|
23
|
+
type PreparationPreferences,
|
|
24
|
+
type PreparationResult,
|
|
25
|
+
} from "../preparation.ts";
|
|
26
|
+
import { validateEnhancedContext } from "../prompt-validation.ts";
|
|
27
|
+
import { getLastPreparationResult, clearPreparationResult } from "../guided-flow.ts";
|
|
28
|
+
|
|
29
|
+
// ─── Test Helpers ───────────────────────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Mock UI context that captures notifications for testing.
|
|
33
|
+
* Follows the pattern from preparation.test.ts.
|
|
34
|
+
*/
|
|
35
|
+
function createMockUI(): PreparationUIContext & { notifications: Array<{ message: string; type?: string }> } {
|
|
36
|
+
const notifications: Array<{ message: string; type?: string }> = [];
|
|
37
|
+
return {
|
|
38
|
+
notifications,
|
|
39
|
+
notify(message: string, type?: "info" | "warning" | "error" | "success") {
|
|
40
|
+
notifications.push({ message, type });
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get the GSD extension source directory for integration testing.
|
|
47
|
+
* This is the real codebase we'll analyze.
|
|
48
|
+
*/
|
|
49
|
+
function getGsdExtensionDir(): string {
|
|
50
|
+
// Navigate from tests/ up to gsd/ directory
|
|
51
|
+
return join(import.meta.dirname, "..");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Get the GSD-2 project root for full codebase analysis.
|
|
56
|
+
*/
|
|
57
|
+
function getProjectRoot(): string {
|
|
58
|
+
// Navigate from tests/ up to the project root
|
|
59
|
+
// tests/ -> gsd/ -> extensions/ -> resources/ -> src/ -> gsd-2/
|
|
60
|
+
return join(import.meta.dirname, "..", "..", "..", "..", "..");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ─── R111 Validation: runPreparation against real codebase ──────────────────────
|
|
64
|
+
|
|
65
|
+
test("R111: runPreparation() produces valid codebase brief for GSD extension", async (t) => {
|
|
66
|
+
const dir = getGsdExtensionDir();
|
|
67
|
+
const ui = createMockUI();
|
|
68
|
+
const prefs: PreparationPreferences = {
|
|
69
|
+
discuss_preparation: true,
|
|
70
|
+
discuss_web_research: false, // Skip web research to avoid API key requirement
|
|
71
|
+
discuss_depth: "standard",
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const result = await runPreparation(dir, ui, prefs);
|
|
75
|
+
|
|
76
|
+
// Verify preparation completed successfully
|
|
77
|
+
assert.equal(result.enabled, true, "preparation should be enabled");
|
|
78
|
+
assert.ok(result.codebase, "should have codebase brief");
|
|
79
|
+
assert.ok(result.codebaseBrief, "should have formatted codebase brief");
|
|
80
|
+
|
|
81
|
+
// Verify TypeScript is detected as primary language
|
|
82
|
+
assert.equal(
|
|
83
|
+
result.codebase.techStack.primaryLanguage,
|
|
84
|
+
"javascript/typescript",
|
|
85
|
+
"should detect TypeScript as primary language",
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// Verify module structure includes top-level directories
|
|
89
|
+
const topLevelDirs = result.codebase.moduleStructure.topLevelDirs;
|
|
90
|
+
assert.ok(topLevelDirs.length > 0, "should detect top-level directories");
|
|
91
|
+
|
|
92
|
+
// Common directories in the GSD extension
|
|
93
|
+
const expectedDirs = ["tests", "prompts", "templates", "migrate"];
|
|
94
|
+
const foundExpected = expectedDirs.filter(d => topLevelDirs.includes(d));
|
|
95
|
+
assert.ok(
|
|
96
|
+
foundExpected.length >= 2,
|
|
97
|
+
`should detect common directories, found: ${topLevelDirs.join(", ")}`,
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
// Verify sampled files exist
|
|
101
|
+
assert.ok(result.codebase.sampledFiles.length > 0, "should sample source files");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("R111: runPreparation() produces valid prior context brief", async (t) => {
|
|
105
|
+
const dir = getGsdExtensionDir();
|
|
106
|
+
const ui = createMockUI();
|
|
107
|
+
const prefs: PreparationPreferences = {
|
|
108
|
+
discuss_preparation: true,
|
|
109
|
+
discuss_web_research: false,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const result = await runPreparation(dir, ui, prefs);
|
|
113
|
+
|
|
114
|
+
// Verify prior context brief structure
|
|
115
|
+
assert.ok(result.priorContext, "should have prior context");
|
|
116
|
+
assert.ok(result.priorContextBrief, "should have formatted prior context brief");
|
|
117
|
+
|
|
118
|
+
// Prior context aggregates decisions, requirements, knowledge, summaries
|
|
119
|
+
assert.ok("decisions" in result.priorContext, "should have decisions");
|
|
120
|
+
assert.ok("requirements" in result.priorContext, "should have requirements");
|
|
121
|
+
assert.ok("knowledge" in result.priorContext, "should have knowledge");
|
|
122
|
+
assert.ok("summaries" in result.priorContext, "should have summaries");
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("R111: runPreparation() produces valid ecosystem brief (skipped without API key)", async (t) => {
|
|
126
|
+
const dir = getGsdExtensionDir();
|
|
127
|
+
const ui = createMockUI();
|
|
128
|
+
const prefs: PreparationPreferences = {
|
|
129
|
+
discuss_preparation: true,
|
|
130
|
+
discuss_web_research: false, // Explicitly disable
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const result = await runPreparation(dir, ui, prefs);
|
|
134
|
+
|
|
135
|
+
// Verify ecosystem brief structure
|
|
136
|
+
assert.ok(result.ecosystem, "should have ecosystem brief");
|
|
137
|
+
assert.ok(result.ecosystemBrief, "should have formatted ecosystem brief");
|
|
138
|
+
assert.equal(result.ecosystem.available, false, "ecosystem should be unavailable when web research disabled");
|
|
139
|
+
assert.ok(result.ecosystem.skippedReason, "should have skip reason");
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("R112: runPreparation() completes within 60s requirement", async (t) => {
|
|
143
|
+
const dir = getGsdExtensionDir();
|
|
144
|
+
const prefs: PreparationPreferences = {
|
|
145
|
+
discuss_preparation: true,
|
|
146
|
+
discuss_web_research: false,
|
|
147
|
+
discuss_depth: "standard",
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const startTime = performance.now();
|
|
151
|
+
const result = await runPreparation(dir, null, prefs);
|
|
152
|
+
const elapsed = performance.now() - startTime;
|
|
153
|
+
|
|
154
|
+
// R112 requirement: preparation must complete within 60 seconds
|
|
155
|
+
assert.ok(result.durationMs < 60000, `should complete within 60s, took ${result.durationMs}ms`);
|
|
156
|
+
assert.ok(elapsed < 60000, `wall-clock time should be under 60s, was ${elapsed}ms`);
|
|
157
|
+
|
|
158
|
+
// Should be much faster for a local directory analysis
|
|
159
|
+
assert.ok(result.durationMs < 10000, `should typically complete within 10s, took ${result.durationMs}ms`);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// ─── Codebase Pattern Detection ─────────────────────────────────────────────────
|
|
163
|
+
|
|
164
|
+
test("runPreparation() detects code patterns from GSD extension", async (t) => {
|
|
165
|
+
const dir = getGsdExtensionDir();
|
|
166
|
+
const prefs: PreparationPreferences = {
|
|
167
|
+
discuss_preparation: true,
|
|
168
|
+
discuss_web_research: false,
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const result = await runPreparation(dir, null, prefs);
|
|
172
|
+
|
|
173
|
+
// The GSD extension uses async/await extensively
|
|
174
|
+
assert.ok(
|
|
175
|
+
result.codebase.patterns.asyncStyle === "async/await" || result.codebase.patterns.asyncStyle === "mixed",
|
|
176
|
+
`should detect async/await or mixed, got ${result.codebase.patterns.asyncStyle}`,
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
// The GSD extension uses try/catch for error handling
|
|
180
|
+
assert.ok(
|
|
181
|
+
result.codebase.patterns.errorHandling === "try/catch" || result.codebase.patterns.errorHandling === "mixed",
|
|
182
|
+
`should detect try/catch or mixed, got ${result.codebase.patterns.errorHandling}`,
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
// TypeScript uses camelCase or mixed naming
|
|
186
|
+
assert.ok(
|
|
187
|
+
result.codebase.patterns.namingConvention === "camelCase" || result.codebase.patterns.namingConvention === "mixed",
|
|
188
|
+
`should detect camelCase or mixed, got ${result.codebase.patterns.namingConvention}`,
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
// Evidence should be populated
|
|
192
|
+
assert.ok(result.codebase.patterns.evidence.asyncStyle.length > 0, "should have async style evidence");
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test("runPreparation() samples TypeScript files from src/ or project root", async (t) => {
|
|
196
|
+
const dir = getGsdExtensionDir();
|
|
197
|
+
const prefs: PreparationPreferences = {
|
|
198
|
+
discuss_preparation: true,
|
|
199
|
+
discuss_web_research: false,
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const result = await runPreparation(dir, null, prefs);
|
|
203
|
+
|
|
204
|
+
// Should sample TypeScript files
|
|
205
|
+
const tsFiles = result.codebase.sampledFiles.filter(
|
|
206
|
+
f => f.endsWith(".ts") || f.endsWith(".tsx"),
|
|
207
|
+
);
|
|
208
|
+
assert.ok(tsFiles.length > 0, "should sample TypeScript files");
|
|
209
|
+
|
|
210
|
+
// Should exclude test files
|
|
211
|
+
const testFiles = result.codebase.sampledFiles.filter(
|
|
212
|
+
f => f.includes(".test.") || f.includes(".spec."),
|
|
213
|
+
);
|
|
214
|
+
assert.equal(testFiles.length, 0, "should not sample test files");
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// ─── Brief Formatting ───────────────────────────────────────────────────────────
|
|
218
|
+
|
|
219
|
+
test("formatCodebaseBrief() produces LLM-readable markdown", async (t) => {
|
|
220
|
+
const dir = getGsdExtensionDir();
|
|
221
|
+
const prefs: PreparationPreferences = {
|
|
222
|
+
discuss_preparation: true,
|
|
223
|
+
discuss_web_research: false,
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const result = await runPreparation(dir, null, prefs);
|
|
227
|
+
const formatted = formatCodebaseBrief(result.codebase);
|
|
228
|
+
|
|
229
|
+
// Should contain expected sections
|
|
230
|
+
assert.ok(formatted.includes("## Tech Stack"), "should have Tech Stack section");
|
|
231
|
+
assert.ok(formatted.includes("## Module Structure"), "should have Module Structure section");
|
|
232
|
+
assert.ok(formatted.includes("## Code Patterns"), "should have Code Patterns section");
|
|
233
|
+
|
|
234
|
+
// Should contain detected tech
|
|
235
|
+
assert.ok(formatted.includes("javascript/typescript"), "should include detected language");
|
|
236
|
+
|
|
237
|
+
// Should be within character limit
|
|
238
|
+
assert.ok(formatted.length <= 3000, `should cap at 3000 chars, got ${formatted.length}`);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test("formatPriorContextBrief() produces structured prior context output", async (t) => {
|
|
242
|
+
const dir = getGsdExtensionDir();
|
|
243
|
+
const prefs: PreparationPreferences = {
|
|
244
|
+
discuss_preparation: true,
|
|
245
|
+
discuss_web_research: false,
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
const result = await runPreparation(dir, null, prefs);
|
|
249
|
+
const formatted = formatPriorContextBrief(result.priorContext);
|
|
250
|
+
|
|
251
|
+
// Should contain expected sections
|
|
252
|
+
assert.ok(formatted.includes("## Prior Decisions"), "should have Prior Decisions section");
|
|
253
|
+
assert.ok(formatted.includes("## Prior Requirements"), "should have Prior Requirements section");
|
|
254
|
+
assert.ok(formatted.includes("## Prior Knowledge"), "should have Prior Knowledge section");
|
|
255
|
+
assert.ok(formatted.includes("## Prior Milestone Summaries"), "should have Prior Milestone Summaries section");
|
|
256
|
+
|
|
257
|
+
// Should be within character limit
|
|
258
|
+
assert.ok(formatted.length <= 6000, `should cap at 6000 chars, got ${formatted.length}`);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
test("formatEcosystemBrief() returns simplified message (research happens during discussion)", async (t) => {
|
|
262
|
+
const dir = getGsdExtensionDir();
|
|
263
|
+
const prefs: PreparationPreferences = {
|
|
264
|
+
discuss_preparation: true,
|
|
265
|
+
discuss_web_research: false,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const result = await runPreparation(dir, null, prefs);
|
|
269
|
+
const formatted = formatEcosystemBrief(result.ecosystem);
|
|
270
|
+
|
|
271
|
+
// Should contain section header
|
|
272
|
+
assert.ok(formatted.includes("## Ecosystem Research"), "should have Ecosystem Research section");
|
|
273
|
+
|
|
274
|
+
// Should indicate research happens during discussion
|
|
275
|
+
assert.ok(formatted.includes("during the discussion"), "should mention research happens during discussion");
|
|
276
|
+
assert.ok(formatted.includes("web search tools"), "should mention web search tools");
|
|
277
|
+
|
|
278
|
+
// Should be within character limit
|
|
279
|
+
assert.ok(formatted.length <= 4000, `should cap at 4000 chars, got ${formatted.length}`);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// ─── Preparation Result Storage ─────────────────────────────────────────────────
|
|
283
|
+
|
|
284
|
+
test("getLastPreparationResult() returns null initially", async (t) => {
|
|
285
|
+
// Clear any existing state
|
|
286
|
+
clearPreparationResult();
|
|
287
|
+
|
|
288
|
+
const result = getLastPreparationResult();
|
|
289
|
+
assert.equal(result, null, "should return null when no preparation has run");
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
test("clearPreparationResult() clears stored result", async (t) => {
|
|
293
|
+
// This test verifies the clear function works
|
|
294
|
+
// We can't easily test the set behavior without running the full guided-flow
|
|
295
|
+
clearPreparationResult();
|
|
296
|
+
const result = getLastPreparationResult();
|
|
297
|
+
assert.equal(result, null, "should be null after clear");
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// ─── TUI Progress Notifications ─────────────────────────────────────────────────
|
|
301
|
+
|
|
302
|
+
test("runPreparation() emits TUI progress notifications", async (t) => {
|
|
303
|
+
const dir = getGsdExtensionDir();
|
|
304
|
+
const ui = createMockUI();
|
|
305
|
+
const prefs: PreparationPreferences = {
|
|
306
|
+
discuss_preparation: true,
|
|
307
|
+
discuss_web_research: false,
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
await runPreparation(dir, ui, prefs);
|
|
311
|
+
|
|
312
|
+
// Should have notifications for each phase
|
|
313
|
+
assert.ok(ui.notifications.length > 0, "should have notifications");
|
|
314
|
+
|
|
315
|
+
// Verify codebase analysis notifications
|
|
316
|
+
assert.ok(
|
|
317
|
+
ui.notifications.some(n => n.message.includes("Analyzing codebase")),
|
|
318
|
+
"should show codebase analysis start",
|
|
319
|
+
);
|
|
320
|
+
assert.ok(
|
|
321
|
+
ui.notifications.some(n => n.message.includes("✓ Analyzed codebase")),
|
|
322
|
+
"should show codebase analysis complete",
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
// Verify prior context notifications
|
|
326
|
+
assert.ok(
|
|
327
|
+
ui.notifications.some(n => n.message.includes("Reviewing prior context")),
|
|
328
|
+
"should show prior context start",
|
|
329
|
+
);
|
|
330
|
+
assert.ok(
|
|
331
|
+
ui.notifications.some(n => n.message.includes("✓ Reviewed prior context")),
|
|
332
|
+
"should show prior context complete",
|
|
333
|
+
);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
test("runPreparation() works in silent mode (no UI)", async (t) => {
|
|
337
|
+
const dir = getGsdExtensionDir();
|
|
338
|
+
const prefs: PreparationPreferences = {
|
|
339
|
+
discuss_preparation: true,
|
|
340
|
+
discuss_web_research: false,
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
// Pass null for UI
|
|
344
|
+
const result = await runPreparation(dir, null, prefs);
|
|
345
|
+
|
|
346
|
+
// Should complete without error
|
|
347
|
+
assert.equal(result.enabled, true, "should work without UI");
|
|
348
|
+
assert.ok(result.codebase, "should have codebase");
|
|
349
|
+
assert.ok(result.priorContext, "should have priorContext");
|
|
350
|
+
assert.ok(result.durationMs > 0, "should have duration");
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
// ─── Preference-Controlled Behavior ─────────────────────────────────────────────
|
|
354
|
+
|
|
355
|
+
test("runPreparation() returns early when discuss_preparation is false", async (t) => {
|
|
356
|
+
const dir = getGsdExtensionDir();
|
|
357
|
+
const ui = createMockUI();
|
|
358
|
+
const prefs: PreparationPreferences = {
|
|
359
|
+
discuss_preparation: false,
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
const result = await runPreparation(dir, ui, prefs);
|
|
363
|
+
|
|
364
|
+
assert.equal(result.enabled, false, "should indicate preparation disabled");
|
|
365
|
+
assert.equal(result.codebaseBrief, "", "should have empty codebase brief");
|
|
366
|
+
assert.equal(result.priorContextBrief, "", "should have empty prior context brief");
|
|
367
|
+
assert.equal(result.ecosystemBrief, "", "should have empty ecosystem brief");
|
|
368
|
+
assert.equal(ui.notifications.length, 0, "should not show any notifications");
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
test("runPreparation() ecosystem research always returns unavailable (happens during discussion)", async (t) => {
|
|
372
|
+
const dir = getGsdExtensionDir();
|
|
373
|
+
const ui = createMockUI();
|
|
374
|
+
const prefs: PreparationPreferences = {
|
|
375
|
+
discuss_preparation: true,
|
|
376
|
+
discuss_web_research: true, // Even with this enabled, ecosystem research returns unavailable
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
const result = await runPreparation(dir, ui, prefs);
|
|
380
|
+
|
|
381
|
+
assert.equal(result.enabled, true);
|
|
382
|
+
assert.equal(result.ecosystemResearchPerformed, false, "should not perform ecosystem research from preparation");
|
|
383
|
+
assert.equal(result.ecosystem.available, false);
|
|
384
|
+
assert.ok(
|
|
385
|
+
result.ecosystem.skippedReason?.includes("during the discussion"),
|
|
386
|
+
"should indicate research happens during discussion",
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
// Should NOT have ecosystem research notifications (no longer part of preparation)
|
|
390
|
+
assert.ok(
|
|
391
|
+
!ui.notifications.some(n => n.message.includes("Researching ecosystem")),
|
|
392
|
+
"should not show ecosystem research notification",
|
|
393
|
+
);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
// ─── validateEnhancedContext Integration ────────────────────────────────────────
|
|
397
|
+
|
|
398
|
+
test("validateEnhancedContext() validates required sections", async (t) => {
|
|
399
|
+
// Test with valid enhanced context
|
|
400
|
+
const validContext = `# M001 — Test Milestone
|
|
401
|
+
|
|
402
|
+
## Scope
|
|
403
|
+
|
|
404
|
+
This milestone covers X, Y, Z.
|
|
405
|
+
|
|
406
|
+
## Architectural Decisions
|
|
407
|
+
|
|
408
|
+
### Decision 1: Use TypeScript
|
|
409
|
+
|
|
410
|
+
We will use TypeScript for type safety.
|
|
411
|
+
|
|
412
|
+
## Acceptance Criteria
|
|
413
|
+
|
|
414
|
+
- [ ] Feature A works
|
|
415
|
+
- [ ] Feature B works
|
|
416
|
+
`;
|
|
417
|
+
|
|
418
|
+
const validResult = validateEnhancedContext(validContext);
|
|
419
|
+
assert.equal(validResult.valid, true, "should validate complete context");
|
|
420
|
+
assert.deepEqual(validResult.missing, [], "should have no missing sections");
|
|
421
|
+
|
|
422
|
+
// Test with missing sections
|
|
423
|
+
const invalidContext = `# M001 — Test Milestone
|
|
424
|
+
|
|
425
|
+
## Scope
|
|
426
|
+
|
|
427
|
+
This milestone covers X, Y, Z.
|
|
428
|
+
`;
|
|
429
|
+
|
|
430
|
+
const invalidResult = validateEnhancedContext(invalidContext);
|
|
431
|
+
assert.equal(invalidResult.valid, false, "should reject incomplete context");
|
|
432
|
+
assert.ok(invalidResult.missing.length > 0, "should list missing sections");
|
|
433
|
+
assert.ok(
|
|
434
|
+
invalidResult.missing.some(m => m.includes("Architectural Decisions")),
|
|
435
|
+
"should report missing Architectural Decisions",
|
|
436
|
+
);
|
|
437
|
+
assert.ok(
|
|
438
|
+
invalidResult.missing.some(m => m.includes("Acceptance Criteria")),
|
|
439
|
+
"should report missing Acceptance Criteria",
|
|
440
|
+
);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
test("validateEnhancedContext() requires decision entries in Architectural Decisions", async (t) => {
|
|
444
|
+
// Empty architectural decisions section
|
|
445
|
+
const emptyDecisions = `# M001 — Test Milestone
|
|
446
|
+
|
|
447
|
+
## Scope
|
|
448
|
+
|
|
449
|
+
This milestone covers X, Y, Z.
|
|
450
|
+
|
|
451
|
+
## Architectural Decisions
|
|
452
|
+
|
|
453
|
+
(No decisions yet)
|
|
454
|
+
|
|
455
|
+
## Acceptance Criteria
|
|
456
|
+
|
|
457
|
+
- [ ] Feature A works
|
|
458
|
+
`;
|
|
459
|
+
|
|
460
|
+
const result = validateEnhancedContext(emptyDecisions);
|
|
461
|
+
assert.equal(result.valid, false, "should reject empty decisions section");
|
|
462
|
+
assert.ok(
|
|
463
|
+
result.missing.some(m => m.includes("decision entry")),
|
|
464
|
+
"should report missing decision entry",
|
|
465
|
+
);
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
// ─── Full Pipeline Integration ──────────────────────────────────────────────────
|
|
469
|
+
|
|
470
|
+
test("Full pipeline: preparation produces consistent results across runs", async (t) => {
|
|
471
|
+
const dir = getGsdExtensionDir();
|
|
472
|
+
const prefs: PreparationPreferences = {
|
|
473
|
+
discuss_preparation: true,
|
|
474
|
+
discuss_web_research: false,
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
// Run preparation twice
|
|
478
|
+
const result1 = await runPreparation(dir, null, prefs);
|
|
479
|
+
const result2 = await runPreparation(dir, null, prefs);
|
|
480
|
+
|
|
481
|
+
// Results should be consistent (same codebase, same analysis)
|
|
482
|
+
assert.equal(
|
|
483
|
+
result1.codebase.techStack.primaryLanguage,
|
|
484
|
+
result2.codebase.techStack.primaryLanguage,
|
|
485
|
+
"primary language should be consistent",
|
|
486
|
+
);
|
|
487
|
+
|
|
488
|
+
assert.deepEqual(
|
|
489
|
+
result1.codebase.moduleStructure.topLevelDirs.sort(),
|
|
490
|
+
result2.codebase.moduleStructure.topLevelDirs.sort(),
|
|
491
|
+
"top-level directories should be consistent",
|
|
492
|
+
);
|
|
493
|
+
|
|
494
|
+
assert.equal(
|
|
495
|
+
result1.codebase.patterns.asyncStyle,
|
|
496
|
+
result2.codebase.patterns.asyncStyle,
|
|
497
|
+
"async style should be consistent",
|
|
498
|
+
);
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
test("Full pipeline: preparation handles empty .gsd directory gracefully", async (t) => {
|
|
502
|
+
// The GSD extension directory may or may not have a .gsd subdirectory
|
|
503
|
+
// Either way, preparation should not crash
|
|
504
|
+
const dir = getGsdExtensionDir();
|
|
505
|
+
const prefs: PreparationPreferences = {
|
|
506
|
+
discuss_preparation: true,
|
|
507
|
+
discuss_web_research: false,
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
let result: PreparationResult | undefined;
|
|
511
|
+
let error: unknown;
|
|
512
|
+
|
|
513
|
+
try {
|
|
514
|
+
result = await runPreparation(dir, null, prefs);
|
|
515
|
+
} catch (e) {
|
|
516
|
+
error = e;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
assert.equal(error, undefined, "should not throw");
|
|
520
|
+
assert.ok(result, "should return result");
|
|
521
|
+
assert.equal(result!.enabled, true, "should be enabled");
|
|
522
|
+
|
|
523
|
+
// Prior context should gracefully handle missing files
|
|
524
|
+
assert.ok(result!.priorContext, "should have prior context even if files missing");
|
|
525
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3675 — isolation:none stale branch guard
|
|
3
|
+
*
|
|
4
|
+
* When switching from isolation:branch/worktree to isolation:none, HEAD
|
|
5
|
+
* could remain on a milestone/<MID> branch. The fix in auto-start.ts
|
|
6
|
+
* detects this and auto-checks out to the integration branch.
|
|
7
|
+
*
|
|
8
|
+
* This structural test verifies the milestone/ branch check exists
|
|
9
|
+
* in auto-start.ts.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { describe, test } from 'node:test';
|
|
13
|
+
import assert from 'node:assert/strict';
|
|
14
|
+
import { readFileSync } from 'node:fs';
|
|
15
|
+
import { fileURLToPath } from 'node:url';
|
|
16
|
+
import { dirname, join } from 'node:path';
|
|
17
|
+
|
|
18
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
19
|
+
const __dirname = dirname(__filename);
|
|
20
|
+
|
|
21
|
+
const source = readFileSync(join(__dirname, '..', 'auto-start.ts'), 'utf-8');
|
|
22
|
+
|
|
23
|
+
describe('isolation:none stale branch guard (#3675)', () => {
|
|
24
|
+
test('checks for milestone/ branch prefix', () => {
|
|
25
|
+
assert.match(source, /startsWith\(["']milestone\//,
|
|
26
|
+
'auto-start should check for milestone/ branch prefix');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('imports nativeGetCurrentBranch', () => {
|
|
30
|
+
assert.match(source, /nativeGetCurrentBranch/,
|
|
31
|
+
'auto-start should import nativeGetCurrentBranch');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('imports nativeDetectMainBranch', () => {
|
|
35
|
+
assert.match(source, /nativeDetectMainBranch/,
|
|
36
|
+
'auto-start should import nativeDetectMainBranch');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('imports nativeCheckoutBranch', () => {
|
|
40
|
+
assert.match(source, /nativeCheckoutBranch/,
|
|
41
|
+
'auto-start should import nativeCheckoutBranch');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('guard is conditional on isolation mode "none"', () => {
|
|
45
|
+
assert.match(source, /getIsolationMode\(\)\s*===\s*["']none["']/,
|
|
46
|
+
'guard should only activate when isolation mode is "none"');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('calls nativeCheckoutBranch to return to integration branch', () => {
|
|
50
|
+
assert.match(source, /nativeCheckoutBranch\(base,\s*integrationBranch\)/,
|
|
51
|
+
'should checkout to the integration branch');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('guard is wrapped in try-catch (non-fatal)', () => {
|
|
55
|
+
// Find the milestone/ check and verify it is inside a try block
|
|
56
|
+
const milestoneIdx = source.indexOf('startsWith("milestone/")');
|
|
57
|
+
assert.ok(milestoneIdx > 0, 'milestone/ check should exist');
|
|
58
|
+
const before = source.slice(Math.max(0, milestoneIdx - 500), milestoneIdx);
|
|
59
|
+
assert.match(before, /try\s*\{/,
|
|
60
|
+
'milestone branch guard should be inside a try block');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3670 — needs-remediation verdict forces re-validation
|
|
3
|
+
*
|
|
4
|
+
* When validation returns needs-remediation, the state machine must route
|
|
5
|
+
* back to validating-milestone instead of completing-milestone. Without this,
|
|
6
|
+
* dispatch blocks completion for needs-remediation while state derives
|
|
7
|
+
* completing-milestone, creating a permanent deadlock.
|
|
8
|
+
*
|
|
9
|
+
* This structural test verifies the verdict === 'needs-remediation' guard
|
|
10
|
+
* exists at all three derivation paths in state.ts.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, test } from 'node:test';
|
|
14
|
+
import assert from 'node:assert/strict';
|
|
15
|
+
import { readFileSync } from 'node:fs';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
import { dirname, join } from 'node:path';
|
|
18
|
+
|
|
19
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
20
|
+
const __dirname = dirname(__filename);
|
|
21
|
+
|
|
22
|
+
const source = readFileSync(join(__dirname, '..', 'state.ts'), 'utf-8');
|
|
23
|
+
|
|
24
|
+
describe('needs-remediation revalidation guard (#3670)', () => {
|
|
25
|
+
test('verdict === needs-remediation guard exists in state.ts', () => {
|
|
26
|
+
const matches = source.match(/verdict\s*===\s*['"]needs-remediation['"]/g);
|
|
27
|
+
assert.ok(matches, 'verdict === "needs-remediation" check must exist in state.ts');
|
|
28
|
+
assert.ok(matches.length >= 2,
|
|
29
|
+
`Expected at least 2 needs-remediation guards (deriveStateFromDb + _deriveStateImpl), found ${matches.length}`);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('needsRevalidation variable is derived from verdict', () => {
|
|
33
|
+
assert.match(source, /needsRevalidation.*=.*verdict\s*===\s*['"]needs-remediation['"]/,
|
|
34
|
+
'needsRevalidation should incorporate verdict === "needs-remediation"');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('deriveStateFromDb path uses needs-remediation guard', () => {
|
|
38
|
+
assert.match(source, /!validationTerminal\s*\|\|\s*verdict\s*===\s*['"]needs-remediation['"]/,
|
|
39
|
+
'deriveStateFromDb should check !validationTerminal || verdict === "needs-remediation"');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('extractVerdict is called on validation content', () => {
|
|
43
|
+
const extractCalls = source.match(/extractVerdict\(validationContent\)/g);
|
|
44
|
+
assert.ok(extractCalls, 'extractVerdict should be called on validation content');
|
|
45
|
+
assert.ok(extractCalls.length >= 2,
|
|
46
|
+
`Expected at least 2 extractVerdict calls, found ${extractCalls.length}`);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3578 — note captures marked as executed
|
|
3
|
+
*
|
|
4
|
+
* Note-classified captures were stuck in "resolved but not executed" limbo
|
|
5
|
+
* because executeTriageResolutions only handled inject/replan/defer. The fix
|
|
6
|
+
* adds a filter for classification === "note" and calls markCaptureExecuted
|
|
7
|
+
* for each matching capture.
|
|
8
|
+
*
|
|
9
|
+
* Structural verification test — reads source to confirm the note filter
|
|
10
|
+
* and markCaptureExecuted call exist.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, test } from 'node:test';
|
|
14
|
+
import assert from 'node:assert/strict';
|
|
15
|
+
import { readFileSync } from 'node:fs';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
import { dirname, join } from 'node:path';
|
|
18
|
+
|
|
19
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
20
|
+
const __dirname = dirname(__filename);
|
|
21
|
+
|
|
22
|
+
const source = readFileSync(join(__dirname, '..', 'triage-resolution.ts'), 'utf-8');
|
|
23
|
+
|
|
24
|
+
describe('note captures executed in triage resolution (#3578)', () => {
|
|
25
|
+
test('markCaptureExecuted is imported', () => {
|
|
26
|
+
assert.match(source, /markCaptureExecuted/,
|
|
27
|
+
'markCaptureExecuted should be imported');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('note classification filter exists', () => {
|
|
31
|
+
assert.match(source, /classification\s*===\s*"note"/,
|
|
32
|
+
'filter should check classification === "note"');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('note filter checks resolved status and not-executed', () => {
|
|
36
|
+
assert.match(source, /status\s*===\s*"resolved"\s*&&\s*!c\.executed\s*&&\s*c\.classification\s*===\s*"note"/,
|
|
37
|
+
'filter should check resolved + not-executed + note classification');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('markCaptureExecuted is called for note captures', () => {
|
|
41
|
+
// The source should call markCaptureExecuted for note captures
|
|
42
|
+
const noteSection = source.slice(source.indexOf('classification === "note"'));
|
|
43
|
+
assert.match(noteSection, /markCaptureExecuted\(basePath,\s*cap\.id\)/,
|
|
44
|
+
'markCaptureExecuted should be called for note captures');
|
|
45
|
+
});
|
|
46
|
+
});
|