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,3 +1,4 @@
|
|
|
1
|
+
import { createTestContext } from './test-helpers.ts';
|
|
1
2
|
import {
|
|
2
3
|
openDatabase,
|
|
3
4
|
closeDatabase,
|
|
@@ -20,90 +21,94 @@ import {
|
|
|
20
21
|
formatMemoriesForPrompt,
|
|
21
22
|
} from '../memory-store.ts';
|
|
22
23
|
import type { MemoryAction } from '../memory-store.ts';
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
|
|
25
|
+
const { assertEq, assertTrue, assertMatch, report } = createTestContext();
|
|
25
26
|
|
|
26
27
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
27
28
|
// memory-store: fallback when DB not open
|
|
28
29
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
console.log('\n=== memory-store: fallback returns empty when DB not open ===');
|
|
32
|
+
{
|
|
31
33
|
closeDatabase();
|
|
32
|
-
|
|
34
|
+
assertTrue(!isDbAvailable(), 'DB should not be available');
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
36
|
+
assertEq(getActiveMemories(), [], 'getActiveMemories returns [] when DB closed');
|
|
37
|
+
assertEq(getActiveMemoriesRanked(), [], 'getActiveMemoriesRanked returns [] when DB closed');
|
|
38
|
+
assertEq(nextMemoryId(), 'MEM001', 'nextMemoryId returns MEM001 when DB closed');
|
|
39
|
+
assertEq(createMemory({ category: 'test', content: 'test' }), null, 'createMemory returns null when DB closed');
|
|
40
|
+
assertTrue(!reinforceMemory('MEM001'), 'reinforceMemory returns false when DB closed');
|
|
41
|
+
assertTrue(!isUnitProcessed('test/key'), 'isUnitProcessed returns false when DB closed');
|
|
42
|
+
}
|
|
41
43
|
|
|
42
44
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
43
45
|
// memory-store: CRUD operations
|
|
44
46
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
console.log('\n=== memory-store: create and query memories ===');
|
|
49
|
+
{
|
|
47
50
|
openDatabase(':memory:');
|
|
48
51
|
|
|
49
52
|
// Create memories
|
|
50
53
|
const id1 = createMemory({ category: 'gotcha', content: 'esbuild drops .node binaries' });
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
assertTrue(id1 !== null, 'createMemory should return an ID');
|
|
55
|
+
assertEq(id1, 'MEM001', 'first memory ID should be MEM001');
|
|
53
56
|
|
|
54
57
|
const id2 = createMemory({ category: 'convention', content: 'use :memory: for tests', confidence: 0.9 });
|
|
55
|
-
|
|
58
|
+
assertEq(id2, 'MEM002', 'second memory ID should be MEM002');
|
|
56
59
|
|
|
57
60
|
const id3 = createMemory({ category: 'architecture', content: 'extensions discovered from src/resources/' });
|
|
58
|
-
|
|
61
|
+
assertEq(id3, 'MEM003', 'third memory ID should be MEM003');
|
|
59
62
|
|
|
60
63
|
// Query all active
|
|
61
64
|
const active = getActiveMemories();
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
assertEq(active.length, 3, 'should have 3 active memories');
|
|
66
|
+
assertEq(active[0].category, 'gotcha', 'first memory category');
|
|
67
|
+
assertEq(active[0].content, 'esbuild drops .node binaries', 'first memory content');
|
|
68
|
+
assertEq(active[1].confidence, 0.9, 'second memory confidence');
|
|
66
69
|
|
|
67
70
|
closeDatabase();
|
|
68
|
-
}
|
|
71
|
+
}
|
|
69
72
|
|
|
70
73
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
71
74
|
// memory-store: update and reinforce
|
|
72
75
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
73
76
|
|
|
74
|
-
|
|
77
|
+
console.log('\n=== memory-store: update and reinforce ===');
|
|
78
|
+
{
|
|
75
79
|
openDatabase(':memory:');
|
|
76
80
|
|
|
77
81
|
createMemory({ category: 'gotcha', content: 'original content' });
|
|
78
82
|
|
|
79
83
|
// Update content
|
|
80
84
|
const updated = updateMemoryContent('MEM001', 'revised content', 0.95);
|
|
81
|
-
|
|
85
|
+
assertTrue(updated, 'updateMemoryContent should return true');
|
|
82
86
|
|
|
83
87
|
const active = getActiveMemories();
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
assertEq(active[0].content, 'revised content', 'content should be updated');
|
|
89
|
+
assertEq(active[0].confidence, 0.95, 'confidence should be updated');
|
|
86
90
|
|
|
87
91
|
// Reinforce
|
|
88
92
|
const reinforced = reinforceMemory('MEM001');
|
|
89
|
-
|
|
93
|
+
assertTrue(reinforced, 'reinforceMemory should return true');
|
|
90
94
|
|
|
91
95
|
const after = getActiveMemories();
|
|
92
|
-
|
|
96
|
+
assertEq(after[0].hit_count, 1, 'hit_count should be 1 after reinforce');
|
|
93
97
|
|
|
94
98
|
// Reinforce again
|
|
95
99
|
reinforceMemory('MEM001');
|
|
96
100
|
const after2 = getActiveMemories();
|
|
97
|
-
|
|
101
|
+
assertEq(after2[0].hit_count, 2, 'hit_count should be 2 after second reinforce');
|
|
98
102
|
|
|
99
103
|
closeDatabase();
|
|
100
|
-
}
|
|
104
|
+
}
|
|
101
105
|
|
|
102
106
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
103
107
|
// memory-store: supersede
|
|
104
108
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
105
109
|
|
|
106
|
-
|
|
110
|
+
console.log('\n=== memory-store: supersede ===');
|
|
111
|
+
{
|
|
107
112
|
openDatabase(':memory:');
|
|
108
113
|
|
|
109
114
|
createMemory({ category: 'convention', content: 'old convention' });
|
|
@@ -112,17 +117,18 @@ test('memory-store: supersede', () => {
|
|
|
112
117
|
supersedeMemory('MEM001', 'MEM002');
|
|
113
118
|
|
|
114
119
|
const active = getActiveMemories();
|
|
115
|
-
|
|
116
|
-
|
|
120
|
+
assertEq(active.length, 1, 'should have 1 active memory after supersede');
|
|
121
|
+
assertEq(active[0].id, 'MEM002', 'active memory should be MEM002');
|
|
117
122
|
|
|
118
123
|
closeDatabase();
|
|
119
|
-
}
|
|
124
|
+
}
|
|
120
125
|
|
|
121
126
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
122
127
|
// memory-store: ranked query ordering
|
|
123
128
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
124
129
|
|
|
125
|
-
|
|
130
|
+
console.log('\n=== memory-store: ranked query ordering ===');
|
|
131
|
+
{
|
|
126
132
|
openDatabase(':memory:');
|
|
127
133
|
|
|
128
134
|
// Low confidence, no hits
|
|
@@ -136,43 +142,45 @@ test('memory-store: ranked query ordering', () => {
|
|
|
136
142
|
for (let i = 0; i < 10; i++) reinforceMemory('MEM003');
|
|
137
143
|
|
|
138
144
|
const ranked = getActiveMemoriesRanked(10);
|
|
139
|
-
|
|
145
|
+
assertEq(ranked.length, 3, 'should have 3 ranked memories');
|
|
140
146
|
// MEM003: 0.7 * (1 + 10*0.1) = 0.7 * 2.0 = 1.4
|
|
141
147
|
// MEM002: 0.95 * (1 + 0*0.1) = 0.95
|
|
142
148
|
// MEM001: 0.5 * (1 + 0*0.1) = 0.5
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
149
|
+
assertEq(ranked[0].id, 'MEM003', 'highest ranked should be MEM003 (reinforced)');
|
|
150
|
+
assertEq(ranked[1].id, 'MEM002', 'second ranked should be MEM002 (high confidence)');
|
|
151
|
+
assertEq(ranked[2].id, 'MEM001', 'lowest ranked should be MEM001');
|
|
146
152
|
|
|
147
153
|
// Test limit
|
|
148
154
|
const limited = getActiveMemoriesRanked(2);
|
|
149
|
-
|
|
155
|
+
assertEq(limited.length, 2, 'limit should cap results');
|
|
150
156
|
|
|
151
157
|
closeDatabase();
|
|
152
|
-
}
|
|
158
|
+
}
|
|
153
159
|
|
|
154
160
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
155
161
|
// memory-store: processed unit tracking
|
|
156
162
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
157
163
|
|
|
158
|
-
|
|
164
|
+
console.log('\n=== memory-store: processed unit tracking ===');
|
|
165
|
+
{
|
|
159
166
|
openDatabase(':memory:');
|
|
160
167
|
|
|
161
|
-
|
|
168
|
+
assertTrue(!isUnitProcessed('execute-task/M001/S01/T01'), 'should not be processed initially');
|
|
162
169
|
|
|
163
170
|
markUnitProcessed('execute-task/M001/S01/T01', '/path/to/activity.jsonl');
|
|
164
171
|
|
|
165
|
-
|
|
166
|
-
|
|
172
|
+
assertTrue(isUnitProcessed('execute-task/M001/S01/T01'), 'should be processed after marking');
|
|
173
|
+
assertTrue(!isUnitProcessed('execute-task/M001/S01/T02'), 'different key should not be processed');
|
|
167
174
|
|
|
168
175
|
closeDatabase();
|
|
169
|
-
}
|
|
176
|
+
}
|
|
170
177
|
|
|
171
178
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
172
179
|
// memory-store: enforce memory cap
|
|
173
180
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
174
181
|
|
|
175
|
-
|
|
182
|
+
console.log('\n=== memory-store: enforce memory cap ===');
|
|
183
|
+
{
|
|
176
184
|
openDatabase(':memory:');
|
|
177
185
|
|
|
178
186
|
// Create 5 memories with varying confidence
|
|
@@ -186,22 +194,23 @@ test('memory-store: enforce memory cap', () => {
|
|
|
186
194
|
enforceMemoryCap(3);
|
|
187
195
|
|
|
188
196
|
const active = getActiveMemories();
|
|
189
|
-
|
|
197
|
+
assertEq(active.length, 3, 'should have 3 active memories after cap enforcement');
|
|
190
198
|
|
|
191
199
|
// The 2 lowest-ranked (MEM003=0.3 and MEM002=0.5) should be superseded
|
|
192
200
|
const ids = active.map(m => m.id).sort();
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
201
|
+
assertTrue(ids.includes('MEM001'), 'MEM001 (0.9) should survive');
|
|
202
|
+
assertTrue(ids.includes('MEM004'), 'MEM004 (0.95) should survive');
|
|
203
|
+
assertTrue(ids.includes('MEM005'), 'MEM005 (0.7) should survive');
|
|
196
204
|
|
|
197
205
|
closeDatabase();
|
|
198
|
-
}
|
|
206
|
+
}
|
|
199
207
|
|
|
200
208
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
201
209
|
// memory-store: applyMemoryActions transaction
|
|
202
210
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
203
211
|
|
|
204
|
-
|
|
212
|
+
console.log('\n=== memory-store: applyMemoryActions ===');
|
|
213
|
+
{
|
|
205
214
|
openDatabase(':memory:');
|
|
206
215
|
|
|
207
216
|
const actions: MemoryAction[] = [
|
|
@@ -212,7 +221,7 @@ test('memory-store: applyMemoryActions', () => {
|
|
|
212
221
|
applyMemoryActions(actions, 'execute-task', 'M001/S01/T01');
|
|
213
222
|
|
|
214
223
|
let active = getActiveMemories();
|
|
215
|
-
|
|
224
|
+
assertEq(active.length, 2, 'should have 2 memories after CREATE actions');
|
|
216
225
|
|
|
217
226
|
// Now apply UPDATE + REINFORCE
|
|
218
227
|
const updateActions: MemoryAction[] = [
|
|
@@ -223,8 +232,8 @@ test('memory-store: applyMemoryActions', () => {
|
|
|
223
232
|
applyMemoryActions(updateActions, 'execute-task', 'M001/S01/T02');
|
|
224
233
|
|
|
225
234
|
active = getActiveMemories();
|
|
226
|
-
|
|
227
|
-
|
|
235
|
+
assertEq(active.find(m => m.id === 'MEM001')?.content, 'updated gotcha', 'MEM001 should be updated');
|
|
236
|
+
assertEq(active.find(m => m.id === 'MEM002')?.hit_count, 1, 'MEM002 should be reinforced');
|
|
228
237
|
|
|
229
238
|
// SUPERSEDE
|
|
230
239
|
const supersedeActions: MemoryAction[] = [
|
|
@@ -235,18 +244,19 @@ test('memory-store: applyMemoryActions', () => {
|
|
|
235
244
|
applyMemoryActions(supersedeActions, 'execute-task', 'M001/S01/T03');
|
|
236
245
|
|
|
237
246
|
active = getActiveMemories();
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
247
|
+
assertEq(active.length, 2, 'should have 2 active after supersede');
|
|
248
|
+
assertTrue(!active.find(m => m.id === 'MEM001'), 'MEM001 should be superseded');
|
|
249
|
+
assertTrue(!!active.find(m => m.id === 'MEM003'), 'MEM003 should be active');
|
|
241
250
|
|
|
242
251
|
closeDatabase();
|
|
243
|
-
}
|
|
252
|
+
}
|
|
244
253
|
|
|
245
254
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
246
255
|
// memory-store: formatMemoriesForPrompt
|
|
247
256
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
248
257
|
|
|
249
|
-
|
|
258
|
+
console.log('\n=== memory-store: formatMemoriesForPrompt ===');
|
|
259
|
+
{
|
|
250
260
|
openDatabase(':memory:');
|
|
251
261
|
|
|
252
262
|
createMemory({ category: 'gotcha', content: 'esbuild drops .node binaries' });
|
|
@@ -257,18 +267,18 @@ test('memory-store: formatMemoriesForPrompt', () => {
|
|
|
257
267
|
const memories = getActiveMemoriesRanked(30);
|
|
258
268
|
const formatted = formatMemoriesForPrompt(memories);
|
|
259
269
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
270
|
+
assertTrue(formatted.includes('## Project Memory (auto-learned)'), 'should have header');
|
|
271
|
+
assertTrue(formatted.includes('### Gotcha'), 'should have gotcha category');
|
|
272
|
+
assertTrue(formatted.includes('### Convention'), 'should have convention category');
|
|
273
|
+
assertTrue(formatted.includes('### Architecture'), 'should have architecture category');
|
|
274
|
+
assertTrue(formatted.includes('- esbuild drops .node binaries'), 'should have gotcha content');
|
|
275
|
+
assertTrue(formatted.includes('- use :memory: for tests'), 'should have convention content');
|
|
266
276
|
|
|
267
277
|
// Test empty memories
|
|
268
278
|
closeDatabase();
|
|
269
279
|
openDatabase(':memory:');
|
|
270
280
|
const emptyFormatted = formatMemoriesForPrompt([]);
|
|
271
|
-
|
|
281
|
+
assertEq(emptyFormatted, '', 'empty memories should return empty string');
|
|
272
282
|
|
|
273
283
|
// Test token budget truncation
|
|
274
284
|
closeDatabase();
|
|
@@ -278,55 +288,58 @@ test('memory-store: formatMemoriesForPrompt', () => {
|
|
|
278
288
|
}
|
|
279
289
|
const budgetMemories = getActiveMemoriesRanked(30);
|
|
280
290
|
const truncated = formatMemoriesForPrompt(budgetMemories, 500);
|
|
281
|
-
|
|
291
|
+
assertTrue(truncated.length < 2500, `formatted length ${truncated.length} should be under budget`);
|
|
282
292
|
|
|
283
293
|
closeDatabase();
|
|
284
|
-
}
|
|
294
|
+
}
|
|
285
295
|
|
|
286
296
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
287
297
|
// memory-store: ID generation
|
|
288
298
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
289
299
|
|
|
290
|
-
|
|
300
|
+
console.log('\n=== memory-store: ID generation ===');
|
|
301
|
+
{
|
|
291
302
|
openDatabase(':memory:');
|
|
292
303
|
|
|
293
|
-
|
|
304
|
+
assertEq(nextMemoryId(), 'MEM001', 'first ID should be MEM001');
|
|
294
305
|
|
|
295
306
|
createMemory({ category: 'test', content: 'test' });
|
|
296
|
-
|
|
307
|
+
assertEq(nextMemoryId(), 'MEM002', 'after first create, next should be MEM002');
|
|
297
308
|
|
|
298
309
|
// Create several more
|
|
299
310
|
for (let i = 0; i < 98; i++) createMemory({ category: 'test', content: `test ${i}` });
|
|
300
|
-
|
|
311
|
+
assertEq(nextMemoryId(), 'MEM100', 'after 99 creates, next should be MEM100');
|
|
301
312
|
|
|
302
313
|
closeDatabase();
|
|
303
|
-
}
|
|
314
|
+
}
|
|
304
315
|
|
|
305
316
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
306
317
|
// memory-store: schema migration (v2 → v3)
|
|
307
318
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
308
319
|
|
|
309
|
-
|
|
320
|
+
console.log('\n=== memory-store: schema includes memories table ===');
|
|
321
|
+
{
|
|
310
322
|
openDatabase(':memory:');
|
|
311
323
|
|
|
312
324
|
const adapter = _getAdapter()!;
|
|
313
325
|
|
|
314
326
|
// Verify memories table exists
|
|
315
327
|
const memCount = adapter.prepare('SELECT count(*) as cnt FROM memories').get();
|
|
316
|
-
|
|
328
|
+
assertEq(memCount?.['cnt'], 0, 'memories table should exist and be empty');
|
|
317
329
|
|
|
318
330
|
// Verify memory_processed_units table exists
|
|
319
331
|
const procCount = adapter.prepare('SELECT count(*) as cnt FROM memory_processed_units').get();
|
|
320
|
-
|
|
332
|
+
assertEq(procCount?.['cnt'], 0, 'memory_processed_units table should exist and be empty');
|
|
321
333
|
|
|
322
334
|
// Verify active_memories view exists
|
|
323
335
|
const viewCount = adapter.prepare('SELECT count(*) as cnt FROM active_memories').get();
|
|
324
|
-
|
|
336
|
+
assertEq(viewCount?.['cnt'], 0, 'active_memories view should exist');
|
|
325
337
|
|
|
326
338
|
// Verify schema version is 10 (after M001 planning migrations)
|
|
327
339
|
const version = adapter.prepare('SELECT MAX(version) as v FROM schema_version').get();
|
|
328
|
-
|
|
340
|
+
assertEq(version?.['v'], 10, 'schema version should be 10');
|
|
329
341
|
|
|
330
342
|
closeDatabase();
|
|
331
|
-
}
|
|
343
|
+
}
|
|
332
344
|
|
|
345
|
+
report();
|
|
@@ -15,9 +15,9 @@ import {
|
|
|
15
15
|
writeGSDDirectory,
|
|
16
16
|
} from '../migrate/index.ts';
|
|
17
17
|
import { deriveState } from '../state.ts';
|
|
18
|
-
import {
|
|
19
|
-
import assert from 'node:assert/strict';
|
|
18
|
+
import { createTestContext } from './test-helpers.ts';
|
|
20
19
|
|
|
20
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
21
21
|
// ─── Fixture Helpers ───────────────────────────────────────────────────────
|
|
22
22
|
|
|
23
23
|
const SAMPLE_PROJECT = `# Integration Test Project
|
|
@@ -195,9 +195,11 @@ function createCompleteFixture(): string {
|
|
|
195
195
|
// Tests
|
|
196
196
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
197
197
|
|
|
198
|
-
|
|
198
|
+
async function main(): Promise<void> {
|
|
199
199
|
|
|
200
|
-
|
|
200
|
+
// ─── Test 1: Path resolution — .planning appended when missing ─────────
|
|
201
|
+
console.log('\n=== Path resolution: .planning appended when source path lacks it ===');
|
|
202
|
+
{
|
|
201
203
|
const base = createCompleteFixture();
|
|
202
204
|
try {
|
|
203
205
|
// Simulate the command's path resolution logic
|
|
@@ -205,16 +207,16 @@ test('Path resolution: .planning appended when source path lacks it', () => {
|
|
|
205
207
|
if (!sourcePath.endsWith('.planning')) {
|
|
206
208
|
sourcePath = join(sourcePath, '.planning');
|
|
207
209
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
+
assertTrue(sourcePath.endsWith('.planning'), 'path-resolution: .planning appended');
|
|
211
|
+
assertTrue(existsSync(sourcePath), 'path-resolution: appended path exists');
|
|
210
212
|
} finally {
|
|
211
213
|
rmSync(base, { recursive: true, force: true });
|
|
212
214
|
}
|
|
213
|
-
}
|
|
215
|
+
}
|
|
214
216
|
|
|
215
217
|
// ─── Test 2: Path resolution — .planning used as-is ────────────────────
|
|
216
|
-
|
|
217
|
-
|
|
218
|
+
console.log('\n=== Path resolution: .planning used as-is when already present ===');
|
|
219
|
+
{
|
|
218
220
|
const base = createCompleteFixture();
|
|
219
221
|
try {
|
|
220
222
|
const planningPath = join(base, '.planning');
|
|
@@ -222,39 +224,39 @@ test('Path resolution: .planning used as-is when already present', () => {
|
|
|
222
224
|
if (!sourcePath.endsWith('.planning')) {
|
|
223
225
|
sourcePath = join(sourcePath, '.planning');
|
|
224
226
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
+
assertEq(sourcePath, resolve(planningPath), 'path-resolution: .planning not double-appended');
|
|
228
|
+
assertTrue(existsSync(sourcePath), 'path-resolution: direct path exists');
|
|
227
229
|
} finally {
|
|
228
230
|
rmSync(base, { recursive: true, force: true });
|
|
229
231
|
}
|
|
230
|
-
}
|
|
232
|
+
}
|
|
231
233
|
|
|
232
234
|
// ─── Test 3: Validation gating — non-existent path ─────────────────────
|
|
233
|
-
|
|
234
|
-
|
|
235
|
+
console.log('\n=== Validation gating: non-existent path returns invalid ===');
|
|
236
|
+
{
|
|
235
237
|
const fakePath = join(tmpdir(), 'gsd-cmd-nonexistent-' + Date.now(), '.planning');
|
|
236
238
|
const result = await validatePlanningDirectory(fakePath);
|
|
237
|
-
|
|
238
|
-
|
|
239
|
+
assertEq(result.valid, false, 'validation: non-existent path is invalid');
|
|
240
|
+
assertTrue(result.issues.length > 0, 'validation: has issues for non-existent path');
|
|
239
241
|
const hasFatal = result.issues.some(i => i.severity === 'fatal');
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
+
assertTrue(hasFatal, 'validation: non-existent path has fatal issue');
|
|
243
|
+
}
|
|
242
244
|
|
|
243
245
|
// ─── Test 4: Validation gating — valid fixture passes ──────────────────
|
|
244
|
-
|
|
245
|
-
|
|
246
|
+
console.log('\n=== Validation gating: valid fixture passes validation ===');
|
|
247
|
+
{
|
|
246
248
|
const base = createCompleteFixture();
|
|
247
249
|
try {
|
|
248
250
|
const result = await validatePlanningDirectory(join(base, '.planning'));
|
|
249
|
-
|
|
251
|
+
assertTrue(result.valid === true, 'validation: valid fixture passes');
|
|
250
252
|
} finally {
|
|
251
253
|
rmSync(base, { recursive: true, force: true });
|
|
252
254
|
}
|
|
253
|
-
}
|
|
255
|
+
}
|
|
254
256
|
|
|
255
257
|
// ─── Test 5: Full pipeline round-trip ──────────────────────────────────
|
|
256
|
-
|
|
257
|
-
|
|
258
|
+
console.log('\n=== Full pipeline: parse → transform → preview → write → deriveState ===');
|
|
259
|
+
{
|
|
258
260
|
const base = createCompleteFixture();
|
|
259
261
|
const writeTarget = mkdtempSync(join(tmpdir(), 'gsd-cmd-write-'));
|
|
260
262
|
try {
|
|
@@ -262,17 +264,17 @@ test('Full pipeline: parse → transform → preview → write → deriveState',
|
|
|
262
264
|
|
|
263
265
|
// (a) Validate
|
|
264
266
|
const validation = await validatePlanningDirectory(planningPath);
|
|
265
|
-
|
|
267
|
+
assertTrue(validation.valid === true, 'pipeline: validation passes');
|
|
266
268
|
|
|
267
269
|
// (b) Parse
|
|
268
270
|
const parsed = await parsePlanningDirectory(planningPath);
|
|
269
|
-
|
|
270
|
-
|
|
271
|
+
assertTrue(parsed.roadmap !== null, 'pipeline: roadmap parsed');
|
|
272
|
+
assertTrue(Object.keys(parsed.phases).length >= 2, 'pipeline: phases parsed');
|
|
271
273
|
|
|
272
274
|
// (c) Transform
|
|
273
275
|
const project = transformToGSD(parsed);
|
|
274
|
-
|
|
275
|
-
|
|
276
|
+
assertTrue(project.milestones.length >= 1, 'pipeline: has milestones');
|
|
277
|
+
assertTrue(project.milestones[0].slices.length >= 1, 'pipeline: has slices');
|
|
276
278
|
|
|
277
279
|
// Count totals for preview verification
|
|
278
280
|
let totalTasks = 0;
|
|
@@ -292,69 +294,76 @@ test('Full pipeline: parse → transform → preview → write → deriveState',
|
|
|
292
294
|
|
|
293
295
|
// (d) Preview — verify counts match project data
|
|
294
296
|
const preview = generatePreview(project);
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
297
|
+
assertEq(preview.milestoneCount, project.milestones.length, 'pipeline: preview milestoneCount');
|
|
298
|
+
assertEq(preview.totalSlices, totalSlices, 'pipeline: preview totalSlices');
|
|
299
|
+
assertEq(preview.totalTasks, totalTasks, 'pipeline: preview totalTasks');
|
|
300
|
+
assertEq(preview.doneSlices, doneSlices, 'pipeline: preview doneSlices');
|
|
301
|
+
assertEq(preview.doneTasks, doneTasks, 'pipeline: preview doneTasks');
|
|
300
302
|
|
|
301
303
|
// Completion percentages
|
|
302
304
|
const expectedSlicePct = totalSlices > 0 ? Math.round((doneSlices / totalSlices) * 100) : 0;
|
|
303
305
|
const expectedTaskPct = totalTasks > 0 ? Math.round((doneTasks / totalTasks) * 100) : 0;
|
|
304
|
-
|
|
305
|
-
|
|
306
|
+
assertEq(preview.sliceCompletionPct, expectedSlicePct, 'pipeline: preview sliceCompletionPct');
|
|
307
|
+
assertEq(preview.taskCompletionPct, expectedTaskPct, 'pipeline: preview taskCompletionPct');
|
|
306
308
|
|
|
307
309
|
// Requirements in preview
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
310
|
+
assertEq(preview.requirements.active, 1, 'pipeline: preview requirements active');
|
|
311
|
+
assertEq(preview.requirements.validated, 1, 'pipeline: preview requirements validated');
|
|
312
|
+
assertEq(preview.requirements.total, 2, 'pipeline: preview requirements total');
|
|
311
313
|
|
|
312
314
|
// (e) Write
|
|
313
315
|
const result = await writeGSDDirectory(project, writeTarget);
|
|
314
|
-
|
|
316
|
+
assertTrue(result.paths.length > 0, 'pipeline: files written');
|
|
315
317
|
|
|
316
318
|
// Key files exist
|
|
317
319
|
const gsd = join(writeTarget, '.gsd');
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
320
|
+
assertTrue(existsSync(join(gsd, 'PROJECT.md')), 'pipeline: PROJECT.md written');
|
|
321
|
+
assertTrue(existsSync(join(gsd, 'STATE.md')), 'pipeline: STATE.md written');
|
|
322
|
+
assertTrue(existsSync(join(gsd, 'REQUIREMENTS.md')), 'pipeline: REQUIREMENTS.md written');
|
|
321
323
|
|
|
322
324
|
const m001 = join(gsd, 'milestones', 'M001');
|
|
323
|
-
|
|
324
|
-
|
|
325
|
+
assertTrue(existsSync(join(m001, 'M001-ROADMAP.md')), 'pipeline: M001-ROADMAP.md written');
|
|
326
|
+
assertTrue(existsSync(join(m001, 'M001-CONTEXT.md')), 'pipeline: M001-CONTEXT.md written');
|
|
325
327
|
|
|
326
328
|
// At least one slice plan exists
|
|
327
329
|
const s01Plan = join(m001, 'slices', 'S01', 'S01-PLAN.md');
|
|
328
|
-
|
|
330
|
+
assertTrue(existsSync(s01Plan), 'pipeline: S01-PLAN.md written');
|
|
329
331
|
|
|
330
332
|
// (f) deriveState — coherent state from written output
|
|
331
333
|
console.log(' --- deriveState ---');
|
|
332
334
|
const state = await deriveState(writeTarget);
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
335
|
+
assertTrue(state.phase !== undefined, 'pipeline: deriveState returns phase');
|
|
336
|
+
assertTrue(state.activeMilestone !== null, 'pipeline: deriveState has activeMilestone');
|
|
337
|
+
assertEq(state.activeMilestone!.id, 'M001', 'pipeline: deriveState activeMilestone is M001');
|
|
338
|
+
assertTrue(state.progress!.slices !== undefined, 'pipeline: deriveState has slices progress');
|
|
339
|
+
assertTrue(state.progress!.tasks !== undefined, 'pipeline: deriveState has tasks progress');
|
|
338
340
|
|
|
339
341
|
} finally {
|
|
340
342
|
rmSync(base, { recursive: true, force: true });
|
|
341
343
|
rmSync(writeTarget, { recursive: true, force: true });
|
|
342
344
|
}
|
|
343
|
-
}
|
|
345
|
+
}
|
|
344
346
|
|
|
345
347
|
// ─── Test 6: .gsd/ exists detection ────────────────────────────────────
|
|
346
|
-
|
|
347
|
-
|
|
348
|
+
console.log('\n=== .gsd/ exists detection ===');
|
|
349
|
+
{
|
|
348
350
|
const base = mkdtempSync(join(tmpdir(), 'gsd-cmd-exists-'));
|
|
349
351
|
try {
|
|
350
352
|
// No .gsd/ yet
|
|
351
|
-
|
|
353
|
+
assertTrue(!existsSync(join(base, '.gsd')), 'exists-detection: .gsd absent initially');
|
|
352
354
|
|
|
353
355
|
// Create .gsd/
|
|
354
356
|
mkdirSync(join(base, '.gsd'), { recursive: true });
|
|
355
|
-
|
|
357
|
+
assertTrue(existsSync(join(base, '.gsd')), 'exists-detection: .gsd detected after creation');
|
|
356
358
|
} finally {
|
|
357
359
|
rmSync(base, { recursive: true, force: true });
|
|
358
360
|
}
|
|
359
|
-
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
report();
|
|
364
|
+
}
|
|
360
365
|
|
|
366
|
+
main().catch((err) => {
|
|
367
|
+
console.error('Unhandled error:', err);
|
|
368
|
+
process.exit(1);
|
|
369
|
+
});
|