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
|
@@ -19,8 +19,9 @@ import {
|
|
|
19
19
|
formatDecisionsForPrompt,
|
|
20
20
|
formatRequirementsForPrompt,
|
|
21
21
|
} from '../context-store.ts';
|
|
22
|
-
import {
|
|
23
|
-
|
|
22
|
+
import { createTestContext } from './test-helpers.ts';
|
|
23
|
+
|
|
24
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
24
25
|
|
|
25
26
|
// ─── Fixture Helper ────────────────────────────────────────────────────────
|
|
26
27
|
|
|
@@ -47,7 +48,8 @@ function generateDecisionsMarkdown(count: number): string {
|
|
|
47
48
|
// Edge Case 1: Empty Project
|
|
48
49
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
console.log('\n=== integration-edge: empty project ===');
|
|
52
|
+
{
|
|
51
53
|
const base = mkdtempSync(join(tmpdir(), 'gsd-int-edge-empty-'));
|
|
52
54
|
const gsdDir = join(base, '.gsd');
|
|
53
55
|
mkdirSync(gsdDir, { recursive: true });
|
|
@@ -57,54 +59,55 @@ test('integration-edge: empty project', () => {
|
|
|
57
59
|
try {
|
|
58
60
|
// Open DB first so migrateFromMarkdown doesn't auto-create at default path
|
|
59
61
|
openDatabase(dbPath);
|
|
60
|
-
|
|
62
|
+
assertTrue(isDbAvailable(), 'empty: DB available after open');
|
|
61
63
|
|
|
62
64
|
// Migrate with no markdown files on disk
|
|
63
65
|
const result = migrateFromMarkdown(base);
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
assertEq(result.decisions, 0, 'empty: 0 decisions imported');
|
|
68
|
+
assertEq(result.requirements, 0, 'empty: 0 requirements imported');
|
|
69
|
+
assertEq(result.artifacts, 0, 'empty: 0 artifacts imported');
|
|
68
70
|
|
|
69
71
|
// Query decisions → empty array
|
|
70
72
|
const decisions = queryDecisions();
|
|
71
|
-
|
|
73
|
+
assertEq(decisions.length, 0, 'empty: queryDecisions returns empty array');
|
|
72
74
|
|
|
73
75
|
// Query requirements → empty array
|
|
74
76
|
const requirements = queryRequirements();
|
|
75
|
-
|
|
77
|
+
assertEq(requirements.length, 0, 'empty: queryRequirements returns empty array');
|
|
76
78
|
|
|
77
79
|
// Query with scope filters → still empty, no crash
|
|
78
80
|
const scopedDecisions = queryDecisions({ milestoneId: 'M001' });
|
|
79
|
-
|
|
81
|
+
assertEq(scopedDecisions.length, 0, 'empty: scoped queryDecisions returns empty');
|
|
80
82
|
|
|
81
83
|
const scopedRequirements = queryRequirements({ sliceId: 'S01' });
|
|
82
|
-
|
|
84
|
+
assertEq(scopedRequirements.length, 0, 'empty: scoped queryRequirements returns empty');
|
|
83
85
|
|
|
84
86
|
// Format empty results → empty strings
|
|
85
87
|
const formattedD = formatDecisionsForPrompt([]);
|
|
86
88
|
const formattedR = formatRequirementsForPrompt([]);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
assertEq(formattedD, '', 'empty: formatDecisionsForPrompt returns empty string');
|
|
90
|
+
assertEq(formattedR, '', 'empty: formatRequirementsForPrompt returns empty string');
|
|
89
91
|
|
|
90
92
|
// Format with actual empty query results
|
|
91
93
|
const formattedD2 = formatDecisionsForPrompt(decisions);
|
|
92
94
|
const formattedR2 = formatRequirementsForPrompt(requirements);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
assertEq(formattedD2, '', 'empty: format of empty query decisions is empty string');
|
|
96
|
+
assertEq(formattedR2, '', 'empty: format of empty query requirements is empty string');
|
|
95
97
|
|
|
96
98
|
closeDatabase();
|
|
97
99
|
} finally {
|
|
98
100
|
closeDatabase();
|
|
99
101
|
rmSync(base, { recursive: true, force: true });
|
|
100
102
|
}
|
|
101
|
-
}
|
|
103
|
+
}
|
|
102
104
|
|
|
103
105
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
104
106
|
// Edge Case 2: Partial Migration (decisions only, no requirements)
|
|
105
107
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
106
108
|
|
|
107
|
-
|
|
109
|
+
console.log('\n=== integration-edge: partial migration ===');
|
|
110
|
+
{
|
|
108
111
|
const base = mkdtempSync(join(tmpdir(), 'gsd-int-edge-partial-'));
|
|
109
112
|
const gsdDir = join(base, '.gsd');
|
|
110
113
|
mkdirSync(gsdDir, { recursive: true });
|
|
@@ -117,48 +120,49 @@ test('integration-edge: partial migration', () => {
|
|
|
117
120
|
|
|
118
121
|
try {
|
|
119
122
|
openDatabase(dbPath);
|
|
120
|
-
|
|
123
|
+
assertTrue(isDbAvailable(), 'partial: DB available after open');
|
|
121
124
|
|
|
122
125
|
const result = migrateFromMarkdown(base);
|
|
123
126
|
|
|
124
127
|
// Decisions imported, requirements skipped gracefully
|
|
125
|
-
|
|
126
|
-
|
|
128
|
+
assertTrue(result.decisions === 6, `partial: imported ${result.decisions} decisions, expected 6`);
|
|
129
|
+
assertEq(result.requirements, 0, 'partial: 0 requirements imported (no file)');
|
|
127
130
|
|
|
128
131
|
// Decisions queryable
|
|
129
132
|
const decisions = queryDecisions();
|
|
130
|
-
|
|
133
|
+
assertTrue(decisions.length === 6, `partial: queryDecisions returns 6 (got ${decisions.length})`);
|
|
131
134
|
|
|
132
135
|
const m001Decisions = queryDecisions({ milestoneId: 'M001' });
|
|
133
|
-
|
|
134
|
-
|
|
136
|
+
assertTrue(m001Decisions.length > 0, 'partial: M001 decisions non-empty');
|
|
137
|
+
assertTrue(m001Decisions.length < decisions.length, 'partial: M001 scope filters correctly');
|
|
135
138
|
|
|
136
139
|
// Requirements return empty — no crash
|
|
137
140
|
const requirements = queryRequirements();
|
|
138
|
-
|
|
141
|
+
assertEq(requirements.length, 0, 'partial: queryRequirements returns empty');
|
|
139
142
|
|
|
140
143
|
const scopedReqs = queryRequirements({ sliceId: 'S01' });
|
|
141
|
-
|
|
144
|
+
assertEq(scopedReqs.length, 0, 'partial: scoped queryRequirements returns empty');
|
|
142
145
|
|
|
143
146
|
// Format works on partial data
|
|
144
147
|
const formattedD = formatDecisionsForPrompt(m001Decisions);
|
|
145
|
-
|
|
148
|
+
assertTrue(formattedD.length > 0, 'partial: formatted decisions non-empty');
|
|
146
149
|
|
|
147
150
|
const formattedR = formatRequirementsForPrompt(requirements);
|
|
148
|
-
|
|
151
|
+
assertEq(formattedR, '', 'partial: formatted empty requirements is empty string');
|
|
149
152
|
|
|
150
153
|
closeDatabase();
|
|
151
154
|
} finally {
|
|
152
155
|
closeDatabase();
|
|
153
156
|
rmSync(base, { recursive: true, force: true });
|
|
154
157
|
}
|
|
155
|
-
}
|
|
158
|
+
}
|
|
156
159
|
|
|
157
160
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
158
161
|
// Edge Case 3: Fallback Mode (_resetProvider)
|
|
159
162
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
160
163
|
|
|
161
|
-
|
|
164
|
+
console.log('\n=== integration-edge: fallback mode ===');
|
|
165
|
+
{
|
|
162
166
|
const base = mkdtempSync(join(tmpdir(), 'gsd-int-edge-fallback-'));
|
|
163
167
|
const gsdDir = join(base, '.gsd');
|
|
164
168
|
mkdirSync(gsdDir, { recursive: true });
|
|
@@ -171,53 +175,54 @@ test('integration-edge: fallback mode', () => {
|
|
|
171
175
|
try {
|
|
172
176
|
// Step 1: Open DB normally and verify it works
|
|
173
177
|
openDatabase(dbPath);
|
|
174
|
-
|
|
178
|
+
assertTrue(isDbAvailable(), 'fallback: DB available after open');
|
|
175
179
|
|
|
176
180
|
migrateFromMarkdown(base);
|
|
177
181
|
const before = queryDecisions();
|
|
178
|
-
|
|
182
|
+
assertTrue(before.length === 4, `fallback: 4 decisions before reset (got ${before.length})`);
|
|
179
183
|
|
|
180
184
|
// Step 2: Close and reset provider → DB unavailable
|
|
181
185
|
closeDatabase();
|
|
182
186
|
_resetProvider();
|
|
183
|
-
|
|
187
|
+
assertTrue(!isDbAvailable(), 'fallback: DB unavailable after _resetProvider');
|
|
184
188
|
|
|
185
189
|
// Step 3: Queries degrade gracefully (return empty, don't throw)
|
|
186
190
|
const degradedDecisions = queryDecisions();
|
|
187
|
-
|
|
191
|
+
assertEq(degradedDecisions.length, 0, 'fallback: queryDecisions returns empty when unavailable');
|
|
188
192
|
|
|
189
193
|
const degradedRequirements = queryRequirements();
|
|
190
|
-
|
|
194
|
+
assertEq(degradedRequirements.length, 0, 'fallback: queryRequirements returns empty when unavailable');
|
|
191
195
|
|
|
192
196
|
const degradedScopedD = queryDecisions({ milestoneId: 'M001' });
|
|
193
|
-
|
|
197
|
+
assertEq(degradedScopedD.length, 0, 'fallback: scoped queryDecisions returns empty when unavailable');
|
|
194
198
|
|
|
195
199
|
const degradedScopedR = queryRequirements({ sliceId: 'S01' });
|
|
196
|
-
|
|
200
|
+
assertEq(degradedScopedR.length, 0, 'fallback: scoped queryRequirements returns empty when unavailable');
|
|
197
201
|
|
|
198
202
|
// Format functions work on empty arrays (no crash)
|
|
199
203
|
const formattedD = formatDecisionsForPrompt(degradedDecisions);
|
|
200
|
-
|
|
204
|
+
assertEq(formattedD, '', 'fallback: format degraded decisions is empty');
|
|
201
205
|
|
|
202
206
|
const formattedR = formatRequirementsForPrompt(degradedRequirements);
|
|
203
|
-
|
|
207
|
+
assertEq(formattedR, '', 'fallback: format degraded requirements is empty');
|
|
204
208
|
|
|
205
209
|
// Step 4: Re-open DB → restores availability
|
|
206
210
|
openDatabase(dbPath);
|
|
207
|
-
|
|
211
|
+
assertTrue(isDbAvailable(), 'fallback: DB available after re-open');
|
|
208
212
|
|
|
209
213
|
// Data should be there from the file-backed DB (persisted by first open)
|
|
210
214
|
// But rows may need re-import since the DB was freshly opened from the file
|
|
211
215
|
migrateFromMarkdown(base);
|
|
212
216
|
const restored = queryDecisions();
|
|
213
|
-
|
|
217
|
+
assertTrue(restored.length === 4, `fallback: 4 decisions after re-open (got ${restored.length})`);
|
|
214
218
|
|
|
215
219
|
closeDatabase();
|
|
216
220
|
} finally {
|
|
217
221
|
closeDatabase();
|
|
218
222
|
rmSync(base, { recursive: true, force: true });
|
|
219
223
|
}
|
|
220
|
-
}
|
|
224
|
+
}
|
|
221
225
|
|
|
222
226
|
// ─── Report ────────────────────────────────────────────────────────────────
|
|
223
227
|
|
|
228
|
+
report();
|
|
@@ -21,8 +21,9 @@ import {
|
|
|
21
21
|
formatRequirementsForPrompt,
|
|
22
22
|
} from '../context-store.ts';
|
|
23
23
|
import { saveDecisionToDb, generateDecisionsMd } from '../db-writer.ts';
|
|
24
|
-
import {
|
|
25
|
-
|
|
24
|
+
import { createTestContext } from './test-helpers.ts';
|
|
25
|
+
|
|
26
|
+
const { assertEq, assertTrue, assertMatch, report } = createTestContext();
|
|
26
27
|
|
|
27
28
|
// ─── Fixture Generators (duplicated from token-savings.test.ts — file-scoped) ──
|
|
28
29
|
|
|
@@ -118,7 +119,10 @@ const ROADMAP_CONTENT = `# M001: Test Milestone\n\n**Vision:** Integration test
|
|
|
118
119
|
// Full Lifecycle Integration Test
|
|
119
120
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
120
121
|
|
|
121
|
-
|
|
122
|
+
async function main(): Promise<void> {
|
|
123
|
+
|
|
124
|
+
console.log('\n=== integration-lifecycle: full pipeline ===');
|
|
125
|
+
{
|
|
122
126
|
// ── Step 1: Set up temp dir with realistic .gsd/ structure ──────────
|
|
123
127
|
const base = mkdtempSync(join(tmpdir(), 'gsd-int-lifecycle-'));
|
|
124
128
|
const gsdDir = join(base, '.gsd');
|
|
@@ -138,37 +142,37 @@ test('integration-lifecycle: full pipeline', async () => {
|
|
|
138
142
|
try {
|
|
139
143
|
// ── Step 2: Open file-backed DB + migrateFromMarkdown ──────────────
|
|
140
144
|
openDatabase(dbPath);
|
|
141
|
-
|
|
145
|
+
assertTrue(isDbAvailable(), 'lifecycle: DB is available after open');
|
|
142
146
|
|
|
143
147
|
const result = migrateFromMarkdown(base);
|
|
144
148
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
149
|
+
assertTrue(result.decisions === DECISIONS_COUNT, `lifecycle: imported ${result.decisions} decisions, expected ${DECISIONS_COUNT}`);
|
|
150
|
+
assertTrue(result.requirements === REQUIREMENTS_COUNT, `lifecycle: imported ${result.requirements} requirements, expected ${REQUIREMENTS_COUNT}`);
|
|
151
|
+
assertTrue(result.artifacts >= 1, `lifecycle: imported at least 1 artifact (got ${result.artifacts})`);
|
|
148
152
|
|
|
149
153
|
// Verify file-backed DB uses WAL
|
|
150
154
|
const adapter = _getAdapter()!;
|
|
151
155
|
const mode = adapter.prepare('PRAGMA journal_mode').get();
|
|
152
|
-
|
|
156
|
+
assertEq(mode?.['journal_mode'], 'wal', 'lifecycle: file-backed DB uses WAL mode');
|
|
153
157
|
|
|
154
158
|
// ── Step 3: Scoped queries — decisions by milestone ────────────────
|
|
155
159
|
const allDecisions = queryDecisions();
|
|
156
160
|
const m001Decisions = queryDecisions({ milestoneId: 'M001' });
|
|
157
161
|
const m002Decisions = queryDecisions({ milestoneId: 'M002' });
|
|
158
162
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
assertTrue(allDecisions.length === DECISIONS_COUNT, `lifecycle: all decisions count = ${DECISIONS_COUNT} (got ${allDecisions.length})`);
|
|
164
|
+
assertTrue(m001Decisions.length > 0, 'lifecycle: M001 decisions non-empty');
|
|
165
|
+
assertTrue(m002Decisions.length > 0, 'lifecycle: M002 decisions non-empty');
|
|
166
|
+
assertTrue(m001Decisions.length < allDecisions.length, 'lifecycle: M001 filtered count < total count');
|
|
167
|
+
assertTrue(m002Decisions.length < allDecisions.length, 'lifecycle: M002 filtered count < total count');
|
|
168
|
+
assertEq(m001Decisions.length + m002Decisions.length, allDecisions.length, 'lifecycle: M001 + M002 = total decisions');
|
|
165
169
|
|
|
166
170
|
// Verify scoping correctness
|
|
167
171
|
for (const d of m001Decisions) {
|
|
168
|
-
|
|
172
|
+
assertTrue(d.when_context.includes('M001'), `lifecycle: M001 decision ${d.id} has M001 in when_context`);
|
|
169
173
|
}
|
|
170
174
|
for (const d of m002Decisions) {
|
|
171
|
-
|
|
175
|
+
assertTrue(d.when_context.includes('M002'), `lifecycle: M002 decision ${d.id} has M002 in when_context`);
|
|
172
176
|
}
|
|
173
177
|
|
|
174
178
|
// ── Step 4: Scoped queries — requirements by slice ─────────────────
|
|
@@ -176,19 +180,19 @@ test('integration-lifecycle: full pipeline', async () => {
|
|
|
176
180
|
const s01Requirements = queryRequirements({ sliceId: 'S01' });
|
|
177
181
|
const s04Requirements = queryRequirements({ sliceId: 'S04' });
|
|
178
182
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
+
assertTrue(allRequirements.length === REQUIREMENTS_COUNT, `lifecycle: all requirements count = ${REQUIREMENTS_COUNT} (got ${allRequirements.length})`);
|
|
184
|
+
assertTrue(s01Requirements.length > 0, 'lifecycle: S01 requirements non-empty');
|
|
185
|
+
assertTrue(s04Requirements.length > 0, 'lifecycle: S04 requirements non-empty');
|
|
186
|
+
assertTrue(s01Requirements.length < allRequirements.length, 'lifecycle: S01 filtered count < total count');
|
|
183
187
|
|
|
184
188
|
// ── Step 5: Format + token savings validation ──────────────────────
|
|
185
189
|
const formattedDecisions = formatDecisionsForPrompt(m001Decisions);
|
|
186
190
|
const formattedRequirements = formatRequirementsForPrompt(s01Requirements);
|
|
187
191
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
+
assertTrue(formattedDecisions.length > 0, 'lifecycle: formatted M001 decisions non-empty');
|
|
193
|
+
assertTrue(formattedRequirements.length > 0, 'lifecycle: formatted S01 requirements non-empty');
|
|
194
|
+
assertMatch(formattedDecisions, /\| D/, 'lifecycle: formatted decisions contains decision rows');
|
|
195
|
+
assertMatch(formattedRequirements, /### R\d+/, 'lifecycle: formatted requirements has headings');
|
|
192
196
|
|
|
193
197
|
// Token savings: scoped output vs full file content
|
|
194
198
|
const fullDecisionsContent = readFileSync(join(gsdDir, 'DECISIONS.md'), 'utf-8');
|
|
@@ -199,24 +203,24 @@ test('integration-lifecycle: full pipeline', async () => {
|
|
|
199
203
|
|
|
200
204
|
console.log(` Token savings: ${savingsPercent.toFixed(1)}% (scoped: ${dbScopedTotal}, full: ${fullTotal})`);
|
|
201
205
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
206
|
+
assertTrue(dbScopedTotal > 0, 'lifecycle: scoped content non-empty');
|
|
207
|
+
assertTrue(dbScopedTotal < fullTotal, 'lifecycle: scoped content smaller than full content');
|
|
208
|
+
assertTrue(savingsPercent >= 30, `lifecycle: savings ≥30% (actual: ${savingsPercent.toFixed(1)}%)`);
|
|
205
209
|
|
|
206
210
|
// ── Step 6: Simulate content change → re-import ────────────────────
|
|
207
211
|
const newDecisionRow = `| D${DECISIONS_COUNT + 1} | M001/S01 | testing | new decision added after initial import | choice X | rationale Y | yes |`;
|
|
208
212
|
appendFileSync(join(gsdDir, 'DECISIONS.md'), '\n' + newDecisionRow + '\n');
|
|
209
213
|
|
|
210
214
|
const result2 = migrateFromMarkdown(base);
|
|
211
|
-
|
|
215
|
+
assertTrue(result2.decisions === DECISIONS_COUNT + 1, `lifecycle: re-import got ${result2.decisions} decisions, expected ${DECISIONS_COUNT + 1}`);
|
|
212
216
|
|
|
213
217
|
const afterReimport = queryDecisions();
|
|
214
|
-
|
|
218
|
+
assertTrue(afterReimport.length === DECISIONS_COUNT + 1, `lifecycle: DB has ${DECISIONS_COUNT + 1} decisions after re-import (got ${afterReimport.length})`);
|
|
215
219
|
|
|
216
220
|
// Verify the new decision is queryable
|
|
217
221
|
const newM001 = queryDecisions({ milestoneId: 'M001' });
|
|
218
222
|
const foundNew = newM001.some(d => d.id === `D${DECISIONS_COUNT + 1}`);
|
|
219
|
-
|
|
223
|
+
assertTrue(foundNew, `lifecycle: newly imported D${DECISIONS_COUNT + 1} found in M001 scope`);
|
|
220
224
|
|
|
221
225
|
// ── Step 7: saveDecisionToDb write-back + round-trip ───────────────
|
|
222
226
|
const saved = await saveDecisionToDb(
|
|
@@ -230,37 +234,44 @@ test('integration-lifecycle: full pipeline', async () => {
|
|
|
230
234
|
base,
|
|
231
235
|
);
|
|
232
236
|
|
|
233
|
-
|
|
234
|
-
|
|
237
|
+
assertTrue(typeof saved.id === 'string', 'lifecycle: saveDecisionToDb returned an id');
|
|
238
|
+
assertMatch(saved.id, /^D\d+$/, 'lifecycle: saved ID matches D### pattern');
|
|
235
239
|
|
|
236
240
|
// Query back from DB
|
|
237
241
|
const allAfterSave = queryDecisions();
|
|
238
242
|
const savedDecision = allAfterSave.find(d => d.id === saved.id);
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
243
|
+
assertTrue(savedDecision !== null && savedDecision !== undefined, `lifecycle: saved decision ${saved.id} found in DB`);
|
|
244
|
+
assertEq(savedDecision?.decision, 'integration test write-back decision', 'lifecycle: saved decision text matches');
|
|
245
|
+
assertEq(savedDecision?.choice, 'option Z', 'lifecycle: saved choice matches');
|
|
242
246
|
|
|
243
247
|
// Verify DECISIONS.md was regenerated with the new decision
|
|
244
248
|
const regeneratedMd = readFileSync(join(gsdDir, 'DECISIONS.md'), 'utf-8');
|
|
245
|
-
|
|
246
|
-
|
|
249
|
+
assertTrue(regeneratedMd.includes(saved.id), `lifecycle: regenerated DECISIONS.md contains ${saved.id}`);
|
|
250
|
+
assertTrue(regeneratedMd.includes('integration test write-back decision'), 'lifecycle: regenerated md contains write-back text');
|
|
247
251
|
|
|
248
252
|
// Round-trip: parse regenerated markdown back → verify field fidelity
|
|
249
253
|
const reparsed = parseDecisionsTable(regeneratedMd);
|
|
250
254
|
const reparsedSaved = reparsed.find(d => d.id === saved.id);
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
255
|
+
assertTrue(reparsedSaved !== undefined, `lifecycle: reparsed markdown contains ${saved.id}`);
|
|
256
|
+
assertEq(reparsedSaved?.choice, 'option Z', 'lifecycle: round-trip choice preserved');
|
|
257
|
+
assertEq(reparsedSaved?.rationale, 'proves round-trip fidelity', 'lifecycle: round-trip rationale preserved');
|
|
254
258
|
|
|
255
259
|
// ── Step 8: DB consistency — total count sanity ─────────────────────
|
|
256
260
|
const finalCount = queryDecisions().length;
|
|
257
261
|
// Original 14 + 1 re-import + 1 saveDecisionToDb = 16
|
|
258
|
-
|
|
262
|
+
assertTrue(finalCount === DECISIONS_COUNT + 2, `lifecycle: final DB count = ${DECISIONS_COUNT + 2} (got ${finalCount})`);
|
|
259
263
|
|
|
260
264
|
closeDatabase();
|
|
261
265
|
} finally {
|
|
262
266
|
closeDatabase();
|
|
263
267
|
rmSync(base, { recursive: true, force: true });
|
|
264
268
|
}
|
|
265
|
-
}
|
|
269
|
+
}
|
|
266
270
|
|
|
271
|
+
report();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
main().catch((error) => {
|
|
275
|
+
console.error(error);
|
|
276
|
+
process.exit(1);
|
|
277
|
+
});
|