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
|
@@ -66,7 +66,7 @@ function createFixture(): string {
|
|
|
66
66
|
return base;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
test("dispatch uat targets last completed slice, not activeSlice (#1693)", async (
|
|
69
|
+
test("dispatch uat targets last completed slice, not activeSlice (#1693)", async () => {
|
|
70
70
|
const base = createFixture();
|
|
71
71
|
invalidateStateCache();
|
|
72
72
|
|
|
@@ -88,29 +88,31 @@ test("dispatch uat targets last completed slice, not activeSlice (#1693)", async
|
|
|
88
88
|
},
|
|
89
89
|
} as any;
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
91
|
+
try {
|
|
92
|
+
await dispatchDirectPhase(ctx, pi, "uat", base);
|
|
93
|
+
|
|
94
|
+
// Should have dispatched (sendMessage called)
|
|
95
|
+
assert.ok(sentPrompt, "sendMessage should have been called with a prompt");
|
|
96
|
+
|
|
97
|
+
// The dispatch notification should reference M001/S01 (completed), not M001/S02 (active)
|
|
98
|
+
const dispatchNotification = notifications.find(n => n.message.startsWith("Dispatching"));
|
|
99
|
+
assert.ok(dispatchNotification, "dispatch notification should be present");
|
|
100
|
+
assert.match(
|
|
101
|
+
dispatchNotification.message,
|
|
102
|
+
/M001\/S01/,
|
|
103
|
+
"dispatch should target completed slice S01, not active slice S02",
|
|
104
|
+
);
|
|
105
|
+
assert.doesNotMatch(
|
|
106
|
+
dispatchNotification.message,
|
|
107
|
+
/M001\/S02/,
|
|
108
|
+
"dispatch should NOT target active (next incomplete) slice S02",
|
|
109
|
+
);
|
|
110
|
+
} finally {
|
|
111
|
+
rmSync(base, { recursive: true, force: true });
|
|
112
|
+
}
|
|
111
113
|
});
|
|
112
114
|
|
|
113
|
-
test("dispatch uat warns when no completed slices exist", async (
|
|
115
|
+
test("dispatch uat warns when no completed slices exist", async () => {
|
|
114
116
|
const base = mkdtempSync(join(tmpdir(), "gsd-dispatch-uat-none-"));
|
|
115
117
|
invalidateStateCache();
|
|
116
118
|
|
|
@@ -162,11 +164,13 @@ test("dispatch uat warns when no completed slices exist", async (t) => {
|
|
|
162
164
|
},
|
|
163
165
|
} as any;
|
|
164
166
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
await dispatchDirectPhase(ctx, pi, "uat", base);
|
|
167
|
+
try {
|
|
168
|
+
await dispatchDirectPhase(ctx, pi, "uat", base);
|
|
168
169
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
const warning = notifications.find(n => n.level === "warning");
|
|
171
|
+
assert.ok(warning, "should show a warning notification");
|
|
172
|
+
assert.match(warning.message, /no completed slices/, "warning should mention no completed slices");
|
|
173
|
+
} finally {
|
|
174
|
+
rmSync(base, { recursive: true, force: true });
|
|
175
|
+
}
|
|
172
176
|
});
|
|
@@ -56,33 +56,35 @@ Done.
|
|
|
56
56
|
`);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
test("doctor does not report any reconciliation issue codes", async (
|
|
59
|
+
test("doctor does not report any reconciliation issue codes", async () => {
|
|
60
60
|
const tmp = makeTmp("no-reconciliation");
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
61
|
+
try {
|
|
62
|
+
buildScaffold(tmp);
|
|
63
|
+
|
|
64
|
+
const report = await runGSDDoctor(tmp, { fix: true, fixLevel: "task" });
|
|
65
|
+
|
|
66
|
+
const REMOVED_CODES = [
|
|
67
|
+
"task_done_missing_summary",
|
|
68
|
+
"task_summary_without_done_checkbox",
|
|
69
|
+
"all_tasks_done_missing_slice_summary",
|
|
70
|
+
"all_tasks_done_missing_slice_uat",
|
|
71
|
+
"all_tasks_done_roadmap_not_checked",
|
|
72
|
+
"slice_checked_missing_summary",
|
|
73
|
+
"slice_checked_missing_uat",
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
const codes = report.issues.map(i => i.code);
|
|
77
|
+
for (const removed of REMOVED_CODES) {
|
|
78
|
+
assert.ok(!codes.includes(removed as any), `should NOT report removed code: ${removed}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// No summary or UAT stubs should be created
|
|
82
|
+
const sliceSummaryPath = join(tmp, ".gsd", "milestones", "M001", "slices", "S01", "S01-SUMMARY.md");
|
|
83
|
+
assert.ok(!existsSync(sliceSummaryPath), "should NOT have created summary stub");
|
|
84
|
+
|
|
85
|
+
const sliceUatPath = join(tmp, ".gsd", "milestones", "M001", "slices", "S01", "S01-UAT.md");
|
|
86
|
+
assert.ok(!existsSync(sliceUatPath), "should NOT have created UAT stub");
|
|
87
|
+
} finally {
|
|
88
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
80
89
|
}
|
|
81
|
-
|
|
82
|
-
// No summary or UAT stubs should be created
|
|
83
|
-
const sliceSummaryPath = join(tmp, ".gsd", "milestones", "M001", "slices", "S01", "S01-SUMMARY.md");
|
|
84
|
-
assert.ok(!existsSync(sliceSummaryPath), "should NOT have created summary stub");
|
|
85
|
-
|
|
86
|
-
const sliceUatPath = join(tmp, ".gsd", "milestones", "M001", "slices", "S01", "S01-UAT.md");
|
|
87
|
-
assert.ok(!existsSync(sliceUatPath), "should NOT have created UAT stub");
|
|
88
90
|
});
|
|
@@ -12,7 +12,7 @@ import { join } from "node:path";
|
|
|
12
12
|
import { tmpdir } from "node:os";
|
|
13
13
|
import { runGSDDoctor } from "../doctor.js";
|
|
14
14
|
|
|
15
|
-
test("doctor fix=true sanitizes em-dash in milestone title", async (
|
|
15
|
+
test("doctor fix=true sanitizes em-dash in milestone title", async () => {
|
|
16
16
|
const tmpBase = mkdtempSync(join(tmpdir(), "gsd-doctor-delim-"));
|
|
17
17
|
const gsd = join(tmpBase, ".gsd");
|
|
18
18
|
const mDir = join(gsd, "milestones", "M001");
|
|
@@ -34,31 +34,33 @@ test("doctor fix=true sanitizes em-dash in milestone title", async (t) => {
|
|
|
34
34
|
writeFileSync(join(sDir, "S01-PLAN.md"), `# S01: Initial Setup\n\n## Tasks\n- [ ] **T01: Scaffold** \`est:15m\`\n`);
|
|
35
35
|
writeFileSync(join(tDir, "T01-PLAN.md"), "# T01: Scaffold\n");
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
37
|
+
try {
|
|
38
|
+
// Run doctor with fix=true
|
|
39
|
+
const report = await runGSDDoctor(tmpBase, { fix: true });
|
|
40
|
+
|
|
41
|
+
// The em-dash should have been replaced
|
|
42
|
+
const fixed = readFileSync(join(mDir, "M001-ROADMAP.md"), "utf-8");
|
|
43
|
+
const h1 = fixed.split("\n").find(l => l.startsWith("# "))!;
|
|
44
|
+
assert.ok(h1, "H1 line should exist");
|
|
45
|
+
assert.ok(!h1.includes("\u2014"), "em-dash should be replaced");
|
|
46
|
+
assert.ok(!h1.includes("\u2013"), "en-dash should be replaced");
|
|
47
|
+
assert.ok(h1.includes("-"), "should contain ASCII hyphen as replacement");
|
|
48
|
+
|
|
49
|
+
// Should have recorded the fix
|
|
50
|
+
assert.ok(
|
|
51
|
+
report.fixesApplied.some(f => f.includes("sanitized")),
|
|
52
|
+
`fixesApplied should mention sanitization, got: ${JSON.stringify(report.fixesApplied)}`,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
// The issue should NOT appear in the report (it was fixed)
|
|
56
|
+
const delimIssues = report.issues.filter(i => i.code === "delimiter_in_title" && i.unitId === "M001");
|
|
57
|
+
assert.equal(delimIssues.length, 0, "fixed issue should not appear in issues list");
|
|
58
|
+
} finally {
|
|
59
|
+
rmSync(tmpBase, { recursive: true, force: true });
|
|
60
|
+
}
|
|
59
61
|
});
|
|
60
62
|
|
|
61
|
-
test("doctor fix=false still reports delimiter_in_title as warning", async (
|
|
63
|
+
test("doctor fix=false still reports delimiter_in_title as warning", async () => {
|
|
62
64
|
const tmpBase = mkdtempSync(join(tmpdir(), "gsd-doctor-delim-nf-"));
|
|
63
65
|
const gsd = join(tmpBase, ".gsd");
|
|
64
66
|
const mDir = join(gsd, "milestones", "M001");
|
|
@@ -70,14 +72,16 @@ test("doctor fix=false still reports delimiter_in_title as warning", async (t) =
|
|
|
70
72
|
writeFileSync(join(sDir, "S01-PLAN.md"), `# S01: Setup\n\n## Tasks\n- [ ] **T01: Init** \`est:10m\`\n`);
|
|
71
73
|
writeFileSync(join(tDir, "T01-PLAN.md"), "# T01: Init\n");
|
|
72
74
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
try {
|
|
76
|
+
const report = await runGSDDoctor(tmpBase, { fix: false });
|
|
77
|
+
const delimIssues = report.issues.filter(i => i.code === "delimiter_in_title");
|
|
78
|
+
assert.ok(delimIssues.length > 0, "should report delimiter_in_title as issue when fix=false");
|
|
79
|
+
assert.equal(delimIssues[0].severity, "warning");
|
|
80
|
+
|
|
81
|
+
// File should be unchanged
|
|
82
|
+
const content = readFileSync(join(mDir, "M001-ROADMAP.md"), "utf-8");
|
|
83
|
+
assert.ok(content.includes("\u2014"), "file should not be modified when fix=false");
|
|
84
|
+
} finally {
|
|
85
|
+
rmSync(tmpBase, { recursive: true, force: true });
|
|
86
|
+
}
|
|
83
87
|
});
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { describe, test } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
1
|
import { mkdtempSync, mkdirSync, rmSync, writeFileSync, existsSync } from "node:fs";
|
|
4
2
|
import { join } from "node:path";
|
|
5
3
|
import { tmpdir } from "node:os";
|
|
6
4
|
|
|
7
5
|
import { runGSDDoctor } from "../doctor.js";
|
|
8
6
|
import { formatDoctorReportJson } from "../doctor-format.js";
|
|
7
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
8
|
+
|
|
9
|
+
const { assertEq, assertTrue, assertMatch, report } = createTestContext();
|
|
10
|
+
|
|
9
11
|
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
10
12
|
|
|
11
13
|
function makeBase(): { base: string; gsd: string; mDir: string } {
|
|
@@ -28,38 +30,41 @@ function writeSlice(mDir: string, sliceId: string, planContent: string): string
|
|
|
28
30
|
return sDir;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
async function main(): Promise<void> {
|
|
32
34
|
// ── 1. Circular dependency detection ──────────────────────────────────────
|
|
33
|
-
|
|
35
|
+
console.log("\n=== circular dependency detection ===");
|
|
36
|
+
{
|
|
34
37
|
const { base, mDir } = makeBase();
|
|
35
38
|
writeRoadmap(mDir, `# M001: Circular Test\n\n## Slices\n- [ ] **S01: Slice A** \`risk:low\` \`depends:[S02]\`\n > After this: done\n- [ ] **S02: Slice B** \`risk:low\` \`depends:[S01]\`\n > After this: done\n`);
|
|
36
39
|
writeSlice(mDir, "S01", "# S01: Slice A\n\n**Goal:** A\n**Demo:** A\n\n## Tasks\n- [ ] **T01: Task** `est:10m`\n Pending.\n");
|
|
37
40
|
writeSlice(mDir, "S02", "# S02: Slice B\n\n**Goal:** B\n**Demo:** B\n\n## Tasks\n- [ ] **T01: Task** `est:10m`\n Pending.\n");
|
|
38
41
|
|
|
39
42
|
const result = await runGSDDoctor(base, { fix: false });
|
|
40
|
-
|
|
43
|
+
assertTrue(
|
|
41
44
|
result.issues.some(i => i.code === "circular_slice_dependency"),
|
|
42
45
|
"detects circular dependency S01 → S02 → S01",
|
|
43
46
|
);
|
|
44
47
|
rmSync(base, { recursive: true, force: true });
|
|
45
|
-
}
|
|
48
|
+
}
|
|
46
49
|
|
|
47
50
|
// ── 2. Duplicate task IDs ──────────────────────────────────────────────────
|
|
48
|
-
|
|
51
|
+
console.log("\n=== duplicate task IDs ===");
|
|
52
|
+
{
|
|
49
53
|
const { base, mDir } = makeBase();
|
|
50
54
|
writeRoadmap(mDir, `# M001: Dup Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
51
55
|
writeSlice(mDir, "S01", "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [ ] **T01: First** `est:10m`\n Task one.\n- [ ] **T01: Duplicate** `est:10m`\n Task dup.\n");
|
|
52
56
|
|
|
53
57
|
const result = await runGSDDoctor(base, { fix: false });
|
|
54
|
-
|
|
58
|
+
assertTrue(
|
|
55
59
|
result.issues.some(i => i.code === "duplicate_task_id"),
|
|
56
60
|
"detects duplicate task ID T01",
|
|
57
61
|
);
|
|
58
62
|
rmSync(base, { recursive: true, force: true });
|
|
59
|
-
}
|
|
63
|
+
}
|
|
60
64
|
|
|
61
65
|
// ── 3. Orphaned slice directory ──────────────────────────────────────────
|
|
62
|
-
|
|
66
|
+
console.log("\n=== orphaned slice directory ===");
|
|
67
|
+
{
|
|
63
68
|
const { base, mDir } = makeBase();
|
|
64
69
|
writeRoadmap(mDir, `# M001: Orphan Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
65
70
|
writeSlice(mDir, "S01", "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [ ] **T01: Task** `est:10m`\n Pending.\n");
|
|
@@ -67,15 +72,16 @@ describe('doctor-enhancements', async () => {
|
|
|
67
72
|
mkdirSync(join(mDir, "slices", "S99"), { recursive: true });
|
|
68
73
|
|
|
69
74
|
const result = await runGSDDoctor(base, { fix: false });
|
|
70
|
-
|
|
75
|
+
assertTrue(
|
|
71
76
|
result.issues.some(i => i.code === "orphaned_slice_directory" && i.message.includes("S99")),
|
|
72
77
|
"detects orphaned slice directory S99",
|
|
73
78
|
);
|
|
74
79
|
rmSync(base, { recursive: true, force: true });
|
|
75
|
-
}
|
|
80
|
+
}
|
|
76
81
|
|
|
77
82
|
// ── 4. Task file not in plan ───────────────────────────────────────────────
|
|
78
|
-
|
|
83
|
+
console.log("\n=== task file not in plan ===");
|
|
84
|
+
{
|
|
79
85
|
const { base, mDir } = makeBase();
|
|
80
86
|
writeRoadmap(mDir, `# M001: Extra Task Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
81
87
|
const sDir = writeSlice(mDir, "S01", "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [x] **T01: Task** `est:10m`\n Done.\n");
|
|
@@ -85,15 +91,16 @@ describe('doctor-enhancements', async () => {
|
|
|
85
91
|
writeFileSync(join(sDir, "tasks", "T99-SUMMARY.md"), "---\nstatus: done\n---\n# T99\nExtra.\n");
|
|
86
92
|
|
|
87
93
|
const result = await runGSDDoctor(base, { fix: false });
|
|
88
|
-
|
|
94
|
+
assertTrue(
|
|
89
95
|
result.issues.some(i => i.code === "task_file_not_in_plan" && i.message.includes("T99")),
|
|
90
96
|
"detects task summary T99 not in plan",
|
|
91
97
|
);
|
|
92
98
|
rmSync(base, { recursive: true, force: true });
|
|
93
|
-
}
|
|
99
|
+
}
|
|
94
100
|
|
|
95
101
|
// ── 5. Stale REPLAN file ────────────────────────────────────────────────────
|
|
96
|
-
|
|
102
|
+
console.log("\n=== stale REPLAN detection ===");
|
|
103
|
+
{
|
|
97
104
|
const { base, mDir } = makeBase();
|
|
98
105
|
writeRoadmap(mDir, `# M001: Replan Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
99
106
|
const sDir = writeSlice(mDir, "S01", "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [x] **T01: Task** `est:10m`\n Done.\n");
|
|
@@ -102,15 +109,16 @@ describe('doctor-enhancements', async () => {
|
|
|
102
109
|
writeFileSync(join(sDir, "S01-REPLAN.md"), "# S01 REPLAN\nSomething changed.\n");
|
|
103
110
|
|
|
104
111
|
const result = await runGSDDoctor(base, { fix: false });
|
|
105
|
-
|
|
112
|
+
assertTrue(
|
|
106
113
|
result.issues.some(i => i.code === "stale_replan_file"),
|
|
107
114
|
"detects stale REPLAN when all tasks are done",
|
|
108
115
|
);
|
|
109
116
|
rmSync(base, { recursive: true, force: true });
|
|
110
|
-
}
|
|
117
|
+
}
|
|
111
118
|
|
|
112
119
|
// ── 6. Metrics ledger corrupt ───────────────────────────────────────────────
|
|
113
|
-
|
|
120
|
+
console.log("\n=== metrics ledger corrupt ===");
|
|
121
|
+
{
|
|
114
122
|
const { base, gsd, mDir } = makeBase();
|
|
115
123
|
writeRoadmap(mDir, `# M001: Metrics Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
116
124
|
writeSlice(mDir, "S01", "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [ ] **T01: Task** `est:10m`\n Pending.\n");
|
|
@@ -118,15 +126,16 @@ describe('doctor-enhancements', async () => {
|
|
|
118
126
|
writeFileSync(join(gsd, "metrics.json"), '{"version":2,"data":[]}');
|
|
119
127
|
|
|
120
128
|
const result = await runGSDDoctor(base, { fix: false });
|
|
121
|
-
|
|
129
|
+
assertTrue(
|
|
122
130
|
result.issues.some(i => i.code === "metrics_ledger_corrupt"),
|
|
123
131
|
"detects corrupt metrics ledger (version != 1)",
|
|
124
132
|
);
|
|
125
133
|
rmSync(base, { recursive: true, force: true });
|
|
126
|
-
}
|
|
134
|
+
}
|
|
127
135
|
|
|
128
136
|
// ── 7. Large planning file ──────────────────────────────────────────────────
|
|
129
|
-
|
|
137
|
+
console.log("\n=== large planning file ===");
|
|
138
|
+
{
|
|
130
139
|
const { base, mDir } = makeBase();
|
|
131
140
|
writeRoadmap(mDir, `# M001: Large File Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
132
141
|
const sDir = writeSlice(mDir, "S01", "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [ ] **T01: Task** `est:10m`\n Pending.\n");
|
|
@@ -135,15 +144,16 @@ describe('doctor-enhancements', async () => {
|
|
|
135
144
|
writeFileSync(join(sDir, "BIGFILE.md"), bigContent);
|
|
136
145
|
|
|
137
146
|
const result = await runGSDDoctor(base, { fix: false });
|
|
138
|
-
|
|
147
|
+
assertTrue(
|
|
139
148
|
result.issues.some(i => i.code === "large_planning_file"),
|
|
140
149
|
"detects large planning file over 100KB",
|
|
141
150
|
);
|
|
142
151
|
rmSync(base, { recursive: true, force: true });
|
|
143
|
-
}
|
|
152
|
+
}
|
|
144
153
|
|
|
145
154
|
// ── 8. Future timestamp ─────────────────────────────────────────────────────
|
|
146
|
-
|
|
155
|
+
console.log("\n=== future timestamp ===");
|
|
156
|
+
{
|
|
147
157
|
const { base, mDir } = makeBase();
|
|
148
158
|
writeRoadmap(mDir, `# M001: Timestamp Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
149
159
|
const sDir = writeSlice(mDir, "S01", "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [x] **T01: Task** `est:10m`\n Done.\n");
|
|
@@ -155,15 +165,16 @@ describe('doctor-enhancements', async () => {
|
|
|
155
165
|
);
|
|
156
166
|
|
|
157
167
|
const result = await runGSDDoctor(base, { fix: false });
|
|
158
|
-
|
|
168
|
+
assertTrue(
|
|
159
169
|
result.issues.some(i => i.code === "future_timestamp"),
|
|
160
170
|
"detects future completed_at timestamp",
|
|
161
171
|
);
|
|
162
172
|
rmSync(base, { recursive: true, force: true });
|
|
163
|
-
}
|
|
173
|
+
}
|
|
164
174
|
|
|
165
175
|
// ── 9. JSON output format ───────────────────────────────────────────────────
|
|
166
|
-
|
|
176
|
+
console.log("\n=== JSON output format ===");
|
|
177
|
+
{
|
|
167
178
|
const { base, mDir } = makeBase();
|
|
168
179
|
writeRoadmap(mDir, `# M001: JSON Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
169
180
|
writeSlice(mDir, "S01", "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [ ] **T01: Task** `est:10m`\n Pending.\n");
|
|
@@ -178,18 +189,19 @@ describe('doctor-enhancements', async () => {
|
|
|
178
189
|
parsed = null;
|
|
179
190
|
}
|
|
180
191
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
192
|
+
assertTrue(parsed !== null, "formatDoctorReportJson produces valid JSON");
|
|
193
|
+
assertTrue(typeof (parsed as Record<string, unknown>)?.ok === "boolean", "JSON has ok field");
|
|
194
|
+
assertTrue(Array.isArray((parsed as Record<string, unknown>)?.issues), "JSON has issues array");
|
|
195
|
+
assertTrue(Array.isArray((parsed as Record<string, unknown>)?.fixesApplied), "JSON has fixesApplied array");
|
|
196
|
+
assertTrue(typeof (parsed as Record<string, unknown>)?.generatedAt === "string", "JSON has generatedAt field");
|
|
197
|
+
assertTrue(typeof (parsed as Record<string, unknown>)?.summary === "object", "JSON has summary object");
|
|
187
198
|
|
|
188
199
|
rmSync(base, { recursive: true, force: true });
|
|
189
|
-
}
|
|
200
|
+
}
|
|
190
201
|
|
|
191
202
|
// ── 10. Dry-run mode ────────────────────────────────────────────────────────
|
|
192
|
-
|
|
203
|
+
console.log("\n=== dry-run mode ===");
|
|
204
|
+
{
|
|
193
205
|
const { base, mDir } = makeBase();
|
|
194
206
|
writeRoadmap(mDir, `# M001: Dry Run Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
195
207
|
writeSlice(mDir, "S01", "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [ ] **T01: Task** `est:10m`\n Pending.\n");
|
|
@@ -197,30 +209,32 @@ describe('doctor-enhancements', async () => {
|
|
|
197
209
|
const result = await runGSDDoctor(base, { fix: true, dryRun: true });
|
|
198
210
|
// dry-run with fix:true still runs the doctor; shouldFix() returns false
|
|
199
211
|
// so no reconciliation fixes are applied through that path
|
|
200
|
-
|
|
201
|
-
|
|
212
|
+
assertTrue(result.issues !== undefined, "dry-run still produces issue list");
|
|
213
|
+
assertTrue(Array.isArray(result.fixesApplied), "dry-run report has fixesApplied array");
|
|
202
214
|
|
|
203
215
|
rmSync(base, { recursive: true, force: true });
|
|
204
|
-
}
|
|
216
|
+
}
|
|
205
217
|
|
|
206
218
|
// ── 11. Per-check timing ─────────────────────────────────────────────────────
|
|
207
|
-
|
|
219
|
+
console.log("\n=== per-check timing ===");
|
|
220
|
+
{
|
|
208
221
|
const { base, mDir } = makeBase();
|
|
209
222
|
writeRoadmap(mDir, `# M001: Timing Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
210
223
|
writeSlice(mDir, "S01", "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [ ] **T01: Task** `est:10m`\n Pending.\n");
|
|
211
224
|
|
|
212
225
|
const result = await runGSDDoctor(base, { fix: false });
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
226
|
+
assertTrue(result.timing !== undefined, "report includes timing");
|
|
227
|
+
assertTrue(typeof result.timing?.git === "number", "timing.git is a number");
|
|
228
|
+
assertTrue(typeof result.timing?.runtime === "number", "timing.runtime is a number");
|
|
229
|
+
assertTrue(typeof result.timing?.environment === "number", "timing.environment is a number");
|
|
230
|
+
assertTrue(typeof result.timing?.gsdState === "number", "timing.gsdState is a number");
|
|
218
231
|
|
|
219
232
|
rmSync(base, { recursive: true, force: true });
|
|
220
|
-
}
|
|
233
|
+
}
|
|
221
234
|
|
|
222
235
|
// ── 12. Doctor history ───────────────────────────────────────────────────────
|
|
223
|
-
|
|
236
|
+
console.log("\n=== doctor history ===");
|
|
237
|
+
{
|
|
224
238
|
const { base, gsd, mDir } = makeBase();
|
|
225
239
|
writeRoadmap(mDir, `# M001: History Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
226
240
|
writeSlice(mDir, "S01", "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [ ] **T01: Task** `est:10m`\n Pending.\n");
|
|
@@ -228,16 +242,23 @@ describe('doctor-enhancements', async () => {
|
|
|
228
242
|
await runGSDDoctor(base, { fix: false });
|
|
229
243
|
|
|
230
244
|
const historyPath = join(gsd, "doctor-history.jsonl");
|
|
231
|
-
|
|
245
|
+
assertTrue(existsSync(historyPath), "doctor-history.jsonl is created after run");
|
|
232
246
|
|
|
233
247
|
const { readDoctorHistory } = await import("../doctor.js");
|
|
234
248
|
const history = await readDoctorHistory(base);
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
249
|
+
assertTrue(history.length >= 1, "history has at least one entry");
|
|
250
|
+
assertTrue(typeof history[0]?.ts === "string", "history entry has ts field");
|
|
251
|
+
assertTrue(typeof history[0]?.ok === "boolean", "history entry has ok field");
|
|
252
|
+
assertTrue(typeof history[0]?.errors === "number", "history entry has errors count");
|
|
253
|
+
assertTrue(Array.isArray(history[0]?.codes), "history entry has codes array");
|
|
240
254
|
|
|
241
255
|
rmSync(base, { recursive: true, force: true });
|
|
242
|
-
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
report();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
main().catch(err => {
|
|
262
|
+
console.error(err);
|
|
263
|
+
process.exit(1);
|
|
243
264
|
});
|