gsd-pi 2.44.0-dev.62b5d6c → 2.44.0-dev.73f2fd5
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/README.md +30 -12
- package/dist/resources/extensions/gsd/auto/infra-errors.js +3 -0
- package/dist/resources/extensions/gsd/auto/phases.js +36 -36
- package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
- package/dist/resources/extensions/gsd/auto-start.js +10 -0
- package/dist/resources/extensions/gsd/auto-timers.js +57 -3
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +4 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +9 -6
- package/dist/resources/extensions/gsd/auto.js +30 -3
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +156 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -12
- package/dist/resources/extensions/gsd/commands/catalog.js +6 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
- package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
- package/dist/resources/extensions/gsd/db-writer.js +34 -16
- package/dist/resources/extensions/gsd/doctor.js +8 -0
- package/dist/resources/extensions/gsd/git-service.js +8 -3
- package/dist/resources/extensions/gsd/gsd-db.js +12 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
- package/dist/resources/extensions/gsd/preferences.js +9 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +3 -14
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
- package/dist/resources/extensions/gsd/provider-error-pause.js +7 -0
- package/dist/resources/extensions/gsd/state.js +19 -2
- package/dist/resources/extensions/gsd/tools/plan-slice.js +1 -0
- package/dist/resources/extensions/gsd/tools/plan-task.js +1 -0
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +6 -0
- package/dist/resources/extensions/mcp-client/index.js +14 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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/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 +17 -17
- 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/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +15 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.js +41 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +20 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +6 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/main.js +17 -0
- package/packages/pi-coding-agent/dist/main.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +32 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +15 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +40 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +1 -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 +4 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +5 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +13 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +17 -8
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -3
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
- package/packages/pi-coding-agent/src/core/auth-storage.ts +15 -1
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
- package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
- package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +21 -1
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
- package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
- package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
- package/packages/pi-coding-agent/src/main.ts +19 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +38 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +48 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +3 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +18 -3
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +16 -7
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +8 -1
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
- package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
- package/src/resources/extensions/gsd/auto/phases.ts +45 -48
- package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
- package/src/resources/extensions/gsd/auto-start.ts +14 -0
- package/src/resources/extensions/gsd/auto-timers.ts +64 -3
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +5 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +9 -6
- package/src/resources/extensions/gsd/auto.ts +37 -3
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +148 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +48 -11
- package/src/resources/extensions/gsd/commands/catalog.ts +6 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
- package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
- package/src/resources/extensions/gsd/db-writer.ts +39 -17
- package/src/resources/extensions/gsd/doctor.ts +7 -1
- package/src/resources/extensions/gsd/git-service.ts +6 -2
- package/src/resources/extensions/gsd/gsd-db.ts +16 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
- package/src/resources/extensions/gsd/preferences.ts +11 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
- package/src/resources/extensions/gsd/prompts/replan-slice.md +3 -14
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
- package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
- package/src/resources/extensions/gsd/state.ts +19 -1
- package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
- package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
- package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
- package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
- package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
- package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
- package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
- package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
- package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +465 -416
- package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +210 -181
- package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
- package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
- package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
- package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
- package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
- package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
- package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
- package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
- package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
- package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
- package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
- package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
- package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
- package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
- package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
- package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
- package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +20 -2
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
- package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
- package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
- package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
- package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
- package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
- package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
- package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
- package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
- package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
- package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
- package/src/resources/extensions/gsd/tests/preferences.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +11 -7
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
- package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
- package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
- package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
- package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
- package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
- package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
- package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
- package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
- package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +10 -11
- package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
- package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
- package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
- package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
- package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
- package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
- package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
- package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -0
- package/src/resources/extensions/gsd/tools/replan-slice.ts +3 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +7 -0
- package/src/resources/extensions/mcp-client/index.ts +20 -0
- /package/dist/web/standalone/.next/static/{fOnWQBjWXMKUs4bqTg530 → kxxAA66bah_yhPYqLBHE2}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{fOnWQBjWXMKUs4bqTg530 → kxxAA66bah_yhPYqLBHE2}/_ssgManifest.js +0 -0
|
@@ -39,61 +39,55 @@ function activeData(overrides: Partial<HealthWidgetData> = {}): HealthWidgetData
|
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
test("detectHealthWidgetProjectState: no .gsd returns none", () => {
|
|
42
|
+
test("detectHealthWidgetProjectState: no .gsd returns none", (t) => {
|
|
43
43
|
const dir = makeTempDir("none");
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
cleanup(dir);
|
|
48
|
-
}
|
|
44
|
+
t.after(() => { cleanup(dir); });
|
|
45
|
+
|
|
46
|
+
assert.equal(detectHealthWidgetProjectState(dir), "none");
|
|
49
47
|
});
|
|
50
48
|
|
|
51
|
-
test("detectHealthWidgetProjectState: bootstrapped .gsd without milestones returns initialized", () => {
|
|
49
|
+
test("detectHealthWidgetProjectState: bootstrapped .gsd without milestones returns initialized", (t) => {
|
|
52
50
|
const dir = makeTempDir("initialized");
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
cleanup(dir);
|
|
58
|
-
}
|
|
51
|
+
t.after(() => { cleanup(dir); });
|
|
52
|
+
|
|
53
|
+
mkdirSync(join(dir, ".gsd"), { recursive: true });
|
|
54
|
+
assert.equal(detectHealthWidgetProjectState(dir), "initialized");
|
|
59
55
|
});
|
|
60
56
|
|
|
61
|
-
test("detectHealthWidgetProjectState: milestone without metrics returns active", () => {
|
|
57
|
+
test("detectHealthWidgetProjectState: milestone without metrics returns active", (t) => {
|
|
62
58
|
const dir = makeTempDir("active");
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
cleanup(dir);
|
|
68
|
-
}
|
|
59
|
+
t.after(() => { cleanup(dir); });
|
|
60
|
+
|
|
61
|
+
mkdirSync(join(dir, ".gsd", "milestones", "M001"), { recursive: true });
|
|
62
|
+
assert.equal(detectHealthWidgetProjectState(dir), "active");
|
|
69
63
|
});
|
|
70
64
|
|
|
71
|
-
test("buildHealthLines: none state shows onboarding copy", () => {
|
|
65
|
+
test("buildHealthLines: none state shows onboarding copy", (t) => {
|
|
72
66
|
assert.deepEqual(buildHealthLines(activeData({ projectState: "none" })), [
|
|
73
67
|
" GSD No project loaded — run /gsd to start",
|
|
74
68
|
]);
|
|
75
69
|
});
|
|
76
70
|
|
|
77
|
-
test("buildHealthLines: initialized state shows continue setup copy", () => {
|
|
71
|
+
test("buildHealthLines: initialized state shows continue setup copy", (t) => {
|
|
78
72
|
assert.deepEqual(buildHealthLines(activeData({ projectState: "initialized" })), [
|
|
79
73
|
" GSD Project initialized — run /gsd to continue setup",
|
|
80
74
|
]);
|
|
81
75
|
});
|
|
82
76
|
|
|
83
|
-
test("buildHealthLines: active state with ledger-driven spend shows spent summary", () => {
|
|
77
|
+
test("buildHealthLines: active state with ledger-driven spend shows spent summary", (t) => {
|
|
84
78
|
const lines = buildHealthLines(activeData({ budgetSpent: 0.42 }));
|
|
85
79
|
assert.equal(lines.length, 1);
|
|
86
80
|
assert.match(lines[0]!, /● System OK/);
|
|
87
81
|
assert.match(lines[0]!, /Spent: 42\.0¢/);
|
|
88
82
|
});
|
|
89
83
|
|
|
90
|
-
test("buildHealthLines: active state with budget ceiling shows percent summary", () => {
|
|
84
|
+
test("buildHealthLines: active state with budget ceiling shows percent summary", (t) => {
|
|
91
85
|
const lines = buildHealthLines(activeData({ budgetSpent: 2.5, budgetCeiling: 10 }));
|
|
92
86
|
assert.equal(lines.length, 1);
|
|
93
87
|
assert.match(lines[0]!, /Budget: \$2\.50\/\$10\.00 \(25%\)/);
|
|
94
88
|
});
|
|
95
89
|
|
|
96
|
-
test("buildHealthLines: active state with issues reports issue summary", () => {
|
|
90
|
+
test("buildHealthLines: active state with issues reports issue summary", (t) => {
|
|
97
91
|
const lines = buildHealthLines(activeData({
|
|
98
92
|
providerIssue: "✗ OpenAI key missing",
|
|
99
93
|
environmentErrorCount: 1,
|
|
@@ -104,17 +98,15 @@ test("buildHealthLines: active state with issues reports issue summary", () => {
|
|
|
104
98
|
assert.match(lines[0]!, /Env: 1 error/);
|
|
105
99
|
});
|
|
106
100
|
|
|
107
|
-
test("detectHealthWidgetProjectState: metrics file alone does not imply project", () => {
|
|
101
|
+
test("detectHealthWidgetProjectState: metrics file alone does not imply project", (t) => {
|
|
108
102
|
const dir = makeTempDir("metrics-only");
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
cleanup(dir);
|
|
119
|
-
}
|
|
103
|
+
t.after(() => { cleanup(dir); });
|
|
104
|
+
|
|
105
|
+
mkdirSync(join(dir, ".gsd"), { recursive: true });
|
|
106
|
+
writeFileSync(
|
|
107
|
+
join(dir, ".gsd", "metrics.json"),
|
|
108
|
+
JSON.stringify({ version: 1, projectStartedAt: Date.now(), units: [] }),
|
|
109
|
+
"utf-8",
|
|
110
|
+
);
|
|
111
|
+
assert.equal(detectHealthWidgetProjectState(dir), "initialized");
|
|
120
112
|
});
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
verifyExpectedArtifact,
|
|
9
9
|
buildLoopRemediationSteps,
|
|
10
10
|
} from "../auto.ts";
|
|
11
|
-
import {
|
|
11
|
+
import { describe, test, beforeEach, afterEach } from 'node:test';
|
|
12
|
+
import assert from 'node:assert/strict';
|
|
12
13
|
|
|
13
|
-
const { assertEq, assertTrue, report } = createTestContext();
|
|
14
14
|
function createFixtureBase(): string {
|
|
15
15
|
const base = mkdtempSync(join(tmpdir(), "gsd-idle-recovery-test-"));
|
|
16
16
|
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks"), { recursive: true });
|
|
@@ -23,99 +23,91 @@ function cleanup(base: string): void {
|
|
|
23
23
|
|
|
24
24
|
// ═══ resolveExpectedArtifactPath ═════════════════════════════════════════════
|
|
25
25
|
|
|
26
|
-
{
|
|
27
|
-
console.log("\n=== resolveExpectedArtifactPath: research-milestone ===");
|
|
26
|
+
test('resolveExpectedArtifactPath: research-milestone', () => {
|
|
28
27
|
const base = createFixtureBase();
|
|
29
28
|
try {
|
|
30
29
|
const result = resolveExpectedArtifactPath("research-milestone", "M001", base);
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
assert.ok(result !== null, "should resolve a path");
|
|
31
|
+
assert.ok(result!.endsWith("M001-RESEARCH.md"), `path should end with M001-RESEARCH.md, got ${result}`);
|
|
33
32
|
} finally {
|
|
34
33
|
cleanup(base);
|
|
35
34
|
}
|
|
36
|
-
}
|
|
35
|
+
});
|
|
37
36
|
|
|
38
|
-
{
|
|
39
|
-
console.log("\n=== resolveExpectedArtifactPath: plan-milestone ===");
|
|
37
|
+
test('resolveExpectedArtifactPath: plan-milestone', () => {
|
|
40
38
|
const base = createFixtureBase();
|
|
41
39
|
try {
|
|
42
40
|
const result = resolveExpectedArtifactPath("plan-milestone", "M001", base);
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
assert.ok(result !== null, "should resolve a path");
|
|
42
|
+
assert.ok(result!.endsWith("M001-ROADMAP.md"), `path should end with M001-ROADMAP.md, got ${result}`);
|
|
45
43
|
} finally {
|
|
46
44
|
cleanup(base);
|
|
47
45
|
}
|
|
48
|
-
}
|
|
46
|
+
});
|
|
49
47
|
|
|
50
|
-
{
|
|
51
|
-
console.log("\n=== resolveExpectedArtifactPath: research-slice ===");
|
|
48
|
+
test('resolveExpectedArtifactPath: research-slice', () => {
|
|
52
49
|
const base = createFixtureBase();
|
|
53
50
|
try {
|
|
54
51
|
const result = resolveExpectedArtifactPath("research-slice", "M001/S01", base);
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
assert.ok(result !== null, "should resolve a path");
|
|
53
|
+
assert.ok(result!.endsWith("S01-RESEARCH.md"), `path should end with S01-RESEARCH.md, got ${result}`);
|
|
57
54
|
} finally {
|
|
58
55
|
cleanup(base);
|
|
59
56
|
}
|
|
60
|
-
}
|
|
57
|
+
});
|
|
61
58
|
|
|
62
|
-
{
|
|
63
|
-
console.log("\n=== resolveExpectedArtifactPath: plan-slice ===");
|
|
59
|
+
test('resolveExpectedArtifactPath: plan-slice', () => {
|
|
64
60
|
const base = createFixtureBase();
|
|
65
61
|
try {
|
|
66
62
|
const result = resolveExpectedArtifactPath("plan-slice", "M001/S01", base);
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
assert.ok(result !== null, "should resolve a path");
|
|
64
|
+
assert.ok(result!.endsWith("S01-PLAN.md"), `path should end with S01-PLAN.md, got ${result}`);
|
|
69
65
|
} finally {
|
|
70
66
|
cleanup(base);
|
|
71
67
|
}
|
|
72
|
-
}
|
|
68
|
+
});
|
|
73
69
|
|
|
74
|
-
{
|
|
75
|
-
console.log("\n=== resolveExpectedArtifactPath: complete-milestone ===");
|
|
70
|
+
test('resolveExpectedArtifactPath: complete-milestone', () => {
|
|
76
71
|
const base = createFixtureBase();
|
|
77
72
|
try {
|
|
78
73
|
const result = resolveExpectedArtifactPath("complete-milestone", "M001", base);
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
assert.ok(result !== null, "should resolve a path");
|
|
75
|
+
assert.ok(result!.endsWith("M001-SUMMARY.md"), `path should end with M001-SUMMARY.md, got ${result}`);
|
|
81
76
|
} finally {
|
|
82
77
|
cleanup(base);
|
|
83
78
|
}
|
|
84
|
-
}
|
|
79
|
+
});
|
|
85
80
|
|
|
86
|
-
{
|
|
87
|
-
console.log("\n=== resolveExpectedArtifactPath: unknown unit type → null ===");
|
|
81
|
+
test('resolveExpectedArtifactPath: unknown unit type → null', () => {
|
|
88
82
|
const base = createFixtureBase();
|
|
89
83
|
try {
|
|
90
84
|
const result = resolveExpectedArtifactPath("unknown-type", "M001/S01", base);
|
|
91
|
-
|
|
85
|
+
assert.deepStrictEqual(result, null, "unknown type returns null");
|
|
92
86
|
} finally {
|
|
93
87
|
cleanup(base);
|
|
94
88
|
}
|
|
95
|
-
}
|
|
89
|
+
});
|
|
96
90
|
|
|
97
91
|
// ═══ writeBlockerPlaceholder ═════════════════════════════════════════════════
|
|
98
92
|
|
|
99
|
-
{
|
|
100
|
-
console.log("\n=== writeBlockerPlaceholder: writes file for research-slice ===");
|
|
93
|
+
test('writeBlockerPlaceholder: writes file for research-slice', () => {
|
|
101
94
|
const base = createFixtureBase();
|
|
102
95
|
try {
|
|
103
96
|
const result = writeBlockerPlaceholder("research-slice", "M001/S01", base, "idle recovery exhausted 2 attempts");
|
|
104
|
-
|
|
97
|
+
assert.ok(result !== null, "should return relative path");
|
|
105
98
|
const absPath = resolveExpectedArtifactPath("research-slice", "M001/S01", base)!;
|
|
106
|
-
|
|
99
|
+
assert.ok(existsSync(absPath), "file should exist on disk");
|
|
107
100
|
const content = readFileSync(absPath, "utf-8");
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
101
|
+
assert.ok(content.includes("BLOCKER"), "should contain BLOCKER heading");
|
|
102
|
+
assert.ok(content.includes("idle recovery exhausted 2 attempts"), "should contain the reason");
|
|
103
|
+
assert.ok(content.includes("research-slice"), "should mention the unit type");
|
|
104
|
+
assert.ok(content.includes("M001/S01"), "should mention the unit ID");
|
|
112
105
|
} finally {
|
|
113
106
|
cleanup(base);
|
|
114
107
|
}
|
|
115
|
-
}
|
|
108
|
+
});
|
|
116
109
|
|
|
117
|
-
{
|
|
118
|
-
console.log("\n=== writeBlockerPlaceholder: creates directory if missing ===");
|
|
110
|
+
test('writeBlockerPlaceholder: creates directory if missing', () => {
|
|
119
111
|
const base = mkdtempSync(join(tmpdir(), "gsd-idle-recovery-test-"));
|
|
120
112
|
try {
|
|
121
113
|
// Only create milestone dir, not slice dir
|
|
@@ -123,38 +115,36 @@ function cleanup(base: string): void {
|
|
|
123
115
|
// resolveSlicePath needs the slice dir to exist to resolve, so this should return null
|
|
124
116
|
const result = writeBlockerPlaceholder("research-slice", "M001/S01", base, "test reason");
|
|
125
117
|
// Since the slice dir doesn't exist, resolveExpectedArtifactPath returns null
|
|
126
|
-
|
|
118
|
+
assert.deepStrictEqual(result, null, "returns null when directory structure doesn't exist");
|
|
127
119
|
} finally {
|
|
128
120
|
cleanup(base);
|
|
129
121
|
}
|
|
130
|
-
}
|
|
122
|
+
});
|
|
131
123
|
|
|
132
|
-
{
|
|
133
|
-
console.log("\n=== writeBlockerPlaceholder: writes file for research-milestone ===");
|
|
124
|
+
test('writeBlockerPlaceholder: writes file for research-milestone', () => {
|
|
134
125
|
const base = createFixtureBase();
|
|
135
126
|
try {
|
|
136
127
|
const result = writeBlockerPlaceholder("research-milestone", "M001", base, "hard timeout");
|
|
137
|
-
|
|
128
|
+
assert.ok(result !== null, "should return relative path");
|
|
138
129
|
const absPath = resolveExpectedArtifactPath("research-milestone", "M001", base)!;
|
|
139
|
-
|
|
130
|
+
assert.ok(existsSync(absPath), "file should exist on disk");
|
|
140
131
|
const content = readFileSync(absPath, "utf-8");
|
|
141
|
-
|
|
142
|
-
|
|
132
|
+
assert.ok(content.includes("BLOCKER"), "should contain BLOCKER heading");
|
|
133
|
+
assert.ok(content.includes("hard timeout"), "should contain the reason");
|
|
143
134
|
} finally {
|
|
144
135
|
cleanup(base);
|
|
145
136
|
}
|
|
146
|
-
}
|
|
137
|
+
});
|
|
147
138
|
|
|
148
|
-
{
|
|
149
|
-
console.log("\n=== writeBlockerPlaceholder: unknown type → null ===");
|
|
139
|
+
test('writeBlockerPlaceholder: unknown type → null', () => {
|
|
150
140
|
const base = createFixtureBase();
|
|
151
141
|
try {
|
|
152
142
|
const result = writeBlockerPlaceholder("unknown-type", "M001/S01", base, "test");
|
|
153
|
-
|
|
143
|
+
assert.deepStrictEqual(result, null, "unknown type returns null");
|
|
154
144
|
} finally {
|
|
155
145
|
cleanup(base);
|
|
156
146
|
}
|
|
157
|
-
}
|
|
147
|
+
});
|
|
158
148
|
|
|
159
149
|
// ═══ verifyExpectedArtifact: complete-slice roadmap check ════════════════════
|
|
160
150
|
// Regression for #indefinite-hang: complete-slice must verify roadmap [x] or
|
|
@@ -177,8 +167,7 @@ const ROADMAP_COMPLETE = `# M001: Test Milestone
|
|
|
177
167
|
> After this: something works
|
|
178
168
|
`;
|
|
179
169
|
|
|
180
|
-
{
|
|
181
|
-
console.log("\n=== verifyExpectedArtifact: complete-slice — all artifacts present + roadmap marked [x] returns true ===");
|
|
170
|
+
test('verifyExpectedArtifact: complete-slice — all artifacts present + roadmap marked [x] returns true', () => {
|
|
182
171
|
const base = createFixtureBase();
|
|
183
172
|
try {
|
|
184
173
|
const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
|
|
@@ -186,14 +175,13 @@ const ROADMAP_COMPLETE = `# M001: Test Milestone
|
|
|
186
175
|
writeFileSync(join(sliceDir, "S01-UAT.md"), "# UAT\n", "utf-8");
|
|
187
176
|
writeFileSync(join(base, ".gsd", "milestones", "M001", "M001-ROADMAP.md"), ROADMAP_COMPLETE, "utf-8");
|
|
188
177
|
const result = verifyExpectedArtifact("complete-slice", "M001/S01", base);
|
|
189
|
-
|
|
178
|
+
assert.ok(result === true, "SUMMARY + UAT + roadmap [x] should verify as true");
|
|
190
179
|
} finally {
|
|
191
180
|
cleanup(base);
|
|
192
181
|
}
|
|
193
|
-
}
|
|
182
|
+
});
|
|
194
183
|
|
|
195
|
-
{
|
|
196
|
-
console.log("\n=== verifyExpectedArtifact: complete-slice — SUMMARY + UAT present but roadmap NOT marked [x] returns false ===");
|
|
184
|
+
test('verifyExpectedArtifact: complete-slice — SUMMARY + UAT present but roadmap NOT marked [x] returns false', () => {
|
|
197
185
|
const base = createFixtureBase();
|
|
198
186
|
try {
|
|
199
187
|
const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
|
|
@@ -201,14 +189,13 @@ const ROADMAP_COMPLETE = `# M001: Test Milestone
|
|
|
201
189
|
writeFileSync(join(sliceDir, "S01-UAT.md"), "# UAT\n", "utf-8");
|
|
202
190
|
writeFileSync(join(base, ".gsd", "milestones", "M001", "M001-ROADMAP.md"), ROADMAP_INCOMPLETE, "utf-8");
|
|
203
191
|
const result = verifyExpectedArtifact("complete-slice", "M001/S01", base);
|
|
204
|
-
|
|
192
|
+
assert.ok(result === false, "roadmap not marked [x] should return false (crash recovery scenario)");
|
|
205
193
|
} finally {
|
|
206
194
|
cleanup(base);
|
|
207
195
|
}
|
|
208
|
-
}
|
|
196
|
+
});
|
|
209
197
|
|
|
210
|
-
{
|
|
211
|
-
console.log("\n=== verifyExpectedArtifact: complete-slice — SUMMARY present but UAT missing returns false ===");
|
|
198
|
+
test('verifyExpectedArtifact: complete-slice — SUMMARY present but UAT missing returns false', () => {
|
|
212
199
|
const base = createFixtureBase();
|
|
213
200
|
try {
|
|
214
201
|
const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
|
|
@@ -216,14 +203,13 @@ const ROADMAP_COMPLETE = `# M001: Test Milestone
|
|
|
216
203
|
// no UAT file
|
|
217
204
|
writeFileSync(join(base, ".gsd", "milestones", "M001", "M001-ROADMAP.md"), ROADMAP_COMPLETE, "utf-8");
|
|
218
205
|
const result = verifyExpectedArtifact("complete-slice", "M001/S01", base);
|
|
219
|
-
|
|
206
|
+
assert.ok(result === false, "missing UAT should return false");
|
|
220
207
|
} finally {
|
|
221
208
|
cleanup(base);
|
|
222
209
|
}
|
|
223
|
-
}
|
|
210
|
+
});
|
|
224
211
|
|
|
225
|
-
{
|
|
226
|
-
console.log("\n=== verifyExpectedArtifact: complete-slice — no roadmap file present is lenient (returns true) ===");
|
|
212
|
+
test('verifyExpectedArtifact: complete-slice — no roadmap file present is lenient (returns true)', () => {
|
|
227
213
|
const base = createFixtureBase();
|
|
228
214
|
try {
|
|
229
215
|
const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
|
|
@@ -231,87 +217,80 @@ const ROADMAP_COMPLETE = `# M001: Test Milestone
|
|
|
231
217
|
writeFileSync(join(sliceDir, "S01-UAT.md"), "# UAT\n", "utf-8");
|
|
232
218
|
// no roadmap file
|
|
233
219
|
const result = verifyExpectedArtifact("complete-slice", "M001/S01", base);
|
|
234
|
-
|
|
220
|
+
assert.ok(result === true, "missing roadmap file should be lenient and return true");
|
|
235
221
|
} finally {
|
|
236
222
|
cleanup(base);
|
|
237
223
|
}
|
|
238
|
-
}
|
|
224
|
+
});
|
|
239
225
|
|
|
240
226
|
// ═══ buildLoopRemediationSteps ═══════════════════════════════════════════════
|
|
241
227
|
|
|
242
|
-
{
|
|
243
|
-
console.log("\n=== buildLoopRemediationSteps: execute-task returns concrete steps ===");
|
|
228
|
+
test('buildLoopRemediationSteps: execute-task returns concrete steps', () => {
|
|
244
229
|
const base = mkdtempSync(join(tmpdir(), "gsd-loop-remediation-test-"));
|
|
245
230
|
try {
|
|
246
231
|
mkdirSync(join(base, ".gsd", "milestones", "M002", "slices", "S03", "tasks"), { recursive: true });
|
|
247
232
|
const result = buildLoopRemediationSteps("execute-task", "M002/S03/T01", base);
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
233
|
+
assert.ok(result !== null, "should return remediation steps");
|
|
234
|
+
assert.ok(result!.includes("gsd undo-task"), "steps include undo-task command");
|
|
235
|
+
assert.ok(result!.includes("T01"), "steps mention the task ID");
|
|
236
|
+
assert.ok(result!.includes("gsd undo-task"), "steps include gsd undo-task command");
|
|
252
237
|
} finally {
|
|
253
238
|
rmSync(base, { recursive: true, force: true });
|
|
254
239
|
}
|
|
255
|
-
}
|
|
240
|
+
});
|
|
256
241
|
|
|
257
|
-
{
|
|
258
|
-
console.log("\n=== buildLoopRemediationSteps: plan-slice returns concrete steps ===");
|
|
242
|
+
test('buildLoopRemediationSteps: plan-slice returns concrete steps', () => {
|
|
259
243
|
const base = mkdtempSync(join(tmpdir(), "gsd-loop-remediation-test-"));
|
|
260
244
|
try {
|
|
261
245
|
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01"), { recursive: true });
|
|
262
246
|
const result = buildLoopRemediationSteps("plan-slice", "M001/S01", base);
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
247
|
+
assert.ok(result !== null, "should return remediation steps for plan-slice");
|
|
248
|
+
assert.ok(result!.includes("S01-PLAN.md"), "steps mention the slice plan file");
|
|
249
|
+
assert.ok(result!.includes("gsd recover"), "steps include gsd recover command");
|
|
266
250
|
} finally {
|
|
267
251
|
rmSync(base, { recursive: true, force: true });
|
|
268
252
|
}
|
|
269
|
-
}
|
|
253
|
+
});
|
|
270
254
|
|
|
271
|
-
{
|
|
272
|
-
console.log("\n=== buildLoopRemediationSteps: research-slice returns concrete steps ===");
|
|
255
|
+
test('buildLoopRemediationSteps: research-slice returns concrete steps', () => {
|
|
273
256
|
const base = mkdtempSync(join(tmpdir(), "gsd-loop-remediation-test-"));
|
|
274
257
|
try {
|
|
275
258
|
mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01"), { recursive: true });
|
|
276
259
|
const result = buildLoopRemediationSteps("research-slice", "M001/S01", base);
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
260
|
+
assert.ok(result !== null, "should return remediation steps for research-slice");
|
|
261
|
+
assert.ok(result!.includes("S01-RESEARCH.md"), "steps mention the slice research file");
|
|
262
|
+
assert.ok(result!.includes("gsd recover"), "steps include gsd recover command");
|
|
280
263
|
} finally {
|
|
281
264
|
rmSync(base, { recursive: true, force: true });
|
|
282
265
|
}
|
|
283
|
-
}
|
|
266
|
+
});
|
|
284
267
|
|
|
285
|
-
{
|
|
286
|
-
console.log("\n=== buildLoopRemediationSteps: unknown type returns null ===");
|
|
268
|
+
test('buildLoopRemediationSteps: unknown type returns null', () => {
|
|
287
269
|
const base = mkdtempSync(join(tmpdir(), "gsd-loop-remediation-test-"));
|
|
288
270
|
try {
|
|
289
271
|
const result = buildLoopRemediationSteps("unknown-type", "M001/S01", base);
|
|
290
|
-
|
|
272
|
+
assert.deepStrictEqual(result, null, "unknown type returns null");
|
|
291
273
|
} finally {
|
|
292
274
|
rmSync(base, { recursive: true, force: true });
|
|
293
275
|
}
|
|
294
|
-
}
|
|
276
|
+
});
|
|
295
277
|
|
|
296
278
|
// ═══ verifyExpectedArtifact: hook unit types ═════════════════════════════════
|
|
297
279
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
{
|
|
280
|
+
test('verifyExpectedArtifact: hook types always return true', () => {
|
|
301
281
|
const base = createFixtureBase();
|
|
302
282
|
try {
|
|
303
283
|
// Hook units don't have standard artifacts — they should always pass
|
|
304
284
|
const result1 = verifyExpectedArtifact("hook/code-review", "M001/S01/T01", base);
|
|
305
|
-
|
|
285
|
+
assert.ok(result1, "hook/code-review should always return true");
|
|
306
286
|
|
|
307
287
|
const result2 = verifyExpectedArtifact("hook/simplify", "M001/S01/T02", base);
|
|
308
|
-
|
|
288
|
+
assert.ok(result2, "hook/simplify should always return true");
|
|
309
289
|
|
|
310
290
|
const result3 = verifyExpectedArtifact("hook/custom-hook", "M001/S01", base);
|
|
311
|
-
|
|
291
|
+
assert.ok(result3, "hook/custom-hook at slice level should return true");
|
|
312
292
|
} finally {
|
|
313
293
|
rmSync(base, { recursive: true, force: true });
|
|
314
294
|
}
|
|
315
|
-
}
|
|
295
|
+
});
|
|
316
296
|
|
|
317
|
-
report();
|
|
@@ -7,10 +7,13 @@ import { isInfrastructureError, INFRA_ERROR_CODES } from "../auto/infra-errors.j
|
|
|
7
7
|
// ── INFRA_ERROR_CODES constant ───────────────────────────────────────────────
|
|
8
8
|
|
|
9
9
|
test("INFRA_ERROR_CODES contains the expected codes", () => {
|
|
10
|
-
for (const code of [
|
|
10
|
+
for (const code of [
|
|
11
|
+
"ENOSPC", "ENOMEM", "EROFS", "EDQUOT", "EMFILE", "ENFILE",
|
|
12
|
+
"ECONNREFUSED", "ENOTFOUND", "ENETUNREACH",
|
|
13
|
+
]) {
|
|
11
14
|
assert.ok(INFRA_ERROR_CODES.has(code), `missing ${code}`);
|
|
12
15
|
}
|
|
13
|
-
assert.equal(INFRA_ERROR_CODES.size,
|
|
16
|
+
assert.equal(INFRA_ERROR_CODES.size, 9, "unexpected extra codes");
|
|
14
17
|
});
|
|
15
18
|
|
|
16
19
|
// ── isInfrastructureError: code property detection ───────────────────────────
|
|
@@ -45,6 +48,21 @@ test("detects ENFILE via code property", () => {
|
|
|
45
48
|
assert.equal(isInfrastructureError(err), "ENFILE");
|
|
46
49
|
});
|
|
47
50
|
|
|
51
|
+
test("detects ECONNREFUSED via code property", () => {
|
|
52
|
+
const err = Object.assign(new Error("connect ECONNREFUSED 127.0.0.1:3000"), { code: "ECONNREFUSED" });
|
|
53
|
+
assert.equal(isInfrastructureError(err), "ECONNREFUSED");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("detects ENOTFOUND via code property", () => {
|
|
57
|
+
const err = Object.assign(new Error("getaddrinfo ENOTFOUND api.example.com"), { code: "ENOTFOUND" });
|
|
58
|
+
assert.equal(isInfrastructureError(err), "ENOTFOUND");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("detects ENETUNREACH via code property", () => {
|
|
62
|
+
const err = Object.assign(new Error("connect ENETUNREACH 2607:f8b0:4004::"), { code: "ENETUNREACH" });
|
|
63
|
+
assert.equal(isInfrastructureError(err), "ENETUNREACH");
|
|
64
|
+
});
|
|
65
|
+
|
|
48
66
|
// ── isInfrastructureError: message fallback ──────────────────────────────────
|
|
49
67
|
|
|
50
68
|
test("falls back to message scanning when no code property", () => {
|
|
@@ -36,19 +36,17 @@ function cleanup(dir: string): void {
|
|
|
36
36
|
|
|
37
37
|
// ─── Detection Integration Tests ────────────────────────────────────────────────
|
|
38
38
|
|
|
39
|
-
test("init-wizard: clean folder detected as state=none", () => {
|
|
39
|
+
test("init-wizard: clean folder detected as state=none", (t) => {
|
|
40
40
|
const dir = makeTempDir("clean");
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
cleanup(dir);
|
|
48
|
-
}
|
|
41
|
+
t.after(() => { cleanup(dir); });
|
|
42
|
+
|
|
43
|
+
const detection = detectProjectState(dir);
|
|
44
|
+
assert.equal(detection.state, "none");
|
|
45
|
+
assert.equal(detection.v1, undefined);
|
|
46
|
+
assert.equal(detection.v2, undefined);
|
|
49
47
|
});
|
|
50
48
|
|
|
51
|
-
test("init-wizard: v1 .planning/ triggers v1-planning state", () => {
|
|
49
|
+
test("init-wizard: v1 .planning/ triggers v1-planning state", (t) => {
|
|
52
50
|
const dir = makeTempDir("v1");
|
|
53
51
|
try {
|
|
54
52
|
mkdirSync(join(dir, ".planning", "phases", "01"), { recursive: true });
|
|
@@ -65,7 +63,7 @@ test("init-wizard: v1 .planning/ triggers v1-planning state", () => {
|
|
|
65
63
|
}
|
|
66
64
|
});
|
|
67
65
|
|
|
68
|
-
test("init-wizard: existing .gsd/ with milestones skips init", () => {
|
|
66
|
+
test("init-wizard: existing .gsd/ with milestones skips init", (t) => {
|
|
69
67
|
const dir = makeTempDir("existing");
|
|
70
68
|
try {
|
|
71
69
|
mkdirSync(join(dir, ".gsd", "milestones", "M001"), { recursive: true });
|
|
@@ -80,7 +78,7 @@ test("init-wizard: existing .gsd/ with milestones skips init", () => {
|
|
|
80
78
|
}
|
|
81
79
|
});
|
|
82
80
|
|
|
83
|
-
test("init-wizard: empty .gsd/ (no milestones) returns v2-gsd-empty", () => {
|
|
81
|
+
test("init-wizard: empty .gsd/ (no milestones) returns v2-gsd-empty", (t) => {
|
|
84
82
|
const dir = makeTempDir("empty-gsd");
|
|
85
83
|
try {
|
|
86
84
|
mkdirSync(join(dir, ".gsd", "milestones"), { recursive: true });
|
|
@@ -94,7 +92,7 @@ test("init-wizard: empty .gsd/ (no milestones) returns v2-gsd-empty", () => {
|
|
|
94
92
|
}
|
|
95
93
|
});
|
|
96
94
|
|
|
97
|
-
test("init-wizard: project signals populate from Node.js project", () => {
|
|
95
|
+
test("init-wizard: project signals populate from Node.js project", (t) => {
|
|
98
96
|
const dir = makeTempDir("node-project");
|
|
99
97
|
try {
|
|
100
98
|
writeFileSync(
|
|
@@ -121,7 +119,7 @@ test("init-wizard: project signals populate from Node.js project", () => {
|
|
|
121
119
|
}
|
|
122
120
|
});
|
|
123
121
|
|
|
124
|
-
test("init-wizard: v2 .gsd/ preferences detected", () => {
|
|
122
|
+
test("init-wizard: v2 .gsd/ preferences detected", (t) => {
|
|
125
123
|
const dir = makeTempDir("prefs-detect");
|
|
126
124
|
try {
|
|
127
125
|
mkdirSync(join(dir, ".gsd", "milestones"), { recursive: true });
|
|
@@ -135,7 +133,7 @@ test("init-wizard: v2 .gsd/ preferences detected", () => {
|
|
|
135
133
|
}
|
|
136
134
|
});
|
|
137
135
|
|
|
138
|
-
test("init-wizard: v2 uppercase PREFERENCES.md also detected", () => {
|
|
136
|
+
test("init-wizard: v2 uppercase PREFERENCES.md also detected", (t) => {
|
|
139
137
|
const dir = makeTempDir("prefs-upper");
|
|
140
138
|
try {
|
|
141
139
|
mkdirSync(join(dir, ".gsd", "milestones"), { recursive: true });
|
|
@@ -149,7 +147,7 @@ test("init-wizard: v2 uppercase PREFERENCES.md also detected", () => {
|
|
|
149
147
|
}
|
|
150
148
|
});
|
|
151
149
|
|
|
152
|
-
test("init-wizard: CONTEXT.md detected in v2", () => {
|
|
150
|
+
test("init-wizard: CONTEXT.md detected in v2", (t) => {
|
|
153
151
|
const dir = makeTempDir("context");
|
|
154
152
|
try {
|
|
155
153
|
mkdirSync(join(dir, ".gsd", "milestones"), { recursive: true });
|
|
@@ -163,7 +161,7 @@ test("init-wizard: CONTEXT.md detected in v2", () => {
|
|
|
163
161
|
}
|
|
164
162
|
});
|
|
165
163
|
|
|
166
|
-
test("init-wizard: multiple project files detected together", () => {
|
|
164
|
+
test("init-wizard: multiple project files detected together", (t) => {
|
|
167
165
|
const dir = makeTempDir("multi-files");
|
|
168
166
|
try {
|
|
169
167
|
writeFileSync(join(dir, "package.json"), JSON.stringify({ name: "test" }), "utf-8");
|
|
@@ -180,7 +178,7 @@ test("init-wizard: multiple project files detected together", () => {
|
|
|
180
178
|
}
|
|
181
179
|
});
|
|
182
180
|
|
|
183
|
-
test("init-wizard: v1 with both .planning/ and .gsd/ prioritizes v2", () => {
|
|
181
|
+
test("init-wizard: v1 with both .planning/ and .gsd/ prioritizes v2", (t) => {
|
|
184
182
|
const dir = makeTempDir("both-v1-v2");
|
|
185
183
|
try {
|
|
186
184
|
mkdirSync(join(dir, ".planning", "phases"), { recursive: true });
|