gsd-pi 2.78.1-dev.b0759e59b → 2.78.1-dev.d8826a445

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.
Files changed (300) hide show
  1. package/README.md +8 -5
  2. package/dist/headless-recover.d.ts +23 -0
  3. package/dist/headless-recover.js +93 -0
  4. package/dist/headless.js +9 -0
  5. package/dist/help-text.js +1 -0
  6. package/dist/resources/.managed-resources-content-hash +1 -1
  7. package/dist/resources/extensions/browser-tools/tools/intent.js +8 -1
  8. package/dist/resources/extensions/gsd/auto/phases.js +7 -2
  9. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +7 -58
  11. package/dist/resources/extensions/gsd/auto-post-unit.js +14 -28
  12. package/dist/resources/extensions/gsd/auto-start.js +1 -8
  13. package/dist/resources/extensions/gsd/auto-worktree.js +244 -216
  14. package/dist/resources/extensions/gsd/auto.js +86 -7
  15. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +1 -1
  16. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +9 -77
  17. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -16
  18. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -55
  19. package/dist/resources/extensions/gsd/commands-codebase.js +2 -2
  20. package/dist/resources/extensions/gsd/commands-handlers.js +5 -5
  21. package/dist/resources/extensions/gsd/commands-logs.js +2 -2
  22. package/dist/resources/extensions/gsd/commands-scan.js +2 -2
  23. package/dist/resources/extensions/gsd/commands-ship.js +2 -2
  24. package/dist/resources/extensions/gsd/commands-workflow-templates.js +5 -5
  25. package/dist/resources/extensions/gsd/db-writer.js +106 -95
  26. package/dist/resources/extensions/gsd/delegation-policy.js +155 -0
  27. package/dist/resources/extensions/gsd/dispatch-guard.js +6 -10
  28. package/dist/resources/extensions/gsd/doctor-engine-checks.js +2 -2
  29. package/dist/resources/extensions/gsd/gsd-db.js +268 -8
  30. package/dist/resources/extensions/gsd/guided-flow-queue.js +1 -1
  31. package/dist/resources/extensions/gsd/guided-flow.js +141 -32
  32. package/dist/resources/extensions/gsd/markdown-renderer.js +14 -51
  33. package/dist/resources/extensions/gsd/metrics.js +287 -1
  34. package/dist/resources/extensions/gsd/parallel-merge.js +14 -13
  35. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +5 -2
  36. package/dist/resources/extensions/gsd/paths.js +114 -9
  37. package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -4
  38. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -3
  39. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +8 -1
  40. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +22 -7
  41. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +6 -2
  42. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -1
  43. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +6 -0
  44. package/dist/resources/extensions/gsd/queue-order.js +6 -1
  45. package/dist/resources/extensions/gsd/rethink.js +2 -2
  46. package/dist/resources/extensions/gsd/state.js +91 -372
  47. package/dist/resources/extensions/gsd/templates/project.md +10 -0
  48. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -5
  49. package/dist/resources/extensions/gsd/tools/complete-slice.js +7 -12
  50. package/dist/resources/extensions/gsd/tools/complete-task.js +19 -31
  51. package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -5
  52. package/dist/resources/extensions/gsd/workflow-manifest.js +2 -1
  53. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +3 -21
  54. package/dist/resources/extensions/gsd/workflow-mcp.js +2 -2
  55. package/dist/resources/extensions/gsd/workflow-reconcile.js +3 -3
  56. package/dist/resources/extensions/gsd/workspace.js +59 -0
  57. package/dist/resources/extensions/gsd/worktree-command.js +4 -3
  58. package/dist/resources/extensions/gsd/worktree-resolver.js +15 -2
  59. package/dist/resources/extensions/gsd/write-intercept.js +3 -3
  60. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  61. package/dist/web/standalone/.next/BUILD_ID +1 -1
  62. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  63. package/dist/web/standalone/.next/build-manifest.json +2 -2
  64. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  65. package/dist/web/standalone/.next/required-server-files.json +1 -1
  66. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  67. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  75. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  83. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  84. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  85. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  86. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  87. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  88. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  89. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  90. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  91. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  92. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  93. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  94. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  95. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  96. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  97. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  98. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  99. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  100. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  101. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  102. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  103. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  104. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  105. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  106. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  107. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  108. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  109. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  110. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  111. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  112. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  113. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  114. package/dist/web/standalone/.next/server/app/index.html +1 -1
  115. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  122. package/dist/web/standalone/.next/server/chunks/6336.js +1 -0
  123. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  124. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  126. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  127. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  128. package/dist/web/standalone/server.js +1 -1
  129. package/package.json +1 -1
  130. package/packages/mcp-server/README.md +2 -11
  131. package/packages/mcp-server/dist/remote-questions.d.ts +27 -0
  132. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
  133. package/packages/mcp-server/dist/remote-questions.js +28 -0
  134. package/packages/mcp-server/dist/remote-questions.js.map +1 -1
  135. package/packages/mcp-server/dist/server.d.ts +28 -0
  136. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  137. package/packages/mcp-server/dist/server.js +94 -4
  138. package/packages/mcp-server/dist/server.js.map +1 -1
  139. package/packages/mcp-server/dist/workflow-tools.d.ts +6 -0
  140. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  141. package/packages/mcp-server/dist/workflow-tools.js +56 -2
  142. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  143. package/packages/mcp-server/src/mcp-server.test.ts +226 -0
  144. package/packages/mcp-server/src/parse-workflow-args.test.ts +80 -0
  145. package/packages/mcp-server/src/remote-questions.test.ts +103 -0
  146. package/packages/mcp-server/src/remote-questions.ts +35 -0
  147. package/packages/mcp-server/src/server.ts +129 -6
  148. package/packages/mcp-server/src/workflow-tools.ts +62 -3
  149. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  150. package/src/resources/extensions/browser-tools/tools/intent.ts +13 -2
  151. package/src/resources/extensions/gsd/auto/phases.ts +8 -2
  152. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  153. package/src/resources/extensions/gsd/auto-dispatch.ts +14 -62
  154. package/src/resources/extensions/gsd/auto-post-unit.ts +15 -27
  155. package/src/resources/extensions/gsd/auto-start.ts +1 -8
  156. package/src/resources/extensions/gsd/auto-worktree.ts +286 -251
  157. package/src/resources/extensions/gsd/auto.ts +102 -7
  158. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +1 -1
  159. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +9 -84
  160. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +17 -17
  161. package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +103 -0
  162. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +80 -55
  163. package/src/resources/extensions/gsd/commands-codebase.ts +2 -2
  164. package/src/resources/extensions/gsd/commands-handlers.ts +5 -5
  165. package/src/resources/extensions/gsd/commands-logs.ts +2 -2
  166. package/src/resources/extensions/gsd/commands-scan.ts +2 -2
  167. package/src/resources/extensions/gsd/commands-ship.ts +2 -2
  168. package/src/resources/extensions/gsd/commands-workflow-templates.ts +5 -5
  169. package/src/resources/extensions/gsd/db-writer.ts +123 -94
  170. package/src/resources/extensions/gsd/delegation-policy.ts +197 -0
  171. package/src/resources/extensions/gsd/dispatch-guard.ts +6 -11
  172. package/src/resources/extensions/gsd/doctor-engine-checks.ts +2 -2
  173. package/src/resources/extensions/gsd/gsd-db.ts +269 -8
  174. package/src/resources/extensions/gsd/guided-flow-queue.ts +1 -1
  175. package/src/resources/extensions/gsd/guided-flow.ts +181 -32
  176. package/src/resources/extensions/gsd/markdown-renderer.ts +13 -64
  177. package/src/resources/extensions/gsd/metrics.ts +321 -1
  178. package/src/resources/extensions/gsd/parallel-merge.ts +14 -13
  179. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +5 -2
  180. package/src/resources/extensions/gsd/paths.ts +122 -9
  181. package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -4
  182. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -3
  183. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +8 -1
  184. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +22 -7
  185. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +6 -2
  186. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -1
  187. package/src/resources/extensions/gsd/prompts/plan-milestone.md +6 -0
  188. package/src/resources/extensions/gsd/queue-order.ts +6 -1
  189. package/src/resources/extensions/gsd/rethink.ts +2 -2
  190. package/src/resources/extensions/gsd/state.ts +91 -389
  191. package/src/resources/extensions/gsd/templates/project.md +10 -0
  192. package/src/resources/extensions/gsd/tests/artifact-corruption-2630.test.ts +1 -0
  193. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +14 -14
  194. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +6 -0
  195. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +21 -34
  196. package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +331 -0
  197. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +176 -0
  198. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +6 -7
  199. package/src/resources/extensions/gsd/tests/complete-task.test.ts +8 -6
  200. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +12 -27
  201. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +18 -5
  202. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +4 -4
  203. package/src/resources/extensions/gsd/tests/db-writer-path-containment.test.ts +152 -0
  204. package/src/resources/extensions/gsd/tests/db-writer-root-artifact.test.ts +221 -0
  205. package/src/resources/extensions/gsd/tests/db-writer-scope.test.ts +230 -0
  206. package/src/resources/extensions/gsd/tests/db-writer.test.ts +14 -16
  207. package/src/resources/extensions/gsd/tests/delegation-policy.test.ts +151 -0
  208. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +6 -5
  209. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +10 -38
  210. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +136 -56
  211. package/src/resources/extensions/gsd/tests/derive-state-draft.test.ts +3 -0
  212. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +119 -61
  213. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -0
  214. package/src/resources/extensions/gsd/tests/dispatch-backgroundable-annotation.test.ts +55 -0
  215. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +6 -20
  216. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +4 -5
  217. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +14 -15
  218. package/src/resources/extensions/gsd/tests/draft-promotion.test.ts +3 -23
  219. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +11 -16
  220. package/src/resources/extensions/gsd/tests/escalation.test.ts +2 -1
  221. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +193 -0
  222. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +246 -0
  223. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +218 -0
  224. package/src/resources/extensions/gsd/tests/gsd-db-failed-open-restore.test.ts +117 -0
  225. package/src/resources/extensions/gsd/tests/gsd-db-workspace-scope.test.ts +226 -0
  226. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +2 -1
  227. package/src/resources/extensions/gsd/tests/gsd-root-canonical.test.ts +66 -0
  228. package/src/resources/extensions/gsd/tests/gsd-root-home-guard.test.ts +68 -5
  229. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +15 -36
  230. package/src/resources/extensions/gsd/tests/guided-flow-prompt-consolidation.test.ts +4 -4
  231. package/src/resources/extensions/gsd/tests/handler-worktree-write-isolation.test.ts +57 -0
  232. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +15 -15
  233. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +15 -5
  234. package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +371 -0
  235. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +14 -8
  236. package/src/resources/extensions/gsd/tests/md-importer.test.ts +2 -1
  237. package/src/resources/extensions/gsd/tests/memory-store.test.ts +3 -2
  238. package/src/resources/extensions/gsd/tests/metrics-atomic-merge.test.ts +222 -0
  239. package/src/resources/extensions/gsd/tests/metrics-lock-hardening.test.ts +400 -0
  240. package/src/resources/extensions/gsd/tests/metrics-lock-not-acquired.test.ts +141 -0
  241. package/src/resources/extensions/gsd/tests/metrics-lock-retry-sleep.test.ts +287 -0
  242. package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +149 -0
  243. package/src/resources/extensions/gsd/tests/metrics-scope.test.ts +378 -0
  244. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +329 -0
  245. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +2 -0
  246. package/src/resources/extensions/gsd/tests/path-cache-decoupled.test.ts +209 -0
  247. package/src/resources/extensions/gsd/tests/path-normalization-unified.test.ts +175 -0
  248. package/src/resources/extensions/gsd/tests/paths-cache.test.ts +170 -0
  249. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +120 -0
  250. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +25 -16
  251. package/src/resources/extensions/gsd/tests/projection-regression.test.ts +1 -0
  252. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +150 -7
  253. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +184 -0
  254. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +6 -1
  255. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +28 -16
  256. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +3 -0
  257. package/src/resources/extensions/gsd/tests/resolve-ts.mjs +4 -0
  258. package/src/resources/extensions/gsd/tests/resume-missing-worktree-warning.test.ts +209 -0
  259. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +3 -4
  260. package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +10 -56
  261. package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +15 -16
  262. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
  263. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +23 -27
  264. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +13 -14
  265. package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +4 -3
  266. package/src/resources/extensions/gsd/tests/sync-layer-scope.test.ts +453 -0
  267. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +10 -33
  268. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +162 -0
  269. package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +102 -0
  270. package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +186 -0
  271. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +1 -1
  272. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +7 -8
  273. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +9 -15
  274. package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +239 -0
  275. package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +12 -7
  276. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +4 -4
  277. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +26 -3
  278. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +9 -15
  279. package/src/resources/extensions/gsd/tests/workspace.test.ts +190 -0
  280. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +13 -0
  281. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +65 -71
  282. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +26 -151
  283. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +35 -35
  284. package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -52
  285. package/src/resources/extensions/gsd/tests/write-intercept.test.ts +1 -1
  286. package/src/resources/extensions/gsd/tools/complete-milestone.ts +7 -5
  287. package/src/resources/extensions/gsd/tools/complete-slice.ts +7 -14
  288. package/src/resources/extensions/gsd/tools/complete-task.ts +19 -34
  289. package/src/resources/extensions/gsd/tools/validate-milestone.ts +7 -5
  290. package/src/resources/extensions/gsd/workflow-manifest.ts +4 -1
  291. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -18
  292. package/src/resources/extensions/gsd/workflow-mcp.ts +2 -2
  293. package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
  294. package/src/resources/extensions/gsd/workspace.ts +95 -0
  295. package/src/resources/extensions/gsd/worktree-command.ts +4 -3
  296. package/src/resources/extensions/gsd/worktree-resolver.ts +16 -2
  297. package/src/resources/extensions/gsd/write-intercept.ts +3 -3
  298. package/dist/web/standalone/.next/server/chunks/8527.js +0 -1
  299. /package/dist/web/standalone/.next/static/{rk1EN3FQTE6Z1yalkW_GE → AT5qi39nKXkdmQIOIoh0f}/_buildManifest.js +0 -0
  300. /package/dist/web/standalone/.next/static/{rk1EN3FQTE6Z1yalkW_GE → AT5qi39nKXkdmQIOIoh0f}/_ssgManifest.js +0 -0
@@ -5,8 +5,8 @@
5
5
  * from the main repo's .gsd/ into the worktree's .gsd/ for the
6
6
  * specified milestone, and deletes gsd.db so it rebuilds from fresh state.
7
7
  *
8
- * Also verifies that syncWorktreeStateBack recurses into tasks/ subdirectories
9
- * so task-level summaries are not dropped on milestone teardown (#1678).
8
+ * Also verifies that syncWorktreeStateBack does not import worktree markdown
9
+ * projections back into the project root.
10
10
  *
11
11
  * Covers:
12
12
  * - Milestone directory synced from main to worktree
@@ -15,12 +15,12 @@
15
15
  * - No-op when paths are equal
16
16
  * - No-op when milestoneId is null
17
17
  * - Non-existent directories handled gracefully
18
- * - syncWorktreeStateBack recurses into tasks/ subdirectory (#1678)
19
- * - syncWorktreeStateBack syncs root-level .gsd/ files (REQUIREMENTS, PROJECT, etc.)
20
- * - syncWorktreeStateBack syncs ALL milestone directories, not just the current one
21
- * - syncWorktreeStateBack handles next-milestone artifacts created during completion
18
+ * - syncWorktreeStateBack skips milestone markdown projections
19
+ * - syncWorktreeStateBack does not import root-level .gsd/ state projections
20
+ * - syncWorktreeStateBack does not copy worktree milestone projections back
21
+ * - syncWorktreeStateBack leaves next-milestone projections DB/project-root authoritative
22
22
  * - syncGsdStateToWorktree syncs non-standard milestone dir names (#1547)
23
- * - syncWorktreeStateBack syncs non-standard milestone dir names (#1547)
23
+ * - syncWorktreeStateBack skips non-standard milestone projection dir names
24
24
  */
25
25
 
26
26
  import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, readFileSync } from 'node:fs';
@@ -213,8 +213,8 @@ describe('worktree-sync-milestones', async () => {
213
213
  }
214
214
  }
215
215
 
216
- // ─── 8. syncWorktreeStateBack recurses into tasks/ (#1678) ───────────
217
- console.log('\n=== 8. syncWorktreeStateBack copies tasks/ subdirectory (#1678) ===');
216
+ // ─── 8. syncWorktreeStateBack does not copy task projections ───────────
217
+ console.log('\n=== 8. syncWorktreeStateBack leaves task projections in worktree ===');
218
218
  {
219
219
  const mainBase = mkdtempSync(join(tmpdir(), 'gsd-wt-back-main-'));
220
220
  const wtBase = mkdtempSync(join(tmpdir(), 'gsd-wt-back-wt-'));
@@ -232,27 +232,26 @@ describe('worktree-sync-milestones', async () => {
232
232
  // Main project root starts with only the milestone directory (no slices yet)
233
233
  mkdirSync(join(mainBase, '.gsd', 'milestones', 'M002'), { recursive: true });
234
234
 
235
- // Pass M001 as milestoneId (the one being merged/skipped), M002 should still sync
236
235
  const { synced } = syncWorktreeStateBack(mainBase, wtBase, 'M001');
237
236
 
238
237
  const mainSliceDir = join(mainBase, '.gsd', 'milestones', 'M002', 'slices', 'S01');
239
238
  const mainTasksDir = join(mainSliceDir, 'tasks');
240
239
 
241
240
  assert.ok(
242
- existsSync(join(mainSliceDir, 'S01-SUMMARY.md')),
243
- '#1678: slice SUMMARY synced to project root',
241
+ !existsSync(join(mainSliceDir, 'S01-SUMMARY.md')),
242
+ 'slice SUMMARY projection is not copied to project root',
244
243
  );
245
244
  assert.ok(
246
- existsSync(join(mainTasksDir, 'T01-SUMMARY.md')),
247
- '#1678: task T01-SUMMARY synced to project root',
245
+ !existsSync(join(mainTasksDir, 'T01-SUMMARY.md')),
246
+ 'task T01-SUMMARY projection is not copied to project root',
248
247
  );
249
248
  assert.ok(
250
- existsSync(join(mainTasksDir, 'T02-SUMMARY.md')),
251
- '#1678: task T02-SUMMARY synced to project root',
249
+ !existsSync(join(mainTasksDir, 'T02-SUMMARY.md')),
250
+ 'task T02-SUMMARY projection is not copied to project root',
252
251
  );
253
252
  assert.ok(
254
- synced.some((p) => p.includes('tasks/T01-SUMMARY.md')),
255
- '#1678: task summary appears in synced list',
253
+ !synced.some((p) => p.includes('tasks/T01-SUMMARY.md')),
254
+ 'task summary does not appear in synced list',
256
255
  );
257
256
  } finally {
258
257
  rmSync(mainBase, { recursive: true, force: true });
@@ -260,8 +259,8 @@ describe('worktree-sync-milestones', async () => {
260
259
  }
261
260
  }
262
261
 
263
- // ─── 9. syncWorktreeStateBack syncs root-level .gsd/ files ──────────
264
- console.log('\n=== 9. syncWorktreeStateBack syncs root-level files (REQUIREMENTS, PROJECT) ===');
262
+ // ─── 9. syncWorktreeStateBack does not import root-level state projections ──────────
263
+ console.log('\n=== 9. syncWorktreeStateBack leaves root-level state projections authoritative ===');
265
264
  {
266
265
  const mainBase = mkdtempSync(join(tmpdir(), 'gsd-wt-back-root-main-'));
267
266
  const wtBase = mkdtempSync(join(tmpdir(), 'gsd-wt-back-root-wt-'));
@@ -281,31 +280,31 @@ describe('worktree-sync-milestones', async () => {
281
280
 
282
281
  const { synced } = syncWorktreeStateBack(mainBase, wtBase, 'M001');
283
282
 
284
- // Root-level files should be overwritten with worktree versions
283
+ // Root-level state projections must not be overwritten with worktree versions.
285
284
  const reqContent = readFileSync(join(mainBase, '.gsd', 'REQUIREMENTS.md'), 'utf-8');
286
285
  assert.ok(
287
- reqContent.includes('R002'),
288
- 'REQUIREMENTS.md updated with worktree content',
286
+ !reqContent.includes('R002'),
287
+ 'REQUIREMENTS.md ignores worktree projection content',
289
288
  );
290
289
 
291
290
  const projContent = readFileSync(join(mainBase, '.gsd', 'PROJECT.md'), 'utf-8');
292
291
  assert.ok(
293
- projContent.includes('M002'),
294
- 'PROJECT.md updated with worktree content',
292
+ !projContent.includes('M002'),
293
+ 'PROJECT.md ignores worktree projection content',
295
294
  );
296
295
 
297
296
  assert.ok(
298
- existsSync(join(mainBase, '.gsd', 'KNOWLEDGE.md')),
299
- 'KNOWLEDGE.md synced from worktree',
297
+ !existsSync(join(mainBase, '.gsd', 'KNOWLEDGE.md')),
298
+ 'KNOWLEDGE.md is not copied back from worktree',
300
299
  );
301
300
 
302
301
  assert.ok(
303
- synced.includes('REQUIREMENTS.md'),
304
- 'REQUIREMENTS.md appears in synced list',
302
+ !synced.includes('REQUIREMENTS.md'),
303
+ 'REQUIREMENTS.md does not appear in synced list',
305
304
  );
306
305
  assert.ok(
307
- synced.includes('PROJECT.md'),
308
- 'PROJECT.md appears in synced list',
306
+ !synced.includes('PROJECT.md'),
307
+ 'PROJECT.md does not appear in synced list',
309
308
  );
310
309
  } finally {
311
310
  rmSync(mainBase, { recursive: true, force: true });
@@ -313,8 +312,8 @@ describe('worktree-sync-milestones', async () => {
313
312
  }
314
313
  }
315
314
 
316
- // ─── 10. syncWorktreeStateBack syncs ALL milestone directories ─────
317
- console.log('\n=== 10. syncWorktreeStateBack syncs all milestone dirs, not just current ===');
315
+ // ─── 10. syncWorktreeStateBack does not copy milestone directories ─────
316
+ console.log('\n=== 10. syncWorktreeStateBack does not copy milestone dirs ===');
318
317
  {
319
318
  const mainBase = mkdtempSync(join(tmpdir(), 'gsd-wt-back-all-main-'));
320
319
  const wtBase = mkdtempSync(join(tmpdir(), 'gsd-wt-back-all-wt-'));
@@ -352,19 +351,19 @@ describe('worktree-sync-milestones', async () => {
352
351
  'M001 SUMMARY NOT synced (current milestone skipped to prevent merge conflicts)',
353
352
  );
354
353
 
355
- // M002 should be synced (other milestone not skipped)
354
+ // M002 should not be synced either; worktree projections are not authoritative.
356
355
  assert.ok(
357
- existsSync(join(mainBase, '.gsd', 'milestones', 'M002-abc123', 'M002-abc123-CONTEXT.md')),
358
- 'M002 CONTEXT synced to main (next-milestone fix)',
356
+ !existsSync(join(mainBase, '.gsd', 'milestones', 'M002-abc123', 'M002-abc123-CONTEXT.md')),
357
+ 'M002 CONTEXT projection is not copied to main',
359
358
  );
360
359
  assert.ok(
361
- existsSync(join(mainBase, '.gsd', 'milestones', 'M002-abc123', 'M002-abc123-ROADMAP.md')),
362
- 'M002 ROADMAP synced to main (next-milestone fix)',
360
+ !existsSync(join(mainBase, '.gsd', 'milestones', 'M002-abc123', 'M002-abc123-ROADMAP.md')),
361
+ 'M002 ROADMAP projection is not copied to main',
363
362
  );
364
363
 
365
364
  assert.ok(
366
- synced.some((p) => p.includes('M002-abc123')),
367
- 'M002 appears in synced list',
365
+ !synced.some((p) => p.includes('M002-abc123')),
366
+ 'M002 does not appear in synced list',
368
367
  );
369
368
  } finally {
370
369
  rmSync(mainBase, { recursive: true, force: true });
@@ -373,7 +372,7 @@ describe('worktree-sync-milestones', async () => {
373
372
  }
374
373
 
375
374
  // ─── 11. Full M006→M007 transition scenario ───────────────────────────
376
- console.log('\n=== 11. complete-milestone creates next-milestone artifacts that survive sync ===');
375
+ console.log('\n=== 11. complete-milestone worktree projections do not overwrite project root ===');
377
376
  {
378
377
  const mainBase = mkdtempSync(join(tmpdir(), 'gsd-wt-transition-main-'));
379
378
  const wtBase = mkdtempSync(join(tmpdir(), 'gsd-wt-transition-wt-'));
@@ -419,27 +418,27 @@ describe('worktree-sync-milestones', async () => {
419
418
  'M006 SUMMARY NOT synced (current milestone skipped)',
420
419
  );
421
420
 
422
- // Verify M007 artifacts synced (the critical fix — other milestones still sync)
421
+ // Verify M007 worktree projections are not copied back.
423
422
  assert.ok(
424
- existsSync(join(mainBase, '.gsd', 'milestones', 'M007-wortc8', 'M007-wortc8-CONTEXT.md')),
425
- 'M007 CONTEXT synced to main (next-milestone)',
423
+ !existsSync(join(mainBase, '.gsd', 'milestones', 'M007-wortc8', 'M007-wortc8-CONTEXT.md')),
424
+ 'M007 CONTEXT projection is not copied to main',
426
425
  );
427
426
  assert.ok(
428
- existsSync(join(mainBase, '.gsd', 'milestones', 'M007-wortc8', 'M007-wortc8-ROADMAP.md')),
429
- 'M007 ROADMAP synced to main (next-milestone)',
427
+ !existsSync(join(mainBase, '.gsd', 'milestones', 'M007-wortc8', 'M007-wortc8-ROADMAP.md')),
428
+ 'M007 ROADMAP projection is not copied to main',
430
429
  );
431
430
 
432
- // Verify root-level files updated
431
+ // Verify root-level projections remain project-root authoritative.
433
432
  const reqContent = readFileSync(join(mainBase, '.gsd', 'REQUIREMENTS.md'), 'utf-8');
434
433
  assert.ok(
435
- reqContent.includes('R090'),
436
- 'REQUIREMENTS.md has R090 from worktree',
434
+ !reqContent.includes('R090'),
435
+ 'REQUIREMENTS.md ignores worktree projection updates',
437
436
  );
438
437
 
439
438
  const projContent = readFileSync(join(mainBase, '.gsd', 'PROJECT.md'), 'utf-8');
440
439
  assert.ok(
441
- projContent.includes('M007'),
442
- 'PROJECT.md has M007 from worktree',
440
+ !projContent.includes('M007'),
441
+ 'PROJECT.md ignores worktree projection updates',
443
442
  );
444
443
  } finally {
445
444
  rmSync(mainBase, { recursive: true, force: true });
@@ -478,8 +477,8 @@ describe('worktree-sync-milestones', async () => {
478
477
  }
479
478
  }
480
479
 
481
- // ─── 13. syncWorktreeStateBack syncs QUEUE.md and completed-units.json (#1787) ──
482
- console.log('\n=== 13. QUEUE.md and completed-units.json synced from worktree (#1787) ===');
480
+ // ─── 13. syncWorktreeStateBack skips QUEUE.md but preserves completed-units diagnostics ──
481
+ console.log('\n=== 13. QUEUE.md skipped; completed-units.json diagnostic synced ===');
483
482
  {
484
483
  const mainBase = mkdtempSync(join(tmpdir(), 'gsd-wt-back-queue-main-'));
485
484
  const wtBase = mkdtempSync(join(tmpdir(), 'gsd-wt-back-queue-wt-'));
@@ -488,7 +487,7 @@ describe('worktree-sync-milestones', async () => {
488
487
  mkdirSync(join(mainBase, '.gsd', 'milestones', 'M001'), { recursive: true });
489
488
  mkdirSync(join(wtBase, '.gsd', 'milestones', 'M001'), { recursive: true });
490
489
 
491
- // Worktree has QUEUE.md and completed-units.json written during milestone closeout
490
+ // Worktree has QUEUE.md projection and completed-units.json diagnostic.
492
491
  writeFileSync(join(wtBase, '.gsd', 'QUEUE.md'), '# Queue\n- M002 next');
493
492
  writeFileSync(
494
493
  join(wtBase, '.gsd', 'completed-units.json'),
@@ -507,22 +506,17 @@ describe('worktree-sync-milestones', async () => {
507
506
 
508
507
  const { synced } = syncWorktreeStateBack(mainBase, wtBase, 'M001');
509
508
 
510
- // QUEUE.md should be synced
511
- assert.ok(
512
- existsSync(join(mainBase, '.gsd', 'QUEUE.md')),
513
- '#1787: QUEUE.md synced from worktree to main',
514
- );
515
- const queueContent = readFileSync(join(mainBase, '.gsd', 'QUEUE.md'), 'utf-8');
509
+ // QUEUE.md is state/projection content and should not be copied back.
516
510
  assert.ok(
517
- queueContent.includes('M002 next'),
518
- '#1787: QUEUE.md has correct content',
511
+ !existsSync(join(mainBase, '.gsd', 'QUEUE.md')),
512
+ 'QUEUE.md is not synced from worktree to main',
519
513
  );
520
514
  assert.ok(
521
- synced.includes('QUEUE.md'),
522
- '#1787: QUEUE.md appears in synced list',
515
+ !synced.includes('QUEUE.md'),
516
+ 'QUEUE.md does not appear in synced list',
523
517
  );
524
518
 
525
- // completed-units.json should be synced
519
+ // completed-units.json is diagnostic and may be copied for operator visibility.
526
520
  assert.ok(
527
521
  existsSync(join(mainBase, '.gsd', 'completed-units.json')),
528
522
  '#1787: completed-units.json synced from worktree to main',
@@ -578,8 +572,8 @@ describe('worktree-sync-milestones', async () => {
578
572
  }
579
573
  }
580
574
 
581
- // ─── 15. syncWorktreeStateBack syncs non-standard milestone dir names (#1547) ──
582
- console.log('\n=== 15. syncWorktreeStateBack syncs non-standard milestone dir names (#1547) ===');
575
+ // ─── 15. syncWorktreeStateBack skips non-standard milestone dir names ──
576
+ console.log('\n=== 15. syncWorktreeStateBack skips non-standard milestone dir names ===');
583
577
  {
584
578
  const mainBase = mkdtempSync(join(tmpdir(), 'gsd-wt-back-custom-main-'));
585
579
  const wtBase = mkdtempSync(join(tmpdir(), 'gsd-wt-back-custom-wt-'));
@@ -601,12 +595,12 @@ describe('worktree-sync-milestones', async () => {
601
595
  const { synced } = syncWorktreeStateBack(mainBase, wtBase, 'M001');
602
596
 
603
597
  assert.ok(
604
- existsSync(join(mainBase, '.gsd', 'milestones', 'sprint-beta', 'SUMMARY.md')),
605
- '#1547: non-standard milestone dir "sprint-beta" synced back to main',
598
+ !existsSync(join(mainBase, '.gsd', 'milestones', 'sprint-beta', 'SUMMARY.md')),
599
+ 'non-standard milestone projection is not copied back to main',
606
600
  );
607
601
  assert.ok(
608
- synced.some((p) => p.includes('sprint-beta')),
609
- '#1547: sprint-beta appears in synced list',
602
+ !synced.some((p) => p.includes('sprint-beta')),
603
+ 'sprint-beta does not appear in synced list',
610
604
  );
611
605
  } finally {
612
606
  rmSync(mainBase, { recursive: true, force: true });
@@ -1,8 +1,9 @@
1
1
  /**
2
- * worktree-sync-tasks.test.ts — Regression test for #1678.
2
+ * worktree-sync-tasks.test.ts
3
3
  *
4
- * Verifies that syncWorktreeStateBack() correctly syncs task summaries
5
- * from the tasks/ subdirectory within each slice, not just slice-level files.
4
+ * DB-authoritative worktree contract: task and milestone markdown under a
5
+ * worktree .gsd directory are legacy projections. syncWorktreeStateBack must
6
+ * not copy them into the canonical project .gsd tree.
6
7
  */
7
8
 
8
9
  import test from "node:test";
@@ -11,7 +12,6 @@ import {
11
12
  existsSync,
12
13
  mkdirSync,
13
14
  mkdtempSync,
14
- readFileSync,
15
15
  rmSync,
16
16
  writeFileSync,
17
17
  } from "node:fs";
@@ -20,19 +20,13 @@ import { tmpdir } from "node:os";
20
20
 
21
21
  import { syncWorktreeStateBack } from "../auto-worktree.ts";
22
22
 
23
- // ─── Helpers ─────────────────────────────────────────────────────────
24
-
25
23
  function makeTempDir(prefix: string): string {
26
24
  return mkdtempSync(join(tmpdir(), `gsd-sync-test-${prefix}-`));
27
25
  }
28
26
 
29
27
  function cleanup(...dirs: string[]): void {
30
28
  for (const dir of dirs) {
31
- try {
32
- rmSync(dir, { recursive: true, force: true });
33
- } catch {
34
- // ignore
35
- }
29
+ rmSync(dir, { recursive: true, force: true });
36
30
  }
37
31
  }
38
32
 
@@ -42,168 +36,49 @@ function writeFile(dir: string, relativePath: string, content: string): void {
42
36
  writeFileSync(fullPath, content, "utf-8");
43
37
  }
44
38
 
45
- // ─── Tests ───────────────────────────────────────────────────────────
46
-
47
- test("syncWorktreeStateBack copies task summaries from tasks/ subdirectory (#1678)", () => {
39
+ test("syncWorktreeStateBack does not copy task markdown projections from worktree", () => {
48
40
  const mainBase = makeTempDir("main");
49
41
  const wtBase = makeTempDir("wt");
50
- const currentMid = "M000"; // milestone being merged (skipped by sync)
51
- const mid = "M001"; // other milestone that should be synced
52
42
 
53
43
  try {
54
- // Set up worktree with milestone, slice, and task files
55
- writeFile(wtBase, `.gsd/milestones/${mid}/${mid}-ROADMAP.md`, "# Roadmap\n");
56
- writeFile(wtBase, `.gsd/milestones/${mid}/${mid}-SUMMARY.md`, "# Summary\n");
57
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/S01-PLAN.md`, "# Plan\n");
58
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/S01-SUMMARY.md`, "# Slice Summary\n");
59
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/S01-UAT.md`, "# UAT\n");
60
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/tasks/T01-PLAN.md`, "# Task 1 Plan\n");
61
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/tasks/T01-SUMMARY.md`, "# Task 1 Summary\n");
62
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/tasks/T02-PLAN.md`, "# Task 2 Plan\n");
63
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/tasks/T02-SUMMARY.md`, "# Task 2 Summary\n");
64
-
65
- // Set up main with empty .gsd
44
+ writeFile(wtBase, ".gsd/milestones/M001/M001-ROADMAP.md", "# Roadmap\n");
45
+ writeFile(wtBase, ".gsd/milestones/M001/slices/S01/S01-PLAN.md", "# Plan\n");
46
+ writeFile(wtBase, ".gsd/milestones/M001/slices/S01/tasks/T01-SUMMARY.md", "# Task Summary\n");
66
47
  mkdirSync(join(mainBase, ".gsd"), { recursive: true });
67
48
 
68
- // Run sync currentMid is skipped, mid (M001) should be synced
69
- const result = syncWorktreeStateBack(mainBase, wtBase, currentMid);
70
-
71
- // Verify milestone-level files synced
72
- assert.ok(
73
- existsSync(join(mainBase, `.gsd/milestones/${mid}/${mid}-ROADMAP.md`)),
74
- "ROADMAP should be synced",
75
- );
76
- assert.ok(
77
- existsSync(join(mainBase, `.gsd/milestones/${mid}/${mid}-SUMMARY.md`)),
78
- "SUMMARY should be synced",
79
- );
80
-
81
- // Verify slice-level files synced
82
- assert.ok(
83
- existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/S01-PLAN.md`)),
84
- "S01-PLAN should be synced",
85
- );
86
- assert.ok(
87
- existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/S01-SUMMARY.md`)),
88
- "S01-SUMMARY should be synced",
89
- );
49
+ const result = syncWorktreeStateBack(mainBase, wtBase, "M000");
90
50
 
91
- // Verify task-level files synced (THE BUG FIX)
92
- assert.ok(
93
- existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/tasks/T01-PLAN.md`)),
94
- "T01-PLAN should be synced (was dropped before fix)",
95
- );
96
- assert.ok(
97
- existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/tasks/T01-SUMMARY.md`)),
98
- "T01-SUMMARY should be synced (was dropped before fix)",
99
- );
100
- assert.ok(
101
- existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/tasks/T02-PLAN.md`)),
102
- "T02-PLAN should be synced (was dropped before fix)",
103
- );
104
- assert.ok(
105
- existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/tasks/T02-SUMMARY.md`)),
106
- "T02-SUMMARY should be synced (was dropped before fix)",
107
- );
108
-
109
- // Verify task files appear in synced list
110
- const taskSynced = result.synced.filter(p => p.includes("/tasks/"));
111
- assert.ok(
112
- taskSynced.length >= 4,
113
- `Expected at least 4 task files in synced list, got ${taskSynced.length}: ${taskSynced.join(", ")}`,
114
- );
115
-
116
- // Verify content integrity
117
- const t1Summary = readFileSync(
118
- join(mainBase, `.gsd/milestones/${mid}/slices/S01/tasks/T01-SUMMARY.md`),
119
- "utf-8",
51
+ assert.equal(result.synced.some((p) => p.includes("milestones/")), false);
52
+ assert.equal(
53
+ existsSync(join(mainBase, ".gsd/milestones/M001/M001-ROADMAP.md")),
54
+ false,
55
+ "milestone markdown projection must not be copied",
120
56
  );
121
- assert.equal(t1Summary, "# Task 1 Summary\n");
122
- } finally {
123
- cleanup(mainBase, wtBase);
124
- }
125
- });
126
-
127
- test("syncWorktreeStateBack handles multiple slices with tasks (#1678)", () => {
128
- const mainBase = makeTempDir("main");
129
- const wtBase = makeTempDir("wt");
130
- const currentMid = "M000"; // milestone being merged (skipped)
131
- const mid = "M002"; // other milestone that should be synced
132
-
133
- try {
134
- // Set up two slices with tasks
135
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/S01-SUMMARY.md`, "# S01\n");
136
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/tasks/T01-SUMMARY.md`, "# S01-T01\n");
137
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S02/S02-SUMMARY.md`, "# S02\n");
138
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S02/tasks/T01-SUMMARY.md`, "# S02-T01\n");
139
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S02/tasks/T02-SUMMARY.md`, "# S02-T02\n");
140
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S02/tasks/T03-SUMMARY.md`, "# S02-T03\n");
141
-
142
- mkdirSync(join(mainBase, ".gsd"), { recursive: true });
143
-
144
- const result = syncWorktreeStateBack(mainBase, wtBase, currentMid);
145
-
146
- // All task summaries from both slices should be synced
147
- assert.ok(existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/tasks/T01-SUMMARY.md`)));
148
- assert.ok(existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S02/tasks/T01-SUMMARY.md`)));
149
- assert.ok(existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S02/tasks/T02-SUMMARY.md`)));
150
- assert.ok(existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S02/tasks/T03-SUMMARY.md`)));
151
-
152
- // Verify content integrity across slices
153
57
  assert.equal(
154
- readFileSync(join(mainBase, `.gsd/milestones/${mid}/slices/S02/tasks/T03-SUMMARY.md`), "utf-8"),
155
- "# S02-T03\n",
58
+ existsSync(join(mainBase, ".gsd/milestones/M001/slices/S01/tasks/T01-SUMMARY.md")),
59
+ false,
60
+ "task summary projection must not be copied",
156
61
  );
157
62
  } finally {
158
63
  cleanup(mainBase, wtBase);
159
64
  }
160
65
  });
161
66
 
162
- test("syncWorktreeStateBack handles slices without tasks/ directory", () => {
163
- const mainBase = makeTempDir("main");
164
- const wtBase = makeTempDir("wt");
165
- const currentMid = "M000"; // milestone being merged (skipped)
166
- const mid = "M003"; // other milestone that should be synced
167
-
168
- try {
169
- // Slice with no tasks/ subdirectory (legitimate case: pre-planning)
170
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/S01-RESEARCH.md`, "# Research\n");
171
-
172
- mkdirSync(join(mainBase, ".gsd"), { recursive: true });
173
-
174
- const result = syncWorktreeStateBack(mainBase, wtBase, currentMid);
175
-
176
- // Should sync the slice file without errors
177
- assert.ok(existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/S01-RESEARCH.md`)));
178
- // Should not have any task entries
179
- const taskSynced = result.synced.filter(p => p.includes("/tasks/"));
180
- assert.equal(taskSynced.length, 0);
181
- } finally {
182
- cleanup(mainBase, wtBase);
183
- }
184
- });
185
-
186
- test("syncWorktreeStateBack ignores non-md files in tasks/", () => {
67
+ test("syncWorktreeStateBack still copies diagnostic root files", () => {
187
68
  const mainBase = makeTempDir("main");
188
69
  const wtBase = makeTempDir("wt");
189
- const currentMid = "M000"; // milestone being merged (skipped)
190
- const mid = "M004"; // other milestone that should be synced
191
70
 
192
71
  try {
193
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/S01-PLAN.md`, "# Plan\n");
194
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/tasks/T01-SUMMARY.md`, "# T01\n");
195
- // Non-md file should be ignored
196
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/tasks/.DS_Store`, "junk");
197
- writeFile(wtBase, `.gsd/milestones/${mid}/slices/S01/tasks/notes.txt`, "notes");
198
-
72
+ writeFile(wtBase, ".gsd/completed-units.json", JSON.stringify({ units: ["M001/S01/T01"] }));
73
+ writeFile(wtBase, ".gsd/metrics.json", JSON.stringify({ version: 1, units: [] }));
199
74
  mkdirSync(join(mainBase, ".gsd"), { recursive: true });
200
75
 
201
- const result = syncWorktreeStateBack(mainBase, wtBase, currentMid);
76
+ const result = syncWorktreeStateBack(mainBase, wtBase, "M001");
202
77
 
203
- // Only .md files should be synced
204
- assert.ok(existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/tasks/T01-SUMMARY.md`)));
205
- assert.ok(!existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/tasks/.DS_Store`)));
206
- assert.ok(!existsSync(join(mainBase, `.gsd/milestones/${mid}/slices/S01/tasks/notes.txt`)));
78
+ assert.ok(result.synced.includes("completed-units.json"));
79
+ assert.ok(result.synced.includes("metrics.json"));
80
+ assert.ok(existsSync(join(mainBase, ".gsd/completed-units.json")));
81
+ assert.ok(existsSync(join(mainBase, ".gsd/metrics.json")));
207
82
  } finally {
208
83
  cleanup(mainBase, wtBase);
209
84
  }