gsd-pi 2.43.0 → 2.44.0-dev.0b97ffd

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 (693) hide show
  1. package/README.md +30 -12
  2. package/dist/cli.js +13 -1
  3. package/dist/help-text.js +24 -0
  4. package/dist/resources/extensions/bg-shell/overlay.js +3 -0
  5. package/dist/resources/extensions/github-sync/sync.js +2 -1
  6. package/dist/resources/extensions/gsd/auto/loop.js +0 -2
  7. package/dist/resources/extensions/gsd/auto/phases.js +7 -12
  8. package/dist/resources/extensions/gsd/auto-dashboard.js +19 -18
  9. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +34 -19
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +36 -21
  11. package/dist/resources/extensions/gsd/auto-post-unit.js +128 -14
  12. package/dist/resources/extensions/gsd/auto-prompts.js +202 -92
  13. package/dist/resources/extensions/gsd/auto-recovery.js +83 -135
  14. package/dist/resources/extensions/gsd/auto-start.js +10 -0
  15. package/dist/resources/extensions/gsd/auto-supervisor.js +14 -0
  16. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +4 -7
  17. package/dist/resources/extensions/gsd/auto-verification.js +5 -10
  18. package/dist/resources/extensions/gsd/auto-worktree.js +123 -30
  19. package/dist/resources/extensions/gsd/auto.js +1 -4
  20. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +611 -0
  21. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +28 -3
  22. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -0
  23. package/dist/resources/extensions/gsd/commands/catalog.js +3 -1
  24. package/dist/resources/extensions/gsd/commands/handlers/ops.js +15 -1
  25. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  26. package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
  27. package/dist/resources/extensions/gsd/commands-maintenance.js +78 -3
  28. package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -31
  29. package/dist/resources/extensions/gsd/db-writer.js +95 -4
  30. package/dist/resources/extensions/gsd/dispatch-guard.js +35 -30
  31. package/dist/resources/extensions/gsd/doctor-checks.js +28 -11
  32. package/dist/resources/extensions/gsd/doctor-environment.js +28 -0
  33. package/dist/resources/extensions/gsd/doctor-types.js +0 -15
  34. package/dist/resources/extensions/gsd/doctor.js +46 -282
  35. package/dist/resources/extensions/gsd/file-watcher.js +5 -1
  36. package/dist/resources/extensions/gsd/files.js +14 -198
  37. package/dist/resources/extensions/gsd/git-service.js +4 -0
  38. package/dist/resources/extensions/gsd/gitignore.js +4 -0
  39. package/dist/resources/extensions/gsd/gsd-db.js +819 -197
  40. package/dist/resources/extensions/gsd/guided-flow.js +18 -8
  41. package/dist/resources/extensions/gsd/markdown-renderer.js +862 -0
  42. package/dist/resources/extensions/gsd/md-importer.js +182 -4
  43. package/dist/resources/extensions/gsd/native-git-bridge.js +10 -1
  44. package/dist/resources/extensions/gsd/parallel-eligibility.js +14 -19
  45. package/dist/resources/extensions/gsd/parallel-orchestrator.js +38 -0
  46. package/dist/resources/extensions/gsd/parsers-legacy.js +239 -0
  47. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  48. package/dist/resources/extensions/gsd/preferences-validation.js +9 -0
  49. package/dist/resources/extensions/gsd/preferences.js +1 -0
  50. package/dist/resources/extensions/gsd/prompts/complete-slice.md +22 -9
  51. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -2
  52. package/dist/resources/extensions/gsd/prompts/execute-task.md +15 -5
  53. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  54. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  55. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  56. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +6 -10
  57. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -7
  58. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
  59. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -7
  60. package/dist/resources/extensions/gsd/prompts/replan-slice.md +6 -6
  61. package/dist/resources/extensions/gsd/reactive-graph.js +33 -3
  62. package/dist/resources/extensions/gsd/skill-health.js +3 -1
  63. package/dist/resources/extensions/gsd/state.js +484 -30
  64. package/dist/resources/extensions/gsd/tools/complete-milestone.js +128 -0
  65. package/dist/resources/extensions/gsd/tools/complete-slice.js +244 -0
  66. package/dist/resources/extensions/gsd/tools/complete-task.js +204 -0
  67. package/dist/resources/extensions/gsd/tools/plan-milestone.js +205 -0
  68. package/dist/resources/extensions/gsd/tools/plan-slice.js +155 -0
  69. package/dist/resources/extensions/gsd/tools/plan-task.js +94 -0
  70. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +152 -0
  71. package/dist/resources/extensions/gsd/tools/replan-slice.js +146 -0
  72. package/dist/resources/extensions/gsd/triage-resolution.js +17 -1
  73. package/dist/resources/extensions/gsd/undo.js +197 -3
  74. package/dist/resources/extensions/gsd/visualizer-data.js +53 -16
  75. package/dist/resources/extensions/gsd/workspace-index.js +63 -39
  76. package/dist/web/standalone/.next/BUILD_ID +1 -1
  77. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -17
  78. package/dist/web/standalone/.next/build-manifest.json +4 -4
  79. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  80. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  81. package/dist/web/standalone/.next/required-server-files.json +4 -4
  82. package/dist/web/standalone/.next/routes-manifest.json +6 -0
  83. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  84. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  86. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  94. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  96. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
  97. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  98. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  103. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  110. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  148. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  154. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -0
  166. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -0
  167. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -0
  168. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  171. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  173. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  175. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/index.html +1 -1
  185. package/dist/web/standalone/.next/server/app/index.rsc +5 -5
  186. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  187. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  188. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  189. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  190. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  191. package/dist/web/standalone/.next/server/app/page.js +2 -2
  192. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -17
  194. package/dist/web/standalone/.next/server/chunks/229.js +3 -3
  195. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  196. package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
  197. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/middleware.js +2 -2
  200. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  202. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  203. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  204. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  205. package/dist/web/standalone/.next/static/alS4hoANx0TK4UVZY27da/_buildManifest.js +1 -0
  206. package/dist/web/standalone/.next/static/chunks/{4024.c195dc1fdd2adbea.js → 4024.0de81b543b28b9fe.js} +2 -2
  207. package/dist/web/standalone/.next/static/chunks/app/_global-error/{page-d07a2c023f1aef1e.js → page-d83ba70a25a85472.js} +1 -1
  208. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
  209. package/dist/web/standalone/.next/static/chunks/app/api/boot/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
  210. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
  211. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
  212. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-d83ba70a25a85472.js +1 -0
  213. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-d83ba70a25a85472.js +1 -0
  214. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-d83ba70a25a85472.js +1 -0
  215. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-d83ba70a25a85472.js +1 -0
  216. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-d83ba70a25a85472.js +1 -0
  217. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-d83ba70a25a85472.js +1 -0
  218. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-d83ba70a25a85472.js +1 -0
  219. package/dist/web/standalone/.next/static/chunks/app/api/files/route-d83ba70a25a85472.js +1 -0
  220. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-d83ba70a25a85472.js +1 -0
  221. package/dist/web/standalone/.next/static/chunks/app/api/git/route-d83ba70a25a85472.js +1 -0
  222. package/dist/web/standalone/.next/static/chunks/app/api/history/route-d83ba70a25a85472.js +1 -0
  223. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-d83ba70a25a85472.js +1 -0
  224. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-d83ba70a25a85472.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-d83ba70a25a85472.js +1 -0
  226. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-d83ba70a25a85472.js +1 -0
  227. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-d83ba70a25a85472.js +1 -0
  228. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-d83ba70a25a85472.js +1 -0
  229. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-d83ba70a25a85472.js +1 -0
  230. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-d83ba70a25a85472.js +1 -0
  231. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-d83ba70a25a85472.js +1 -0
  232. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-d83ba70a25a85472.js +1 -0
  233. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-d83ba70a25a85472.js +1 -0
  234. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-d83ba70a25a85472.js +1 -0
  235. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-d83ba70a25a85472.js +1 -0
  236. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-d83ba70a25a85472.js +1 -0
  237. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-d83ba70a25a85472.js +1 -0
  238. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-d83ba70a25a85472.js +1 -0
  239. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-d83ba70a25a85472.js +1 -0
  240. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-d83ba70a25a85472.js +1 -0
  241. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-d83ba70a25a85472.js +1 -0
  242. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-d83ba70a25a85472.js +1 -0
  243. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-d83ba70a25a85472.js +1 -0
  244. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-d83ba70a25a85472.js +1 -0
  245. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-d83ba70a25a85472.js +1 -0
  246. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-d83ba70a25a85472.js +1 -0
  247. package/dist/web/standalone/.next/static/chunks/app/api/update/route-d83ba70a25a85472.js +1 -0
  248. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-d83ba70a25a85472.js +1 -0
  249. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
  250. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
  251. package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
  252. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-d83ba70a25a85472.js +1 -0
  253. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d83ba70a25a85472.js +1 -0
  254. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  255. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d83ba70a25a85472.js +1 -0
  256. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d83ba70a25a85472.js +1 -0
  257. package/dist/web/standalone/.next/static/chunks/{webpack-fa307370fcf9fb2c.js → webpack-9014b5adb127a98a.js} +1 -1
  258. package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +1 -0
  259. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  260. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  261. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  262. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  263. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  264. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  265. package/dist/web/standalone/server.js +1 -1
  266. package/package.json +4 -4
  267. package/packages/pi-ai/dist/models.custom.d.ts +173 -0
  268. package/packages/pi-ai/dist/models.custom.d.ts.map +1 -0
  269. package/packages/pi-ai/dist/models.custom.js +170 -0
  270. package/packages/pi-ai/dist/models.custom.js.map +1 -0
  271. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  272. package/packages/pi-ai/dist/models.js +16 -1
  273. package/packages/pi-ai/dist/models.js.map +1 -1
  274. package/packages/pi-ai/dist/models.test.d.ts +2 -0
  275. package/packages/pi-ai/dist/models.test.d.ts.map +1 -0
  276. package/packages/pi-ai/dist/models.test.js +67 -0
  277. package/packages/pi-ai/dist/models.test.js.map +1 -0
  278. package/packages/pi-ai/src/models.custom.ts +172 -0
  279. package/packages/pi-ai/src/models.test.ts +85 -0
  280. package/packages/pi-ai/src/models.ts +17 -1
  281. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +10 -3
  282. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/agent-session.js +21 -34
  284. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  286. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts +2 -2
  288. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
  290. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +2 -2
  291. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  292. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +4 -4
  294. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  296. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  298. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +6 -0
  299. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  300. package/packages/pi-coding-agent/dist/core/extensions/loader.js +80 -0
  301. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/core/extensions/loader.test.js +63 -0
  303. package/packages/pi-coding-agent/dist/core/extensions/loader.test.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  305. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  306. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +37 -0
  307. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  308. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  309. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -1
  310. package/packages/pi-coding-agent/dist/core/fallback-resolver.js +2 -3
  311. package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +12 -2
  313. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -1
  314. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  315. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  316. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +38 -0
  317. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -0
  318. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +192 -0
  319. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -0
  320. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts +5 -0
  321. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  322. package/packages/pi-coding-agent/dist/core/lsp/client.js +69 -21
  323. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  324. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts +2 -0
  325. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts.map +1 -0
  326. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +255 -0
  327. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -0
  328. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +15 -0
  329. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  330. package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
  331. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  332. package/packages/pi-coding-agent/dist/core/package-commands.d.ts +25 -0
  333. package/packages/pi-coding-agent/dist/core/package-commands.d.ts.map +1 -0
  334. package/packages/pi-coding-agent/dist/core/package-commands.js +253 -0
  335. package/packages/pi-coding-agent/dist/core/package-commands.js.map +1 -0
  336. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts +2 -0
  337. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts.map +1 -0
  338. package/packages/pi-coding-agent/dist/core/package-commands.test.js +225 -0
  339. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -0
  340. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  341. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  342. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  343. package/packages/pi-coding-agent/dist/core/sdk.js +4 -0
  344. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  345. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  346. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  347. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  348. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  349. package/packages/pi-coding-agent/dist/index.d.ts +3 -1
  350. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  351. package/packages/pi-coding-agent/dist/index.js +1 -0
  352. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  353. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  354. package/packages/pi-coding-agent/dist/main.js +11 -199
  355. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  356. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts +6 -0
  357. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  358. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +21 -0
  359. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  360. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
  361. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +8 -15
  363. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  364. package/packages/pi-coding-agent/dist/modes/print-mode.d.ts.map +1 -1
  365. package/packages/pi-coding-agent/dist/modes/print-mode.js +45 -34
  366. package/packages/pi-coding-agent/dist/modes/print-mode.js.map +1 -1
  367. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts +1 -0
  368. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js +7 -2
  370. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  372. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +2 -1
  373. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  374. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  375. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  376. package/packages/pi-coding-agent/package.json +1 -1
  377. package/packages/pi-coding-agent/src/core/agent-session.ts +26 -37
  378. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  379. package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +2 -2
  380. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +3 -3
  381. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +4 -4
  382. package/packages/pi-coding-agent/src/core/extensions/index.ts +5 -0
  383. package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +96 -0
  384. package/packages/pi-coding-agent/src/core/extensions/loader.ts +89 -0
  385. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  386. package/packages/pi-coding-agent/src/core/extensions/types.ts +44 -0
  387. package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +15 -2
  388. package/packages/pi-coding-agent/src/core/fallback-resolver.ts +2 -3
  389. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  390. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +274 -0
  391. package/packages/pi-coding-agent/src/core/lsp/client.ts +83 -21
  392. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +288 -0
  393. package/packages/pi-coding-agent/src/core/model-registry.ts +39 -3
  394. package/packages/pi-coding-agent/src/core/package-commands.test.ts +240 -0
  395. package/packages/pi-coding-agent/src/core/package-commands.ts +310 -0
  396. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  397. package/packages/pi-coding-agent/src/core/sdk.ts +4 -0
  398. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  399. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  400. package/packages/pi-coding-agent/src/index.ts +7 -0
  401. package/packages/pi-coding-agent/src/main.ts +11 -232
  402. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +20 -0
  403. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +9 -16
  404. package/packages/pi-coding-agent/src/modes/print-mode.ts +42 -32
  405. package/packages/pi-coding-agent/src/modes/rpc/rpc-client.ts +8 -2
  406. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +2 -1
  407. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  408. package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
  409. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  410. package/pkg/dist/modes/interactive/theme/theme.js +8 -15
  411. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  412. package/pkg/package.json +1 -1
  413. package/src/resources/extensions/bg-shell/overlay.ts +4 -0
  414. package/src/resources/extensions/github-sync/sync.ts +2 -1
  415. package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -8
  416. package/src/resources/extensions/gsd/auto/loop.ts +0 -2
  417. package/src/resources/extensions/gsd/auto/phases.ts +7 -20
  418. package/src/resources/extensions/gsd/auto/types.ts +0 -1
  419. package/src/resources/extensions/gsd/auto-dashboard.ts +20 -16
  420. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +34 -19
  421. package/src/resources/extensions/gsd/auto-dispatch.ts +38 -21
  422. package/src/resources/extensions/gsd/auto-post-unit.ts +150 -15
  423. package/src/resources/extensions/gsd/auto-prompts.ts +186 -103
  424. package/src/resources/extensions/gsd/auto-recovery.ts +77 -142
  425. package/src/resources/extensions/gsd/auto-start.ts +14 -0
  426. package/src/resources/extensions/gsd/auto-supervisor.ts +14 -0
  427. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +6 -7
  428. package/src/resources/extensions/gsd/auto-verification.ts +4 -9
  429. package/src/resources/extensions/gsd/auto-worktree.ts +126 -30
  430. package/src/resources/extensions/gsd/auto.ts +0 -9
  431. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +675 -4
  432. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +31 -3
  433. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -0
  434. package/src/resources/extensions/gsd/commands/catalog.ts +3 -1
  435. package/src/resources/extensions/gsd/commands/handlers/ops.ts +15 -1
  436. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  437. package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
  438. package/src/resources/extensions/gsd/commands-maintenance.ts +86 -3
  439. package/src/resources/extensions/gsd/dashboard-overlay.ts +17 -13
  440. package/src/resources/extensions/gsd/db-writer.ts +105 -4
  441. package/src/resources/extensions/gsd/dispatch-guard.ts +32 -30
  442. package/src/resources/extensions/gsd/doctor-checks.ts +25 -11
  443. package/src/resources/extensions/gsd/doctor-environment.ts +31 -0
  444. package/src/resources/extensions/gsd/doctor-types.ts +0 -23
  445. package/src/resources/extensions/gsd/doctor.ts +45 -295
  446. package/src/resources/extensions/gsd/file-watcher.ts +4 -1
  447. package/src/resources/extensions/gsd/files.ts +16 -220
  448. package/src/resources/extensions/gsd/git-service.ts +4 -0
  449. package/src/resources/extensions/gsd/gitignore.ts +4 -0
  450. package/src/resources/extensions/gsd/gsd-db.ts +1157 -370
  451. package/src/resources/extensions/gsd/guided-flow.ts +20 -8
  452. package/src/resources/extensions/gsd/markdown-renderer.ts +1098 -0
  453. package/src/resources/extensions/gsd/md-importer.ts +211 -2
  454. package/src/resources/extensions/gsd/native-git-bridge.ts +12 -1
  455. package/src/resources/extensions/gsd/parallel-eligibility.ts +14 -18
  456. package/src/resources/extensions/gsd/parallel-orchestrator.ts +43 -0
  457. package/src/resources/extensions/gsd/parsers-legacy.ts +271 -0
  458. package/src/resources/extensions/gsd/preferences-types.ts +3 -0
  459. package/src/resources/extensions/gsd/preferences-validation.ts +9 -0
  460. package/src/resources/extensions/gsd/preferences.ts +1 -0
  461. package/src/resources/extensions/gsd/prompts/complete-slice.md +22 -9
  462. package/src/resources/extensions/gsd/prompts/discuss.md +2 -2
  463. package/src/resources/extensions/gsd/prompts/execute-task.md +15 -5
  464. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  465. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  466. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  467. package/src/resources/extensions/gsd/prompts/plan-milestone.md +6 -10
  468. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -7
  469. package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
  470. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -7
  471. package/src/resources/extensions/gsd/prompts/replan-slice.md +6 -6
  472. package/src/resources/extensions/gsd/reactive-graph.ts +33 -3
  473. package/src/resources/extensions/gsd/skill-health.ts +2 -1
  474. package/src/resources/extensions/gsd/state.ts +547 -29
  475. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  476. package/src/resources/extensions/gsd/tests/atomic-task-closeout.test.ts +8 -120
  477. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  478. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +20 -11
  479. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  480. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  481. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +600 -513
  482. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  483. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  484. package/src/resources/extensions/gsd/tests/auto-stash-merge.test.ts +121 -0
  485. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +540 -668
  486. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  487. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  488. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  489. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  490. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  491. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  492. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  493. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +39 -60
  494. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +375 -0
  495. package/src/resources/extensions/gsd/tests/complete-task.test.ts +387 -0
  496. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  497. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  498. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  499. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  500. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +0 -2
  501. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  502. package/src/resources/extensions/gsd/tests/db-writer.test.ts +390 -420
  503. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  504. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +512 -0
  505. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +644 -84
  506. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  507. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  508. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  509. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  510. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +192 -161
  511. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  512. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  513. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +30 -90
  514. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  515. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +57 -80
  516. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +164 -0
  517. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  518. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +55 -153
  519. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  520. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  521. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +53 -97
  522. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  523. package/src/resources/extensions/gsd/tests/doctor.test.ts +109 -149
  524. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  525. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  526. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  527. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  528. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +278 -0
  529. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +232 -0
  530. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  531. package/src/resources/extensions/gsd/tests/git-service.test.ts +291 -390
  532. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  533. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  534. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  535. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  536. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +440 -0
  537. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  538. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  539. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  540. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -270
  541. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  542. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  543. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  544. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  545. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +643 -0
  546. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -3
  547. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1161 -0
  548. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  549. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  550. package/src/resources/extensions/gsd/tests/memory-store.test.ts +81 -94
  551. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  552. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +429 -0
  553. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  554. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  555. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  556. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +89 -97
  557. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +127 -164
  558. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  559. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
  560. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  561. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  562. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  563. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  564. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  565. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  566. package/src/resources/extensions/gsd/tests/parsers.test.ts +548 -612
  567. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  568. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +176 -113
  569. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +7 -0
  570. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +179 -0
  571. package/src/resources/extensions/gsd/tests/plan-task.test.ts +145 -0
  572. package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +305 -0
  573. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  574. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +139 -0
  575. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  576. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  577. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  578. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  579. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  580. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  581. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +325 -0
  582. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  583. package/src/resources/extensions/gsd/tests/replan-handler.test.ts +410 -0
  584. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  585. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  586. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  587. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  588. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  589. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +1 -1
  590. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +296 -0
  591. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  592. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  593. package/src/resources/extensions/gsd/tests/schema-v9-sequence.test.ts +176 -0
  594. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  595. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  596. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +209 -0
  597. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  598. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  599. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  600. package/src/resources/extensions/gsd/tests/token-cost-display.test.ts +118 -0
  601. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  602. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  603. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +19 -13
  604. package/src/resources/extensions/gsd/tests/undo.test.ts +321 -1
  605. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  606. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  607. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +1 -1
  608. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +0 -142
  609. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  610. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  611. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  612. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  613. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  614. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  615. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  616. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  617. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  618. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  619. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  620. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +12 -5
  621. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  622. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  623. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  624. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  625. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  626. package/src/resources/extensions/gsd/tools/complete-milestone.ts +176 -0
  627. package/src/resources/extensions/gsd/tools/complete-slice.ts +300 -0
  628. package/src/resources/extensions/gsd/tools/complete-task.ts +245 -0
  629. package/src/resources/extensions/gsd/tools/plan-milestone.ts +249 -0
  630. package/src/resources/extensions/gsd/tools/plan-slice.ts +194 -0
  631. package/src/resources/extensions/gsd/tools/plan-task.ts +116 -0
  632. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +203 -0
  633. package/src/resources/extensions/gsd/tools/replan-slice.ts +192 -0
  634. package/src/resources/extensions/gsd/triage-resolution.ts +20 -1
  635. package/src/resources/extensions/gsd/types.ts +50 -0
  636. package/src/resources/extensions/gsd/undo.ts +247 -3
  637. package/src/resources/extensions/gsd/visualizer-data.ts +54 -17
  638. package/src/resources/extensions/gsd/workspace-index.ts +64 -46
  639. package/dist/resources/extensions/gsd/auto-observability.js +0 -56
  640. package/dist/resources/extensions/gsd/observability-validator.js +0 -422
  641. package/dist/resources/extensions/gsd/roadmap-mutations.js +0 -110
  642. package/dist/web/standalone/.next/static/VvclDCW6TAWjEyLU-EYL1/_buildManifest.js +0 -1
  643. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
  644. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-d07a2c023f1aef1e.js +0 -1
  645. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-d07a2c023f1aef1e.js +0 -1
  646. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-d07a2c023f1aef1e.js +0 -1
  647. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-d07a2c023f1aef1e.js +0 -1
  648. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-d07a2c023f1aef1e.js +0 -1
  649. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-d07a2c023f1aef1e.js +0 -1
  650. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-d07a2c023f1aef1e.js +0 -1
  651. package/dist/web/standalone/.next/static/chunks/app/api/files/route-d07a2c023f1aef1e.js +0 -1
  652. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-d07a2c023f1aef1e.js +0 -1
  653. package/dist/web/standalone/.next/static/chunks/app/api/git/route-d07a2c023f1aef1e.js +0 -1
  654. package/dist/web/standalone/.next/static/chunks/app/api/history/route-d07a2c023f1aef1e.js +0 -1
  655. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-d07a2c023f1aef1e.js +0 -1
  656. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-d07a2c023f1aef1e.js +0 -1
  657. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-d07a2c023f1aef1e.js +0 -1
  658. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-d07a2c023f1aef1e.js +0 -1
  659. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-d07a2c023f1aef1e.js +0 -1
  660. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-d07a2c023f1aef1e.js +0 -1
  661. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-d07a2c023f1aef1e.js +0 -1
  662. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-d07a2c023f1aef1e.js +0 -1
  663. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-d07a2c023f1aef1e.js +0 -1
  664. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-d07a2c023f1aef1e.js +0 -1
  665. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-d07a2c023f1aef1e.js +0 -1
  666. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-d07a2c023f1aef1e.js +0 -1
  667. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-d07a2c023f1aef1e.js +0 -1
  668. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-d07a2c023f1aef1e.js +0 -1
  669. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-d07a2c023f1aef1e.js +0 -1
  670. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-d07a2c023f1aef1e.js +0 -1
  671. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-d07a2c023f1aef1e.js +0 -1
  672. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-d07a2c023f1aef1e.js +0 -1
  673. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-d07a2c023f1aef1e.js +0 -1
  674. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-d07a2c023f1aef1e.js +0 -1
  675. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-d07a2c023f1aef1e.js +0 -1
  676. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-d07a2c023f1aef1e.js +0 -1
  677. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-d07a2c023f1aef1e.js +0 -1
  678. package/dist/web/standalone/.next/static/chunks/app/api/update/route-d07a2c023f1aef1e.js +0 -1
  679. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-d07a2c023f1aef1e.js +0 -1
  680. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
  681. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
  682. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-d07a2c023f1aef1e.js +0 -1
  683. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d07a2c023f1aef1e.js +0 -1
  684. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
  685. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d07a2c023f1aef1e.js +0 -1
  686. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d07a2c023f1aef1e.js +0 -1
  687. package/dist/web/standalone/.next/static/css/123c0bb039697968.css +0 -1
  688. package/src/resources/extensions/gsd/auto-observability.ts +0 -74
  689. package/src/resources/extensions/gsd/observability-validator.ts +0 -456
  690. package/src/resources/extensions/gsd/roadmap-mutations.ts +0 -134
  691. package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +0 -174
  692. package/src/resources/extensions/gsd/tests/plan-quality-validator.test.ts +0 -474
  693. /package/dist/web/standalone/.next/static/{VvclDCW6TAWjEyLU-EYL1 → alS4hoANx0TK4UVZY27da}/_ssgManifest.js +0 -0
@@ -1,3 +1,5 @@
1
+ import { describe, test } from 'node:test';
2
+ import assert from 'node:assert/strict';
1
3
  import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
2
4
  import { join, dirname } from 'node:path';
3
5
  import { tmpdir } from 'node:os';
@@ -22,7 +24,6 @@ function loadPromptFromWorktree(name: string, vars: Record<string, string> = {})
22
24
  return content.trim();
23
25
  }
24
26
 
25
- const { assertEq, assertTrue, report } = createTestContext();
26
27
  // ─── Fixture Helpers ───────────────────────────────────────────────────────
27
28
 
28
29
  function createFixtureBase(): string {
@@ -161,7 +162,7 @@ Found a blocker.
161
162
  `;
162
163
 
163
164
  const s = parseSummary(content);
164
- assertEq(s.frontmatter.blocker_discovered, true, 'blocker_discovered: true (string) extracts as true');
165
+ assert.deepStrictEqual(s.frontmatter.blocker_discovered, true, 'blocker_discovered: true (string) extracts as true');
165
166
  }
166
167
 
167
168
  console.log('\n=== parseSummary: blocker_discovered false (string) ===');
@@ -184,7 +185,7 @@ No blocker.
184
185
  `;
185
186
 
186
187
  const s = parseSummary(content);
187
- assertEq(s.frontmatter.blocker_discovered, false, 'blocker_discovered: false extracts as false');
188
+ assert.deepStrictEqual(s.frontmatter.blocker_discovered, false, 'blocker_discovered: false extracts as false');
188
189
  }
189
190
 
190
191
  console.log('\n=== parseSummary: blocker_discovered missing (defaults to false) ===');
@@ -206,7 +207,7 @@ No blocker field at all.
206
207
  `;
207
208
 
208
209
  const s = parseSummary(content);
209
- assertEq(s.frontmatter.blocker_discovered, false, 'blocker_discovered missing defaults to false');
210
+ assert.deepStrictEqual(s.frontmatter.blocker_discovered, false, 'blocker_discovered missing defaults to false');
210
211
  }
211
212
 
212
213
  console.log('\n=== parseSummary: blocker_discovered true (boolean from YAML) ===');
@@ -232,7 +233,7 @@ Blocker as boolean.
232
233
  `;
233
234
 
234
235
  const s = parseSummary(content);
235
- assertEq(s.frontmatter.blocker_discovered, true, 'blocker_discovered: true (YAML boolean) extracts as true');
236
+ assert.deepStrictEqual(s.frontmatter.blocker_discovered, true, 'blocker_discovered: true (YAML boolean) extracts as true');
236
237
  }
237
238
 
238
239
  console.log('\n=== parseSummary: blocker_discovered with full frontmatter ===');
@@ -275,10 +276,10 @@ Major deviation from plan.
275
276
  `;
276
277
 
277
278
  const s = parseSummary(content);
278
- assertEq(s.frontmatter.blocker_discovered, true, 'blocker_discovered true with full frontmatter');
279
- assertEq(s.frontmatter.id, 'T05', 'other fields still parse correctly alongside blocker_discovered');
280
- assertEq(s.frontmatter.duration, '15min', 'duration still parsed');
281
- assertEq(s.frontmatter.provides[0], 'something', 'provides still parsed');
279
+ assert.deepStrictEqual(s.frontmatter.blocker_discovered, true, 'blocker_discovered true with full frontmatter');
280
+ assert.deepStrictEqual(s.frontmatter.id, 'T05', 'other fields still parse correctly alongside blocker_discovered');
281
+ assert.deepStrictEqual(s.frontmatter.duration, '15min', 'duration still parsed');
282
+ assert.deepStrictEqual(s.frontmatter.provides[0], 'something', 'provides still parsed');
282
283
  }
283
284
 
284
285
  // ═══════════════════════════════════════════════════════════════════════════
@@ -294,11 +295,11 @@ console.log('\n=== deriveState: blocker found, no REPLAN → replanning-slice ==
294
295
  writeTaskSummary(base, 'M001', 'S01', 'T01', makeTaskSummary('T01', true));
295
296
 
296
297
  const state = await deriveState(base);
297
- assertEq(state.phase, 'replanning-slice', 'phase is replanning-slice when blocker found and no REPLAN.md');
298
- assertTrue(state.nextAction.includes('T01'), 'nextAction mentions blocker task T01');
299
- assertTrue(state.nextAction.includes('blocker_discovered'), 'nextAction mentions blocker_discovered');
300
- assertEq(state.activeTask?.id, 'T02', 'activeTask is still T02 (the next incomplete task)');
301
- assertTrue(state.blockers.length > 0, 'blockers array is non-empty');
298
+ assert.deepStrictEqual(state.phase, 'replanning-slice', 'phase is replanning-slice when blocker found and no REPLAN.md');
299
+ assert.ok(state.nextAction.includes('T01'), 'nextAction mentions blocker task T01');
300
+ assert.ok(state.nextAction.includes('blocker_discovered'), 'nextAction mentions blocker_discovered');
301
+ assert.deepStrictEqual(state.activeTask?.id, 'T02', 'activeTask is still T02 (the next incomplete task)');
302
+ assert.ok(state.blockers.length > 0, 'blockers array is non-empty');
302
303
  rmSync(base, { recursive: true, force: true });
303
304
  }
304
305
 
@@ -312,8 +313,8 @@ console.log('\n=== deriveState: blocker found + REPLAN exists → executing (loo
312
313
  writeReplanFile(base, 'M001', 'S01', '# Replan\n\nAlready replanned.');
313
314
 
314
315
  const state = await deriveState(base);
315
- assertEq(state.phase, 'executing', 'phase is executing when REPLAN.md exists (loop protection)');
316
- assertEq(state.activeTask?.id, 'T02', 'activeTask is T02');
316
+ assert.deepStrictEqual(state.phase, 'executing', 'phase is executing when REPLAN.md exists (loop protection)');
317
+ assert.deepStrictEqual(state.activeTask?.id, 'T02', 'activeTask is T02');
317
318
  rmSync(base, { recursive: true, force: true });
318
319
  }
319
320
 
@@ -326,8 +327,8 @@ console.log('\n=== deriveState: no blocker in completed tasks → executing ==='
326
327
  writeTaskSummary(base, 'M001', 'S01', 'T01', makeTaskSummary('T01', false));
327
328
 
328
329
  const state = await deriveState(base);
329
- assertEq(state.phase, 'executing', 'phase is executing when no blocker found');
330
- assertEq(state.activeTask?.id, 'T02', 'activeTask is T02');
330
+ assert.deepStrictEqual(state.phase, 'executing', 'phase is executing when no blocker found');
331
+ assert.deepStrictEqual(state.activeTask?.id, 'T02', 'activeTask is T02');
331
332
  rmSync(base, { recursive: true, force: true });
332
333
  }
333
334
 
@@ -341,9 +342,9 @@ console.log('\n=== deriveState: multiple completed tasks, one blocker → replan
341
342
  writeTaskSummary(base, 'M001', 'S01', 'T02', makeTaskSummary('T02', true));
342
343
 
343
344
  const state = await deriveState(base);
344
- assertEq(state.phase, 'replanning-slice', 'phase is replanning-slice when T02 has blocker');
345
- assertTrue(state.nextAction.includes('T02'), 'nextAction mentions blocker task T02');
346
- assertEq(state.activeTask?.id, 'T03', 'activeTask is T03 (next incomplete)');
345
+ assert.deepStrictEqual(state.phase, 'replanning-slice', 'phase is replanning-slice when T02 has blocker');
346
+ assert.ok(state.nextAction.includes('T02'), 'nextAction mentions blocker task T02');
347
+ assert.deepStrictEqual(state.activeTask?.id, 'T03', 'activeTask is T03 (next incomplete)');
347
348
  rmSync(base, { recursive: true, force: true });
348
349
  }
349
350
 
@@ -356,7 +357,7 @@ console.log('\n=== deriveState: completed task with no summary file → executin
356
357
  // No summary file written for T01
357
358
 
358
359
  const state = await deriveState(base);
359
- assertEq(state.phase, 'executing', 'phase is executing when completed task has no summary');
360
+ assert.deepStrictEqual(state.phase, 'executing', 'phase is executing when completed task has no summary');
360
361
  rmSync(base, { recursive: true, force: true });
361
362
  }
362
363
 
@@ -376,11 +377,11 @@ console.log('\n=== prompt: replan-slice template loads and substitutes variables
376
377
  inlinedContext: '## Inlined Context\n\nTest context here.',
377
378
  });
378
379
 
379
- assertTrue(prompt.includes('M001'), 'prompt contains milestoneId');
380
- assertTrue(prompt.includes('S01'), 'prompt contains sliceId');
381
- assertTrue(prompt.includes('Test Slice'), 'prompt contains sliceTitle');
382
- assertTrue(prompt.includes('.gsd/milestones/M001/slices/S01/S01-PLAN.md'), 'prompt contains planPath');
383
- assertTrue(prompt.includes('Test context here'), 'prompt contains inlined context');
380
+ assert.ok(prompt.includes('M001'), 'prompt contains milestoneId');
381
+ assert.ok(prompt.includes('S01'), 'prompt contains sliceId');
382
+ assert.ok(prompt.includes('Test Slice'), 'prompt contains sliceTitle');
383
+ assert.ok(prompt.includes('.gsd/milestones/M001/slices/S01/S01-PLAN.md'), 'prompt contains planPath');
384
+ assert.ok(prompt.includes('Test context here'), 'prompt contains inlined context');
384
385
  }
385
386
 
386
387
  console.log('\n=== prompt: replan-slice contains preserve-completed-tasks instruction ===');
@@ -397,10 +398,10 @@ console.log('\n=== prompt: replan-slice contains preserve-completed-tasks instru
397
398
  inlinedContext: '',
398
399
  });
399
400
 
400
- assertTrue(prompt.includes('Do NOT renumber or remove completed tasks'), 'prompt contains preserve-completed-tasks instruction');
401
- assertTrue(prompt.includes('[x]'), 'prompt mentions [x] checkmarks');
402
- assertTrue(prompt.includes('REPLAN'), 'prompt references replan output path');
403
- assertTrue(prompt.includes('blocker_discovered'), 'prompt mentions blocker_discovered');
401
+ assert.ok(prompt.includes('Do NOT renumber or remove completed tasks'), 'prompt contains preserve-completed-tasks instruction');
402
+ assert.ok(prompt.includes('[x]'), 'prompt mentions [x] checkmarks');
403
+ assert.ok(prompt.includes('REPLAN'), 'prompt references replan output path');
404
+ assert.ok(prompt.includes('blocker_discovered'), 'prompt mentions blocker_discovered');
404
405
  }
405
406
 
406
407
  // ═══════════════════════════════════════════════════════════════════════════
@@ -421,8 +422,8 @@ console.log('\n=== dispatch: diagnoseExpectedArtifact returns REPLAN.md path ===
421
422
  writeTaskSummary(base, 'M001', 'S01', 'T01', makeTaskSummary('T01', true));
422
423
 
423
424
  const state = await deriveState(base);
424
- assertEq(state.phase, 'replanning-slice', 'dispatch: state routes to replanning-slice when blocker found');
425
- assertTrue(state.activeSlice?.id === 'S01', 'dispatch: activeSlice is S01');
425
+ assert.deepStrictEqual(state.phase, 'replanning-slice', 'dispatch: state routes to replanning-slice when blocker found');
426
+ assert.ok(state.activeSlice?.id === 'S01', 'dispatch: activeSlice is S01');
426
427
  rmSync(base, { recursive: true, force: true });
427
428
  }
428
429
 
@@ -443,8 +444,8 @@ console.log('\n=== display: replan-slice prompt template has correct unit header
443
444
  inlinedContext: '',
444
445
  });
445
446
 
446
- assertTrue(prompt.includes('UNIT: Replan Slice'), 'prompt has Replan Slice unit header');
447
- assertTrue(prompt.includes('Slice S01 replanned'), 'prompt has completion message');
447
+ assert.ok(prompt.includes('UNIT: Replan Slice'), 'prompt has Replan Slice unit header');
448
+ assert.ok(prompt.includes('Slice S01 replanned'), 'prompt has completion message');
448
449
  }
449
450
 
450
451
  // ═══════════════════════════════════════════════════════════════════════════
@@ -452,8 +453,6 @@ console.log('\n=== display: replan-slice prompt template has correct unit header
452
453
  // ═══════════════════════════════════════════════════════════════════════════
453
454
 
454
455
  import { runGSDDoctor } from '../doctor.ts';
455
- import { createTestContext } from './test-helpers.ts';
456
-
457
456
  // (a) blocker + no REPLAN.md → issue emitted
458
457
  console.log('\n=== doctor: blocker + no REPLAN.md → blocker_discovered_no_replan issue ===');
459
458
  {
@@ -464,10 +463,10 @@ console.log('\n=== doctor: blocker + no REPLAN.md → blocker_discovered_no_repl
464
463
 
465
464
  const report = await runGSDDoctor(base, { fix: false, scope: 'M001/S01' });
466
465
  const blockerIssues = report.issues.filter(i => i.code === 'blocker_discovered_no_replan');
467
- assertTrue(blockerIssues.length > 0, 'doctor emits blocker_discovered_no_replan when blocker + no REPLAN');
468
- assertTrue(blockerIssues[0]?.message.includes('T01'), 'issue message mentions the blocker task T01');
469
- assertEq(blockerIssues[0]?.severity, 'warning', 'blocker_discovered_no_replan is warning severity');
470
- assertEq(blockerIssues[0]?.scope, 'slice', 'blocker_discovered_no_replan has slice scope');
466
+ assert.ok(blockerIssues.length > 0, 'doctor emits blocker_discovered_no_replan when blocker + no REPLAN');
467
+ assert.ok(blockerIssues[0]?.message.includes('T01'), 'issue message mentions the blocker task T01');
468
+ assert.deepStrictEqual(blockerIssues[0]?.severity, 'warning', 'blocker_discovered_no_replan is warning severity');
469
+ assert.deepStrictEqual(blockerIssues[0]?.scope, 'slice', 'blocker_discovered_no_replan has slice scope');
471
470
  rmSync(base, { recursive: true, force: true });
472
471
  }
473
472
 
@@ -482,7 +481,7 @@ console.log('\n=== doctor: blocker + REPLAN.md exists → no blocker_discovered_
482
481
 
483
482
  const report = await runGSDDoctor(base, { fix: false, scope: 'M001/S01' });
484
483
  const blockerIssues = report.issues.filter(i => i.code === 'blocker_discovered_no_replan');
485
- assertEq(blockerIssues.length, 0, 'no blocker_discovered_no_replan when REPLAN.md exists');
484
+ assert.deepStrictEqual(blockerIssues.length, 0, 'no blocker_discovered_no_replan when REPLAN.md exists');
486
485
  rmSync(base, { recursive: true, force: true });
487
486
  }
488
487
 
@@ -496,7 +495,7 @@ console.log('\n=== doctor: no blocker → no blocker_discovered_no_replan issue
496
495
 
497
496
  const report = await runGSDDoctor(base, { fix: false, scope: 'M001/S01' });
498
497
  const blockerIssues = report.issues.filter(i => i.code === 'blocker_discovered_no_replan');
499
- assertEq(blockerIssues.length, 0, 'no blocker_discovered_no_replan when no blocker');
498
+ assert.deepStrictEqual(blockerIssues.length, 0, 'no blocker_discovered_no_replan when no blocker');
500
499
  rmSync(base, { recursive: true, force: true });
501
500
  }
502
501
 
@@ -506,48 +505,45 @@ console.log('\n=== doctor: no blocker → no blocker_discovered_no_replan issue
506
505
 
507
506
  import { resolveExpectedArtifactPath, verifyExpectedArtifact } from '../auto-recovery.ts';
508
507
 
509
- console.log('\n=== artifact: resolveExpectedArtifactPath returns REPLAN.md path for replan-slice ===');
510
- {
508
+
509
+ describe('replan-slice', () => {
510
+ test('artifact: resolveExpectedArtifactPath returns REPLAN.md path for replan-slice', () => {
511
511
  const base = createFixtureBase();
512
512
  writeRoadmap(base, 'M001', ROADMAP_ONE_SLICE);
513
513
  writePlan(base, 'M001', 'S01', makePlanT01DoneT02Pending());
514
514
 
515
515
  const path = resolveExpectedArtifactPath('replan-slice', 'M001/S01', base);
516
- assertTrue(path !== null, 'resolveExpectedArtifactPath returns non-null for replan-slice');
517
- assertTrue(path!.endsWith('S01-REPLAN.md'), 'path ends with S01-REPLAN.md');
516
+ assert.ok(path !== null, 'resolveExpectedArtifactPath returns non-null for replan-slice');
517
+ assert.ok(path!.endsWith('S01-REPLAN.md'), 'path ends with S01-REPLAN.md');
518
518
  rmSync(base, { recursive: true, force: true });
519
- }
519
+ });
520
520
 
521
- console.log('\n=== artifact: verifyExpectedArtifact fails when REPLAN.md missing (#858) ===');
522
- {
521
+ test('artifact: verifyExpectedArtifact fails when REPLAN.md missing (#858)', () => {
523
522
  const base = createFixtureBase();
524
523
  writeRoadmap(base, 'M001', ROADMAP_ONE_SLICE);
525
524
  writePlan(base, 'M001', 'S01', makePlanT01DoneT02Pending());
526
525
 
527
526
  const result = verifyExpectedArtifact('replan-slice', 'M001/S01', base);
528
- assertEq(result, false, 'verifyExpectedArtifact returns false when REPLAN.md is missing');
527
+ assert.deepStrictEqual(result, false, 'verifyExpectedArtifact returns false when REPLAN.md is missing');
529
528
  rmSync(base, { recursive: true, force: true });
530
- }
529
+ });
531
530
 
532
- console.log('\n=== artifact: verifyExpectedArtifact passes when REPLAN.md exists (#858) ===');
533
- {
531
+ test('artifact: verifyExpectedArtifact passes when REPLAN.md exists (#858)', () => {
534
532
  const base = createFixtureBase();
535
533
  writeRoadmap(base, 'M001', ROADMAP_ONE_SLICE);
536
534
  writePlan(base, 'M001', 'S01', makePlanT01DoneT02Pending());
537
535
  writeReplanFile(base, 'M001', 'S01', '# Replan\n\nBlocker addressed.');
538
536
 
539
537
  const result = verifyExpectedArtifact('replan-slice', 'M001/S01', base);
540
- assertEq(result, true, 'verifyExpectedArtifact returns true when REPLAN.md exists');
538
+ assert.deepStrictEqual(result, true, 'verifyExpectedArtifact returns true when REPLAN.md exists');
541
539
  rmSync(base, { recursive: true, force: true });
542
- }
540
+ });
543
541
 
544
542
  // ═══════════════════════════════════════════════════════════════════════════
545
543
  // REPLAN-TRIGGER.md detection (triage-initiated replan, #1701)
546
544
  // ═══════════════════════════════════════════════════════════════════════════
547
-
548
545
  // (a) REPLAN-TRIGGER.md exists + no REPLAN.md → replanning-slice
549
- console.log('\n=== deriveState: REPLAN-TRIGGER.md exists, no REPLAN → replanning-slice (#1701) ===');
550
- {
546
+ test('deriveState: REPLAN-TRIGGER.md exists, no REPLAN → replanning-slice (#1701)', async () => {
551
547
  const base = createFixtureBase();
552
548
  writeRoadmap(base, 'M001', ROADMAP_ONE_SLICE);
553
549
  writePlan(base, 'M001', 'S01', makePlanT01DoneT02Pending());
@@ -556,17 +552,16 @@ console.log('\n=== deriveState: REPLAN-TRIGGER.md exists, no REPLAN → replanni
556
552
  writeReplanTrigger(base, 'M001', 'S01', '# Replan Trigger\n\n**Source:** Capture C001\n');
557
553
 
558
554
  const state = await deriveState(base);
559
- assertEq(state.phase, 'replanning-slice', 'phase is replanning-slice when REPLAN-TRIGGER.md exists');
560
- assertTrue(state.blockers.length > 0, 'blockers array is non-empty for triage replan trigger');
561
- assertTrue(state.nextAction.includes('Triage replan'), 'nextAction mentions triage replan');
562
- assertEq(state.activeSlice?.id, 'S01', 'activeSlice is S01');
563
- assertEq(state.activeTask?.id, 'T02', 'activeTask is T02 (next incomplete task)');
555
+ assert.deepStrictEqual(state.phase, 'replanning-slice', 'phase is replanning-slice when REPLAN-TRIGGER.md exists');
556
+ assert.ok(state.blockers.length > 0, 'blockers array is non-empty for triage replan trigger');
557
+ assert.ok(state.nextAction.includes('Triage replan'), 'nextAction mentions triage replan');
558
+ assert.deepStrictEqual(state.activeSlice?.id, 'S01', 'activeSlice is S01');
559
+ assert.deepStrictEqual(state.activeTask?.id, 'T02', 'activeTask is T02 (next incomplete task)');
564
560
  rmSync(base, { recursive: true, force: true });
565
- }
561
+ });
566
562
 
567
563
  // (b) REPLAN-TRIGGER.md + REPLAN.md both exist → executing (loop protection)
568
- console.log('\n=== deriveState: REPLAN-TRIGGER.md + REPLAN.md → executing (loop protection, #1701) ===');
569
- {
564
+ test('deriveState: REPLAN-TRIGGER.md + REPLAN.md → executing (loop protection, #1701)', async () => {
570
565
  const base = createFixtureBase();
571
566
  writeRoadmap(base, 'M001', ROADMAP_ONE_SLICE);
572
567
  writePlan(base, 'M001', 'S01', makePlanT01DoneT02Pending());
@@ -575,27 +570,25 @@ console.log('\n=== deriveState: REPLAN-TRIGGER.md + REPLAN.md → executing (loo
575
570
  writeReplanFile(base, 'M001', 'S01', '# Replan\n\nAlready replanned.');
576
571
 
577
572
  const state = await deriveState(base);
578
- assertEq(state.phase, 'executing', 'phase is executing when REPLAN.md exists (loop protection)');
579
- assertEq(state.activeTask?.id, 'T02', 'activeTask is T02');
573
+ assert.deepStrictEqual(state.phase, 'executing', 'phase is executing when REPLAN.md exists (loop protection)');
574
+ assert.deepStrictEqual(state.activeTask?.id, 'T02', 'activeTask is T02');
580
575
  rmSync(base, { recursive: true, force: true });
581
- }
576
+ });
582
577
 
583
578
  // (c) No REPLAN-TRIGGER.md, no blocker → executing (no false positive)
584
- console.log('\n=== deriveState: no REPLAN-TRIGGER.md, no blocker → executing (#1701) ===');
585
- {
579
+ test('deriveState: no REPLAN-TRIGGER.md, no blocker → executing (#1701)', async () => {
586
580
  const base = createFixtureBase();
587
581
  writeRoadmap(base, 'M001', ROADMAP_ONE_SLICE);
588
582
  writePlan(base, 'M001', 'S01', makePlanT01DoneT02Pending());
589
583
  writeTaskSummary(base, 'M001', 'S01', 'T01', makeTaskSummary('T01', false));
590
584
 
591
585
  const state = await deriveState(base);
592
- assertEq(state.phase, 'executing', 'phase is executing when no trigger and no blocker');
586
+ assert.deepStrictEqual(state.phase, 'executing', 'phase is executing when no trigger and no blocker');
593
587
  rmSync(base, { recursive: true, force: true });
594
- }
588
+ });
595
589
 
596
590
  // (d) blocker_discovered takes priority over REPLAN-TRIGGER.md
597
- console.log('\n=== deriveState: blocker_discovered takes priority over REPLAN-TRIGGER.md (#1701) ===');
598
- {
591
+ test('deriveState: blocker_discovered takes priority over REPLAN-TRIGGER.md (#1701)', async () => {
599
592
  const base = createFixtureBase();
600
593
  writeRoadmap(base, 'M001', ROADMAP_ONE_SLICE);
601
594
  writePlan(base, 'M001', 'S01', makePlanT01DoneT02Pending());
@@ -603,10 +596,10 @@ console.log('\n=== deriveState: blocker_discovered takes priority over REPLAN-TR
603
596
  writeReplanTrigger(base, 'M001', 'S01', '# Replan Trigger\n\n**Source:** Capture C001\n');
604
597
 
605
598
  const state = await deriveState(base);
606
- assertEq(state.phase, 'replanning-slice', 'phase is replanning-slice');
599
+ assert.deepStrictEqual(state.phase, 'replanning-slice', 'phase is replanning-slice');
607
600
  // blocker_discovered path should fire first (blockerTaskId is set, so REPLAN-TRIGGER check is skipped)
608
- assertTrue(state.nextAction.includes('T01'), 'nextAction mentions blocker task T01 (blocker path, not trigger path)');
601
+ assert.ok(state.nextAction.includes('T01'), 'nextAction mentions blocker task T01 (blocker path, not trigger path)');
609
602
  rmSync(base, { recursive: true, force: true });
610
- }
603
+ });
611
604
 
612
- report();
605
+ });
@@ -1,13 +1,11 @@
1
+ import { describe, test, before, after } from 'node:test';
2
+ import assert from 'node:assert/strict';
1
3
  import { mkdtempSync, rmSync, writeFileSync, existsSync, lstatSync, realpathSync, mkdirSync, symlinkSync, renameSync } from "node:fs";
2
4
  import { join } from "node:path";
3
5
  import { tmpdir } from "node:os";
4
6
  import { execSync } from "node:child_process";
5
7
 
6
8
  import { repoIdentity, externalGsdRoot, ensureGsdSymlink, validateProjectId, readRepoMeta, isInheritedRepo } from "../repo-identity.ts";
7
- import { createTestContext } from "./test-helpers.ts";
8
-
9
- const { assertEq, assertTrue, report } = createTestContext();
10
-
11
9
  /**
12
10
  * Normalize a path for reliable comparison on Windows CI runners.
13
11
  * `os.tmpdir()` may return the 8.3 short-path form (e.g. `C:\Users\RUNNER~1`)
@@ -23,11 +21,15 @@ function run(command: string, cwd: string): string {
23
21
  return execSync(command, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
24
22
  }
25
23
 
26
- async function main(): Promise<void> {
27
- const base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-repo-identity-")));
28
- const stateDir = realpathSync(mkdtempSync(join(tmpdir(), "gsd-state-")));
24
+ describe('repo-identity-worktree', () => {
25
+ let base: string;
26
+ let stateDir: string;
27
+ let worktreePath: string;
28
+ let expectedExternalState: string;
29
29
 
30
- try {
30
+ before(() => {
31
+ base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-repo-identity-")));
32
+ stateDir = realpathSync(mkdtempSync(join(tmpdir(), "gsd-state-")));
31
33
  process.env.GSD_STATE_DIR = stateDir;
32
34
 
33
35
  run("git init -b main", base);
@@ -38,57 +40,69 @@ async function main(): Promise<void> {
38
40
  run("git add README.md", base);
39
41
  run('git commit -m "chore: init"', base);
40
42
 
41
- const worktreePath = join(base, ".gsd", "worktrees", "M001");
43
+ worktreePath = join(base, ".gsd", "worktrees", "M001");
42
44
  run(`git worktree add -b milestone/M001 ${worktreePath}`, base);
43
45
 
44
- console.log("\n=== ensureGsdSymlink points worktree at main repo external state dir ===");
45
- const expectedExternalState = externalGsdRoot(base);
46
+ expectedExternalState = externalGsdRoot(base);
47
+ });
48
+
49
+ after(() => {
50
+ delete process.env.GSD_PROJECT_ID;
51
+ delete process.env.GSD_STATE_DIR;
52
+ rmSync(base, { recursive: true, force: true });
53
+ rmSync(stateDir, { recursive: true, force: true });
54
+ });
55
+
56
+ test('ensureGsdSymlink points worktree at main repo external state dir', () => {
46
57
  const mainState = ensureGsdSymlink(base);
47
- assertEq(mainState, realpathSync(join(base, ".gsd")), "ensureGsdSymlink(base) returns the current main repo .gsd target");
58
+ assert.deepStrictEqual(mainState, realpathSync(join(base, ".gsd")), "ensureGsdSymlink(base) returns the current main repo .gsd target");
48
59
  const worktreeState = ensureGsdSymlink(worktreePath);
49
- assertEq(worktreeState, expectedExternalState, "worktree symlink target matches main repo external state dir");
50
- assertTrue(existsSync(join(worktreePath, ".gsd")), "worktree .gsd exists");
51
- assertTrue(lstatSync(join(worktreePath, ".gsd")).isSymbolicLink(), "worktree .gsd is a symlink");
52
- assertEq(realpathSync(join(worktreePath, ".gsd")), realpathSync(expectedExternalState), "worktree .gsd symlink resolves to main repo external state dir");
60
+ assert.deepStrictEqual(worktreeState, expectedExternalState, "worktree symlink target matches main repo external state dir");
61
+ assert.ok(existsSync(join(worktreePath, ".gsd")), "worktree .gsd exists");
62
+ assert.ok(lstatSync(join(worktreePath, ".gsd")).isSymbolicLink(), "worktree .gsd is a symlink");
63
+ assert.deepStrictEqual(realpathSync(join(worktreePath, ".gsd")), realpathSync(expectedExternalState), "worktree .gsd symlink resolves to main repo external state dir");
64
+ });
53
65
 
54
- console.log("\n=== ensureGsdSymlink heals stale worktree symlinks ===");
66
+ test('ensureGsdSymlink heals stale worktree symlinks', () => {
55
67
  const staleState = join(stateDir, "projects", "stale-worktree-state");
56
68
  mkdirSync(staleState, { recursive: true });
57
69
  rmSync(join(worktreePath, ".gsd"), { recursive: true, force: true });
58
70
  symlinkSync(staleState, join(worktreePath, ".gsd"), "junction");
59
71
  const healedState = ensureGsdSymlink(worktreePath);
60
- assertEq(healedState, expectedExternalState, "stale worktree symlink is repaired to canonical external state dir");
61
- assertEq(realpathSync(join(worktreePath, ".gsd")), realpathSync(expectedExternalState), "healed worktree symlink resolves to canonical external state dir");
72
+ assert.deepStrictEqual(healedState, expectedExternalState, "stale worktree symlink is repaired to canonical external state dir");
73
+ assert.deepStrictEqual(realpathSync(join(worktreePath, ".gsd")), realpathSync(expectedExternalState), "healed worktree symlink resolves to canonical external state dir");
74
+ });
62
75
 
63
- console.log("\n=== ensureGsdSymlink preserves worktree .gsd directories ===");
76
+ test('ensureGsdSymlink preserves worktree .gsd directories', () => {
64
77
  rmSync(join(worktreePath, ".gsd"), { recursive: true, force: true });
65
78
  mkdirSync(join(worktreePath, ".gsd", "milestones"), { recursive: true });
66
79
  writeFileSync(join(worktreePath, ".gsd", "milestones", "stale.txt"), "stale\n", "utf-8");
67
80
  const preservedDirState = ensureGsdSymlink(worktreePath);
68
- assertEq(preservedDirState, join(worktreePath, ".gsd"), "worktree .gsd directory is left in place for sync-based refresh");
69
- assertTrue(lstatSync(join(worktreePath, ".gsd")).isDirectory(), "worktree .gsd directory remains a directory");
70
- assertTrue(existsSync(join(worktreePath, ".gsd", "milestones", "stale.txt")), "existing worktree .gsd directory contents remain available for sync logic");
81
+ assert.deepStrictEqual(preservedDirState, join(worktreePath, ".gsd"), "worktree .gsd directory is left in place for sync-based refresh");
82
+ assert.ok(lstatSync(join(worktreePath, ".gsd")).isDirectory(), "worktree .gsd directory remains a directory");
83
+ assert.ok(existsSync(join(worktreePath, ".gsd", "milestones", "stale.txt")), "existing worktree .gsd directory contents remain available for sync logic");
84
+ });
71
85
 
72
- console.log("\n=== GSD_PROJECT_ID overrides computed repo hash ===");
86
+ test('GSD_PROJECT_ID overrides computed repo hash', () => {
73
87
  process.env.GSD_PROJECT_ID = "my-project";
74
- assertEq(repoIdentity(base), "my-project", "repoIdentity returns GSD_PROJECT_ID when set");
75
- assertEq(externalGsdRoot(base), join(stateDir, "projects", "my-project"), "externalGsdRoot uses GSD_PROJECT_ID");
88
+ assert.deepStrictEqual(repoIdentity(base), "my-project", "repoIdentity returns GSD_PROJECT_ID when set");
89
+ assert.deepStrictEqual(externalGsdRoot(base), join(stateDir, "projects", "my-project"), "externalGsdRoot uses GSD_PROJECT_ID");
76
90
  delete process.env.GSD_PROJECT_ID;
91
+ });
77
92
 
78
- console.log("\n=== GSD_PROJECT_ID falls back to hash when unset ===");
93
+ test('GSD_PROJECT_ID falls back to hash when unset', () => {
79
94
  const hashIdentity = repoIdentity(base);
80
- assertTrue(/^[0-9a-f]{12}$/.test(hashIdentity), "repoIdentity returns 12-char hex hash when GSD_PROJECT_ID is unset");
95
+ assert.ok(/^[0-9a-f]{12}$/.test(hashIdentity), "repoIdentity returns 12-char hex hash when GSD_PROJECT_ID is unset");
96
+ });
81
97
 
82
- console.log("\n=== readRepoMeta returns null for malformed metadata ===");
83
- {
98
+ test('readRepoMeta returns null for malformed metadata', () => {
84
99
  const malformedPath = join(stateDir, "projects", "malformed");
85
100
  mkdirSync(malformedPath, { recursive: true });
86
101
  writeFileSync(join(malformedPath, "repo-meta.json"), JSON.stringify({ version: 1 }) + "\n", "utf-8");
87
- assertEq(readRepoMeta(malformedPath), null, "malformed repo-meta.json is treated as unknown metadata");
88
- }
102
+ assert.deepStrictEqual(readRepoMeta(malformedPath), null, "malformed repo-meta.json is treated as unknown metadata");
103
+ });
89
104
 
90
- console.log("\n=== ensureGsdSymlink refreshes repo-meta gitRoot after repo move with fixed project id ===");
91
- {
105
+ test('ensureGsdSymlink refreshes repo-meta gitRoot after repo move with fixed project id', () => {
92
106
  const moveRepo = realpathSync(mkdtempSync(join(tmpdir(), "gsd-repo-identity-move-")));
93
107
  run("git init -b main", moveRepo);
94
108
  run('git config user.name "Pi Test"', moveRepo);
@@ -100,26 +114,25 @@ async function main(): Promise<void> {
100
114
  process.env.GSD_PROJECT_ID = "fixed-project";
101
115
  const fixedExternal = ensureGsdSymlink(moveRepo);
102
116
  const before = readRepoMeta(fixedExternal);
103
- assertTrue(before !== null, "repo metadata exists before repo move");
104
- assertEq(normalizePath(before!.gitRoot), normalizePath(moveRepo), "repo metadata tracks current git root before move");
117
+ assert.ok(before !== null, "repo metadata exists before repo move");
118
+ assert.deepStrictEqual(normalizePath(before!.gitRoot), normalizePath(moveRepo), "repo metadata tracks current git root before move");
105
119
 
106
120
  const movedBaseRaw = join(tmpdir(), `gsd-repo-identity-moved-${Date.now()}-${Math.random().toString(36).slice(2)}`);
107
121
  renameSync(moveRepo, movedBaseRaw);
108
122
  const movedBase = realpathSync(movedBaseRaw);
109
123
  const movedExternal = ensureGsdSymlink(movedBase);
110
- assertEq(realpathSync(movedExternal), realpathSync(fixedExternal), "fixed project id keeps the same external state dir");
124
+ assert.deepStrictEqual(realpathSync(movedExternal), realpathSync(fixedExternal), "fixed project id keeps the same external state dir");
111
125
 
112
126
  const after = readRepoMeta(movedExternal);
113
- assertTrue(after !== null, "repo metadata exists after repo move");
114
- assertEq(normalizePath(after!.gitRoot), normalizePath(movedBase), "repo metadata gitRoot is refreshed to moved repo path");
115
- assertEq(after!.createdAt, before!.createdAt, "repo metadata preserves createdAt on refresh");
127
+ assert.ok(after !== null, "repo metadata exists after repo move");
128
+ assert.deepStrictEqual(normalizePath(after!.gitRoot), normalizePath(movedBase), "repo metadata gitRoot is refreshed to moved repo path");
129
+ assert.deepStrictEqual(after!.createdAt, before!.createdAt, "repo metadata preserves createdAt on refresh");
116
130
 
117
131
  rmSync(movedBase, { recursive: true, force: true });
118
132
  delete process.env.GSD_PROJECT_ID;
119
- }
133
+ });
120
134
 
121
- console.log("\n=== isInheritedRepo detects subdirectory of parent repo without .gsd (#1639) ===");
122
- {
135
+ test('isInheritedRepo detects subdirectory of parent repo without .gsd (#1639)', () => {
123
136
  const parentRepo = realpathSync(mkdtempSync(join(tmpdir(), "gsd-inherited-parent-")));
124
137
  run("git init -b main", parentRepo);
125
138
  run('git config user.name "Pi Test"', parentRepo);
@@ -128,31 +141,26 @@ async function main(): Promise<void> {
128
141
  run("git add README.md", parentRepo);
129
142
  run('git commit -m "init"', parentRepo);
130
143
 
131
- // Create a subdirectory — no .gsd at parent
132
144
  const subdir = join(parentRepo, "newproject");
133
145
  mkdirSync(subdir, { recursive: true });
134
- assertTrue(isInheritedRepo(subdir), "subdirectory of parent repo without .gsd is inherited");
146
+ assert.ok(isInheritedRepo(subdir), "subdirectory of parent repo without .gsd is inherited");
135
147
 
136
- // After adding .gsd at parent, subdirectory is a legitimate child
137
148
  mkdirSync(join(parentRepo, ".gsd"), { recursive: true });
138
- assertTrue(!isInheritedRepo(subdir), "subdirectory of parent repo WITH .gsd is NOT inherited");
149
+ assert.ok(!isInheritedRepo(subdir), "subdirectory of parent repo WITH .gsd is NOT inherited");
139
150
 
140
- // The git root itself is never inherited
141
- assertTrue(!isInheritedRepo(parentRepo), "git root is not inherited");
151
+ assert.ok(!isInheritedRepo(parentRepo), "git root is not inherited");
142
152
 
143
- // A standalone repo (not a subdir) is not inherited
144
153
  const standaloneRepo = realpathSync(mkdtempSync(join(tmpdir(), "gsd-inherited-standalone-")));
145
154
  run("git init -b main", standaloneRepo);
146
155
  run('git config user.name "Pi Test"', standaloneRepo);
147
156
  run('git config user.email "pi@example.com"', standaloneRepo);
148
- assertTrue(!isInheritedRepo(standaloneRepo), "standalone repo is not inherited");
157
+ assert.ok(!isInheritedRepo(standaloneRepo), "standalone repo is not inherited");
149
158
 
150
159
  rmSync(parentRepo, { recursive: true, force: true });
151
160
  rmSync(standaloneRepo, { recursive: true, force: true });
152
- }
161
+ });
153
162
 
154
- console.log("\n=== subdirectory of parent repo gets unique identity after git init (#1639) ===");
155
- {
163
+ test('subdirectory of parent repo gets unique identity after git init (#1639)', () => {
156
164
  const parentRepo = realpathSync(mkdtempSync(join(tmpdir(), "gsd-identity-parent-")));
157
165
  run("git init -b main", parentRepo);
158
166
  run('git config user.name "Pi Test"', parentRepo);
@@ -165,38 +173,27 @@ async function main(): Promise<void> {
165
173
  const subdir = join(parentRepo, "childproject");
166
174
  mkdirSync(subdir, { recursive: true });
167
175
 
168
- // Before git init, subdirectory shares parent's identity
169
176
  const parentIdentity = repoIdentity(parentRepo);
170
177
  const subdirIdentityBefore = repoIdentity(subdir);
171
- assertEq(subdirIdentityBefore, parentIdentity, "subdirectory shares parent identity before its own git init");
178
+ assert.deepStrictEqual(subdirIdentityBefore, parentIdentity, "subdirectory shares parent identity before its own git init");
172
179
 
173
- // After git init, subdirectory gets its own identity
174
180
  run("git init -b main", subdir);
175
181
  const subdirIdentityAfter = repoIdentity(subdir);
176
- assertTrue(subdirIdentityAfter !== parentIdentity, "subdirectory gets unique identity after git init");
182
+ assert.ok(subdirIdentityAfter !== parentIdentity, "subdirectory gets unique identity after git init");
177
183
 
178
184
  rmSync(parentRepo, { recursive: true, force: true });
179
- }
185
+ });
180
186
 
181
- console.log("\n=== validateProjectId rejects invalid values ===");
187
+ test('validateProjectId rejects invalid values', () => {
182
188
  for (const invalid of ["has spaces", "path/traversal", "dot..dot", "back\\slash"]) {
183
- assertTrue(!validateProjectId(invalid), `validateProjectId rejects invalid value: "${invalid}"`);
189
+ assert.ok(!validateProjectId(invalid), `validateProjectId rejects invalid value: "${invalid}"`);
184
190
  }
191
+ });
185
192
 
186
- console.log("\n=== validateProjectId accepts valid values ===");
193
+ test('validateProjectId accepts valid values', () => {
187
194
  for (const valid of ["my-project", "foo_bar", "abc123", "A-Z_0-9"]) {
188
- assertTrue(validateProjectId(valid), `validateProjectId accepts valid value: "${valid}"`);
195
+ assert.ok(validateProjectId(valid), `validateProjectId accepts valid value: "${valid}"`);
189
196
  }
190
- } finally {
191
- delete process.env.GSD_PROJECT_ID;
192
- delete process.env.GSD_STATE_DIR;
193
- rmSync(base, { recursive: true, force: true });
194
- rmSync(stateDir, { recursive: true, force: true });
195
- report();
196
- }
197
- }
197
+ });
198
198
 
199
- main().catch((error) => {
200
- console.error(error);
201
- process.exit(1);
202
199
  });