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,5 +1,3 @@
|
|
|
1
|
-
import { describe, test } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
1
|
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
2
|
import { join } from 'node:path';
|
|
5
3
|
import { tmpdir } from 'node:os';
|
|
@@ -14,6 +12,10 @@ import {
|
|
|
14
12
|
insertSlice,
|
|
15
13
|
insertTask,
|
|
16
14
|
} from '../gsd-db.ts';
|
|
15
|
+
import { createTestContext } from './test-helpers.ts';
|
|
16
|
+
|
|
17
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
18
|
+
|
|
17
19
|
// ─── Fixture Helpers ───────────────────────────────────────────────────────
|
|
18
20
|
|
|
19
21
|
function createFixtureBase(): string {
|
|
@@ -98,10 +100,11 @@ const REQUIREMENTS_CONTENT = `# Requirements
|
|
|
98
100
|
- Description: Already validated.
|
|
99
101
|
`;
|
|
100
102
|
|
|
101
|
-
|
|
103
|
+
async function main(): Promise<void> {
|
|
102
104
|
|
|
103
105
|
// ─── Test 1: DB-backed deriveState produces identical GSDState ─────────
|
|
104
|
-
|
|
106
|
+
console.log('\n=== derive-state-db: DB path matches file path ===');
|
|
107
|
+
{
|
|
105
108
|
const base = createFixtureBase();
|
|
106
109
|
try {
|
|
107
110
|
// Write files to disk (for file-only path)
|
|
@@ -117,7 +120,7 @@ describe('derive-state-db', async () => {
|
|
|
117
120
|
|
|
118
121
|
// Now open DB, insert matching artifacts
|
|
119
122
|
openDatabase(':memory:');
|
|
120
|
-
|
|
123
|
+
assertTrue(isDbAvailable(), 'db-match: DB is available after open');
|
|
121
124
|
|
|
122
125
|
insertArtifactRow('milestones/M001/M001-ROADMAP.md', ROADMAP_CONTENT, {
|
|
123
126
|
artifact_type: 'roadmap',
|
|
@@ -137,35 +140,36 @@ describe('derive-state-db', async () => {
|
|
|
137
140
|
const dbState = await deriveState(base);
|
|
138
141
|
|
|
139
142
|
// Field-by-field equality
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
143
|
+
assertEq(dbState.phase, fileState.phase, 'db-match: phase matches');
|
|
144
|
+
assertEq(dbState.activeMilestone?.id, fileState.activeMilestone?.id, 'db-match: activeMilestone.id matches');
|
|
145
|
+
assertEq(dbState.activeMilestone?.title, fileState.activeMilestone?.title, 'db-match: activeMilestone.title matches');
|
|
146
|
+
assertEq(dbState.activeSlice?.id, fileState.activeSlice?.id, 'db-match: activeSlice.id matches');
|
|
147
|
+
assertEq(dbState.activeSlice?.title, fileState.activeSlice?.title, 'db-match: activeSlice.title matches');
|
|
148
|
+
assertEq(dbState.activeTask?.id, fileState.activeTask?.id, 'db-match: activeTask.id matches');
|
|
149
|
+
assertEq(dbState.activeTask?.title, fileState.activeTask?.title, 'db-match: activeTask.title matches');
|
|
150
|
+
assertEq(dbState.blockers, fileState.blockers, 'db-match: blockers match');
|
|
151
|
+
assertEq(dbState.registry.length, fileState.registry.length, 'db-match: registry length matches');
|
|
152
|
+
assertEq(dbState.registry[0]?.status, fileState.registry[0]?.status, 'db-match: registry[0] status matches');
|
|
153
|
+
assertEq(dbState.requirements?.active, fileState.requirements?.active, 'db-match: requirements.active matches');
|
|
154
|
+
assertEq(dbState.requirements?.validated, fileState.requirements?.validated, 'db-match: requirements.validated matches');
|
|
155
|
+
assertEq(dbState.requirements?.total, fileState.requirements?.total, 'db-match: requirements.total matches');
|
|
156
|
+
assertEq(dbState.progress?.milestones?.done, fileState.progress?.milestones?.done, 'db-match: milestones.done matches');
|
|
157
|
+
assertEq(dbState.progress?.milestones?.total, fileState.progress?.milestones?.total, 'db-match: milestones.total matches');
|
|
158
|
+
assertEq(dbState.progress?.slices?.done, fileState.progress?.slices?.done, 'db-match: slices.done matches');
|
|
159
|
+
assertEq(dbState.progress?.slices?.total, fileState.progress?.slices?.total, 'db-match: slices.total matches');
|
|
160
|
+
assertEq(dbState.progress?.tasks?.done, fileState.progress?.tasks?.done, 'db-match: tasks.done matches');
|
|
161
|
+
assertEq(dbState.progress?.tasks?.total, fileState.progress?.tasks?.total, 'db-match: tasks.total matches');
|
|
159
162
|
|
|
160
163
|
closeDatabase();
|
|
161
164
|
} finally {
|
|
162
165
|
closeDatabase();
|
|
163
166
|
cleanup(base);
|
|
164
167
|
}
|
|
165
|
-
}
|
|
168
|
+
}
|
|
166
169
|
|
|
167
170
|
// ─── Test 2: Fallback when DB unavailable ─────────────────────────────
|
|
168
|
-
|
|
171
|
+
console.log('\n=== derive-state-db: fallback when DB unavailable ===');
|
|
172
|
+
{
|
|
169
173
|
const base = createFixtureBase();
|
|
170
174
|
try {
|
|
171
175
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_CONTENT);
|
|
@@ -174,21 +178,22 @@ describe('derive-state-db', async () => {
|
|
|
174
178
|
writeFile(base, 'milestones/M001/slices/S01/tasks/T01-PLAN.md', '# T01 Plan');
|
|
175
179
|
|
|
176
180
|
// No DB open — isDbAvailable() is false
|
|
177
|
-
|
|
181
|
+
assertTrue(!isDbAvailable(), 'fallback: DB is not available');
|
|
178
182
|
invalidateStateCache();
|
|
179
183
|
const state = await deriveState(base);
|
|
180
184
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
+
assertEq(state.phase, 'executing', 'fallback: phase is executing');
|
|
186
|
+
assertEq(state.activeMilestone?.id, 'M001', 'fallback: activeMilestone is M001');
|
|
187
|
+
assertEq(state.activeSlice?.id, 'S01', 'fallback: activeSlice is S01');
|
|
188
|
+
assertEq(state.activeTask?.id, 'T01', 'fallback: activeTask is T01');
|
|
185
189
|
} finally {
|
|
186
190
|
cleanup(base);
|
|
187
191
|
}
|
|
188
|
-
}
|
|
192
|
+
}
|
|
189
193
|
|
|
190
194
|
// ─── Test 3: Empty DB falls back to file reads ────────────────────────
|
|
191
|
-
|
|
195
|
+
console.log('\n=== derive-state-db: empty DB falls back to files ===');
|
|
196
|
+
{
|
|
192
197
|
const base = createFixtureBase();
|
|
193
198
|
try {
|
|
194
199
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_CONTENT);
|
|
@@ -198,26 +203,27 @@ describe('derive-state-db', async () => {
|
|
|
198
203
|
|
|
199
204
|
// Open DB but insert nothing — empty artifacts table
|
|
200
205
|
openDatabase(':memory:');
|
|
201
|
-
|
|
206
|
+
assertTrue(isDbAvailable(), 'empty-db: DB is available');
|
|
202
207
|
|
|
203
208
|
invalidateStateCache();
|
|
204
209
|
const state = await deriveState(base);
|
|
205
210
|
|
|
206
211
|
// Should still work via cachedLoadFile → loadFile disk fallback
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
212
|
+
assertEq(state.phase, 'executing', 'empty-db: phase is executing');
|
|
213
|
+
assertEq(state.activeMilestone?.id, 'M001', 'empty-db: activeMilestone is M001');
|
|
214
|
+
assertEq(state.activeSlice?.id, 'S01', 'empty-db: activeSlice is S01');
|
|
215
|
+
assertEq(state.activeTask?.id, 'T01', 'empty-db: activeTask is T01');
|
|
211
216
|
|
|
212
217
|
closeDatabase();
|
|
213
218
|
} finally {
|
|
214
219
|
closeDatabase();
|
|
215
220
|
cleanup(base);
|
|
216
221
|
}
|
|
217
|
-
}
|
|
222
|
+
}
|
|
218
223
|
|
|
219
224
|
// ─── Test 4: Partial DB content fills gaps from disk ──────────────────
|
|
220
|
-
|
|
225
|
+
console.log('\n=== derive-state-db: partial DB fills gaps from disk ===');
|
|
226
|
+
{
|
|
221
227
|
const base = createFixtureBase();
|
|
222
228
|
try {
|
|
223
229
|
// Write all files to disk
|
|
@@ -238,24 +244,25 @@ describe('derive-state-db', async () => {
|
|
|
238
244
|
const state = await deriveState(base);
|
|
239
245
|
|
|
240
246
|
// Should work: roadmap from DB, plan from disk fallback
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
247
|
+
assertEq(state.phase, 'executing', 'partial-db: phase is executing');
|
|
248
|
+
assertEq(state.activeMilestone?.id, 'M001', 'partial-db: activeMilestone is M001');
|
|
249
|
+
assertEq(state.activeSlice?.id, 'S01', 'partial-db: activeSlice is S01');
|
|
250
|
+
assertEq(state.activeTask?.id, 'T01', 'partial-db: activeTask is T01');
|
|
245
251
|
// Requirements loaded from disk fallback
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
252
|
+
assertEq(state.requirements?.active, 2, 'partial-db: requirements.active from disk');
|
|
253
|
+
assertEq(state.requirements?.validated, 1, 'partial-db: requirements.validated from disk');
|
|
254
|
+
assertEq(state.requirements?.total, 3, 'partial-db: requirements.total from disk');
|
|
249
255
|
|
|
250
256
|
closeDatabase();
|
|
251
257
|
} finally {
|
|
252
258
|
closeDatabase();
|
|
253
259
|
cleanup(base);
|
|
254
260
|
}
|
|
255
|
-
}
|
|
261
|
+
}
|
|
256
262
|
|
|
257
263
|
// ─── Test 5: Requirements counting from disk (DB no longer used for content) ─
|
|
258
|
-
|
|
264
|
+
console.log('\n=== derive-state-db: requirements from disk content ===');
|
|
265
|
+
{
|
|
259
266
|
const base = createFixtureBase();
|
|
260
267
|
try {
|
|
261
268
|
// Write minimal milestone dir (needed for milestone discovery)
|
|
@@ -267,16 +274,17 @@ describe('derive-state-db', async () => {
|
|
|
267
274
|
const state = await deriveState(base);
|
|
268
275
|
|
|
269
276
|
// Requirements should come from disk
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
277
|
+
assertEq(state.requirements?.active, 2, 'req-from-disk: requirements.active = 2');
|
|
278
|
+
assertEq(state.requirements?.validated, 1, 'req-from-disk: requirements.validated = 1');
|
|
279
|
+
assertEq(state.requirements?.total, 3, 'req-from-disk: requirements.total = 3');
|
|
273
280
|
} finally {
|
|
274
281
|
cleanup(base);
|
|
275
282
|
}
|
|
276
|
-
}
|
|
283
|
+
}
|
|
277
284
|
|
|
278
285
|
// ─── Test 6: DB content with multi-milestone registry ─────────────────
|
|
279
|
-
|
|
286
|
+
console.log('\n=== derive-state-db: multi-milestone from DB ===');
|
|
287
|
+
{
|
|
280
288
|
const base = createFixtureBase();
|
|
281
289
|
|
|
282
290
|
const completedRoadmap = `# M001: First Milestone
|
|
@@ -329,23 +337,24 @@ describe('derive-state-db', async () => {
|
|
|
329
337
|
invalidateStateCache();
|
|
330
338
|
const state = await deriveState(base);
|
|
331
339
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
340
|
+
assertEq(state.registry.length, 2, 'multi-ms-db: registry has 2 entries');
|
|
341
|
+
assertEq(state.registry[0]?.id, 'M001', 'multi-ms-db: registry[0] is M001');
|
|
342
|
+
assertEq(state.registry[0]?.status, 'complete', 'multi-ms-db: M001 is complete');
|
|
343
|
+
assertEq(state.registry[1]?.id, 'M002', 'multi-ms-db: registry[1] is M002');
|
|
344
|
+
assertEq(state.registry[1]?.status, 'active', 'multi-ms-db: M002 is active');
|
|
345
|
+
assertEq(state.activeMilestone?.id, 'M002', 'multi-ms-db: activeMilestone is M002');
|
|
346
|
+
assertEq(state.phase, 'planning', 'multi-ms-db: phase is planning (no plan for S01)');
|
|
339
347
|
|
|
340
348
|
closeDatabase();
|
|
341
349
|
} finally {
|
|
342
350
|
closeDatabase();
|
|
343
351
|
cleanup(base);
|
|
344
352
|
}
|
|
345
|
-
}
|
|
353
|
+
}
|
|
346
354
|
|
|
347
355
|
// ─── Test 7: Cache invalidation works for DB path ─────────────────────
|
|
348
|
-
|
|
356
|
+
console.log('\n=== derive-state-db: cache invalidation ===');
|
|
357
|
+
{
|
|
349
358
|
const base = createFixtureBase();
|
|
350
359
|
try {
|
|
351
360
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_CONTENT);
|
|
@@ -366,7 +375,7 @@ describe('derive-state-db', async () => {
|
|
|
366
375
|
|
|
367
376
|
invalidateStateCache();
|
|
368
377
|
const state1 = await deriveState(base);
|
|
369
|
-
|
|
378
|
+
assertEq(state1.activeTask?.id, 'T01', 'cache-inv: first call gets T01');
|
|
370
379
|
|
|
371
380
|
// Simulate task completion by updating the plan in DB
|
|
372
381
|
const updatedPlan = PLAN_CONTENT.replace('- [ ] **T01:', '- [x] **T01:');
|
|
@@ -380,27 +389,28 @@ describe('derive-state-db', async () => {
|
|
|
380
389
|
|
|
381
390
|
// Without invalidation, should return cached result (T01 still active)
|
|
382
391
|
const state2 = await deriveState(base);
|
|
383
|
-
|
|
392
|
+
assertEq(state2.activeTask?.id, 'T01', 'cache-inv: cached result still has T01');
|
|
384
393
|
|
|
385
394
|
// After invalidation, should pick up updated content
|
|
386
395
|
invalidateStateCache();
|
|
387
396
|
const state3 = await deriveState(base);
|
|
388
|
-
|
|
389
|
-
|
|
397
|
+
assertEq(state3.phase, 'summarizing', 'cache-inv: after invalidation, phase is summarizing (all tasks done)');
|
|
398
|
+
assertEq(state3.activeTask, null, 'cache-inv: activeTask is null after all done');
|
|
390
399
|
|
|
391
400
|
closeDatabase();
|
|
392
401
|
} finally {
|
|
393
402
|
closeDatabase();
|
|
394
403
|
cleanup(base);
|
|
395
404
|
}
|
|
396
|
-
}
|
|
405
|
+
}
|
|
397
406
|
|
|
398
407
|
// ═════════════════════════════════════════════════════════════════════════
|
|
399
408
|
// New: deriveStateFromDb() cross-validation tests
|
|
400
409
|
// ═════════════════════════════════════════════════════════════════════════
|
|
401
410
|
|
|
402
411
|
// ─── Test 8: Pre-planning — milestone exists, no roadmap, no slices ───
|
|
403
|
-
|
|
412
|
+
console.log('\n=== derive-state-db: pre-planning via DB ===');
|
|
413
|
+
{
|
|
404
414
|
const base = createFixtureBase();
|
|
405
415
|
try {
|
|
406
416
|
// Create milestone dir on disk with a CONTEXT file (not a ghost)
|
|
@@ -417,22 +427,23 @@ describe('derive-state-db', async () => {
|
|
|
417
427
|
invalidateStateCache();
|
|
418
428
|
const dbState = await deriveStateFromDb(base);
|
|
419
429
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
430
|
+
assertEq(dbState.phase, fileState.phase, 'pre-plan-db: phase matches');
|
|
431
|
+
assertEq(dbState.activeMilestone?.id, fileState.activeMilestone?.id, 'pre-plan-db: activeMilestone.id matches');
|
|
432
|
+
assertEq(dbState.activeSlice, fileState.activeSlice, 'pre-plan-db: activeSlice matches');
|
|
433
|
+
assertEq(dbState.activeTask, fileState.activeTask, 'pre-plan-db: activeTask matches');
|
|
434
|
+
assertEq(dbState.registry.length, fileState.registry.length, 'pre-plan-db: registry length matches');
|
|
435
|
+
assertEq(dbState.registry[0]?.status, fileState.registry[0]?.status, 'pre-plan-db: registry[0] status matches');
|
|
426
436
|
|
|
427
437
|
closeDatabase();
|
|
428
438
|
} finally {
|
|
429
439
|
closeDatabase();
|
|
430
440
|
cleanup(base);
|
|
431
441
|
}
|
|
432
|
-
}
|
|
442
|
+
}
|
|
433
443
|
|
|
434
444
|
// ─── Test 9: Executing — active task with partial completion ──────────
|
|
435
|
-
|
|
445
|
+
console.log('\n=== derive-state-db: executing via DB ===');
|
|
446
|
+
{
|
|
436
447
|
const base = createFixtureBase();
|
|
437
448
|
try {
|
|
438
449
|
// Build filesystem fixture
|
|
@@ -455,23 +466,24 @@ describe('derive-state-db', async () => {
|
|
|
455
466
|
invalidateStateCache();
|
|
456
467
|
const dbState = await deriveStateFromDb(base);
|
|
457
468
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
469
|
+
assertEq(dbState.phase, 'executing', 'exec-db: phase is executing');
|
|
470
|
+
assertEq(dbState.activeMilestone?.id, 'M001', 'exec-db: activeMilestone is M001');
|
|
471
|
+
assertEq(dbState.activeSlice?.id, 'S01', 'exec-db: activeSlice is S01');
|
|
472
|
+
assertEq(dbState.activeTask?.id, 'T01', 'exec-db: activeTask is T01');
|
|
473
|
+
assertEq(dbState.progress?.tasks?.done, 1, 'exec-db: tasks.done = 1');
|
|
474
|
+
assertEq(dbState.progress?.tasks?.total, 2, 'exec-db: tasks.total = 2');
|
|
475
|
+
assertEq(dbState.phase, fileState.phase, 'exec-db: phase matches filesystem');
|
|
465
476
|
|
|
466
477
|
closeDatabase();
|
|
467
478
|
} finally {
|
|
468
479
|
closeDatabase();
|
|
469
480
|
cleanup(base);
|
|
470
481
|
}
|
|
471
|
-
}
|
|
482
|
+
}
|
|
472
483
|
|
|
473
484
|
// ─── Test 10: Summarizing — all tasks complete, no slice summary ──────
|
|
474
|
-
|
|
485
|
+
console.log('\n=== derive-state-db: summarizing via DB ===');
|
|
486
|
+
{
|
|
475
487
|
const base = createFixtureBase();
|
|
476
488
|
try {
|
|
477
489
|
const allDonePlan = `# S01: First Slice
|
|
@@ -505,20 +517,21 @@ describe('derive-state-db', async () => {
|
|
|
505
517
|
invalidateStateCache();
|
|
506
518
|
const dbState = await deriveStateFromDb(base);
|
|
507
519
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
520
|
+
assertEq(dbState.phase, 'summarizing', 'summarize-db: phase is summarizing');
|
|
521
|
+
assertEq(dbState.phase, fileState.phase, 'summarize-db: phase matches filesystem');
|
|
522
|
+
assertEq(dbState.activeSlice?.id, 'S01', 'summarize-db: activeSlice is S01');
|
|
523
|
+
assertEq(dbState.activeTask, null, 'summarize-db: activeTask is null');
|
|
512
524
|
|
|
513
525
|
closeDatabase();
|
|
514
526
|
} finally {
|
|
515
527
|
closeDatabase();
|
|
516
528
|
cleanup(base);
|
|
517
529
|
}
|
|
518
|
-
}
|
|
530
|
+
}
|
|
519
531
|
|
|
520
532
|
// ─── Test 11: Complete — all milestones complete ──────────────────────
|
|
521
|
-
|
|
533
|
+
console.log('\n=== derive-state-db: all complete via DB ===');
|
|
534
|
+
{
|
|
522
535
|
const base = createFixtureBase();
|
|
523
536
|
try {
|
|
524
537
|
const completedRoadmap = `# M001: Done Milestone
|
|
@@ -544,20 +557,21 @@ describe('derive-state-db', async () => {
|
|
|
544
557
|
invalidateStateCache();
|
|
545
558
|
const dbState = await deriveStateFromDb(base);
|
|
546
559
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
560
|
+
assertEq(dbState.phase, 'complete', 'complete-db: phase is complete');
|
|
561
|
+
assertEq(dbState.phase, fileState.phase, 'complete-db: phase matches filesystem');
|
|
562
|
+
assertEq(dbState.registry.length, 1, 'complete-db: registry has 1 entry');
|
|
563
|
+
assertEq(dbState.registry[0]?.status, 'complete', 'complete-db: M001 is complete');
|
|
551
564
|
|
|
552
565
|
closeDatabase();
|
|
553
566
|
} finally {
|
|
554
567
|
closeDatabase();
|
|
555
568
|
cleanup(base);
|
|
556
569
|
}
|
|
557
|
-
}
|
|
570
|
+
}
|
|
558
571
|
|
|
559
572
|
// ─── Test 12: Blocked — slice deps unmet ──────────────────────────────
|
|
560
|
-
|
|
573
|
+
console.log('\n=== derive-state-db: blocked slice via DB ===');
|
|
574
|
+
{
|
|
561
575
|
const base = createFixtureBase();
|
|
562
576
|
try {
|
|
563
577
|
// Roadmap with S02 depending on S01, but S01 not done
|
|
@@ -587,19 +601,20 @@ describe('derive-state-db', async () => {
|
|
|
587
601
|
invalidateStateCache();
|
|
588
602
|
const dbState = await deriveStateFromDb(base);
|
|
589
603
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
604
|
+
assertEq(dbState.phase, 'blocked', 'blocked-db: phase is blocked');
|
|
605
|
+
assertEq(dbState.phase, fileState.phase, 'blocked-db: phase matches filesystem');
|
|
606
|
+
assertTrue(dbState.blockers.length > 0, 'blocked-db: has blockers');
|
|
593
607
|
|
|
594
608
|
closeDatabase();
|
|
595
609
|
} finally {
|
|
596
610
|
closeDatabase();
|
|
597
611
|
cleanup(base);
|
|
598
612
|
}
|
|
599
|
-
}
|
|
613
|
+
}
|
|
600
614
|
|
|
601
615
|
// ─── Test 13: Parked milestone ────────────────────────────────────────
|
|
602
|
-
|
|
616
|
+
console.log('\n=== derive-state-db: parked milestone via DB ===');
|
|
617
|
+
{
|
|
603
618
|
const base = createFixtureBase();
|
|
604
619
|
try {
|
|
605
620
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_CONTENT);
|
|
@@ -616,19 +631,20 @@ describe('derive-state-db', async () => {
|
|
|
616
631
|
invalidateStateCache();
|
|
617
632
|
const dbState = await deriveStateFromDb(base);
|
|
618
633
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
634
|
+
assertEq(dbState.phase, fileState.phase, 'parked-db: phase matches filesystem');
|
|
635
|
+
assertEq(dbState.activeMilestone?.id, 'M002', 'parked-db: activeMilestone is M002');
|
|
636
|
+
assertTrue(dbState.registry.some(e => e.id === 'M001' && e.status === 'parked'), 'parked-db: M001 is parked in registry');
|
|
622
637
|
|
|
623
638
|
closeDatabase();
|
|
624
639
|
} finally {
|
|
625
640
|
closeDatabase();
|
|
626
641
|
cleanup(base);
|
|
627
642
|
}
|
|
628
|
-
}
|
|
643
|
+
}
|
|
629
644
|
|
|
630
645
|
// ─── Test 14: Validating-milestone — all slices done, no terminal validation ─
|
|
631
|
-
|
|
646
|
+
console.log('\n=== derive-state-db: validating-milestone via DB ===');
|
|
647
|
+
{
|
|
632
648
|
const base = createFixtureBase();
|
|
633
649
|
try {
|
|
634
650
|
const doneRoadmap = `# M001: Validate Test
|
|
@@ -653,19 +669,20 @@ describe('derive-state-db', async () => {
|
|
|
653
669
|
invalidateStateCache();
|
|
654
670
|
const dbState = await deriveStateFromDb(base);
|
|
655
671
|
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
672
|
+
assertEq(dbState.phase, 'validating-milestone', 'validate-db: phase is validating-milestone');
|
|
673
|
+
assertEq(dbState.phase, fileState.phase, 'validate-db: phase matches filesystem');
|
|
674
|
+
assertEq(dbState.activeMilestone?.id, 'M001', 'validate-db: activeMilestone is M001');
|
|
659
675
|
|
|
660
676
|
closeDatabase();
|
|
661
677
|
} finally {
|
|
662
678
|
closeDatabase();
|
|
663
679
|
cleanup(base);
|
|
664
680
|
}
|
|
665
|
-
}
|
|
681
|
+
}
|
|
666
682
|
|
|
667
683
|
// ─── Test 15: Completing-milestone — terminal validation, no summary ──
|
|
668
|
-
|
|
684
|
+
console.log('\n=== derive-state-db: completing-milestone via DB ===');
|
|
685
|
+
{
|
|
669
686
|
const base = createFixtureBase();
|
|
670
687
|
try {
|
|
671
688
|
const doneRoadmap = `# M001: Complete Test
|
|
@@ -690,18 +707,19 @@ describe('derive-state-db', async () => {
|
|
|
690
707
|
invalidateStateCache();
|
|
691
708
|
const dbState = await deriveStateFromDb(base);
|
|
692
709
|
|
|
693
|
-
|
|
694
|
-
|
|
710
|
+
assertEq(dbState.phase, 'completing-milestone', 'completing-db: phase is completing-milestone');
|
|
711
|
+
assertEq(dbState.phase, fileState.phase, 'completing-db: phase matches filesystem');
|
|
695
712
|
|
|
696
713
|
closeDatabase();
|
|
697
714
|
} finally {
|
|
698
715
|
closeDatabase();
|
|
699
716
|
cleanup(base);
|
|
700
717
|
}
|
|
701
|
-
}
|
|
718
|
+
}
|
|
702
719
|
|
|
703
720
|
// ─── Test 16: Replanning-slice — REPLAN-TRIGGER file exists ───────────
|
|
704
|
-
|
|
721
|
+
console.log('\n=== derive-state-db: replanning-slice via DB ===');
|
|
722
|
+
{
|
|
705
723
|
const base = createFixtureBase();
|
|
706
724
|
try {
|
|
707
725
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_CONTENT);
|
|
@@ -731,18 +749,19 @@ describe('derive-state-db', async () => {
|
|
|
731
749
|
invalidateStateCache();
|
|
732
750
|
const dbState = await deriveStateFromDb(base);
|
|
733
751
|
|
|
734
|
-
|
|
735
|
-
|
|
752
|
+
assertEq(dbState.phase, 'replanning-slice', 'replan-db: phase is replanning-slice');
|
|
753
|
+
assertEq(dbState.phase, fileState.phase, 'replan-db: phase matches filesystem');
|
|
736
754
|
|
|
737
755
|
closeDatabase();
|
|
738
756
|
} finally {
|
|
739
757
|
closeDatabase();
|
|
740
758
|
cleanup(base);
|
|
741
759
|
}
|
|
742
|
-
}
|
|
760
|
+
}
|
|
743
761
|
|
|
744
762
|
// ─── Test 17: Performance — deriveStateFromDb < 1ms on populated DB ───
|
|
745
|
-
|
|
763
|
+
console.log('\n=== derive-state-db: performance assertion ===');
|
|
764
|
+
{
|
|
746
765
|
const base = createFixtureBase();
|
|
747
766
|
try {
|
|
748
767
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_CONTENT);
|
|
@@ -770,17 +789,18 @@ describe('derive-state-db', async () => {
|
|
|
770
789
|
console.log(` deriveStateFromDb() took ${elapsed.toFixed(3)}ms`);
|
|
771
790
|
// Use 10ms threshold — catches real regressions without flaking on
|
|
772
791
|
// CI runners under load (1ms threshold failed at 1.050ms on GitHub Actions)
|
|
773
|
-
|
|
792
|
+
assertTrue(elapsed < 10, `perf-db: deriveStateFromDb() <10ms (got ${elapsed.toFixed(3)}ms)`);
|
|
774
793
|
|
|
775
794
|
closeDatabase();
|
|
776
795
|
} finally {
|
|
777
796
|
closeDatabase();
|
|
778
797
|
cleanup(base);
|
|
779
798
|
}
|
|
780
|
-
}
|
|
799
|
+
}
|
|
781
800
|
|
|
782
801
|
// ─── Test 18: Multi-milestone with deps — M001 complete, M002 depends on M001, M003 depends on M002 ─
|
|
783
|
-
|
|
802
|
+
console.log('\n=== derive-state-db: multi-milestone deps via DB ===');
|
|
803
|
+
{
|
|
784
804
|
const base = createFixtureBase();
|
|
785
805
|
try {
|
|
786
806
|
const m1Roadmap = `# M001: First
|
|
@@ -821,28 +841,29 @@ describe('derive-state-db', async () => {
|
|
|
821
841
|
invalidateStateCache();
|
|
822
842
|
const dbState = await deriveStateFromDb(base);
|
|
823
843
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
844
|
+
assertEq(dbState.registry.length, fileState.registry.length, 'multi-deps-db: registry length matches');
|
|
845
|
+
assertEq(dbState.activeMilestone?.id, 'M002', 'multi-deps-db: activeMilestone is M002 (M001 complete, M003 dep unmet)');
|
|
846
|
+
assertEq(dbState.activeMilestone?.id, fileState.activeMilestone?.id, 'multi-deps-db: activeMilestone matches filesystem');
|
|
847
|
+
assertEq(dbState.phase, fileState.phase, 'multi-deps-db: phase matches filesystem');
|
|
828
848
|
|
|
829
849
|
// Check registry statuses
|
|
830
850
|
const m1reg = dbState.registry.find(e => e.id === 'M001');
|
|
831
851
|
const m2reg = dbState.registry.find(e => e.id === 'M002');
|
|
832
852
|
const m3reg = dbState.registry.find(e => e.id === 'M003');
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
853
|
+
assertEq(m1reg?.status, 'complete', 'multi-deps-db: M001 is complete');
|
|
854
|
+
assertEq(m2reg?.status, 'active', 'multi-deps-db: M002 is active');
|
|
855
|
+
assertEq(m3reg?.status, 'pending', 'multi-deps-db: M003 is pending (dep M002 unmet)');
|
|
836
856
|
|
|
837
857
|
closeDatabase();
|
|
838
858
|
} finally {
|
|
839
859
|
closeDatabase();
|
|
840
860
|
cleanup(base);
|
|
841
861
|
}
|
|
842
|
-
}
|
|
862
|
+
}
|
|
843
863
|
|
|
844
864
|
// ─── Test 19: K002 — both 'complete' and 'done' treated as done ───────
|
|
845
|
-
|
|
865
|
+
console.log('\n=== derive-state-db: K002 status handling ===');
|
|
866
|
+
{
|
|
846
867
|
const base = createFixtureBase();
|
|
847
868
|
try {
|
|
848
869
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_CONTENT);
|
|
@@ -861,19 +882,20 @@ describe('derive-state-db', async () => {
|
|
|
861
882
|
invalidateStateCache();
|
|
862
883
|
const dbState = await deriveStateFromDb(base);
|
|
863
884
|
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
885
|
+
assertEq(dbState.phase, 'executing', 'k002-db: phase is executing');
|
|
886
|
+
assertEq(dbState.activeTask?.id, 'T01', 'k002-db: activeTask is T01 (T02 done)');
|
|
887
|
+
assertEq(dbState.progress?.tasks?.done, 1, 'k002-db: tasks.done counts done status');
|
|
867
888
|
|
|
868
889
|
closeDatabase();
|
|
869
890
|
} finally {
|
|
870
891
|
closeDatabase();
|
|
871
892
|
cleanup(base);
|
|
872
893
|
}
|
|
873
|
-
}
|
|
894
|
+
}
|
|
874
895
|
|
|
875
896
|
// ─── Test 20: Dual-path wiring — deriveState() uses DB when populated ─
|
|
876
|
-
|
|
897
|
+
console.log('\n=== derive-state-db: dual-path wiring ===');
|
|
898
|
+
{
|
|
877
899
|
const base = createFixtureBase();
|
|
878
900
|
try {
|
|
879
901
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_CONTENT);
|
|
@@ -892,20 +914,21 @@ describe('derive-state-db', async () => {
|
|
|
892
914
|
invalidateStateCache();
|
|
893
915
|
const state = await deriveState(base);
|
|
894
916
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
917
|
+
assertEq(state.phase, 'executing', 'dual-path: phase is executing');
|
|
918
|
+
assertEq(state.activeMilestone?.id, 'M001', 'dual-path: activeMilestone is M001');
|
|
919
|
+
assertEq(state.activeSlice?.id, 'S01', 'dual-path: activeSlice is S01');
|
|
920
|
+
assertEq(state.activeTask?.id, 'T01', 'dual-path: activeTask is T01');
|
|
899
921
|
|
|
900
922
|
closeDatabase();
|
|
901
923
|
} finally {
|
|
902
924
|
closeDatabase();
|
|
903
925
|
cleanup(base);
|
|
904
926
|
}
|
|
905
|
-
}
|
|
927
|
+
}
|
|
906
928
|
|
|
907
929
|
// ─── Test 21: Ghost milestone skipped ─────────────────────────────────
|
|
908
|
-
|
|
930
|
+
console.log('\n=== derive-state-db: ghost milestone skipped ===');
|
|
931
|
+
{
|
|
909
932
|
const base = createFixtureBase();
|
|
910
933
|
try {
|
|
911
934
|
// Ghost: milestone dir exists with only META.json, no context/roadmap/summary
|
|
@@ -926,20 +949,21 @@ describe('derive-state-db', async () => {
|
|
|
926
949
|
const dbState = await deriveStateFromDb(base);
|
|
927
950
|
|
|
928
951
|
// Ghost should be skipped — M002 should be active
|
|
929
|
-
|
|
930
|
-
|
|
952
|
+
assertEq(dbState.activeMilestone?.id, 'M002', 'ghost-db: activeMilestone is M002 (ghost skipped)');
|
|
953
|
+
assertEq(dbState.activeMilestone?.id, fileState.activeMilestone?.id, 'ghost-db: matches filesystem');
|
|
931
954
|
// Ghost should not appear in registry
|
|
932
|
-
|
|
955
|
+
assertTrue(!dbState.registry.some(e => e.id === 'M001'), 'ghost-db: M001 not in registry');
|
|
933
956
|
|
|
934
957
|
closeDatabase();
|
|
935
958
|
} finally {
|
|
936
959
|
closeDatabase();
|
|
937
960
|
cleanup(base);
|
|
938
961
|
}
|
|
939
|
-
}
|
|
962
|
+
}
|
|
940
963
|
|
|
941
964
|
// ─── Test 22: Needs-discussion — CONTEXT-DRAFT exists ─────────────────
|
|
942
|
-
|
|
965
|
+
console.log('\n=== derive-state-db: needs-discussion via DB ===');
|
|
966
|
+
{
|
|
943
967
|
const base = createFixtureBase();
|
|
944
968
|
try {
|
|
945
969
|
writeFile(base, 'milestones/M001/M001-CONTEXT-DRAFT.md', '# M001: Draft\n\nDraft content.');
|
|
@@ -953,13 +977,20 @@ describe('derive-state-db', async () => {
|
|
|
953
977
|
invalidateStateCache();
|
|
954
978
|
const dbState = await deriveStateFromDb(base);
|
|
955
979
|
|
|
956
|
-
|
|
957
|
-
|
|
980
|
+
assertEq(dbState.phase, 'needs-discussion', 'discuss-db: phase is needs-discussion');
|
|
981
|
+
assertEq(dbState.phase, fileState.phase, 'discuss-db: phase matches filesystem');
|
|
958
982
|
|
|
959
983
|
closeDatabase();
|
|
960
984
|
} finally {
|
|
961
985
|
closeDatabase();
|
|
962
986
|
cleanup(base);
|
|
963
987
|
}
|
|
964
|
-
}
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
report();
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
main().catch((error) => {
|
|
994
|
+
console.error(error);
|
|
995
|
+
process.exit(1);
|
|
965
996
|
});
|