gsd-pi 2.43.0-next.8 → 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 (399) 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/gsd/auto-direct-dispatch.js +21 -8
  5. package/dist/resources/extensions/gsd/auto-prompts.js +130 -51
  6. package/dist/resources/extensions/gsd/auto-start.js +10 -0
  7. package/dist/resources/extensions/gsd/auto-worktree.js +16 -2
  8. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  9. package/dist/resources/extensions/gsd/dispatch-guard.js +34 -10
  10. package/dist/resources/extensions/gsd/markdown-renderer.js +7 -5
  11. package/dist/resources/extensions/gsd/reactive-graph.js +13 -2
  12. package/dist/resources/extensions/gsd/skill-health.js +3 -1
  13. package/dist/resources/extensions/gsd/tools/plan-milestone.js +2 -11
  14. package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -10
  15. package/dist/resources/extensions/gsd/visualizer-data.js +45 -13
  16. package/dist/resources/extensions/gsd/workspace-index.js +46 -15
  17. package/dist/web/standalone/.next/BUILD_ID +1 -1
  18. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -18
  19. package/dist/web/standalone/.next/build-manifest.json +3 -3
  20. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  21. package/dist/web/standalone/.next/required-server-files.json +4 -4
  22. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  23. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  24. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  25. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  33. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  34. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  35. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  36. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  37. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  39. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  43. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  44. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  45. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  46. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  47. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  48. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  49. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  50. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  51. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  52. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  53. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  54. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  55. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  62. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  87. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  93. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  109. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  111. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  113. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/index.html +1 -1
  123. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  124. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  125. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  126. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  128. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/page.js +2 -2
  130. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -18
  132. package/dist/web/standalone/.next/server/chunks/229.js +1 -1
  133. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  134. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/middleware.js +2 -2
  136. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  138. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  139. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  140. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  141. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
  142. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
  143. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
  144. package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
  145. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  146. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  147. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  148. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  149. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  150. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  151. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  152. package/dist/web/standalone/server.js +1 -1
  153. package/package.json +4 -4
  154. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +3 -3
  155. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  156. package/packages/pi-coding-agent/dist/core/agent-session.js +11 -34
  157. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  158. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  159. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts +2 -2
  161. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  162. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
  163. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +2 -2
  164. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  165. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  166. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +4 -4
  167. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  168. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  169. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  170. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  171. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  172. package/packages/pi-coding-agent/dist/core/extensions/loader.js +18 -0
  173. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  174. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  175. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  176. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +37 -0
  177. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  178. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -1
  180. package/packages/pi-coding-agent/dist/core/fallback-resolver.js +2 -3
  181. package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -1
  182. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +12 -2
  183. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  185. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  186. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +38 -0
  187. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -0
  188. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +192 -0
  189. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -0
  190. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts +2 -0
  191. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts.map +1 -0
  192. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +255 -0
  193. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -0
  194. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +15 -0
  195. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
  197. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  198. package/packages/pi-coding-agent/dist/core/package-commands.d.ts +25 -0
  199. package/packages/pi-coding-agent/dist/core/package-commands.d.ts.map +1 -0
  200. package/packages/pi-coding-agent/dist/core/package-commands.js +253 -0
  201. package/packages/pi-coding-agent/dist/core/package-commands.js.map +1 -0
  202. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts +2 -0
  203. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts.map +1 -0
  204. package/packages/pi-coding-agent/dist/core/package-commands.test.js +225 -0
  205. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -0
  206. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  207. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  209. package/packages/pi-coding-agent/dist/core/sdk.js +4 -0
  210. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  211. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  212. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  213. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  214. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  215. package/packages/pi-coding-agent/dist/index.d.ts +3 -1
  216. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  217. package/packages/pi-coding-agent/dist/index.js +1 -0
  218. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  219. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  220. package/packages/pi-coding-agent/dist/main.js +11 -199
  221. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  222. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  223. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  224. package/packages/pi-coding-agent/package.json +1 -1
  225. package/packages/pi-coding-agent/src/core/agent-session.ts +13 -37
  226. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  227. package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +2 -2
  228. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +3 -3
  229. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +4 -4
  230. package/packages/pi-coding-agent/src/core/extensions/index.ts +5 -0
  231. package/packages/pi-coding-agent/src/core/extensions/loader.ts +23 -0
  232. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  233. package/packages/pi-coding-agent/src/core/extensions/types.ts +44 -0
  234. package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +15 -2
  235. package/packages/pi-coding-agent/src/core/fallback-resolver.ts +2 -3
  236. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  237. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +274 -0
  238. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +288 -0
  239. package/packages/pi-coding-agent/src/core/model-registry.ts +39 -3
  240. package/packages/pi-coding-agent/src/core/package-commands.test.ts +240 -0
  241. package/packages/pi-coding-agent/src/core/package-commands.ts +310 -0
  242. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  243. package/packages/pi-coding-agent/src/core/sdk.ts +4 -0
  244. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  245. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  246. package/packages/pi-coding-agent/src/index.ts +7 -0
  247. package/packages/pi-coding-agent/src/main.ts +11 -232
  248. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  249. package/pkg/package.json +1 -1
  250. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +22 -7
  251. package/src/resources/extensions/gsd/auto-prompts.ts +109 -42
  252. package/src/resources/extensions/gsd/auto-start.ts +14 -0
  253. package/src/resources/extensions/gsd/auto-worktree.ts +16 -3
  254. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  255. package/src/resources/extensions/gsd/dispatch-guard.ts +28 -10
  256. package/src/resources/extensions/gsd/markdown-renderer.ts +7 -5
  257. package/src/resources/extensions/gsd/reactive-graph.ts +12 -2
  258. package/src/resources/extensions/gsd/skill-health.ts +2 -1
  259. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  260. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  261. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  262. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  263. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
  264. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  265. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  266. package/src/resources/extensions/gsd/tests/auto-stash-merge.test.ts +3 -3
  267. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
  268. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  269. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  270. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  271. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  272. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  273. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  274. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  275. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
  276. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
  277. package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
  278. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  279. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  280. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  281. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  282. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  283. package/src/resources/extensions/gsd/tests/db-writer.test.ts +390 -420
  284. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  285. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
  286. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +152 -183
  287. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  288. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  289. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  290. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  291. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
  292. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  293. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  294. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
  295. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  296. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
  297. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
  298. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  299. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
  300. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  301. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  302. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
  303. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  304. package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
  305. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  306. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  307. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  308. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  309. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
  310. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
  311. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  312. package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
  313. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  314. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  315. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  316. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  317. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
  318. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  319. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  320. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  321. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
  322. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  323. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  324. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  325. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  326. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
  327. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
  328. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  329. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  330. package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
  331. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  332. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
  333. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  334. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  335. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  336. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
  337. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
  338. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  339. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
  340. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  341. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  342. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  343. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  344. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  345. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  346. package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
  347. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  348. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  349. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  350. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  351. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  352. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  353. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  354. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  355. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  356. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  357. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  358. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  359. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  360. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  361. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  362. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  363. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  364. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  365. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
  366. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  367. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  368. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  369. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  370. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  371. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +9 -11
  372. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  373. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  374. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  375. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  376. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  377. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  378. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  379. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  380. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  381. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  382. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  383. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  384. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  385. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  386. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  387. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  388. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  389. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  390. package/src/resources/extensions/gsd/tools/plan-milestone.ts +1 -18
  391. package/src/resources/extensions/gsd/tools/plan-slice.ts +1 -15
  392. package/src/resources/extensions/gsd/visualizer-data.ts +46 -14
  393. package/src/resources/extensions/gsd/workspace-index.ts +49 -18
  394. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
  395. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
  396. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
  397. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
  398. /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → alS4hoANx0TK4UVZY27da}/_buildManifest.js +0 -0
  399. /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → alS4hoANx0TK4UVZY27da}/_ssgManifest.js +0 -0
@@ -17,9 +17,9 @@ import {
17
17
  } from "../worktree.ts";
18
18
  import { readIntegrationBranch } from "../git-service.ts";
19
19
  import { _resetHasChangesCache } from "../native-git-bridge.ts";
20
- import { createTestContext } from './test-helpers.ts';
20
+ import { describe, test } from 'node:test';
21
+ import assert from 'node:assert/strict';
21
22
 
22
- const { assertEq, assertTrue, report } = createTestContext();
23
23
 
24
24
  /**
25
25
  * Normalize a path for reliable comparison on Windows CI runners.
@@ -47,56 +47,56 @@ writeFileSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "S01-PLA
47
47
  run("git add .", base);
48
48
  run('git commit -m "chore: init"', base);
49
49
 
50
- async function main(): Promise<void> {
50
+ describe('worktree', async () => {
51
51
 
52
52
  console.log("\n=== autoCommitCurrentBranch ===");
53
53
  // Clean — should return null
54
54
  const cleanResult = autoCommitCurrentBranch(base, "execute-task", "M001/S01/T01");
55
- assertEq(cleanResult, null, "returns null for clean repo");
55
+ assert.deepStrictEqual(cleanResult, null, "returns null for clean repo");
56
56
 
57
57
  // Make dirty — reset the nativeHasChanges cache so the fresh dirt is detected
58
58
  _resetHasChangesCache();
59
59
  writeFileSync(join(base, "dirty.txt"), "uncommitted\n", "utf-8");
60
60
  const dirtyResult = autoCommitCurrentBranch(base, "execute-task", "M001/S01/T01");
61
- assertTrue(dirtyResult !== null, "returns commit message for dirty repo");
62
- assertTrue(dirtyResult!.includes("M001/S01/T01"), "commit message includes unit id");
63
- assertEq(run("git status --short", base), "", "repo is clean after auto-commit");
61
+ assert.ok(dirtyResult !== null, "returns commit message for dirty repo");
62
+ assert.ok(dirtyResult!.includes("M001/S01/T01"), "commit message includes unit id");
63
+ assert.deepStrictEqual(run("git status --short", base), "", "repo is clean after auto-commit");
64
64
 
65
65
  console.log("\n=== getSliceBranchName ===");
66
- assertEq(getSliceBranchName("M001", "S01"), "gsd/M001/S01", "branch name format correct");
67
- assertEq(getSliceBranchName("M001", "S01", null), "gsd/M001/S01", "null worktree = plain branch");
68
- assertEq(getSliceBranchName("M001", "S01", "my-wt"), "gsd/my-wt/M001/S01", "worktree-namespaced branch");
66
+ assert.deepStrictEqual(getSliceBranchName("M001", "S01"), "gsd/M001/S01", "branch name format correct");
67
+ assert.deepStrictEqual(getSliceBranchName("M001", "S01", null), "gsd/M001/S01", "null worktree = plain branch");
68
+ assert.deepStrictEqual(getSliceBranchName("M001", "S01", "my-wt"), "gsd/my-wt/M001/S01", "worktree-namespaced branch");
69
69
 
70
70
  console.log("\n=== parseSliceBranch ===");
71
71
  const plain = parseSliceBranch("gsd/M001/S01");
72
- assertTrue(plain !== null, "parses plain branch");
73
- assertEq(plain!.worktreeName, null, "plain branch has no worktree name");
74
- assertEq(plain!.milestoneId, "M001", "plain branch milestone");
75
- assertEq(plain!.sliceId, "S01", "plain branch slice");
72
+ assert.ok(plain !== null, "parses plain branch");
73
+ assert.deepStrictEqual(plain!.worktreeName, null, "plain branch has no worktree name");
74
+ assert.deepStrictEqual(plain!.milestoneId, "M001", "plain branch milestone");
75
+ assert.deepStrictEqual(plain!.sliceId, "S01", "plain branch slice");
76
76
 
77
77
  const namespaced = parseSliceBranch("gsd/feature-auth/M001/S01");
78
- assertTrue(namespaced !== null, "parses worktree-namespaced branch");
79
- assertEq(namespaced!.worktreeName, "feature-auth", "worktree name extracted");
80
- assertEq(namespaced!.milestoneId, "M001", "namespaced branch milestone");
81
- assertEq(namespaced!.sliceId, "S01", "namespaced branch slice");
78
+ assert.ok(namespaced !== null, "parses worktree-namespaced branch");
79
+ assert.deepStrictEqual(namespaced!.worktreeName, "feature-auth", "worktree name extracted");
80
+ assert.deepStrictEqual(namespaced!.milestoneId, "M001", "namespaced branch milestone");
81
+ assert.deepStrictEqual(namespaced!.sliceId, "S01", "namespaced branch slice");
82
82
 
83
83
  const invalid = parseSliceBranch("main");
84
- assertEq(invalid, null, "non-slice branch returns null");
84
+ assert.deepStrictEqual(invalid, null, "non-slice branch returns null");
85
85
 
86
86
  const worktreeBranch = parseSliceBranch("worktree/foo");
87
- assertEq(worktreeBranch, null, "worktree/ prefix is not a slice branch");
87
+ assert.deepStrictEqual(worktreeBranch, null, "worktree/ prefix is not a slice branch");
88
88
 
89
89
  console.log("\n=== SLICE_BRANCH_RE ===");
90
- assertTrue(SLICE_BRANCH_RE.test("gsd/M001/S01"), "regex matches plain branch");
91
- assertTrue(SLICE_BRANCH_RE.test("gsd/my-wt/M001/S01"), "regex matches worktree branch");
92
- assertTrue(!SLICE_BRANCH_RE.test("main"), "regex rejects main");
93
- assertTrue(!SLICE_BRANCH_RE.test("gsd/"), "regex rejects bare gsd/");
94
- assertTrue(!SLICE_BRANCH_RE.test("worktree/foo"), "regex rejects worktree/foo");
90
+ assert.ok(SLICE_BRANCH_RE.test("gsd/M001/S01"), "regex matches plain branch");
91
+ assert.ok(SLICE_BRANCH_RE.test("gsd/my-wt/M001/S01"), "regex matches worktree branch");
92
+ assert.ok(!SLICE_BRANCH_RE.test("main"), "regex rejects main");
93
+ assert.ok(!SLICE_BRANCH_RE.test("gsd/"), "regex rejects bare gsd/");
94
+ assert.ok(!SLICE_BRANCH_RE.test("worktree/foo"), "regex rejects worktree/foo");
95
95
 
96
96
  console.log("\n=== detectWorktreeName ===");
97
- assertEq(detectWorktreeName("/projects/myapp"), null, "no worktree in plain path");
98
- assertEq(detectWorktreeName("/projects/myapp/.gsd/worktrees/feature-auth"), "feature-auth", "detects worktree name");
99
- assertEq(detectWorktreeName("/projects/myapp/.gsd/worktrees/my-wt/subdir"), "my-wt", "detects worktree with subdir");
97
+ assert.deepStrictEqual(detectWorktreeName("/projects/myapp"), null, "no worktree in plain path");
98
+ assert.deepStrictEqual(detectWorktreeName("/projects/myapp/.gsd/worktrees/feature-auth"), "feature-auth", "detects worktree name");
99
+ assert.deepStrictEqual(detectWorktreeName("/projects/myapp/.gsd/worktrees/my-wt/subdir"), "my-wt", "detects worktree with subdir");
100
100
 
101
101
  // ═══════════════════════════════════════════════════════════════════════
102
102
  // Integration branch — facade-level tests
@@ -115,16 +115,16 @@ async function main(): Promise<void> {
115
115
  run("git add -A && git commit -m init", repo);
116
116
 
117
117
  run("git checkout -b f-123-thing", repo);
118
- assertEq(getCurrentBranch(repo), "f-123-thing", "on feature branch");
118
+ assert.deepStrictEqual(getCurrentBranch(repo), "f-123-thing", "on feature branch");
119
119
 
120
120
  const commitsBefore = run("git rev-list --count HEAD", repo);
121
121
  captureIntegrationBranch(repo, "M001");
122
- assertEq(readIntegrationBranch(repo, "M001"), "f-123-thing",
122
+ assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), "f-123-thing",
123
123
  "captureIntegrationBranch records the current branch");
124
124
 
125
125
  // Metadata is stored in external state, not committed to git.
126
126
  const commitsAfter = run("git rev-list --count HEAD", repo);
127
- assertEq(commitsAfter, commitsBefore, "captureIntegrationBranch does not create a git commit");
127
+ assert.deepStrictEqual(commitsAfter, commitsBefore, "captureIntegrationBranch does not create a git commit");
128
128
 
129
129
  rmSync(repo, { recursive: true, force: true });
130
130
  }
@@ -144,7 +144,7 @@ async function main(): Promise<void> {
144
144
  run("git checkout -b gsd/M001/S01", repo);
145
145
  captureIntegrationBranch(repo, "M001");
146
146
 
147
- assertEq(readIntegrationBranch(repo, "M001"), null,
147
+ assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), null,
148
148
  "capture from slice branch is a no-op");
149
149
 
150
150
  rmSync(repo, { recursive: true, force: true });
@@ -167,12 +167,12 @@ async function main(): Promise<void> {
167
167
 
168
168
  // Without milestone set, getMainBranch returns "main"
169
169
  setActiveMilestoneId(repo, null);
170
- assertEq(getMainBranch(repo), "main",
170
+ assert.deepStrictEqual(getMainBranch(repo), "main",
171
171
  "getMainBranch returns main without milestone set");
172
172
 
173
173
  // With milestone set, getMainBranch returns feature branch
174
174
  setActiveMilestoneId(repo, "M001");
175
- assertEq(getMainBranch(repo), "my-feature",
175
+ assert.deepStrictEqual(getMainBranch(repo), "my-feature",
176
176
  "getMainBranch returns integration branch with milestone set");
177
177
 
178
178
  rmSync(repo, { recursive: true, force: true });
@@ -180,22 +180,22 @@ async function main(): Promise<void> {
180
180
 
181
181
  // ── detectWorktreeName: symlink-resolved paths ───────────────────────────
182
182
  console.log("\n=== detectWorktreeName (symlink-resolved paths) ===");
183
- assertEq(
183
+ assert.deepStrictEqual(
184
184
  detectWorktreeName("/Users/fran/.gsd/projects/89e1c9ad49bf/worktrees/M001"),
185
185
  "M001",
186
186
  "detects milestone in symlink-resolved path",
187
187
  );
188
- assertEq(
188
+ assert.deepStrictEqual(
189
189
  detectWorktreeName("/Users/fran/.gsd/projects/abc123/worktrees/M002/subdir"),
190
190
  "M002",
191
191
  "detects milestone with trailing subdir in symlink-resolved path",
192
192
  );
193
- assertEq(
193
+ assert.deepStrictEqual(
194
194
  detectWorktreeName("/Users/fran/.gsd/projects/abc123"),
195
195
  null,
196
196
  "returns null for project root without worktrees segment",
197
197
  );
198
- assertEq(
198
+ assert.deepStrictEqual(
199
199
  detectWorktreeName("/foo/.gsd/worktrees/M001"),
200
200
  "M001",
201
201
  "still detects direct layout path",
@@ -211,7 +211,7 @@ async function main(): Promise<void> {
211
211
 
212
212
  // With GSD_PROJECT_ROOT env var set (layer 1 — coordinator passes it)
213
213
  process.env.GSD_PROJECT_ROOT = "/real/project";
214
- assertEq(
214
+ assert.deepStrictEqual(
215
215
  resolveProjectRoot("/Users/fran/.gsd/projects/89e1c9ad49bf/worktrees/M001"),
216
216
  "/real/project",
217
217
  "uses GSD_PROJECT_ROOT when set",
@@ -219,7 +219,7 @@ async function main(): Promise<void> {
219
219
  delete process.env.GSD_PROJECT_ROOT;
220
220
 
221
221
  // Without GSD_PROJECT_ROOT, direct layout still works (no ~/.gsd collision)
222
- assertEq(
222
+ assert.deepStrictEqual(
223
223
  resolveProjectRoot("/some/repo"),
224
224
  "/some/repo",
225
225
  "ignores GSD_PROJECT_ROOT override for non-worktree paths",
@@ -227,19 +227,19 @@ async function main(): Promise<void> {
227
227
  delete process.env.GSD_PROJECT_ROOT;
228
228
 
229
229
  // Without GSD_PROJECT_ROOT, direct layout still works (no ~/.gsd collision)
230
- assertEq(
230
+ assert.deepStrictEqual(
231
231
  resolveProjectRoot("/foo/.gsd/worktrees/M001"),
232
232
  "/foo",
233
233
  "still resolves direct layout path",
234
234
  );
235
- assertEq(
235
+ assert.deepStrictEqual(
236
236
  resolveProjectRoot("/some/repo"),
237
237
  "/some/repo",
238
238
  "returns unchanged for non-worktree path",
239
239
  );
240
240
 
241
241
  // Without GSD_PROJECT_ROOT, direct layout with nested subdirs
242
- assertEq(
242
+ assert.deepStrictEqual(
243
243
  resolveProjectRoot("/data/.gsd/worktrees/M003/nested"),
244
244
  "/data",
245
245
  "resolves correctly with nested subdirs after worktree name (direct layout)",
@@ -264,7 +264,7 @@ async function main(): Promise<void> {
264
264
  mkdirSync(deep, { recursive: true });
265
265
 
266
266
  process.env.GSD_HOME = join(fakeHome, ".gsd");
267
- assertEq(
267
+ assert.deepStrictEqual(
268
268
  normalizePath(resolveProjectRoot(realpathSync(deep))),
269
269
  normalizePath(project),
270
270
  "resolves to real project root from deep symlink-resolved worktree path",
@@ -276,10 +276,4 @@ async function main(): Promise<void> {
276
276
  }
277
277
 
278
278
  rmSync(base, { recursive: true, force: true });
279
- report();
280
- }
281
-
282
- main().catch((error) => {
283
- console.error(error);
284
- process.exit(1);
285
279
  });
@@ -233,25 +233,8 @@ export async function handlePlanMilestone(
233
233
  roadmapPath = renderResult.roadmapPath;
234
234
  } catch (renderErr) {
235
235
  process.stderr.write(
236
- `gsd-db: plan_milestone — render failed, rolling back DB rows: ${(renderErr as Error).message}\n`,
236
+ `gsd-db: plan_milestone — render failed (DB rows preserved for debugging): ${(renderErr as Error).message}\n`,
237
237
  );
238
- const rollbackAdapter = _getAdapter();
239
- if (rollbackAdapter) {
240
- for (const slice of params.slices) {
241
- rollbackAdapter.prepare(
242
- `DELETE FROM slice_planning WHERE milestone_id = :mid AND slice_id = :sid`,
243
- ).run({ ":mid": params.milestoneId, ":sid": slice.sliceId });
244
- rollbackAdapter.prepare(
245
- `DELETE FROM slices WHERE milestone_id = :mid AND id = :sid`,
246
- ).run({ ":mid": params.milestoneId, ":sid": slice.sliceId });
247
- }
248
- rollbackAdapter.prepare(
249
- `DELETE FROM milestone_planning WHERE milestone_id = :mid`,
250
- ).run({ ":mid": params.milestoneId });
251
- rollbackAdapter.prepare(
252
- `DELETE FROM milestones WHERE id = :mid`,
253
- ).run({ ":mid": params.milestoneId });
254
- }
255
238
  invalidateStateCache();
256
239
  return { error: `render failed: ${(renderErr as Error).message}` };
257
240
  }
@@ -186,22 +186,8 @@ export async function handlePlanSlice(
186
186
  };
187
187
  } catch (renderErr) {
188
188
  process.stderr.write(
189
- `gsd-db: plan_slice — render failed, rolling back DB rows: ${(renderErr as Error).message}\n`,
189
+ `gsd-db: plan_slice — render failed (DB rows preserved for debugging): ${(renderErr as Error).message}\n`,
190
190
  );
191
- const rollbackAdapter = _getAdapter();
192
- if (rollbackAdapter) {
193
- for (const task of params.tasks) {
194
- rollbackAdapter.prepare(
195
- `DELETE FROM task_planning WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid`,
196
- ).run({ ":mid": params.milestoneId, ":sid": params.sliceId, ":tid": task.taskId });
197
- rollbackAdapter.prepare(
198
- `DELETE FROM tasks WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`,
199
- ).run({ ":mid": params.milestoneId, ":sid": params.sliceId, ":tid": task.taskId });
200
- }
201
- rollbackAdapter.prepare(
202
- `DELETE FROM slice_planning WHERE milestone_id = :mid AND slice_id = :sid`,
203
- ).run({ ":mid": params.milestoneId, ":sid": params.sliceId });
204
- }
205
191
  invalidateStateCache();
206
192
  return { error: `render failed: ${(renderErr as Error).message}` };
207
193
  }
@@ -5,6 +5,7 @@ import { join } from 'node:path';
5
5
  import { deriveState } from './state.js';
6
6
  import { parseSummary, loadFile } from './files.js';
7
7
  import { isDbAvailable, getMilestoneSlices, getSliceTasks } from './gsd-db.js';
8
+ import { parseRoadmap, parsePlan } from './parsers-legacy.js';
8
9
  import { findMilestoneIds } from './milestone-ids.js';
9
10
  import { resolveMilestoneFile, resolveSliceFile, resolveGsdRootFile, gsdRoot } from './paths.js';
10
11
  import {
@@ -798,14 +799,21 @@ export async function loadVisualizerData(basePath: string): Promise<VisualizerDa
798
799
  const roadmapContent = roadmapFile ? readFileCached(roadmapFile) : null;
799
800
 
800
801
  if (roadmapContent || isDbAvailable()) {
801
- // Normalize slices from DB
802
+ // Normalize slices from DB, fall back to file-based parsing when DB has no data
802
803
  type NormSlice = { id: string; done: boolean; title: string; risk: string; depends: string[]; demo: string };
803
- let normSlices: NormSlice[];
804
+ let normSlices: NormSlice[] | null = null;
804
805
  if (isDbAvailable()) {
805
- normSlices = getMilestoneSlices(mid).map(s => ({ id: s.id, done: s.status === 'complete', title: s.title, risk: s.risk || 'medium', depends: s.depends, demo: s.demo }));
806
- } else {
807
- normSlices = [];
806
+ const dbSlices = getMilestoneSlices(mid);
807
+ if (dbSlices.length > 0) {
808
+ normSlices = dbSlices.map(s => ({ id: s.id, done: s.status === 'complete', title: s.title, risk: s.risk || 'medium', depends: s.depends, demo: s.demo }));
809
+ }
810
+ }
811
+ if (!normSlices && roadmapContent) {
812
+ // File-based fallback: parse roadmap for slice entries
813
+ const parsed = parseRoadmap(roadmapContent);
814
+ normSlices = parsed.slices.map(s => ({ id: s.id, done: s.done, title: s.title, risk: s.risk || 'medium', depends: s.depends, demo: '' }));
808
815
  }
816
+ if (!normSlices) normSlices = [];
809
817
 
810
818
  for (const s of normSlices) {
811
819
  const isActiveSlice =
@@ -815,16 +823,40 @@ export async function loadVisualizerData(basePath: string): Promise<VisualizerDa
815
823
  const tasks: VisualizerTask[] = [];
816
824
 
817
825
  if (isActiveSlice) {
818
- // Normalize tasks from DB
826
+ // Normalize tasks from DB, fall back to file parsing when DB has no data
827
+ let usedDbTasks = false;
819
828
  if (isDbAvailable()) {
820
- for (const t of getSliceTasks(mid, s.id)) {
821
- tasks.push({
822
- id: t.id,
823
- title: t.title,
824
- done: t.status === 'complete' || t.status === 'done',
825
- active: state.activeTask?.id === t.id,
826
- estimate: t.estimate || undefined,
827
- });
829
+ const dbTasks = getSliceTasks(mid, s.id);
830
+ if (dbTasks.length > 0) {
831
+ usedDbTasks = true;
832
+ for (const t of dbTasks) {
833
+ tasks.push({
834
+ id: t.id,
835
+ title: t.title,
836
+ done: t.status === 'complete' || t.status === 'done',
837
+ active: state.activeTask?.id === t.id,
838
+ estimate: t.estimate || undefined,
839
+ });
840
+ }
841
+ }
842
+ }
843
+ if (!usedDbTasks) {
844
+ // File-based fallback: parse slice plan for task entries
845
+ const slicePlanFile = resolveSliceFile(basePath, mid, s.id, 'PLAN');
846
+ if (slicePlanFile) {
847
+ const planContent = readFileCached(slicePlanFile);
848
+ if (planContent) {
849
+ const parsed = parsePlan(planContent);
850
+ for (const t of parsed.tasks) {
851
+ tasks.push({
852
+ id: t.id,
853
+ title: t.title,
854
+ done: t.done,
855
+ active: state.activeTask?.id === t.id,
856
+ estimate: t.estimate || undefined,
857
+ });
858
+ }
859
+ }
828
860
  }
829
861
  }
830
862
  }
@@ -2,6 +2,7 @@ import { join } from "node:path";
2
2
 
3
3
  import { loadFile } from "./files.js";
4
4
  import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
5
+ import { parseRoadmap, parsePlan } from "./parsers-legacy.js";
5
6
  import {
6
7
  resolveMilestoneFile,
7
8
  resolveSliceFile,
@@ -79,21 +80,40 @@ async function indexSlice(basePath: string, milestoneId: string, sliceId: string
79
80
  const tasks: WorkspaceTaskTarget[] = [];
80
81
  let title = fallbackTitle;
81
82
 
82
- // Prefer DB for task data
83
+ // Prefer DB for task data, fall back to file parsing when DB has no data
84
+ let usedDb = false;
83
85
  if (isDbAvailable()) {
84
86
  const dbTasks = getSliceTasks(milestoneId, sliceId);
85
- for (const task of dbTasks) {
86
- title = fallbackTitle; // title comes from slice-level data, not plan
87
- tasks.push({
88
- id: task.id,
89
- title: task.title,
90
- done: task.status === "complete" || task.status === "done",
91
- planPath: resolveTaskFile(basePath, milestoneId, sliceId, task.id, "PLAN") ?? undefined,
92
- summaryPath: resolveTaskFile(basePath, milestoneId, sliceId, task.id, "SUMMARY") ?? undefined,
93
- });
87
+ if (dbTasks.length > 0) {
88
+ usedDb = true;
89
+ for (const task of dbTasks) {
90
+ title = fallbackTitle; // title comes from slice-level data, not plan
91
+ tasks.push({
92
+ id: task.id,
93
+ title: task.title,
94
+ done: task.status === "complete" || task.status === "done",
95
+ planPath: resolveTaskFile(basePath, milestoneId, sliceId, task.id, "PLAN") ?? undefined,
96
+ summaryPath: resolveTaskFile(basePath, milestoneId, sliceId, task.id, "SUMMARY") ?? undefined,
97
+ });
98
+ }
99
+ }
100
+ }
101
+ if (!usedDb && planPath) {
102
+ // File-based fallback: parse slice plan for task entries
103
+ const planContent = await loadFile(planPath);
104
+ if (planContent) {
105
+ const parsed = parsePlan(planContent);
106
+ for (const task of parsed.tasks) {
107
+ tasks.push({
108
+ id: task.id,
109
+ title: task.title,
110
+ done: task.done,
111
+ planPath: resolveTaskFile(basePath, milestoneId, sliceId, task.id, "PLAN") ?? undefined,
112
+ summaryPath: resolveTaskFile(basePath, milestoneId, sliceId, task.id, "SUMMARY") ?? undefined,
113
+ });
114
+ }
94
115
  }
95
116
  }
96
- // When DB unavailable, tasks stays empty
97
117
 
98
118
  return {
99
119
  id: sliceId,
@@ -125,23 +145,34 @@ export async function indexWorkspace(basePath: string, opts: IndexWorkspaceOptio
125
145
  const slices: WorkspaceSliceTarget[] = [];
126
146
 
127
147
  if (roadmapPath || isDbAvailable()) {
128
- // Normalize slices from DB
148
+ // Normalize slices from DB, fall back to file-based parsing when DB has no data
129
149
  type NormSlice = { id: string; done: boolean; title: string; risk: string; depends: string[]; demo: string };
130
- let normSlices: NormSlice[];
150
+ let normSlices: NormSlice[] | null = null;
131
151
  if (isDbAvailable()) {
132
- normSlices = getMilestoneSlices(milestoneId).map(s => ({ id: s.id, done: s.status === "complete", title: s.title, risk: s.risk || "medium", depends: s.depends, demo: s.demo }));
152
+ const dbSlices = getMilestoneSlices(milestoneId);
153
+ if (dbSlices.length > 0) {
154
+ normSlices = dbSlices.map(s => ({ id: s.id, done: s.status === "complete", title: s.title, risk: s.risk || "medium", depends: s.depends, demo: s.demo }));
155
+ }
133
156
  // Get title from roadmap header
134
157
  if (roadmapPath) {
135
158
  const roadmapContent = await loadFile(roadmapPath);
136
159
  if (roadmapContent) title = titleFromRoadmapHeader(roadmapContent, milestoneId);
137
160
  }
138
- } else {
139
- normSlices = [];
140
161
  }
162
+ if (!normSlices && roadmapPath) {
163
+ // File-based fallback: parse roadmap for slice entries
164
+ const roadmapContent = await loadFile(roadmapPath);
165
+ if (roadmapContent) {
166
+ title = titleFromRoadmapHeader(roadmapContent, milestoneId);
167
+ const parsed = parseRoadmap(roadmapContent);
168
+ normSlices = parsed.slices.map(s => ({ id: s.id, done: s.done, title: s.title, risk: s.risk || "medium", depends: s.depends, demo: s.demo || "" }));
169
+ }
170
+ }
171
+ if (!normSlices) normSlices = [];
141
172
 
142
- if (normSlices!.length > 0) {
173
+ if (normSlices.length > 0) {
143
174
  const sliceResults = await Promise.all(
144
- normSlices!.map(async (slice) => {
175
+ normSlices.map(async (slice) => {
145
176
  return indexSlice(basePath, milestoneId, slice.id, slice.title, slice.done, { risk: slice.risk as RiskLevel, depends: slice.depends, demo: slice.demo });
146
177
  }),
147
178
  );
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9492],{9541:(e,t,l)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return o}});let r=l(95155),n=l(35949),o=function(){return(0,r.jsx)("html",{children:(0,r.jsx)("body",{children:(0,r.jsx)(n.HTTPAccessErrorFallback,{status:404,message:"This page could not be found."})})})};("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},23002:(e,t,l)=>{(window.__NEXT_P=window.__NEXT_P||[]).push(["/_not-found/page",function(){return l(9541)}])},35949:(e,t,l)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"HTTPAccessErrorFallback",{enumerable:!0,get:function(){return o}});let r=l(95155),n=l(37356);function o({status:e,message:t}){return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("title",{children:`${e}: ${t}`}),(0,r.jsx)("div",{style:n.styles.error,children:(0,r.jsxs)("div",{children:[(0,r.jsx)("style",{dangerouslySetInnerHTML:{__html:"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}),(0,r.jsx)("h1",{className:"next-error-h1",style:n.styles.h1,children:e}),(0,r.jsx)("div",{style:n.styles.desc,children:(0,r.jsx)("h2",{style:n.styles.h2,children:t})})]})})]})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},37356:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"styles",{enumerable:!0,get:function(){return l}});let l={error:{fontFamily:'system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"',height:"100vh",textAlign:"center",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center"},desc:{display:"inline-block"},h1:{display:"inline-block",margin:"0 20px 0 0",padding:"0 23px 0 0",fontSize:24,fontWeight:500,verticalAlign:"top",lineHeight:"49px"},h2:{fontSize:14,fontWeight:400,lineHeight:"49px",margin:0}};("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=23002)),_N_E=e.O()}]);
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7177],{9065:(e,r,s)=>{Promise.resolve().then(s.bind(s,21942)),Promise.resolve().then(s.bind(s,61549)),Promise.resolve().then(s.t.bind(s,85048,23)),Promise.resolve().then(s.t.bind(s,35696,23)),Promise.resolve().then(s.t.bind(s,66872,23))},21942:(e,r,s)=>{"use strict";s.d(r,{ThemeProvider:()=>o});var a=s(95155);s(12115);var t=s(70460);function o({children:e,...r}){return(0,a.jsx)(t.N,{...r,children:e})}},35696:e=>{e.exports={style:{fontFamily:"'Geist Mono', 'Geist Mono Fallback'",fontStyle:"normal"},className:"__className_9a8899",variable:"__variable_9a8899"}},61549:(e,r,s)=>{"use strict";s.d(r,{Toaster:()=>l});var a=s(95155),t=s(70460),o=s(66609);let l=({...e})=>{let{theme:r="system"}=(0,t.D)();return(0,a.jsx)(o.l$,{theme:r,className:"toaster group",style:{"--normal-bg":"var(--popover)","--normal-text":"var(--popover-foreground)","--normal-border":"var(--border)"},...e})}},66872:()=>{},85048:e=>{e.exports={style:{fontFamily:"'Geist', 'Geist Fallback'",fontStyle:"normal"},className:"__className_188709",variable:"__variable_188709"}}},e=>{e.O(0,[2557,7513,4986,8441,3794,7358],()=>e(e.s=9065)),_N_E=e.O()}]);
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8974],{5214:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorage",{enumerable:!0,get:function(){return r.workAsyncStorageInstance}});let r=n(17828)},17828:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorageInstance",{enumerable:!0,get:function(){return r}});let r=(0,n(64054).createAsyncLocalStorage)()},19975:(e,t,n)=>{Promise.resolve().then(n.bind(n,66919))},21957:(e,t,n)=>{"use strict";function r({moduleIds:e}){return null}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"PreloadChunks",{enumerable:!0,get:function(){return r}}),n(95155),n(47650),n(5214),n(2451),n(53887)},37206:(e,t,n)=>{"use strict";n.d(t,{default:()=>u.a});var r=n(75707),u=n.n(r)},41112:(e,t,n)=>{"use strict";function r({reason:e,children:t}){return t}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"BailoutToCSR",{enumerable:!0,get:function(){return r}}),n(1980)},64054:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n={bindSnapshot:function(){return s},createAsyncLocalStorage:function(){return a},createSnapshot:function(){return i}};for(var r in n)Object.defineProperty(t,r,{enumerable:!0,get:n[r]});let u=Object.defineProperty(Error("Invariant: AsyncLocalStorage accessed in runtime where it is not available"),"__NEXT_ERROR_CODE",{value:"E504",enumerable:!1,configurable:!0});class l{disable(){throw u}getStore(){}run(){throw u}exit(){throw u}enterWith(){throw u}static bind(e){return e}}let o="u">typeof globalThis&&globalThis.AsyncLocalStorage;function a(){return o?new o:new l}function s(e){return o?o.bind(e):l.bind(e)}function i(){return o?o.snapshot():function(e,...t){return e(...t)}}},66919:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>l});var r=n(95155);let u=(0,n(37206).default)(()=>Promise.all([n.e(1838),n.e(6079),n.e(4986),n.e(3721),n.e(4024)]).then(n.bind(n,4024)).then(e=>e.GSDAppShell),{loadableGenerated:{webpack:()=>[4024]},ssr:!1,loading:()=>(0,r.jsx)("div",{className:"flex h-screen items-center justify-center bg-background text-sm text-muted-foreground",children:"Loading workspace…"})});function l(){return(0,r.jsx)(u,{})}},68635:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return s}});let r=n(95155),u=n(12115),l=n(41112);function o(e){return{default:e&&"default"in e?e.default:e}}n(21957);let a={loader:()=>Promise.resolve(o(()=>null)),loading:null,ssr:!0},s=function(e){let t={...a,...e},n=(0,u.lazy)(()=>t.loader().then(o)),s=t.loading;function i(e){let o=s?(0,r.jsx)(s,{isLoading:!0,pastDelay:!0,error:null}):null,a=!t.ssr||!!t.loading,i=a?u.Suspense:u.Fragment,c=t.ssr?(0,r.jsxs)(r.Fragment,{children:[null,(0,r.jsx)(n,{...e})]}):(0,r.jsx)(l.BailoutToCSR,{reason:"next/dynamic",children:(0,r.jsx)(n,{...e})});return(0,r.jsx)(i,{...a?{fallback:o}:{},children:c})}return i.displayName="LoadableComponent",i}},75707:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return u}});let r=n(73623)._(n(68635));function u(e,t){let n={};"function"==typeof e&&(n.loader=e);let u={...n,...t};return(0,r.default)({...u,modules:u.loadableGenerated?.modules})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=19975)),_N_E=e.O()}]);
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9337],{50341:(e,s,_)=>{Promise.resolve().then(_.t.bind(_,27123,23))}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=50341)),_N_E=e.O()}]);