gsd-pi 2.43.0-next.8 → 2.44.0-dev.62b5d6c

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 (244) hide show
  1. package/dist/cli.js +13 -1
  2. package/dist/help-text.js +24 -0
  3. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +21 -8
  4. package/dist/resources/extensions/gsd/auto-prompts.js +130 -51
  5. package/dist/resources/extensions/gsd/auto-worktree.js +16 -2
  6. package/dist/resources/extensions/gsd/dispatch-guard.js +34 -10
  7. package/dist/resources/extensions/gsd/markdown-renderer.js +7 -5
  8. package/dist/resources/extensions/gsd/reactive-graph.js +13 -2
  9. package/dist/resources/extensions/gsd/skill-health.js +3 -1
  10. package/dist/resources/extensions/gsd/tools/plan-milestone.js +2 -11
  11. package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -10
  12. package/dist/resources/extensions/gsd/visualizer-data.js +45 -13
  13. package/dist/resources/extensions/gsd/workspace-index.js +46 -15
  14. package/dist/web/standalone/.next/BUILD_ID +1 -1
  15. package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
  16. package/dist/web/standalone/.next/build-manifest.json +3 -3
  17. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  18. package/dist/web/standalone/.next/required-server-files.json +4 -4
  19. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  20. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  21. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  22. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  23. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  30. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  31. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  32. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  33. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  34. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  36. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  40. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  41. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  42. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  43. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  44. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  45. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  46. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  47. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  48. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  49. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  50. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  51. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  52. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  53. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  54. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  55. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  62. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  84. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  90. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  106. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  108. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  110. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/index.html +1 -1
  120. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  121. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  122. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  123. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  125. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/page.js +2 -2
  127. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
  129. package/dist/web/standalone/.next/server/chunks/229.js +1 -1
  130. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  131. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/middleware.js +2 -2
  133. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  135. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  136. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  137. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  138. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
  139. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
  140. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
  141. package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
  142. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  143. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  144. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  145. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  146. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  147. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  148. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  149. package/dist/web/standalone/server.js +1 -1
  150. package/package.json +4 -4
  151. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +3 -3
  152. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  153. package/packages/pi-coding-agent/dist/core/agent-session.js +11 -34
  154. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  155. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts +2 -2
  156. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  157. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
  158. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +2 -2
  159. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  161. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +4 -4
  162. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  163. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  164. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  165. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  166. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  167. package/packages/pi-coding-agent/dist/core/extensions/loader.js +18 -0
  168. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  169. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +37 -0
  170. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  171. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  172. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -1
  173. package/packages/pi-coding-agent/dist/core/fallback-resolver.js +2 -3
  174. package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -1
  175. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +12 -2
  176. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -1
  177. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +38 -0
  178. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -0
  179. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +192 -0
  180. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -0
  181. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts +2 -0
  182. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts.map +1 -0
  183. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +255 -0
  184. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -0
  185. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +15 -0
  186. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
  188. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/package-commands.d.ts +25 -0
  190. package/packages/pi-coding-agent/dist/core/package-commands.d.ts.map +1 -0
  191. package/packages/pi-coding-agent/dist/core/package-commands.js +253 -0
  192. package/packages/pi-coding-agent/dist/core/package-commands.js.map +1 -0
  193. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts +2 -0
  194. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts.map +1 -0
  195. package/packages/pi-coding-agent/dist/core/package-commands.test.js +225 -0
  196. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -0
  197. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  198. package/packages/pi-coding-agent/dist/core/sdk.js +4 -0
  199. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  200. package/packages/pi-coding-agent/dist/index.d.ts +3 -1
  201. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  202. package/packages/pi-coding-agent/dist/index.js +1 -0
  203. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  204. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  205. package/packages/pi-coding-agent/dist/main.js +11 -199
  206. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  207. package/packages/pi-coding-agent/package.json +1 -1
  208. package/packages/pi-coding-agent/src/core/agent-session.ts +13 -37
  209. package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +2 -2
  210. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +3 -3
  211. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +4 -4
  212. package/packages/pi-coding-agent/src/core/extensions/index.ts +5 -0
  213. package/packages/pi-coding-agent/src/core/extensions/loader.ts +23 -0
  214. package/packages/pi-coding-agent/src/core/extensions/types.ts +44 -0
  215. package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +15 -2
  216. package/packages/pi-coding-agent/src/core/fallback-resolver.ts +2 -3
  217. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +274 -0
  218. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +288 -0
  219. package/packages/pi-coding-agent/src/core/model-registry.ts +39 -3
  220. package/packages/pi-coding-agent/src/core/package-commands.test.ts +240 -0
  221. package/packages/pi-coding-agent/src/core/package-commands.ts +310 -0
  222. package/packages/pi-coding-agent/src/core/sdk.ts +4 -0
  223. package/packages/pi-coding-agent/src/index.ts +7 -0
  224. package/packages/pi-coding-agent/src/main.ts +11 -232
  225. package/pkg/package.json +1 -1
  226. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +22 -7
  227. package/src/resources/extensions/gsd/auto-prompts.ts +109 -42
  228. package/src/resources/extensions/gsd/auto-worktree.ts +16 -3
  229. package/src/resources/extensions/gsd/dispatch-guard.ts +28 -10
  230. package/src/resources/extensions/gsd/markdown-renderer.ts +7 -5
  231. package/src/resources/extensions/gsd/reactive-graph.ts +12 -2
  232. package/src/resources/extensions/gsd/skill-health.ts +2 -1
  233. package/src/resources/extensions/gsd/tests/auto-stash-merge.test.ts +3 -3
  234. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +1 -1
  235. package/src/resources/extensions/gsd/tools/plan-milestone.ts +1 -18
  236. package/src/resources/extensions/gsd/tools/plan-slice.ts +1 -15
  237. package/src/resources/extensions/gsd/visualizer-data.ts +46 -14
  238. package/src/resources/extensions/gsd/workspace-index.ts +49 -18
  239. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
  240. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
  241. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
  242. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
  243. /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → fOnWQBjWXMKUs4bqTg530}/_buildManifest.js +0 -0
  244. /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → fOnWQBjWXMKUs4bqTg530}/_ssgManifest.js +0 -0
package/dist/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- import { AuthStorage, DefaultResourceLoader, ModelRegistry, SettingsManager, SessionManager, createAgentSession, InteractiveMode, runPrintMode, runRpcMode, } from '@gsd/pi-coding-agent';
1
+ import { AuthStorage, DefaultResourceLoader, ModelRegistry, runPackageCommand, SettingsManager, SessionManager, createAgentSession, InteractiveMode, runPrintMode, runRpcMode, } from '@gsd/pi-coding-agent';
2
2
  import { readFileSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
4
  import { agentDir, sessionsDir, authFilePath } from './app-paths.js';
@@ -121,6 +121,18 @@ if (subcommand && process.argv.includes('--help')) {
121
121
  process.exit(0);
122
122
  }
123
123
  }
124
+ const packageCommand = await runPackageCommand({
125
+ appName: 'gsd',
126
+ args: process.argv.slice(2),
127
+ cwd: process.cwd(),
128
+ agentDir,
129
+ stdout: process.stdout,
130
+ stderr: process.stderr,
131
+ allowedCommands: new Set(['install', 'remove', 'list']),
132
+ });
133
+ if (packageCommand.handled) {
134
+ process.exit(packageCommand.exitCode);
135
+ }
124
136
  // `gsd config` — replay the setup wizard and exit
125
137
  if (cliFlags.messages[0] === 'config') {
126
138
  const authStorage = AuthStorage.create(authFilePath);
package/dist/help-text.js CHANGED
@@ -29,6 +29,27 @@ const SUBCOMMAND_HELP = {
29
29
  '',
30
30
  'Compare with --continue (-c) which always resumes the most recent session.',
31
31
  ].join('\n'),
32
+ install: [
33
+ 'Usage: gsd install <source> [-l, --local]',
34
+ '',
35
+ 'Install a package/extension source and run declared lifecycle hooks.',
36
+ '',
37
+ 'Examples:',
38
+ ' gsd install npm:@foo/bar',
39
+ ' gsd install git:github.com/user/repo',
40
+ ' gsd install https://github.com/user/repo',
41
+ ' gsd install ./local/path',
42
+ ].join('\n'),
43
+ remove: [
44
+ 'Usage: gsd remove <source> [-l, --local]',
45
+ '',
46
+ 'Remove an installed package source and its settings entry.',
47
+ ].join('\n'),
48
+ list: [
49
+ 'Usage: gsd list',
50
+ '',
51
+ 'List installed package sources from user and project settings.',
52
+ ].join('\n'),
32
53
  worktree: [
33
54
  'Usage: gsd worktree <command> [args]',
34
55
  '',
@@ -122,6 +143,9 @@ export function printHelp(version) {
122
143
  process.stdout.write(' --help, -h Print this help and exit\n');
123
144
  process.stdout.write('\nSubcommands:\n');
124
145
  process.stdout.write(' config Re-run the setup wizard\n');
146
+ process.stdout.write(' install <source> Install a package/extension source\n');
147
+ process.stdout.write(' remove <source> Remove an installed package source\n');
148
+ process.stdout.write(' list List installed package sources\n');
125
149
  process.stdout.write(' update Update GSD to the latest version\n');
126
150
  process.stdout.write(' sessions List and resume a past session\n');
127
151
  process.stdout.write(' worktree <cmd> Manage worktrees (list, merge, clean, remove)\n');
@@ -5,7 +5,8 @@
5
5
  import { deriveState } from "./state.js";
6
6
  import { loadFile } from "./files.js";
7
7
  import { isDbAvailable, getMilestoneSlices } from "./gsd-db.js";
8
- import { resolveSliceFile, relSliceFile, } from "./paths.js";
8
+ import { parseRoadmap } from "./parsers-legacy.js";
9
+ import { resolveMilestoneFile, resolveSliceFile, relSliceFile, } from "./paths.js";
9
10
  import { buildResearchSlicePrompt, buildResearchMilestonePrompt, buildPlanSlicePrompt, buildPlanMilestonePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildReassessRoadmapPrompt, buildRunUatPrompt, buildReplanSlicePrompt, } from "./auto-prompts.js";
10
11
  import { loadEffectiveGSDPreferences } from "./preferences.js";
11
12
  import { pauseAuto } from "./auto.js";
@@ -118,14 +119,20 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
118
119
  }
119
120
  case "reassess":
120
121
  case "reassess-roadmap": {
121
- // DB primary path — get completed slices
122
+ // DB primary path — get completed slices, fall back to file parsing when DB has no data
122
123
  let completedSliceIds = [];
123
124
  if (isDbAvailable()) {
124
125
  completedSliceIds = getMilestoneSlices(mid).filter(s => s.status === "complete").map(s => s.id);
125
126
  }
126
- else {
127
- ctx.ui.notify("Cannot dispatch reassess-roadmap: DB unavailable.", "warning");
128
- return;
127
+ if (completedSliceIds.length === 0) {
128
+ // File-based fallback: parse roadmap checkboxes
129
+ const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
130
+ if (roadmapPath) {
131
+ const roadmapContent = await loadFile(roadmapPath);
132
+ if (roadmapContent) {
133
+ completedSliceIds = parseRoadmap(roadmapContent).slices.filter(s => s.done).map(s => s.id);
134
+ }
135
+ }
129
136
  }
130
137
  if (completedSliceIds.length === 0) {
131
138
  ctx.ui.notify("Cannot dispatch reassess-roadmap: no completed slices.", "warning");
@@ -147,9 +154,15 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
147
154
  if (isDbAvailable()) {
148
155
  uatCompletedSliceIds = getMilestoneSlices(mid).filter(s => s.status === "complete").map(s => s.id);
149
156
  }
150
- else {
151
- ctx.ui.notify("Cannot dispatch run-uat: DB unavailable.", "warning");
152
- return;
157
+ if (uatCompletedSliceIds.length === 0) {
158
+ // File-based fallback: parse roadmap checkboxes
159
+ const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
160
+ if (roadmapPath) {
161
+ const roadmapContent = await loadFile(roadmapPath);
162
+ if (roadmapContent) {
163
+ uatCompletedSliceIds = parseRoadmap(roadmapContent).slices.filter(s => s.done).map(s => s.id);
164
+ }
165
+ }
153
166
  }
154
167
  if (uatCompletedSliceIds.length === 0) {
155
168
  ctx.ui.notify("Cannot dispatch run-uat: no completed slices.", "warning");
@@ -9,6 +9,7 @@ import { loadFile, parseContinue, parseSummary, extractUatType, loadActiveOverri
9
9
  import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
10
10
  import { resolveMilestoneFile, resolveSliceFile, resolveSlicePath, resolveTasksDir, resolveTaskFiles, resolveTaskFile, relMilestoneFile, relSliceFile, relSlicePath, relMilestonePath, resolveGsdRootFile, relGsdRootFile, resolveRuntimeFile, } from "./paths.js";
11
11
  import { resolveSkillDiscoveryMode, resolveInlineLevel, loadEffectiveGSDPreferences, resolveAllSkillReferences } from "./preferences.js";
12
+ import { parseRoadmap } from "./parsers-legacy.js";
12
13
  import { getLoadedSkills } from "@gsd/pi-coding-agent";
13
14
  import { join, basename } from "node:path";
14
15
  import { existsSync } from "node:fs";
@@ -145,15 +146,31 @@ export async function inlineDependencySummaries(mid, sid, base, budgetChars) {
145
146
  const { isDbAvailable, getSlice } = await import("./gsd-db.js");
146
147
  if (isDbAvailable()) {
147
148
  const slice = getSlice(mid, sid);
148
- if (!slice || slice.depends.length === 0)
149
- return "- (no dependencies)";
150
- depends = slice.depends;
149
+ if (slice) {
150
+ if (slice.depends.length === 0)
151
+ return "- (no dependencies)";
152
+ depends = slice.depends;
153
+ }
154
+ // If slice not found in DB, fall through to file-based parsing
151
155
  }
152
156
  }
153
157
  catch { /* fall through */ }
154
- // If DB didn't provide depends, we can't determine them without parsers
158
+ // If DB didn't provide depends, fall back to roadmap parsing
155
159
  if (!depends) {
156
- return "- (no dependencies)";
160
+ const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
161
+ if (roadmapPath) {
162
+ const roadmapContent = await loadFile(roadmapPath);
163
+ if (roadmapContent) {
164
+ const parsed = parseRoadmap(roadmapContent);
165
+ const slice = parsed.slices.find(s => s.id === sid);
166
+ if (slice && slice.depends.length > 0) {
167
+ depends = slice.depends;
168
+ }
169
+ }
170
+ }
171
+ if (!depends) {
172
+ return "- (no dependencies)";
173
+ }
157
174
  }
158
175
  const sections = [];
159
176
  const seen = new Set();
@@ -565,32 +582,52 @@ export async function getDependencyTaskSummaryPaths(mid, sid, currentTid, depend
565
582
  * - All slices are complete (milestone done — no point reassessing)
566
583
  */
567
584
  export async function checkNeedsReassessment(base, mid, state) {
568
- // DB primary path
569
- let completedSliceIds = [];
570
- let hasIncomplete = false;
585
+ // DB primary path — fall through to file-based when DB has no data for this milestone
571
586
  try {
572
587
  const { isDbAvailable, getMilestoneSlices } = await import("./gsd-db.js");
573
588
  if (isDbAvailable()) {
574
589
  const slices = getMilestoneSlices(mid);
575
- completedSliceIds = slices.filter(s => s.status === "complete").map(s => s.id);
576
- hasIncomplete = slices.some(s => s.status !== "complete");
577
- if (completedSliceIds.length === 0 || !hasIncomplete)
578
- return null;
579
- const lastCompleted = completedSliceIds[completedSliceIds.length - 1];
580
- const assessmentFile = resolveSliceFile(base, mid, lastCompleted, "ASSESSMENT");
581
- const hasAssessment = !!(assessmentFile && await loadFile(assessmentFile));
582
- if (hasAssessment)
583
- return null;
584
- const summaryFile = resolveSliceFile(base, mid, lastCompleted, "SUMMARY");
585
- const hasSummary = !!(summaryFile && await loadFile(summaryFile));
586
- if (!hasSummary)
587
- return null;
588
- return { sliceId: lastCompleted };
590
+ if (slices.length > 0) {
591
+ const completedSliceIds = slices.filter(s => s.status === "complete").map(s => s.id);
592
+ const hasIncomplete = slices.some(s => s.status !== "complete");
593
+ if (completedSliceIds.length === 0 || !hasIncomplete)
594
+ return null;
595
+ const lastCompleted = completedSliceIds[completedSliceIds.length - 1];
596
+ const assessmentFile = resolveSliceFile(base, mid, lastCompleted, "ASSESSMENT");
597
+ const hasAssessment = !!(assessmentFile && await loadFile(assessmentFile));
598
+ if (hasAssessment)
599
+ return null;
600
+ const summaryFile = resolveSliceFile(base, mid, lastCompleted, "SUMMARY");
601
+ const hasSummary = !!(summaryFile && await loadFile(summaryFile));
602
+ if (!hasSummary)
603
+ return null;
604
+ return { sliceId: lastCompleted };
605
+ }
589
606
  }
590
607
  }
591
608
  catch { /* fall through */ }
592
- // DB unavailable cannot determine assessment needs
593
- return null;
609
+ // File-based fallback using roadmap checkboxes
610
+ const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
611
+ if (!roadmapPath)
612
+ return null;
613
+ const roadmapContent = await loadFile(roadmapPath);
614
+ if (!roadmapContent)
615
+ return null;
616
+ const parsed = parseRoadmap(roadmapContent);
617
+ const fileCompletedIds = parsed.slices.filter(s => s.done).map(s => s.id);
618
+ const fileHasIncomplete = parsed.slices.some(s => !s.done);
619
+ if (fileCompletedIds.length === 0 || !fileHasIncomplete)
620
+ return null;
621
+ const lastDone = fileCompletedIds[fileCompletedIds.length - 1];
622
+ const assessFile = resolveSliceFile(base, mid, lastDone, "ASSESSMENT");
623
+ const hasAssess = !!(assessFile && await loadFile(assessFile));
624
+ if (hasAssess)
625
+ return null;
626
+ const summFile = resolveSliceFile(base, mid, lastDone, "SUMMARY");
627
+ const hasSumm = !!(summFile && await loadFile(summFile));
628
+ if (!hasSumm)
629
+ return null;
630
+ return { sliceId: lastDone };
594
631
  }
595
632
  /**
596
633
  * Check if the most recently completed slice needs a UAT run.
@@ -604,40 +641,70 @@ export async function checkNeedsReassessment(base, mid, state) {
604
641
  * - UAT result file already exists (idempotent — already ran)
605
642
  */
606
643
  export async function checkNeedsRunUat(base, mid, state, prefs) {
607
- // DB primary path
644
+ // DB primary path — fall through to file-based when DB has no data for this milestone
608
645
  try {
609
646
  const { isDbAvailable, getMilestoneSlices } = await import("./gsd-db.js");
610
647
  if (isDbAvailable()) {
611
648
  const slices = getMilestoneSlices(mid);
612
- const completedSlices = slices.filter(s => s.status === "complete");
613
- const incompleteSlices = slices.filter(s => s.status !== "complete");
614
- if (completedSlices.length === 0)
615
- return null;
616
- if (incompleteSlices.length === 0)
617
- return null;
618
- if (!prefs?.uat_dispatch)
619
- return null;
620
- const lastCompleted = completedSlices[completedSlices.length - 1];
621
- const sid = lastCompleted.id;
622
- const uatFile = resolveSliceFile(base, mid, sid, "UAT");
623
- if (!uatFile)
624
- return null;
625
- const uatContent = await loadFile(uatFile);
626
- if (!uatContent)
627
- return null;
628
- const uatResultFile = resolveSliceFile(base, mid, sid, "UAT-RESULT");
629
- if (uatResultFile) {
630
- const hasResult = !!(await loadFile(uatResultFile));
631
- if (hasResult)
649
+ if (slices.length > 0) {
650
+ const completedSlices = slices.filter(s => s.status === "complete");
651
+ const incompleteSlices = slices.filter(s => s.status !== "complete");
652
+ if (completedSlices.length === 0)
653
+ return null;
654
+ if (incompleteSlices.length === 0)
632
655
  return null;
656
+ if (!prefs?.uat_dispatch)
657
+ return null;
658
+ const lastCompleted = completedSlices[completedSlices.length - 1];
659
+ const sid = lastCompleted.id;
660
+ const uatFile = resolveSliceFile(base, mid, sid, "UAT");
661
+ if (!uatFile)
662
+ return null;
663
+ const uatContent = await loadFile(uatFile);
664
+ if (!uatContent)
665
+ return null;
666
+ const uatResultFile = resolveSliceFile(base, mid, sid, "UAT-RESULT");
667
+ if (uatResultFile) {
668
+ const hasResult = !!(await loadFile(uatResultFile));
669
+ if (hasResult)
670
+ return null;
671
+ }
672
+ const uatType = extractUatType(uatContent) ?? "artifact-driven";
673
+ return { sliceId: sid, uatType };
633
674
  }
634
- const uatType = extractUatType(uatContent) ?? "artifact-driven";
635
- return { sliceId: sid, uatType };
636
675
  }
637
676
  }
638
677
  catch { /* fall through */ }
639
- // DB unavailable cannot determine UAT needs
640
- return null;
678
+ // File-based fallback using roadmap checkboxes
679
+ if (!prefs?.uat_dispatch)
680
+ return null;
681
+ const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
682
+ if (!roadmapPath)
683
+ return null;
684
+ const roadmapContent = await loadFile(roadmapPath);
685
+ if (!roadmapContent)
686
+ return null;
687
+ const parsed = parseRoadmap(roadmapContent);
688
+ const completedFileSlices = parsed.slices.filter(s => s.done);
689
+ const incompleteFileSlices = parsed.slices.filter(s => !s.done);
690
+ if (completedFileSlices.length === 0 || incompleteFileSlices.length === 0)
691
+ return null;
692
+ const lastCompletedFile = completedFileSlices[completedFileSlices.length - 1];
693
+ const uatSid = lastCompletedFile.id;
694
+ const uatFileFb = resolveSliceFile(base, mid, uatSid, "UAT");
695
+ if (!uatFileFb)
696
+ return null;
697
+ const uatContentFb = await loadFile(uatFileFb);
698
+ if (!uatContentFb)
699
+ return null;
700
+ const uatResultFb = resolveSliceFile(base, mid, uatSid, "UAT-RESULT");
701
+ if (uatResultFb) {
702
+ const hasResultFb = !!(await loadFile(uatResultFb));
703
+ if (hasResultFb)
704
+ return null;
705
+ }
706
+ const uatTypeFb = extractUatType(uatContentFb) ?? "artifact-driven";
707
+ return { sliceId: uatSid, uatType: uatTypeFb };
641
708
  }
642
709
  // ─── Prompt Builders ──────────────────────────────────────────────────────
643
710
  /**
@@ -1042,7 +1109,13 @@ export async function buildCompleteMilestonePrompt(mid, midTitle, base, level) {
1042
1109
  }
1043
1110
  }
1044
1111
  catch { /* fall through */ }
1045
- // If DB didn't provide slice IDs, sliceIds stays empty no summaries to inline
1112
+ // File-based fallback: parse roadmap for slice IDs when DB has no data
1113
+ if (sliceIds.length === 0 && roadmapPath) {
1114
+ const roadmapContent = await loadFile(roadmapPath);
1115
+ if (roadmapContent) {
1116
+ sliceIds = parseRoadmap(roadmapContent).slices.map(s => s.id);
1117
+ }
1118
+ }
1046
1119
  const seenSlices = new Set();
1047
1120
  for (const sid of sliceIds) {
1048
1121
  if (seenSlices.has(sid))
@@ -1100,7 +1173,13 @@ export async function buildValidateMilestonePrompt(mid, midTitle, base, level) {
1100
1173
  }
1101
1174
  }
1102
1175
  catch { /* fall through */ }
1103
- // If DB didn't provide slice IDs, valSliceIds stays empty
1176
+ // File-based fallback: parse roadmap for slice IDs when DB has no data
1177
+ if (valSliceIds.length === 0 && roadmapPath) {
1178
+ const roadmapContent = await loadFile(roadmapPath);
1179
+ if (roadmapContent) {
1180
+ valSliceIds = parseRoadmap(roadmapContent).slices.map(s => s.id);
1181
+ }
1182
+ }
1104
1183
  const seenValSlices = new Set();
1105
1184
  for (const sid of valSliceIds) {
1106
1185
  if (seenValSlices.has(sid))
@@ -869,7 +869,14 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
869
869
  .filter(s => s.status === "complete")
870
870
  .map(s => ({ id: s.id, title: s.title }));
871
871
  }
872
- // When DB unavailable, completedSlices stays empty commit message will omit slice details
872
+ // Fallback: parse roadmap content when DB is unavailable
873
+ if (completedSlices.length === 0 && roadmapContent) {
874
+ const sliceRe = /- \[x\] \*\*(\w+):\s*(.+?)\*\*/gi;
875
+ let m;
876
+ while ((m = sliceRe.exec(roadmapContent)) !== null) {
877
+ completedSlices.push({ id: m[1], title: m[2] });
878
+ }
879
+ }
873
880
  // 3. chdir to original base
874
881
  const previousCwd = process.cwd();
875
882
  process.chdir(originalBasePath_);
@@ -891,7 +898,14 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
891
898
  }
892
899
  // 6. Build rich commit message
893
900
  const dbMilestone = getMilestone(milestoneId);
894
- const milestoneTitle = (dbMilestone?.title ?? "").replace(/^M\d+:\s*/, "").trim() || milestoneId;
901
+ let milestoneTitle = (dbMilestone?.title ?? "").replace(/^M\d+:\s*/, "").trim();
902
+ // Fallback: parse title from roadmap content header (e.g. "# M020: Backend foundation")
903
+ if (!milestoneTitle && roadmapContent) {
904
+ const titleMatch = roadmapContent.match(new RegExp(`^#\\s+${milestoneId}:\\s*(.+)`, "m"));
905
+ if (titleMatch)
906
+ milestoneTitle = titleMatch[1].trim();
907
+ }
908
+ milestoneTitle = milestoneTitle || milestoneId;
895
909
  const subject = `feat(${milestoneId}): ${milestoneTitle}`;
896
910
  let body = "";
897
911
  if (completedSlices.length > 0) {
@@ -2,6 +2,8 @@
2
2
  import { resolveMilestoneFile } from "./paths.js";
3
3
  import { findMilestoneIds } from "./guided-flow.js";
4
4
  import { isDbAvailable, getMilestoneSlices } from "./gsd-db.js";
5
+ import { parseRoadmap } from "./parsers-legacy.js";
6
+ import { readFileSync } from "node:fs";
5
7
  const SLICE_DISPATCH_TYPES = new Set([
6
8
  "research-slice",
7
9
  "plan-slice",
@@ -27,16 +29,38 @@ export function getPriorSliceCompletionBlocker(base, _mainBranch, unitType, unit
27
29
  continue;
28
30
  if (resolveMilestoneFile(base, mid, "SUMMARY"))
29
31
  continue;
30
- if (!isDbAvailable())
31
- continue;
32
- const rows = getMilestoneSlices(mid);
33
- if (rows.length === 0)
34
- continue;
35
- const slices = rows.map((r) => ({
36
- id: r.id,
37
- done: r.status === "complete",
38
- depends: r.depends ?? [],
39
- }));
32
+ let slices = null;
33
+ if (isDbAvailable()) {
34
+ const rows = getMilestoneSlices(mid);
35
+ if (rows.length > 0) {
36
+ slices = rows.map((r) => ({
37
+ id: r.id,
38
+ done: r.status === "complete",
39
+ depends: r.depends ?? [],
40
+ }));
41
+ }
42
+ }
43
+ if (!slices) {
44
+ // File-based fallback: parse roadmap checkboxes
45
+ const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
46
+ if (!roadmapPath)
47
+ continue;
48
+ let roadmapContent;
49
+ try {
50
+ roadmapContent = readFileSync(roadmapPath, "utf-8");
51
+ }
52
+ catch {
53
+ continue;
54
+ }
55
+ const parsed = parseRoadmap(roadmapContent);
56
+ if (parsed.slices.length === 0)
57
+ continue;
58
+ slices = parsed.slices.map((s) => ({
59
+ id: s.id,
60
+ done: s.done,
61
+ depends: s.depends ?? [],
62
+ }));
63
+ }
40
64
  if (mid !== targetMid) {
41
65
  const incomplete = slices.find((slice) => !slice.done);
42
66
  if (incomplete) {
@@ -733,11 +733,13 @@ export async function repairStaleRenders(basePath) {
733
733
  for (const entry of staleEntries) {
734
734
  if (repairedPaths.has(entry.path))
735
735
  continue;
736
+ // Normalize path separators for cross-platform regex matching
737
+ const normPath = entry.path.replace(/\\/g, "/");
736
738
  try {
737
739
  // Determine repair action from the reason
738
740
  if (entry.reason.includes("in roadmap")) {
739
741
  // Roadmap checkbox mismatch — extract milestone ID from path
740
- const milestoneMatch = entry.path.match(/milestones\/([^/]+)\//);
742
+ const milestoneMatch = normPath.match(/milestones\/([^/]+)\//);
741
743
  if (milestoneMatch) {
742
744
  const ok = await renderRoadmapCheckboxes(basePath, milestoneMatch[1]);
743
745
  if (ok) {
@@ -748,7 +750,7 @@ export async function repairStaleRenders(basePath) {
748
750
  }
749
751
  else if (entry.reason.includes("in plan")) {
750
752
  // Plan checkbox mismatch — extract milestone + slice IDs from path
751
- const pathMatch = entry.path.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
753
+ const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
752
754
  if (pathMatch) {
753
755
  const ok = await renderPlanCheckboxes(basePath, pathMatch[1], pathMatch[2]);
754
756
  if (ok) {
@@ -759,7 +761,7 @@ export async function repairStaleRenders(basePath) {
759
761
  }
760
762
  else if (entry.reason.includes("SUMMARY.md missing") && entry.reason.match(/^T\d+/)) {
761
763
  // Missing task summary — extract IDs from path
762
- const pathMatch = entry.path.match(/milestones\/([^/]+)\/slices\/([^/]+)\/tasks\//);
764
+ const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\/tasks\//);
763
765
  const taskMatch = entry.reason.match(/^(T\d+)/);
764
766
  if (pathMatch && taskMatch) {
765
767
  const ok = await renderTaskSummary(basePath, pathMatch[1], pathMatch[2], taskMatch[1]);
@@ -771,7 +773,7 @@ export async function repairStaleRenders(basePath) {
771
773
  }
772
774
  else if (entry.reason.includes("SUMMARY.md missing") && entry.reason.match(/^S\d+/)) {
773
775
  // Missing slice summary — extract IDs from path
774
- const pathMatch = entry.path.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
776
+ const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
775
777
  if (pathMatch) {
776
778
  const ok = await renderSliceSummary(basePath, pathMatch[1], pathMatch[2]);
777
779
  if (ok) {
@@ -782,7 +784,7 @@ export async function repairStaleRenders(basePath) {
782
784
  }
783
785
  else if (entry.reason.includes("UAT.md missing")) {
784
786
  // Missing slice UAT — renderSliceSummary handles both SUMMARY + UAT
785
- const pathMatch = entry.path.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
787
+ const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
786
788
  if (pathMatch) {
787
789
  const ok = await renderSliceSummary(basePath, pathMatch[1], pathMatch[2]);
788
790
  if (ok) {
@@ -10,6 +10,7 @@
10
10
  */
11
11
  import { loadFile, parseTaskPlanIO } from "./files.js";
12
12
  import { isDbAvailable, getSliceTasks } from "./gsd-db.js";
13
+ import { parsePlan } from "./parsers-legacy.js";
13
14
  import { resolveTasksDir, resolveTaskFiles } from "./paths.js";
14
15
  import { join } from "node:path";
15
16
  import { loadJsonFileOrNull, saveJsonFile } from "./json-persistence.js";
@@ -165,8 +166,18 @@ export async function loadSliceTaskIO(basePath, mid, sid) {
165
166
  }
166
167
  catch { /* fall through */ }
167
168
  if (!taskEntries) {
168
- // DB unavailable cannot determine task graph
169
- return [];
169
+ // File-based fallback: parse slice plan for task entries
170
+ const parsed = parsePlan(planContent);
171
+ if (parsed.tasks.length > 0) {
172
+ taskEntries = parsed.tasks.map(t => ({
173
+ id: t.id,
174
+ title: t.title,
175
+ done: t.done,
176
+ }));
177
+ }
178
+ else {
179
+ return [];
180
+ }
170
181
  }
171
182
  const tDir = resolveTasksDir(basePath, mid, sid);
172
183
  if (!tDir)
@@ -209,7 +209,9 @@ The human review step is what makes this valuable.`;
209
209
  */
210
210
  export function computeStaleAvoidList(basePath, currentAvoidList, staleDays) {
211
211
  const ledger = loadLedgerFromDisk(basePath);
212
- const units = (ledger?.units ?? []).filter(u => u.skills && u.skills.length > 0);
212
+ if (!ledger)
213
+ return [];
214
+ const units = ledger.units.filter(u => u.skills && u.skills.length > 0);
213
215
  const stale = detectStaleSkills(units, staleDays ?? DEFAULT_STALE_DAYS);
214
216
  const avoidSet = new Set(currentAvoidList);
215
217
  return stale.filter(s => !avoidSet.has(s));
@@ -1,5 +1,5 @@
1
1
  import { clearParseCache } from "../files.js";
2
- import { transaction, insertMilestone, insertSlice, upsertMilestonePlanning, upsertSlicePlanning, _getAdapter, } from "../gsd-db.js";
2
+ import { transaction, insertMilestone, insertSlice, upsertMilestonePlanning, upsertSlicePlanning, } from "../gsd-db.js";
3
3
  import { invalidateStateCache } from "../state.js";
4
4
  import { renderRoadmapFromDb } from "../markdown-renderer.js";
5
5
  function isNonEmptyString(value) {
@@ -192,16 +192,7 @@ export async function handlePlanMilestone(rawParams, basePath) {
192
192
  roadmapPath = renderResult.roadmapPath;
193
193
  }
194
194
  catch (renderErr) {
195
- process.stderr.write(`gsd-db: plan_milestone — render failed, rolling back DB rows: ${renderErr.message}\n`);
196
- const rollbackAdapter = _getAdapter();
197
- if (rollbackAdapter) {
198
- for (const slice of params.slices) {
199
- rollbackAdapter.prepare(`DELETE FROM slice_planning WHERE milestone_id = :mid AND slice_id = :sid`).run({ ":mid": params.milestoneId, ":sid": slice.sliceId });
200
- rollbackAdapter.prepare(`DELETE FROM slices WHERE milestone_id = :mid AND id = :sid`).run({ ":mid": params.milestoneId, ":sid": slice.sliceId });
201
- }
202
- rollbackAdapter.prepare(`DELETE FROM milestone_planning WHERE milestone_id = :mid`).run({ ":mid": params.milestoneId });
203
- rollbackAdapter.prepare(`DELETE FROM milestones WHERE id = :mid`).run({ ":mid": params.milestoneId });
204
- }
195
+ process.stderr.write(`gsd-db: plan_milestone — render failed (DB rows preserved for debugging): ${renderErr.message}\n`);
205
196
  invalidateStateCache();
206
197
  return { error: `render failed: ${renderErr.message}` };
207
198
  }
@@ -1,5 +1,5 @@
1
1
  import { clearParseCache } from "../files.js";
2
- import { transaction, getSlice, insertTask, upsertSlicePlanning, upsertTaskPlanning, _getAdapter, } from "../gsd-db.js";
2
+ import { transaction, getSlice, insertTask, upsertSlicePlanning, upsertTaskPlanning, } from "../gsd-db.js";
3
3
  import { invalidateStateCache } from "../state.js";
4
4
  import { renderPlanFromDb } from "../markdown-renderer.js";
5
5
  function isNonEmptyString(value) {
@@ -148,15 +148,7 @@ export async function handlePlanSlice(rawParams, basePath) {
148
148
  };
149
149
  }
150
150
  catch (renderErr) {
151
- process.stderr.write(`gsd-db: plan_slice — render failed, rolling back DB rows: ${renderErr.message}\n`);
152
- const rollbackAdapter = _getAdapter();
153
- if (rollbackAdapter) {
154
- for (const task of params.tasks) {
155
- rollbackAdapter.prepare(`DELETE FROM task_planning WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid`).run({ ":mid": params.milestoneId, ":sid": params.sliceId, ":tid": task.taskId });
156
- rollbackAdapter.prepare(`DELETE FROM tasks WHERE milestone_id = :mid AND slice_id = :sid AND id = :tid`).run({ ":mid": params.milestoneId, ":sid": params.sliceId, ":tid": task.taskId });
157
- }
158
- rollbackAdapter.prepare(`DELETE FROM slice_planning WHERE milestone_id = :mid AND slice_id = :sid`).run({ ":mid": params.milestoneId, ":sid": params.sliceId });
159
- }
151
+ process.stderr.write(`gsd-db: plan_slice — render failed (DB rows preserved for debugging): ${renderErr.message}\n`);
160
152
  invalidateStateCache();
161
153
  return { error: `render failed: ${renderErr.message}` };
162
154
  }