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
|
/**
|
|
4
2
|
* flag-file-db.test.ts — Verify that REPLAN.md and REPLAN-TRIGGER.md
|
|
5
3
|
* flag-file detection in deriveStateFromDb() works from DB-only data
|
|
@@ -26,6 +24,10 @@ import {
|
|
|
26
24
|
insertReplanHistory,
|
|
27
25
|
_getAdapter,
|
|
28
26
|
} from '../gsd-db.ts';
|
|
27
|
+
import { createTestContext } from './test-helpers.ts';
|
|
28
|
+
|
|
29
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
30
|
+
|
|
29
31
|
// ─── Fixture Helpers ───────────────────────────────────────────────────────
|
|
30
32
|
|
|
31
33
|
function createFixtureBase(): string {
|
|
@@ -76,10 +78,11 @@ const TASK_SUMMARY_STUB = `---\nblocker_discovered: false\n---\n# T01 Summary\nD
|
|
|
76
78
|
// Tests
|
|
77
79
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
78
80
|
|
|
79
|
-
|
|
81
|
+
async function main(): Promise<void> {
|
|
80
82
|
|
|
81
83
|
// ─── Test 1: blocker_discovered + no replan_history → replanning-slice ──
|
|
82
|
-
|
|
84
|
+
console.log('\n=== flag-file-db: blocker + no history → replanning ===');
|
|
85
|
+
{
|
|
83
86
|
const base = createFixtureBase();
|
|
84
87
|
try {
|
|
85
88
|
// Write disk files needed by deriveStateFromDb (roadmap check, task dir check)
|
|
@@ -88,7 +91,7 @@ describe('flag-file-db', async () => {
|
|
|
88
91
|
writeFile(base, 'milestones/M001/slices/S01/tasks/T02-PLAN.md', TASK_PLAN_STUB);
|
|
89
92
|
|
|
90
93
|
openDatabase(':memory:');
|
|
91
|
-
|
|
94
|
+
assertTrue(isDbAvailable(), 'test1: DB is available');
|
|
92
95
|
|
|
93
96
|
insertMilestone({ id: 'M001', title: 'Flag-File DB Test', status: 'active' });
|
|
94
97
|
insertSlice({ id: 'S01', milestoneId: 'M001', title: 'Test Slice', status: 'active', risk: 'low', depends: [] });
|
|
@@ -99,19 +102,20 @@ describe('flag-file-db', async () => {
|
|
|
99
102
|
invalidateStateCache();
|
|
100
103
|
const state = await deriveStateFromDb(base);
|
|
101
104
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
+
assertEq(state.phase, 'replanning-slice', 'test1: phase is replanning-slice');
|
|
106
|
+
assertTrue(state.blockers.length > 0, 'test1: has blockers');
|
|
107
|
+
assertTrue(state.blockers[0]?.includes('blocker'), 'test1: blocker message mentions blocker');
|
|
105
108
|
|
|
106
109
|
closeDatabase();
|
|
107
110
|
} finally {
|
|
108
111
|
closeDatabase();
|
|
109
112
|
cleanup(base);
|
|
110
113
|
}
|
|
111
|
-
}
|
|
114
|
+
}
|
|
112
115
|
|
|
113
116
|
// ─── Test 2: blocker_discovered + replan_history exists → loop protection → executing ──
|
|
114
|
-
|
|
117
|
+
console.log('\n=== flag-file-db: blocker + history → loop protection ===');
|
|
118
|
+
{
|
|
115
119
|
const base = createFixtureBase();
|
|
116
120
|
try {
|
|
117
121
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_CONTENT);
|
|
@@ -135,17 +139,18 @@ describe('flag-file-db', async () => {
|
|
|
135
139
|
invalidateStateCache();
|
|
136
140
|
const state = await deriveStateFromDb(base);
|
|
137
141
|
|
|
138
|
-
|
|
142
|
+
assertEq(state.phase, 'executing', 'test2: phase is executing (loop protection)');
|
|
139
143
|
|
|
140
144
|
closeDatabase();
|
|
141
145
|
} finally {
|
|
142
146
|
closeDatabase();
|
|
143
147
|
cleanup(base);
|
|
144
148
|
}
|
|
145
|
-
}
|
|
149
|
+
}
|
|
146
150
|
|
|
147
151
|
// ─── Test 3: replan_triggered_at set + no replan_history → replanning-slice ──
|
|
148
|
-
|
|
152
|
+
console.log('\n=== flag-file-db: trigger column + no history → replanning ===');
|
|
153
|
+
{
|
|
149
154
|
const base = createFixtureBase();
|
|
150
155
|
try {
|
|
151
156
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_CONTENT);
|
|
@@ -168,19 +173,20 @@ describe('flag-file-db', async () => {
|
|
|
168
173
|
invalidateStateCache();
|
|
169
174
|
const state = await deriveStateFromDb(base);
|
|
170
175
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
176
|
+
assertEq(state.phase, 'replanning-slice', 'test3: phase is replanning-slice');
|
|
177
|
+
assertTrue(state.blockers.length > 0, 'test3: has blockers');
|
|
178
|
+
assertTrue(state.blockers[0]?.includes('Triage replan trigger'), 'test3: blocker message mentions triage trigger');
|
|
174
179
|
|
|
175
180
|
closeDatabase();
|
|
176
181
|
} finally {
|
|
177
182
|
closeDatabase();
|
|
178
183
|
cleanup(base);
|
|
179
184
|
}
|
|
180
|
-
}
|
|
185
|
+
}
|
|
181
186
|
|
|
182
187
|
// ─── Test 4: replan_triggered_at set + replan_history exists → loop protection ──
|
|
183
|
-
|
|
188
|
+
console.log('\n=== flag-file-db: trigger column + history → loop protection ===');
|
|
189
|
+
{
|
|
184
190
|
const base = createFixtureBase();
|
|
185
191
|
try {
|
|
186
192
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_CONTENT);
|
|
@@ -210,17 +216,18 @@ describe('flag-file-db', async () => {
|
|
|
210
216
|
invalidateStateCache();
|
|
211
217
|
const state = await deriveStateFromDb(base);
|
|
212
218
|
|
|
213
|
-
|
|
219
|
+
assertEq(state.phase, 'executing', 'test4: phase is executing (loop protection)');
|
|
214
220
|
|
|
215
221
|
closeDatabase();
|
|
216
222
|
} finally {
|
|
217
223
|
closeDatabase();
|
|
218
224
|
cleanup(base);
|
|
219
225
|
}
|
|
220
|
-
}
|
|
226
|
+
}
|
|
221
227
|
|
|
222
228
|
// ─── Test 5: no blocker, no trigger → phase is executing ──────────────
|
|
223
|
-
|
|
229
|
+
console.log('\n=== flag-file-db: no blocker, no trigger → executing ===');
|
|
230
|
+
{
|
|
224
231
|
const base = createFixtureBase();
|
|
225
232
|
try {
|
|
226
233
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_CONTENT);
|
|
@@ -238,19 +245,20 @@ describe('flag-file-db', async () => {
|
|
|
238
245
|
invalidateStateCache();
|
|
239
246
|
const state = await deriveStateFromDb(base);
|
|
240
247
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
248
|
+
assertEq(state.phase, 'executing', 'test5: phase is executing');
|
|
249
|
+
assertEq(state.activeTask?.id, 'T02', 'test5: activeTask is T02');
|
|
250
|
+
assertEq(state.blockers.length, 0, 'test5: no blockers');
|
|
244
251
|
|
|
245
252
|
closeDatabase();
|
|
246
253
|
} finally {
|
|
247
254
|
closeDatabase();
|
|
248
255
|
cleanup(base);
|
|
249
256
|
}
|
|
250
|
-
}
|
|
257
|
+
}
|
|
251
258
|
|
|
252
259
|
// ─── Diagnostic test: DB column inspection ──────────────────────────
|
|
253
|
-
|
|
260
|
+
console.log('\n=== flag-file-db: replan_triggered_at column is queryable ===');
|
|
261
|
+
{
|
|
254
262
|
openDatabase(':memory:');
|
|
255
263
|
|
|
256
264
|
insertMilestone({ id: 'M001', title: 'Diagnostic', status: 'active' });
|
|
@@ -261,7 +269,7 @@ describe('flag-file-db', async () => {
|
|
|
261
269
|
const before = adapter!.prepare(
|
|
262
270
|
"SELECT id, replan_triggered_at FROM slices WHERE milestone_id = :mid",
|
|
263
271
|
).get({ ":mid": "M001" }) as Record<string, unknown>;
|
|
264
|
-
|
|
272
|
+
assertEq(before["replan_triggered_at"], null, 'diagnostic: replan_triggered_at initially null');
|
|
265
273
|
|
|
266
274
|
// After setting
|
|
267
275
|
adapter!.prepare(
|
|
@@ -271,8 +279,12 @@ describe('flag-file-db', async () => {
|
|
|
271
279
|
const after = adapter!.prepare(
|
|
272
280
|
"SELECT id, replan_triggered_at FROM slices WHERE milestone_id = :mid",
|
|
273
281
|
).get({ ":mid": "M001" }) as Record<string, unknown>;
|
|
274
|
-
|
|
282
|
+
assertEq(after["replan_triggered_at"], "2025-01-01T00:00:00Z", 'diagnostic: replan_triggered_at is set');
|
|
275
283
|
|
|
276
284
|
closeDatabase();
|
|
277
|
-
}
|
|
278
|
-
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
report();
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
main();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
1
|
+
import { createTestContext } from './test-helpers.ts';
|
|
3
2
|
import * as path from 'node:path';
|
|
4
3
|
import * as os from 'node:os';
|
|
5
4
|
import * as fs from 'node:fs';
|
|
@@ -14,6 +13,8 @@ import {
|
|
|
14
13
|
saveDecisionToDb,
|
|
15
14
|
} from '../db-writer.ts';
|
|
16
15
|
|
|
16
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
17
|
+
|
|
17
18
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
18
19
|
// Helpers
|
|
19
20
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -34,199 +35,206 @@ function cleanupDir(dir: string): void {
|
|
|
34
35
|
// Bug reproduction: freeform DECISIONS.md content destroyed (#2301)
|
|
35
36
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
38
|
+
console.log('\n── parseDecisionsTable silently drops freeform content ──');
|
|
39
|
+
|
|
40
|
+
{
|
|
41
|
+
const freeform = `# Project Decisions
|
|
42
|
+
|
|
43
|
+
## Architecture
|
|
44
|
+
We decided to use a microservices architecture because monoliths don't scale.
|
|
45
|
+
|
|
46
|
+
## Database
|
|
47
|
+
PostgreSQL was chosen for its reliability and JSONB support.
|
|
48
|
+
|
|
49
|
+
## Deployment
|
|
50
|
+
- Kubernetes for orchestration
|
|
51
|
+
- Helm charts for packaging
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
const parsed = parseDecisionsTable(freeform);
|
|
55
|
+
assertEq(parsed.length, 0, 'freeform content yields zero parsed decisions (expected — it is not a table)');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
console.log('\n── saveDecisionToDb destroys freeform DECISIONS.md content ──');
|
|
59
|
+
|
|
60
|
+
{
|
|
61
|
+
const tmpDir = makeTmpDir();
|
|
62
|
+
const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
|
|
63
|
+
const mdPath = path.join(tmpDir, '.gsd', 'DECISIONS.md');
|
|
64
|
+
openDatabase(dbPath);
|
|
65
|
+
|
|
66
|
+
const freeformContent = `# Project Decisions
|
|
67
|
+
|
|
68
|
+
## Architecture
|
|
69
|
+
We decided to use a microservices architecture because monoliths don't scale.
|
|
70
|
+
|
|
71
|
+
## Database
|
|
72
|
+
PostgreSQL was chosen for its reliability and JSONB support.
|
|
73
|
+
|
|
74
|
+
## Deployment
|
|
75
|
+
- Kubernetes for orchestration
|
|
76
|
+
- Helm charts for packaging
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
// Pre-populate DECISIONS.md with freeform content
|
|
80
|
+
fs.writeFileSync(mdPath, freeformContent, 'utf-8');
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
// Save a new decision — this should NOT destroy the freeform content
|
|
84
|
+
const result = await saveDecisionToDb({
|
|
85
|
+
scope: 'testing',
|
|
86
|
+
decision: 'Use Jest for unit tests',
|
|
87
|
+
choice: 'Jest',
|
|
88
|
+
rationale: 'Well-known, good DX',
|
|
89
|
+
when_context: 'M001',
|
|
90
|
+
}, tmpDir);
|
|
91
|
+
|
|
92
|
+
assertEq(result.id, 'D001', 'decision ID assigned correctly');
|
|
93
|
+
|
|
94
|
+
// Read back the file
|
|
95
|
+
const afterContent = fs.readFileSync(mdPath, 'utf-8');
|
|
96
|
+
|
|
97
|
+
// The freeform content MUST still be present
|
|
98
|
+
assertTrue(
|
|
99
|
+
afterContent.includes('microservices architecture'),
|
|
100
|
+
'freeform architecture section preserved after saveDecisionToDb',
|
|
101
|
+
);
|
|
102
|
+
assertTrue(
|
|
103
|
+
afterContent.includes('PostgreSQL was chosen'),
|
|
104
|
+
'freeform database section preserved after saveDecisionToDb',
|
|
105
|
+
);
|
|
106
|
+
assertTrue(
|
|
107
|
+
afterContent.includes('Kubernetes for orchestration'),
|
|
108
|
+
'freeform deployment section preserved after saveDecisionToDb',
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
// The new decision MUST also be present
|
|
112
|
+
assertTrue(
|
|
113
|
+
afterContent.includes('D001'),
|
|
114
|
+
'new decision D001 present in file',
|
|
115
|
+
);
|
|
116
|
+
assertTrue(
|
|
117
|
+
afterContent.includes('Use Jest for unit tests'),
|
|
118
|
+
'new decision text present in file',
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
// Save a second decision — freeform content must still survive
|
|
122
|
+
const result2 = await saveDecisionToDb({
|
|
123
|
+
scope: 'ci',
|
|
124
|
+
decision: 'Use GitHub Actions for CI',
|
|
125
|
+
choice: 'GitHub Actions',
|
|
126
|
+
rationale: 'Native integration',
|
|
127
|
+
when_context: 'M001',
|
|
128
|
+
}, tmpDir);
|
|
129
|
+
|
|
130
|
+
assertEq(result2.id, 'D002', 'second decision ID assigned correctly');
|
|
131
|
+
|
|
132
|
+
const afterContent2 = fs.readFileSync(mdPath, 'utf-8');
|
|
133
|
+
|
|
134
|
+
assertTrue(
|
|
135
|
+
afterContent2.includes('microservices architecture'),
|
|
136
|
+
'freeform content still preserved after second save',
|
|
137
|
+
);
|
|
138
|
+
assertTrue(
|
|
139
|
+
afterContent2.includes('D001'),
|
|
140
|
+
'first decision still present after second save',
|
|
141
|
+
);
|
|
142
|
+
assertTrue(
|
|
143
|
+
afterContent2.includes('D002'),
|
|
144
|
+
'second decision present after second save',
|
|
145
|
+
);
|
|
146
|
+
assertTrue(
|
|
147
|
+
afterContent2.includes('Use GitHub Actions for CI'),
|
|
148
|
+
'second decision text present in file',
|
|
149
|
+
);
|
|
150
|
+
} finally {
|
|
151
|
+
closeDatabase();
|
|
152
|
+
cleanupDir(tmpDir);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
console.log('\n── saveDecisionToDb with table-format DECISIONS.md still regenerates normally ──');
|
|
157
|
+
|
|
158
|
+
{
|
|
159
|
+
const tmpDir = makeTmpDir();
|
|
160
|
+
const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
|
|
161
|
+
const mdPath = path.join(tmpDir, '.gsd', 'DECISIONS.md');
|
|
162
|
+
openDatabase(dbPath);
|
|
163
|
+
|
|
164
|
+
// Pre-populate with canonical table format
|
|
165
|
+
const tableContent = `# Decisions Register
|
|
166
|
+
|
|
167
|
+
<!-- Append-only. Never edit or remove existing rows.
|
|
168
|
+
To reverse a decision, add a new row that supersedes it.
|
|
169
|
+
Read this file at the start of any planning or research phase. -->
|
|
170
|
+
|
|
171
|
+
| # | When | Scope | Decision | Choice | Rationale | Revisable? | Made By |
|
|
172
|
+
|---|------|-------|----------|--------|-----------|------------|---------|
|
|
173
|
+
| D001 | M001 | arch | Use REST API | REST | Simpler | Yes | human |
|
|
174
|
+
`;
|
|
175
|
+
|
|
176
|
+
fs.writeFileSync(mdPath, tableContent, 'utf-8');
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
const result = await saveDecisionToDb({
|
|
180
|
+
scope: 'testing',
|
|
181
|
+
decision: 'Use Vitest',
|
|
182
|
+
choice: 'Vitest',
|
|
183
|
+
rationale: 'Fast',
|
|
184
|
+
when_context: 'M001',
|
|
185
|
+
}, tmpDir);
|
|
186
|
+
|
|
187
|
+
// The pre-existing table decision was NOT in DB, so it won't appear after regen.
|
|
188
|
+
// But the new decision should be there.
|
|
189
|
+
assertEq(result.id, 'D001', 'gets D001 since DB was empty');
|
|
190
|
+
|
|
191
|
+
const afterContent = fs.readFileSync(mdPath, 'utf-8');
|
|
192
|
+
// Table-format file gets fully regenerated — this is the normal path
|
|
193
|
+
assertTrue(
|
|
194
|
+
afterContent.includes('# Decisions Register'),
|
|
195
|
+
'table-format file still has header after save',
|
|
196
|
+
);
|
|
197
|
+
assertTrue(
|
|
198
|
+
afterContent.includes('Use Vitest'),
|
|
199
|
+
'new decision present in regenerated table',
|
|
200
|
+
);
|
|
201
|
+
} finally {
|
|
202
|
+
closeDatabase();
|
|
203
|
+
cleanupDir(tmpDir);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
console.log('\n── saveDecisionToDb with no existing DECISIONS.md creates table ──');
|
|
208
|
+
|
|
209
|
+
{
|
|
210
|
+
const tmpDir = makeTmpDir();
|
|
211
|
+
const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
|
|
212
|
+
const mdPath = path.join(tmpDir, '.gsd', 'DECISIONS.md');
|
|
213
|
+
openDatabase(dbPath);
|
|
214
|
+
|
|
215
|
+
// No DECISIONS.md exists at all
|
|
216
|
+
assertTrue(!fs.existsSync(mdPath), 'DECISIONS.md does not exist initially');
|
|
217
|
+
|
|
218
|
+
try {
|
|
219
|
+
const result = await saveDecisionToDb({
|
|
220
|
+
scope: 'arch',
|
|
221
|
+
decision: 'Brand new decision',
|
|
222
|
+
choice: 'Option A',
|
|
223
|
+
rationale: 'Best fit',
|
|
224
|
+
}, tmpDir);
|
|
225
|
+
|
|
226
|
+
assertEq(result.id, 'D001', 'first decision gets D001');
|
|
227
|
+
assertTrue(fs.existsSync(mdPath), 'DECISIONS.md created');
|
|
228
|
+
|
|
229
|
+
const content = fs.readFileSync(mdPath, 'utf-8');
|
|
230
|
+
assertTrue(content.includes('# Decisions Register'), 'new file has header');
|
|
231
|
+
assertTrue(content.includes('Brand new decision'), 'new file has decision');
|
|
232
|
+
} finally {
|
|
233
|
+
closeDatabase();
|
|
234
|
+
cleanupDir(tmpDir);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
239
|
+
|
|
240
|
+
report();
|