gsd-pi 2.44.0-dev.848dd4c → 2.44.0
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 +12 -30
- package/dist/resources/extensions/gsd/auto-start.js +0 -10
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +0 -5
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
- 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/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
- package/dist/web/standalone/.next/server/chunks/229.js +1 -1
- package/dist/web/standalone/.next/server/chunks/471.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-7e9530a7122506c5.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +8 -6
- 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 +26 -24
- 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 +48 -29
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +44 -34
- 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 +34 -30
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +12 -10
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +47 -43
- 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/extensions/runner.test.ts +26 -26
- package/packages/pi-coding-agent/src/core/fs-utils.test.ts +43 -31
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +45 -40
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
- package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
- package/src/resources/extensions/gsd/auto-start.ts +0 -14
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +0 -8
- 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 +16 -14
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +57 -43
- package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +13 -11
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +523 -465
- package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +75 -73
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +56 -34
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +656 -533
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +143 -165
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +52 -29
- package/src/resources/extensions/gsd/tests/captures.test.ts +176 -148
- package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +33 -32
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +143 -141
- 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 +59 -38
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +263 -228
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +302 -250
- package/src/resources/extensions/gsd/tests/context-store.test.ts +367 -354
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +72 -68
- package/src/resources/extensions/gsd/tests/cost-projection.test.ts +106 -92
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +35 -27
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +237 -220
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +420 -390
- package/src/resources/extensions/gsd/tests/definition-loader.test.ts +92 -76
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +83 -68
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +183 -152
- package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +101 -78
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +227 -192
- package/src/resources/extensions/gsd/tests/detection.test.ts +278 -232
- package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +34 -30
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +180 -164
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +49 -43
- package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +32 -28
- package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +29 -27
- package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +38 -34
- package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +75 -54
- package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +32 -21
- package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +97 -72
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +44 -38
- package/src/resources/extensions/gsd/tests/doctor-git.test.ts +145 -104
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +106 -84
- package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +60 -54
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +93 -72
- package/src/resources/extensions/gsd/tests/doctor.test.ts +134 -104
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +131 -123
- package/src/resources/extensions/gsd/tests/exit-command.test.ts +24 -20
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +57 -48
- package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +42 -30
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +206 -198
- package/src/resources/extensions/gsd/tests/git-locale.test.ts +27 -13
- package/src/resources/extensions/gsd/tests/git-service.test.ts +388 -285
- package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +39 -31
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +69 -63
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +264 -255
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +119 -108
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +103 -81
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +262 -229
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +37 -29
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +102 -81
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +18 -16
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +46 -41
- package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +53 -42
- package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +91 -75
- package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +194 -150
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +125 -101
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +54 -45
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +93 -80
- package/src/resources/extensions/gsd/tests/migrate-command.test.ts +66 -57
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +93 -83
- package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +170 -161
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +141 -125
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +131 -107
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +96 -87
- package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +164 -125
- package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +94 -81
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +36 -35
- package/src/resources/extensions/gsd/tests/overrides.test.ts +106 -99
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +47 -40
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +28 -25
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +83 -66
- package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +77 -54
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +115 -68
- package/src/resources/extensions/gsd/tests/parsers.test.ts +611 -546
- package/src/resources/extensions/gsd/tests/paths.test.ts +87 -72
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +117 -77
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +119 -93
- package/src/resources/extensions/gsd/tests/queue-order.test.ts +82 -70
- package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +55 -42
- package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +73 -45
- package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +38 -28
- package/src/resources/extensions/gsd/tests/replan-slice.test.ts +80 -73
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +74 -71
- package/src/resources/extensions/gsd/tests/requirements.test.ts +75 -70
- package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +66 -44
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +181 -114
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +65 -63
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +128 -66
- package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +25 -18
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +44 -37
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +26 -19
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +8 -6
- package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +28 -22
- package/src/resources/extensions/gsd/tests/token-savings.test.ts +56 -54
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +25 -23
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +11 -9
- package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +82 -66
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +47 -46
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +22 -20
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +86 -84
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +43 -41
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +96 -94
- package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +13 -11
- package/src/resources/extensions/gsd/tests/worker-registry.test.ts +29 -27
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +52 -50
- package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +13 -10
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +18 -14
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +39 -38
- package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +21 -17
- package/src/resources/extensions/gsd/tests/worktree-health.test.ts +30 -25
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +37 -30
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +22 -15
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +66 -59
- package/src/resources/extensions/gsd/tests/worktree.test.ts +50 -44
- package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +0 -100
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +0 -63
- /package/dist/web/standalone/.next/static/{-zps1Q9mQmioAKLcQiCr8 → mgkxN0mGP6gSUmGPEzbk_}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{-zps1Q9mQmioAKLcQiCr8 → mgkxN0mGP6gSUmGPEzbk_}/_ssgManifest.js +0 -0
|
@@ -1,114 +1,125 @@
|
|
|
1
|
-
import { describe, test } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
1
|
// gsd-inspect — Tests for /gsd inspect output formatting
|
|
4
2
|
//
|
|
5
3
|
// Tests the pure formatInspectOutput function with known data.
|
|
6
4
|
|
|
5
|
+
import { createTestContext } from './test-helpers.ts';
|
|
7
6
|
import { formatInspectOutput, type InspectData } from '../commands-inspect.ts';
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
8
|
+
const { assertEq, assertTrue, assertMatch, report } = createTestContext();
|
|
9
|
+
|
|
10
|
+
// ── formats output with schema version, counts, and recent entries ──
|
|
11
|
+
console.log("# === gsd-inspect: full output formatting ===");
|
|
12
|
+
{
|
|
13
|
+
const data: InspectData = {
|
|
14
|
+
schemaVersion: 2,
|
|
15
|
+
counts: { decisions: 12, requirements: 8, artifacts: 3 },
|
|
16
|
+
recentDecisions: [
|
|
17
|
+
{ id: "D012", decision: "Use SQLite for persistence", choice: "node:sqlite with fallback" },
|
|
18
|
+
{ id: "D011", decision: "Markdown dual-write", choice: "DB-first then regenerate" },
|
|
19
|
+
],
|
|
20
|
+
recentRequirements: [
|
|
21
|
+
{ id: "R015", status: "active", description: "Commands register via pi.registerCommand" },
|
|
22
|
+
{ id: "R014", status: "active", description: "DB writes use upsert pattern" },
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const output = formatInspectOutput(data);
|
|
27
|
+
|
|
28
|
+
assertMatch(output, /=== GSD Database Inspect ===/, "contains header");
|
|
29
|
+
assertMatch(output, /Schema version: 2/, "contains schema version");
|
|
30
|
+
assertMatch(output, /Decisions:\s+12/, "contains decisions count");
|
|
31
|
+
assertMatch(output, /Requirements:\s+8/, "contains requirements count");
|
|
32
|
+
assertMatch(output, /Artifacts:\s+3/, "contains artifacts count");
|
|
33
|
+
assertMatch(output, /Recent decisions:/, "contains recent decisions header");
|
|
34
|
+
assertMatch(output, /D012: Use SQLite for persistence → node:sqlite with fallback/, "contains D012 entry");
|
|
35
|
+
assertMatch(output, /D011: Markdown dual-write → DB-first then regenerate/, "contains D011 entry");
|
|
36
|
+
assertMatch(output, /Recent requirements:/, "contains recent requirements header");
|
|
37
|
+
assertMatch(output, /R015 \[active\]: Commands register via pi\.registerCommand/, "contains R015 entry");
|
|
38
|
+
assertMatch(output, /R014 \[active\]: DB writes use upsert pattern/, "contains R014 entry");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ── handles zero counts and no recent entries ──
|
|
42
|
+
console.log("# === gsd-inspect: empty data ===");
|
|
43
|
+
{
|
|
44
|
+
const data: InspectData = {
|
|
45
|
+
schemaVersion: 1,
|
|
46
|
+
counts: { decisions: 0, requirements: 0, artifacts: 0 },
|
|
47
|
+
recentDecisions: [],
|
|
48
|
+
recentRequirements: [],
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const output = formatInspectOutput(data);
|
|
52
|
+
|
|
53
|
+
assertMatch(output, /Schema version: 1/, "contains schema version 1");
|
|
54
|
+
assertMatch(output, /Decisions:\s+0/, "zero decisions");
|
|
55
|
+
assertMatch(output, /Requirements:\s+0/, "zero requirements");
|
|
56
|
+
assertMatch(output, /Artifacts:\s+0/, "zero artifacts");
|
|
57
|
+
assertTrue(!output.includes("Recent decisions:"), "no recent decisions section when empty");
|
|
58
|
+
assertTrue(!output.includes("Recent requirements:"), "no recent requirements section when empty");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ── handles null schema version ──
|
|
62
|
+
console.log("# === gsd-inspect: null schema version ===");
|
|
63
|
+
{
|
|
64
|
+
const data: InspectData = {
|
|
65
|
+
schemaVersion: null,
|
|
66
|
+
counts: { decisions: 0, requirements: 0, artifacts: 0 },
|
|
67
|
+
recentDecisions: [],
|
|
68
|
+
recentRequirements: [],
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const output = formatInspectOutput(data);
|
|
72
|
+
assertMatch(output, /Schema version: unknown/, "null version shows as unknown");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ── formats up to 5 recent entries ──
|
|
76
|
+
console.log("# === gsd-inspect: five recent entries ===");
|
|
77
|
+
{
|
|
78
|
+
const data: InspectData = {
|
|
79
|
+
schemaVersion: 2,
|
|
80
|
+
counts: { decisions: 5, requirements: 5, artifacts: 0 },
|
|
81
|
+
recentDecisions: [
|
|
82
|
+
{ id: "D005", decision: "Dec 5", choice: "C5" },
|
|
83
|
+
{ id: "D004", decision: "Dec 4", choice: "C4" },
|
|
84
|
+
{ id: "D003", decision: "Dec 3", choice: "C3" },
|
|
85
|
+
{ id: "D002", decision: "Dec 2", choice: "C2" },
|
|
86
|
+
{ id: "D001", decision: "Dec 1", choice: "C1" },
|
|
87
|
+
],
|
|
88
|
+
recentRequirements: [
|
|
89
|
+
{ id: "R005", status: "active", description: "Req 5" },
|
|
90
|
+
{ id: "R004", status: "done", description: "Req 4" },
|
|
91
|
+
{ id: "R003", status: "active", description: "Req 3" },
|
|
92
|
+
{ id: "R002", status: "active", description: "Req 2" },
|
|
93
|
+
{ id: "R001", status: "done", description: "Req 1" },
|
|
94
|
+
],
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const output = formatInspectOutput(data);
|
|
98
|
+
|
|
99
|
+
for (let i = 1; i <= 5; i++) {
|
|
100
|
+
assertMatch(output, new RegExp(`D00${i}: Dec ${i} → C${i}`), `contains D00${i}`);
|
|
101
|
+
}
|
|
102
|
+
for (let i = 1; i <= 5; i++) {
|
|
103
|
+
assertMatch(output, new RegExp(`R00${i}`), `contains R00${i}`);
|
|
104
|
+
}
|
|
105
|
+
assertMatch(output, /\[active\]/, "contains active status");
|
|
106
|
+
assertMatch(output, /\[done\]/, "contains done status");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ── output is multiline text (not JSON) ──
|
|
110
|
+
console.log("# === gsd-inspect: output format ===");
|
|
111
|
+
{
|
|
112
|
+
const data: InspectData = {
|
|
113
|
+
schemaVersion: 2,
|
|
114
|
+
counts: { decisions: 1, requirements: 1, artifacts: 0 },
|
|
115
|
+
recentDecisions: [{ id: "D001", decision: "Test", choice: "Yes" }],
|
|
116
|
+
recentRequirements: [{ id: "R001", status: "active", description: "Test req" }],
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const output = formatInspectOutput(data);
|
|
120
|
+
const lines = output.split("\n");
|
|
121
|
+
assertTrue(lines.length > 5, "output has multiple lines");
|
|
122
|
+
assertTrue(!output.startsWith("{"), "output is not JSON");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
report();
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { describe, test } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
1
|
// gsd-recover.test.ts — Tests for the `gsd recover` recovery logic.
|
|
4
2
|
// Verifies: populate DB → clear hierarchy → recover from markdown → state matches.
|
|
5
3
|
|
|
@@ -24,6 +22,10 @@ import {
|
|
|
24
22
|
} from '../gsd-db.ts';
|
|
25
23
|
import { migrateHierarchyToDb } from '../md-importer.ts';
|
|
26
24
|
import { deriveStateFromDb, invalidateStateCache } from '../state.ts';
|
|
25
|
+
import { createTestContext } from './test-helpers.ts';
|
|
26
|
+
|
|
27
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
28
|
+
|
|
27
29
|
// ─── Fixture Helpers ───────────────────────────────────────────────────────
|
|
28
30
|
|
|
29
31
|
function createFixtureBase(): string {
|
|
@@ -146,8 +148,10 @@ function clearHierarchyTables(): void {
|
|
|
146
148
|
|
|
147
149
|
// ─── Tests ────────────────────────────────────────────────────────────────
|
|
148
150
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
+
async function main() {
|
|
152
|
+
// ─── Test (a): Full recovery round-trip ─────────────────────────────────
|
|
153
|
+
console.log('\n=== recover: full round-trip (populate → clear → recover → verify) ===');
|
|
154
|
+
{
|
|
151
155
|
const base = createFixtureBase();
|
|
152
156
|
try {
|
|
153
157
|
// Set up markdown fixtures
|
|
@@ -159,14 +163,14 @@ describe('gsd-recover', async () => {
|
|
|
159
163
|
// Step 1: Open DB and populate from markdown
|
|
160
164
|
openDatabase(':memory:');
|
|
161
165
|
const counts1 = migrateHierarchyToDb(base);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
166
|
+
assertEq(counts1.milestones, 1, 'round-trip: initial migration — 1 milestone');
|
|
167
|
+
assertEq(counts1.slices, 2, 'round-trip: initial migration — 2 slices');
|
|
168
|
+
assertTrue(counts1.tasks >= 5, 'round-trip: initial migration — at least 5 tasks');
|
|
165
169
|
|
|
166
170
|
// Step 2: Capture state from DB before clearing
|
|
167
171
|
invalidateStateCache();
|
|
168
172
|
const stateBefore = await deriveStateFromDb(base);
|
|
169
|
-
|
|
173
|
+
assertTrue(stateBefore.activeMilestone !== null, 'round-trip: state before has active milestone');
|
|
170
174
|
const milestonesBefore = getAllMilestones();
|
|
171
175
|
const slicesBefore = getMilestoneSlices('M001');
|
|
172
176
|
const s01TasksBefore = getSliceTasks('M001', 'S01');
|
|
@@ -175,30 +179,30 @@ describe('gsd-recover', async () => {
|
|
|
175
179
|
// Step 3: Clear hierarchy tables
|
|
176
180
|
clearHierarchyTables();
|
|
177
181
|
const milestonesAfterClear = getAllMilestones();
|
|
178
|
-
|
|
182
|
+
assertEq(milestonesAfterClear.length, 0, 'round-trip: milestones cleared');
|
|
179
183
|
|
|
180
184
|
// Step 4: Recover from markdown
|
|
181
185
|
const counts2 = migrateHierarchyToDb(base);
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
186
|
+
assertEq(counts2.milestones, counts1.milestones, 'round-trip: recovery milestone count matches');
|
|
187
|
+
assertEq(counts2.slices, counts1.slices, 'round-trip: recovery slice count matches');
|
|
188
|
+
assertEq(counts2.tasks, counts1.tasks, 'round-trip: recovery task count matches');
|
|
185
189
|
|
|
186
190
|
// Step 5: Verify state matches
|
|
187
191
|
invalidateStateCache();
|
|
188
192
|
const stateAfter = await deriveStateFromDb(base);
|
|
189
193
|
|
|
190
|
-
|
|
191
|
-
|
|
194
|
+
assertEq(stateAfter.phase, stateBefore.phase, 'round-trip: phase matches');
|
|
195
|
+
assertEq(
|
|
192
196
|
stateAfter.activeMilestone?.id,
|
|
193
197
|
stateBefore.activeMilestone?.id,
|
|
194
198
|
'round-trip: active milestone ID matches',
|
|
195
199
|
);
|
|
196
|
-
|
|
200
|
+
assertEq(
|
|
197
201
|
stateAfter.activeSlice?.id,
|
|
198
202
|
stateBefore.activeSlice?.id,
|
|
199
203
|
'round-trip: active slice ID matches',
|
|
200
204
|
);
|
|
201
|
-
|
|
205
|
+
assertEq(
|
|
202
206
|
stateAfter.activeTask?.id,
|
|
203
207
|
stateBefore.activeTask?.id,
|
|
204
208
|
'round-trip: active task ID matches',
|
|
@@ -206,30 +210,32 @@ describe('gsd-recover', async () => {
|
|
|
206
210
|
|
|
207
211
|
// Verify row-level data matches
|
|
208
212
|
const milestonesAfter = getAllMilestones();
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
213
|
+
assertEq(milestonesAfter.length, milestonesBefore.length, 'round-trip: milestone row count');
|
|
214
|
+
assertEq(milestonesAfter[0]?.id, milestonesBefore[0]?.id, 'round-trip: milestone ID');
|
|
215
|
+
assertEq(milestonesAfter[0]?.title, milestonesBefore[0]?.title, 'round-trip: milestone title');
|
|
212
216
|
|
|
213
217
|
const slicesAfter = getMilestoneSlices('M001');
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
+
assertEq(slicesAfter.length, slicesBefore.length, 'round-trip: slice row count');
|
|
219
|
+
assertEq(slicesAfter[0]?.id, slicesBefore[0]?.id, 'round-trip: S01 ID');
|
|
220
|
+
assertEq(slicesAfter[0]?.status, slicesBefore[0]?.status, 'round-trip: S01 status');
|
|
221
|
+
assertEq(slicesAfter[1]?.id, slicesBefore[1]?.id, 'round-trip: S02 ID');
|
|
218
222
|
|
|
219
223
|
const s01TasksAfter = getSliceTasks('M001', 'S01');
|
|
220
|
-
|
|
224
|
+
assertEq(s01TasksAfter.length, s01TasksBefore.length, 'round-trip: S01 task count');
|
|
221
225
|
|
|
222
226
|
const s02TasksAfter = getSliceTasks('M001', 'S02');
|
|
223
|
-
|
|
227
|
+
assertEq(s02TasksAfter.length, s02TasksBefore.length, 'round-trip: S02 task count');
|
|
224
228
|
|
|
225
229
|
closeDatabase();
|
|
226
230
|
} finally {
|
|
227
231
|
closeDatabase();
|
|
228
232
|
cleanup(base);
|
|
229
233
|
}
|
|
230
|
-
}
|
|
234
|
+
}
|
|
231
235
|
|
|
232
|
-
|
|
236
|
+
// ─── Test (a2): v8 planning columns populated after recovery ───────────
|
|
237
|
+
console.log('\n=== recover: v8 planning columns populated ===');
|
|
238
|
+
{
|
|
233
239
|
const base = createFixtureBase();
|
|
234
240
|
try {
|
|
235
241
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_M001);
|
|
@@ -242,70 +248,75 @@ describe('gsd-recover', async () => {
|
|
|
242
248
|
|
|
243
249
|
// Milestone planning columns
|
|
244
250
|
const milestone = getMilestone('M001');
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
+
assertTrue(milestone !== null, 'v8: milestone exists');
|
|
252
|
+
assertEq(milestone!.vision, 'Test recovery round-trip.', 'v8: milestone vision populated');
|
|
253
|
+
assertTrue(milestone!.success_criteria.length >= 2, 'v8: milestone success_criteria has entries');
|
|
254
|
+
assertEq(milestone!.success_criteria[0], 'All recovery tests pass', 'v8: first success criterion');
|
|
255
|
+
assertTrue(milestone!.boundary_map_markdown.includes('Boundary Map'), 'v8: boundary_map_markdown populated');
|
|
256
|
+
assertTrue(milestone!.boundary_map_markdown.includes('S01'), 'v8: boundary_map_markdown has S01');
|
|
251
257
|
|
|
252
258
|
// Tool-only fields left empty per D004
|
|
253
|
-
|
|
254
|
-
|
|
259
|
+
assertEq(milestone!.key_risks.length, 0, 'v8: key_risks left empty (tool-only per D004)');
|
|
260
|
+
assertEq(milestone!.requirement_coverage, '', 'v8: requirement_coverage left empty (tool-only per D004)');
|
|
255
261
|
|
|
256
262
|
// Slice planning columns
|
|
257
263
|
const sliceS01 = getSlice('M001', 'S01');
|
|
258
|
-
|
|
259
|
-
|
|
264
|
+
assertTrue(sliceS01 !== null, 'v8: slice S01 exists');
|
|
265
|
+
assertEq(sliceS01!.goal, 'Setup fixtures.', 'v8: S01 goal populated');
|
|
260
266
|
|
|
261
267
|
const sliceS02 = getSlice('M001', 'S02');
|
|
262
|
-
|
|
263
|
-
|
|
268
|
+
assertTrue(sliceS02 !== null, 'v8: slice S02 exists');
|
|
269
|
+
assertEq(sliceS02!.goal, 'Build core.', 'v8: S02 goal populated');
|
|
264
270
|
|
|
265
271
|
// Slice tool-only fields left empty per D004
|
|
266
|
-
|
|
272
|
+
assertEq(sliceS01!.proof_level, '', 'v8: S01 proof_level left empty (tool-only per D004)');
|
|
267
273
|
|
|
268
|
-
// Task planning columns
|
|
274
|
+
// Task planning columns — S01/T01
|
|
269
275
|
const taskS01T01 = getTask('M001', 'S01', 'T01');
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
276
|
+
assertTrue(taskS01T01 !== null, 'v8: task S01/T01 exists');
|
|
277
|
+
assertTrue(taskS01T01!.files.length >= 2, 'v8: S01/T01 files populated');
|
|
278
|
+
assertTrue(taskS01T01!.files.includes('init.ts'), 'v8: S01/T01 files includes init.ts');
|
|
279
|
+
assertTrue(taskS01T01!.files.includes('config.ts'), 'v8: S01/T01 files includes config.ts');
|
|
280
|
+
assertEq(taskS01T01!.verify, '`node test-init.ts`', 'v8: S01/T01 verify populated');
|
|
275
281
|
|
|
276
|
-
// Task planning columns
|
|
282
|
+
// Task planning columns — S02/T02
|
|
277
283
|
const taskS02T02 = getTask('M001', 'S02', 'T02');
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
284
|
+
assertTrue(taskS02T02 !== null, 'v8: task S02/T02 exists');
|
|
285
|
+
assertTrue(taskS02T02!.files.length >= 2, 'v8: S02/T02 files populated');
|
|
286
|
+
assertTrue(taskS02T02!.files.includes('test-core.ts'), 'v8: S02/T02 files includes test-core.ts');
|
|
287
|
+
assertEq(taskS02T02!.verify, '`npm test`', 'v8: S02/T02 verify populated');
|
|
282
288
|
|
|
289
|
+
// Task with no Files/Verify — not applicable since all fixtures now have them,
|
|
290
|
+
// but confirm a task from S02 has correct data
|
|
283
291
|
const taskS02T03 = getTask('M001', 'S02', 'T03');
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
292
|
+
assertTrue(taskS02T03 !== null, 'v8: task S02/T03 exists');
|
|
293
|
+
assertTrue(taskS02T03!.files.includes('polish.ts'), 'v8: S02/T03 files includes polish.ts');
|
|
294
|
+
assertEq(taskS02T03!.verify, '`node test-polish.ts`', 'v8: S02/T03 verify populated');
|
|
287
295
|
|
|
288
296
|
// Diagnostic: v8 planning columns queryable via SQL
|
|
289
297
|
const db = _getAdapter()!;
|
|
290
298
|
const milestoneRow = db.prepare("SELECT vision, success_criteria, boundary_map_markdown FROM milestones WHERE id = 'M001'").get() as any;
|
|
291
|
-
|
|
292
|
-
|
|
299
|
+
assertTrue(milestoneRow.vision.length > 0, 'v8-diag: vision column queryable');
|
|
300
|
+
assertTrue(milestoneRow.boundary_map_markdown.length > 0, 'v8-diag: boundary_map_markdown column queryable');
|
|
293
301
|
|
|
294
302
|
const sliceRow = db.prepare("SELECT goal FROM slices WHERE milestone_id = 'M001' AND id = 'S01'").get() as any;
|
|
295
|
-
|
|
303
|
+
assertTrue(sliceRow.goal.length > 0, 'v8-diag: goal column queryable');
|
|
296
304
|
|
|
297
305
|
const taskRow = db.prepare("SELECT files, verify FROM tasks WHERE milestone_id = 'M001' AND slice_id = 'S01' AND id = 'T01'").get() as any;
|
|
298
|
-
|
|
299
|
-
|
|
306
|
+
assertTrue(taskRow.files.length > 2, 'v8-diag: files column queryable (JSON array)');
|
|
307
|
+
assertTrue(taskRow.verify.length > 0, 'v8-diag: verify column queryable');
|
|
300
308
|
|
|
301
309
|
closeDatabase();
|
|
302
310
|
} finally {
|
|
303
311
|
closeDatabase();
|
|
304
312
|
cleanup(base);
|
|
305
313
|
}
|
|
306
|
-
}
|
|
314
|
+
}
|
|
315
|
+
|
|
307
316
|
|
|
308
|
-
|
|
317
|
+
// ─── Test (b): Idempotent recovery — double recover ────────────────────
|
|
318
|
+
console.log('\n=== recover: idempotent — double recovery produces same state ===');
|
|
319
|
+
{
|
|
309
320
|
const base = createFixtureBase();
|
|
310
321
|
try {
|
|
311
322
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_M001);
|
|
@@ -326,18 +337,18 @@ describe('gsd-recover', async () => {
|
|
|
326
337
|
invalidateStateCache();
|
|
327
338
|
const state2 = await deriveStateFromDb(base);
|
|
328
339
|
|
|
329
|
-
|
|
330
|
-
|
|
340
|
+
assertEq(state2.phase, state1.phase, 'idempotent: phase matches');
|
|
341
|
+
assertEq(
|
|
331
342
|
state2.activeMilestone?.id,
|
|
332
343
|
state1.activeMilestone?.id,
|
|
333
344
|
'idempotent: active milestone matches',
|
|
334
345
|
);
|
|
335
|
-
|
|
346
|
+
assertEq(
|
|
336
347
|
state2.activeSlice?.id,
|
|
337
348
|
state1.activeSlice?.id,
|
|
338
349
|
'idempotent: active slice matches',
|
|
339
350
|
);
|
|
340
|
-
|
|
351
|
+
assertEq(
|
|
341
352
|
state2.activeTask?.id,
|
|
342
353
|
state1.activeTask?.id,
|
|
343
354
|
'idempotent: active task matches',
|
|
@@ -348,9 +359,11 @@ describe('gsd-recover', async () => {
|
|
|
348
359
|
closeDatabase();
|
|
349
360
|
cleanup(base);
|
|
350
361
|
}
|
|
351
|
-
}
|
|
362
|
+
}
|
|
352
363
|
|
|
353
|
-
|
|
364
|
+
// ─── Test (c): Recovery preserves non-hierarchy data ───────────────────
|
|
365
|
+
console.log('\n=== recover: preserves decisions/requirements ===');
|
|
366
|
+
{
|
|
354
367
|
const base = createFixtureBase();
|
|
355
368
|
try {
|
|
356
369
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_M001);
|
|
@@ -389,33 +402,35 @@ describe('gsd-recover', async () => {
|
|
|
389
402
|
|
|
390
403
|
// Verify decisions and requirements survived
|
|
391
404
|
const decisions = db.prepare('SELECT * FROM decisions').all();
|
|
392
|
-
|
|
393
|
-
|
|
405
|
+
assertEq(decisions.length, 1, 'preserve: decision survives clear');
|
|
406
|
+
assertEq((decisions[0] as any).id, 'D001', 'preserve: decision ID intact');
|
|
394
407
|
|
|
395
408
|
const requirements = db.prepare('SELECT * FROM requirements').all();
|
|
396
|
-
|
|
397
|
-
|
|
409
|
+
assertEq(requirements.length, 1, 'preserve: requirement survives clear');
|
|
410
|
+
assertEq((requirements[0] as any).id, 'R001', 'preserve: requirement ID intact');
|
|
398
411
|
|
|
399
412
|
// Recover hierarchy
|
|
400
413
|
migrateHierarchyToDb(base);
|
|
401
414
|
const milestones = getAllMilestones();
|
|
402
|
-
|
|
415
|
+
assertTrue(milestones.length > 0, 'preserve: milestones recovered after clear');
|
|
403
416
|
|
|
404
417
|
// Verify non-hierarchy data still intact after recovery
|
|
405
418
|
const decisionsAfter = db.prepare('SELECT * FROM decisions').all();
|
|
406
|
-
|
|
419
|
+
assertEq(decisionsAfter.length, 1, 'preserve: decision still present after recovery');
|
|
407
420
|
|
|
408
421
|
closeDatabase();
|
|
409
422
|
} finally {
|
|
410
423
|
closeDatabase();
|
|
411
424
|
cleanup(base);
|
|
412
425
|
}
|
|
413
|
-
}
|
|
426
|
+
}
|
|
414
427
|
|
|
415
|
-
|
|
428
|
+
// ─── Test (d): Recovery from empty markdown dir ────────────────────────
|
|
429
|
+
console.log('\n=== recover: empty milestones dir ===');
|
|
430
|
+
{
|
|
416
431
|
const base = createFixtureBase();
|
|
417
432
|
try {
|
|
418
|
-
// No milestones written
|
|
433
|
+
// No milestones written — just the empty dir
|
|
419
434
|
openDatabase(':memory:');
|
|
420
435
|
|
|
421
436
|
// Pre-populate to simulate existing state
|
|
@@ -424,17 +439,24 @@ describe('gsd-recover', async () => {
|
|
|
424
439
|
// Clear and recover from empty
|
|
425
440
|
clearHierarchyTables();
|
|
426
441
|
const counts = migrateHierarchyToDb(base);
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
442
|
+
assertEq(counts.milestones, 0, 'empty: zero milestones recovered');
|
|
443
|
+
assertEq(counts.slices, 0, 'empty: zero slices recovered');
|
|
444
|
+
assertEq(counts.tasks, 0, 'empty: zero tasks recovered');
|
|
430
445
|
|
|
431
446
|
const all = getAllMilestones();
|
|
432
|
-
|
|
447
|
+
assertEq(all.length, 0, 'empty: no milestones in DB after recovery');
|
|
433
448
|
|
|
434
449
|
closeDatabase();
|
|
435
450
|
} finally {
|
|
436
451
|
closeDatabase();
|
|
437
452
|
cleanup(base);
|
|
438
453
|
}
|
|
439
|
-
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
report();
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
main().catch((error) => {
|
|
460
|
+
console.error(error);
|
|
461
|
+
process.exit(1);
|
|
440
462
|
});
|