gsd-pi 2.18.0 → 2.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/README.md +5 -1
  2. package/dist/cli.js +3 -3
  3. package/dist/onboarding.d.ts +3 -1
  4. package/dist/onboarding.js +77 -3
  5. package/dist/remote-questions-config.d.ts +1 -1
  6. package/dist/resources/extensions/google-search/index.ts +164 -47
  7. package/dist/resources/extensions/gsd/auto-dashboard.ts +14 -2
  8. package/dist/resources/extensions/gsd/auto-prompts.ts +148 -39
  9. package/dist/resources/extensions/gsd/auto-worktree.ts +93 -9
  10. package/dist/resources/extensions/gsd/auto.ts +690 -39
  11. package/dist/resources/extensions/gsd/captures.ts +384 -0
  12. package/dist/resources/extensions/gsd/commands.ts +654 -36
  13. package/dist/resources/extensions/gsd/complexity-classifier.ts +322 -0
  14. package/dist/resources/extensions/gsd/context-budget.ts +243 -0
  15. package/dist/resources/extensions/gsd/context-store.ts +195 -0
  16. package/dist/resources/extensions/gsd/dashboard-overlay.ts +51 -3
  17. package/dist/resources/extensions/gsd/db-writer.ts +341 -0
  18. package/dist/resources/extensions/gsd/debug-logger.ts +178 -0
  19. package/dist/resources/extensions/gsd/dispatch-guard.ts +0 -1
  20. package/dist/resources/extensions/gsd/docs/preferences-reference.md +54 -0
  21. package/dist/resources/extensions/gsd/doctor-proactive.ts +286 -0
  22. package/dist/resources/extensions/gsd/doctor.ts +283 -2
  23. package/dist/resources/extensions/gsd/export.ts +81 -2
  24. package/dist/resources/extensions/gsd/files.ts +39 -9
  25. package/dist/resources/extensions/gsd/git-service.ts +6 -0
  26. package/dist/resources/extensions/gsd/gsd-db.ts +752 -0
  27. package/dist/resources/extensions/gsd/guided-flow.ts +26 -1
  28. package/dist/resources/extensions/gsd/history.ts +0 -1
  29. package/dist/resources/extensions/gsd/index.ts +277 -1
  30. package/dist/resources/extensions/gsd/md-importer.ts +526 -0
  31. package/dist/resources/extensions/gsd/metrics.ts +84 -0
  32. package/dist/resources/extensions/gsd/model-cost-table.ts +65 -0
  33. package/dist/resources/extensions/gsd/model-router.ts +256 -0
  34. package/dist/resources/extensions/gsd/notifications.ts +0 -1
  35. package/dist/resources/extensions/gsd/post-unit-hooks.ts +72 -2
  36. package/dist/resources/extensions/gsd/preferences.ts +198 -150
  37. package/dist/resources/extensions/gsd/prompt-loader.ts +45 -9
  38. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -5
  39. package/dist/resources/extensions/gsd/prompts/heal-skill.md +45 -0
  40. package/dist/resources/extensions/gsd/prompts/plan-slice.md +5 -1
  41. package/dist/resources/extensions/gsd/prompts/quick-task.md +48 -0
  42. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -0
  43. package/dist/resources/extensions/gsd/prompts/replan-slice.md +8 -0
  44. package/dist/resources/extensions/gsd/prompts/system.md +2 -1
  45. package/dist/resources/extensions/gsd/prompts/triage-captures.md +62 -0
  46. package/dist/resources/extensions/gsd/quick.ts +156 -0
  47. package/dist/resources/extensions/gsd/skill-discovery.ts +5 -3
  48. package/dist/resources/extensions/gsd/skill-health.ts +417 -0
  49. package/dist/resources/extensions/gsd/skill-telemetry.ts +127 -0
  50. package/dist/resources/extensions/gsd/state.ts +30 -0
  51. package/dist/resources/extensions/gsd/templates/preferences.md +1 -0
  52. package/dist/resources/extensions/gsd/tests/captures.test.ts +438 -0
  53. package/dist/resources/extensions/gsd/tests/complexity-classifier.test.ts +181 -0
  54. package/dist/resources/extensions/gsd/tests/context-budget.test.ts +283 -0
  55. package/dist/resources/extensions/gsd/tests/context-compression.test.ts +1 -1
  56. package/dist/resources/extensions/gsd/tests/context-store.test.ts +462 -0
  57. package/dist/resources/extensions/gsd/tests/continue-here.test.ts +204 -0
  58. package/dist/resources/extensions/gsd/tests/dashboard-budget.test.ts +346 -0
  59. package/dist/resources/extensions/gsd/tests/db-writer.test.ts +602 -0
  60. package/dist/resources/extensions/gsd/tests/debug-logger.test.ts +185 -0
  61. package/dist/resources/extensions/gsd/tests/derive-state-db.test.ts +406 -0
  62. package/dist/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -1
  63. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +22 -0
  64. package/dist/resources/extensions/gsd/tests/doctor-proactive.test.ts +244 -0
  65. package/dist/resources/extensions/gsd/tests/doctor-runtime.test.ts +303 -0
  66. package/dist/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +434 -0
  67. package/dist/resources/extensions/gsd/tests/gsd-db.test.ts +353 -0
  68. package/dist/resources/extensions/gsd/tests/gsd-inspect.test.ts +125 -0
  69. package/dist/resources/extensions/gsd/tests/gsd-tools.test.ts +326 -0
  70. package/dist/resources/extensions/gsd/tests/integration-edge.test.ts +228 -0
  71. package/dist/resources/extensions/gsd/tests/integration-lifecycle.test.ts +277 -0
  72. package/dist/resources/extensions/gsd/tests/md-importer.test.ts +411 -0
  73. package/dist/resources/extensions/gsd/tests/metrics.test.ts +197 -0
  74. package/dist/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +144 -0
  75. package/dist/resources/extensions/gsd/tests/model-cost-table.test.ts +69 -0
  76. package/dist/resources/extensions/gsd/tests/model-isolation.test.ts +99 -0
  77. package/dist/resources/extensions/gsd/tests/model-router.test.ts +167 -0
  78. package/dist/resources/extensions/gsd/tests/parsers.test.ts +40 -0
  79. package/dist/resources/extensions/gsd/tests/post-unit-hooks.test.ts +41 -1
  80. package/dist/resources/extensions/gsd/tests/preferences-git.test.ts +0 -1
  81. package/dist/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -1
  82. package/dist/resources/extensions/gsd/tests/preferences-mode.test.ts +110 -0
  83. package/dist/resources/extensions/gsd/tests/preferences-models.test.ts +0 -1
  84. package/dist/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +464 -0
  85. package/dist/resources/extensions/gsd/tests/prompt-db.test.ts +385 -0
  86. package/dist/resources/extensions/gsd/tests/remote-questions.test.ts +488 -1
  87. package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +17 -29
  88. package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +2 -8
  89. package/dist/resources/extensions/gsd/tests/routing-history.test.ts +215 -62
  90. package/dist/resources/extensions/gsd/tests/skill-lifecycle.test.ts +126 -0
  91. package/dist/resources/extensions/gsd/tests/stop-auto-remote.test.ts +31 -8
  92. package/dist/resources/extensions/gsd/tests/token-savings.test.ts +366 -0
  93. package/dist/resources/extensions/gsd/tests/triage-dispatch.test.ts +224 -0
  94. package/dist/resources/extensions/gsd/tests/triage-resolution.test.ts +215 -0
  95. package/dist/resources/extensions/gsd/tests/unit-runtime.test.ts +25 -1
  96. package/dist/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +145 -0
  97. package/dist/resources/extensions/gsd/tests/visualizer-data.test.ts +290 -0
  98. package/dist/resources/extensions/gsd/tests/visualizer-overlay.test.ts +120 -0
  99. package/dist/resources/extensions/gsd/tests/visualizer-views.test.ts +478 -0
  100. package/dist/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
  101. package/dist/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
  102. package/dist/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +165 -0
  103. package/dist/resources/extensions/gsd/triage-resolution.ts +200 -0
  104. package/dist/resources/extensions/gsd/triage-ui.ts +175 -0
  105. package/dist/resources/extensions/gsd/types.ts +29 -0
  106. package/dist/resources/extensions/gsd/undo.ts +0 -1
  107. package/dist/resources/extensions/gsd/unit-runtime.ts +5 -1
  108. package/dist/resources/extensions/gsd/visualizer-data.ts +505 -0
  109. package/dist/resources/extensions/gsd/visualizer-overlay.ts +337 -0
  110. package/dist/resources/extensions/gsd/visualizer-views.ts +755 -0
  111. package/dist/resources/extensions/gsd/worktree-command.ts +18 -0
  112. package/dist/resources/extensions/gsd/worktree-manager.ts +11 -4
  113. package/dist/resources/extensions/remote-questions/config.ts +4 -2
  114. package/dist/resources/extensions/remote-questions/discord-adapter.ts +35 -4
  115. package/dist/resources/extensions/remote-questions/format.ts +166 -14
  116. package/dist/resources/extensions/remote-questions/manager.ts +14 -4
  117. package/dist/resources/extensions/remote-questions/remote-command.ts +100 -4
  118. package/dist/resources/extensions/remote-questions/slack-adapter.ts +58 -2
  119. package/dist/resources/extensions/remote-questions/telegram-adapter.ts +161 -0
  120. package/dist/resources/extensions/remote-questions/types.ts +2 -1
  121. package/dist/resources/extensions/ttsr/ttsr-manager.ts +26 -0
  122. package/dist/resources/extensions/voice/index.ts +4 -3
  123. package/package.json +1 -1
  124. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  125. package/packages/pi-coding-agent/dist/core/agent-session.js +12 -1
  126. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  127. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  128. package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
  129. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  130. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts +6 -0
  131. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  132. package/packages/pi-coding-agent/dist/core/lsp/client.js +25 -0
  133. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  134. package/packages/pi-coding-agent/dist/core/lsp/index.d.ts +2 -0
  135. package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
  136. package/packages/pi-coding-agent/dist/core/lsp/index.js +106 -3
  137. package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
  138. package/packages/pi-coding-agent/dist/core/lsp/lsp.md +6 -0
  139. package/packages/pi-coding-agent/dist/core/lsp/types.d.ts +35 -0
  140. package/packages/pi-coding-agent/dist/core/lsp/types.d.ts.map +1 -1
  141. package/packages/pi-coding-agent/dist/core/lsp/types.js +6 -0
  142. package/packages/pi-coding-agent/dist/core/lsp/types.js.map +1 -1
  143. package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts +3 -1
  144. package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts.map +1 -1
  145. package/packages/pi-coding-agent/dist/core/lsp/utils.js +45 -0
  146. package/packages/pi-coding-agent/dist/core/lsp/utils.js.map +1 -1
  147. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +6 -0
  148. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  149. package/packages/pi-coding-agent/dist/core/settings-manager.js +43 -11
  150. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  151. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  152. package/packages/pi-coding-agent/dist/core/system-prompt.js +7 -1
  153. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  154. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  155. package/packages/pi-coding-agent/dist/core/tools/edit.js +5 -0
  156. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  157. package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -0
  158. package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
  159. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/tools/write.js +5 -0
  161. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  162. package/packages/pi-coding-agent/src/core/agent-session.ts +13 -1
  163. package/packages/pi-coding-agent/src/core/extensions/loader.ts +6 -0
  164. package/packages/pi-coding-agent/src/core/lsp/client.ts +26 -0
  165. package/packages/pi-coding-agent/src/core/lsp/index.ts +157 -2
  166. package/packages/pi-coding-agent/src/core/lsp/lsp.md +6 -0
  167. package/packages/pi-coding-agent/src/core/lsp/types.ts +53 -0
  168. package/packages/pi-coding-agent/src/core/lsp/utils.ts +56 -0
  169. package/packages/pi-coding-agent/src/core/settings-manager.ts +41 -11
  170. package/packages/pi-coding-agent/src/core/system-prompt.ts +7 -1
  171. package/packages/pi-coding-agent/src/core/tools/edit.ts +3 -0
  172. package/packages/pi-coding-agent/src/core/tools/write.ts +3 -0
  173. package/src/resources/extensions/google-search/index.ts +164 -47
  174. package/src/resources/extensions/gsd/auto-dashboard.ts +14 -2
  175. package/src/resources/extensions/gsd/auto-prompts.ts +148 -39
  176. package/src/resources/extensions/gsd/auto-worktree.ts +93 -9
  177. package/src/resources/extensions/gsd/auto.ts +690 -39
  178. package/src/resources/extensions/gsd/captures.ts +384 -0
  179. package/src/resources/extensions/gsd/commands.ts +654 -36
  180. package/src/resources/extensions/gsd/complexity-classifier.ts +322 -0
  181. package/src/resources/extensions/gsd/context-budget.ts +243 -0
  182. package/src/resources/extensions/gsd/context-store.ts +195 -0
  183. package/src/resources/extensions/gsd/dashboard-overlay.ts +51 -3
  184. package/src/resources/extensions/gsd/db-writer.ts +341 -0
  185. package/src/resources/extensions/gsd/debug-logger.ts +178 -0
  186. package/src/resources/extensions/gsd/dispatch-guard.ts +0 -1
  187. package/src/resources/extensions/gsd/docs/preferences-reference.md +54 -0
  188. package/src/resources/extensions/gsd/doctor-proactive.ts +286 -0
  189. package/src/resources/extensions/gsd/doctor.ts +283 -2
  190. package/src/resources/extensions/gsd/export.ts +81 -2
  191. package/src/resources/extensions/gsd/files.ts +39 -9
  192. package/src/resources/extensions/gsd/git-service.ts +6 -0
  193. package/src/resources/extensions/gsd/gsd-db.ts +752 -0
  194. package/src/resources/extensions/gsd/guided-flow.ts +26 -1
  195. package/src/resources/extensions/gsd/history.ts +0 -1
  196. package/src/resources/extensions/gsd/index.ts +277 -1
  197. package/src/resources/extensions/gsd/md-importer.ts +526 -0
  198. package/src/resources/extensions/gsd/metrics.ts +84 -0
  199. package/src/resources/extensions/gsd/model-cost-table.ts +65 -0
  200. package/src/resources/extensions/gsd/model-router.ts +256 -0
  201. package/src/resources/extensions/gsd/notifications.ts +0 -1
  202. package/src/resources/extensions/gsd/post-unit-hooks.ts +72 -2
  203. package/src/resources/extensions/gsd/preferences.ts +198 -150
  204. package/src/resources/extensions/gsd/prompt-loader.ts +45 -9
  205. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -5
  206. package/src/resources/extensions/gsd/prompts/heal-skill.md +45 -0
  207. package/src/resources/extensions/gsd/prompts/plan-slice.md +5 -1
  208. package/src/resources/extensions/gsd/prompts/quick-task.md +48 -0
  209. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -0
  210. package/src/resources/extensions/gsd/prompts/replan-slice.md +8 -0
  211. package/src/resources/extensions/gsd/prompts/system.md +2 -1
  212. package/src/resources/extensions/gsd/prompts/triage-captures.md +62 -0
  213. package/src/resources/extensions/gsd/quick.ts +156 -0
  214. package/src/resources/extensions/gsd/skill-discovery.ts +5 -3
  215. package/src/resources/extensions/gsd/skill-health.ts +417 -0
  216. package/src/resources/extensions/gsd/skill-telemetry.ts +127 -0
  217. package/src/resources/extensions/gsd/state.ts +30 -0
  218. package/src/resources/extensions/gsd/templates/preferences.md +1 -0
  219. package/src/resources/extensions/gsd/tests/captures.test.ts +438 -0
  220. package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +181 -0
  221. package/src/resources/extensions/gsd/tests/context-budget.test.ts +283 -0
  222. package/src/resources/extensions/gsd/tests/context-compression.test.ts +1 -1
  223. package/src/resources/extensions/gsd/tests/context-store.test.ts +462 -0
  224. package/src/resources/extensions/gsd/tests/continue-here.test.ts +204 -0
  225. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +346 -0
  226. package/src/resources/extensions/gsd/tests/db-writer.test.ts +602 -0
  227. package/src/resources/extensions/gsd/tests/debug-logger.test.ts +185 -0
  228. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +406 -0
  229. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -1
  230. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +22 -0
  231. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +244 -0
  232. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +303 -0
  233. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +434 -0
  234. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +353 -0
  235. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +125 -0
  236. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +326 -0
  237. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +228 -0
  238. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +277 -0
  239. package/src/resources/extensions/gsd/tests/md-importer.test.ts +411 -0
  240. package/src/resources/extensions/gsd/tests/metrics.test.ts +197 -0
  241. package/src/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +144 -0
  242. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +69 -0
  243. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +99 -0
  244. package/src/resources/extensions/gsd/tests/model-router.test.ts +167 -0
  245. package/src/resources/extensions/gsd/tests/parsers.test.ts +40 -0
  246. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +41 -1
  247. package/src/resources/extensions/gsd/tests/preferences-git.test.ts +0 -1
  248. package/src/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -1
  249. package/src/resources/extensions/gsd/tests/preferences-mode.test.ts +110 -0
  250. package/src/resources/extensions/gsd/tests/preferences-models.test.ts +0 -1
  251. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +464 -0
  252. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +385 -0
  253. package/src/resources/extensions/gsd/tests/remote-questions.test.ts +488 -1
  254. package/src/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +17 -29
  255. package/src/resources/extensions/gsd/tests/resolve-ts.mjs +2 -8
  256. package/src/resources/extensions/gsd/tests/routing-history.test.ts +215 -62
  257. package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +126 -0
  258. package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +31 -8
  259. package/src/resources/extensions/gsd/tests/token-savings.test.ts +366 -0
  260. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +224 -0
  261. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +215 -0
  262. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +25 -1
  263. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +145 -0
  264. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +290 -0
  265. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +120 -0
  266. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +478 -0
  267. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
  268. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
  269. package/src/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +165 -0
  270. package/src/resources/extensions/gsd/triage-resolution.ts +200 -0
  271. package/src/resources/extensions/gsd/triage-ui.ts +175 -0
  272. package/src/resources/extensions/gsd/types.ts +29 -0
  273. package/src/resources/extensions/gsd/undo.ts +0 -1
  274. package/src/resources/extensions/gsd/unit-runtime.ts +5 -1
  275. package/src/resources/extensions/gsd/visualizer-data.ts +505 -0
  276. package/src/resources/extensions/gsd/visualizer-overlay.ts +337 -0
  277. package/src/resources/extensions/gsd/visualizer-views.ts +755 -0
  278. package/src/resources/extensions/gsd/worktree-command.ts +18 -0
  279. package/src/resources/extensions/gsd/worktree-manager.ts +11 -4
  280. package/src/resources/extensions/remote-questions/config.ts +4 -2
  281. package/src/resources/extensions/remote-questions/discord-adapter.ts +35 -4
  282. package/src/resources/extensions/remote-questions/format.ts +166 -14
  283. package/src/resources/extensions/remote-questions/manager.ts +14 -4
  284. package/src/resources/extensions/remote-questions/remote-command.ts +100 -4
  285. package/src/resources/extensions/remote-questions/slack-adapter.ts +58 -2
  286. package/src/resources/extensions/remote-questions/telegram-adapter.ts +161 -0
  287. package/src/resources/extensions/remote-questions/types.ts +2 -1
  288. package/src/resources/extensions/ttsr/ttsr-manager.ts +26 -0
  289. package/src/resources/extensions/voice/index.ts +4 -3
@@ -214,7 +214,11 @@ export function findMilestoneIds(basePath: string): string[] {
214
214
  // Apply custom queue order if available, else fall back to numeric sort
215
215
  const customOrder = loadQueueOrder(basePath);
216
216
  return sortByQueueOrder(ids, customOrder);
217
- } catch {
217
+ } catch (err) {
218
+ // Log why milestone scanning failed — silent [] here causes infinite loops (#456)
219
+ if (existsSync(dir)) {
220
+ console.error(`[gsd] findMilestoneIds: .gsd/milestones/ exists but readdirSync failed — ${err instanceof Error ? err.message : String(err)}`);
221
+ }
218
222
  return [];
219
223
  }
220
224
  }
@@ -1002,6 +1006,27 @@ export async function showSmartEntry(
1002
1006
  }
1003
1007
 
1004
1008
  const milestoneIds = findMilestoneIds(basePath);
1009
+
1010
+ // Sanity check (#456): if findMilestoneIds returns [] but the milestones
1011
+ // directory has contents, something went wrong (permissions, stale worktree
1012
+ // cwd, etc). Warn instead of silently starting a new-project flow.
1013
+ if (milestoneIds.length === 0) {
1014
+ const mDir = milestonesDir(basePath);
1015
+ if (existsSync(mDir)) {
1016
+ try {
1017
+ const entries = readdirSync(mDir);
1018
+ if (entries.length > 0) {
1019
+ ctx.ui.notify(
1020
+ `Milestone directory has ${entries.length} entries but none were recognized as milestones. ` +
1021
+ `This may indicate a corrupted state or wrong working directory. Run \`/gsd doctor\` to diagnose.`,
1022
+ "warning",
1023
+ );
1024
+ return;
1025
+ }
1026
+ } catch { /* directory exists but unreadable — fall through to normal flow */ }
1027
+ }
1028
+ }
1029
+
1005
1030
  const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
1006
1031
  const nextId = nextMilestoneId(milestoneIds, uniqueMilestoneIds);
1007
1032
  const isFirst = milestoneIds.length === 0;
@@ -1,6 +1,5 @@
1
1
  // GSD Extension — Session History View
2
2
  // Human-readable display of past auto-mode unit executions.
3
- // Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
4
3
 
5
4
  import type { ExtensionCommandContext } from "@gsd/pi-coding-agent";
6
5
  import {
@@ -24,7 +24,9 @@ import type {
24
24
  ExtensionContext,
25
25
  } from "@gsd/pi-coding-agent";
26
26
  import { createBashTool, createWriteTool, createReadTool, createEditTool, isToolCallEventType } from "@gsd/pi-coding-agent";
27
+ import { Type } from "@sinclair/typebox";
27
28
 
29
+ import { debugLog, debugTime } from "./debug-logger.js";
28
30
  import { registerGSDCommand, loadToolApiKeys } from "./commands.js";
29
31
  import { registerExitCommand } from "./exit-command.js";
30
32
  import { registerWorktreeCommand, getWorktreeOriginalCwd, getActiveWorktreeName } from "./worktree-command.js";
@@ -53,10 +55,39 @@ import {
53
55
  import { Key } from "@gsd/pi-tui";
54
56
  import { join } from "node:path";
55
57
  import { existsSync, readFileSync } from "node:fs";
58
+ import { homedir } from "node:os";
56
59
  import { shortcutDesc } from "../shared/terminal.js";
57
60
  import { Text } from "@gsd/pi-tui";
58
61
  import { pauseAutoForProviderError } from "./provider-error-pause.js";
59
62
 
63
+ // ── Agent Instructions ────────────────────────────────────────────────────
64
+ // Lightweight "always follow" files injected into every GSD agent session.
65
+ // Global: ~/.gsd/agent-instructions.md Project: .gsd/agent-instructions.md
66
+ // Both are loaded and concatenated (global first, project appends).
67
+
68
+ function loadAgentInstructions(): string | null {
69
+ const parts: string[] = [];
70
+
71
+ const globalPath = join(homedir(), ".gsd", "agent-instructions.md");
72
+ if (existsSync(globalPath)) {
73
+ try {
74
+ const content = readFileSync(globalPath, "utf-8").trim();
75
+ if (content) parts.push(content);
76
+ } catch { /* non-fatal — skip unreadable file */ }
77
+ }
78
+
79
+ const projectPath = join(process.cwd(), ".gsd", "agent-instructions.md");
80
+ if (existsSync(projectPath)) {
81
+ try {
82
+ const content = readFileSync(projectPath, "utf-8").trim();
83
+ if (content) parts.push(content);
84
+ } catch { /* non-fatal — skip unreadable file */ }
85
+ }
86
+
87
+ if (parts.length === 0) return null;
88
+ return parts.join("\n\n");
89
+ }
90
+
60
91
  // ── Depth verification state ──────────────────────────────────────────────
61
92
  let depthVerificationDone = false;
62
93
 
@@ -190,6 +221,235 @@ export default function (pi: ExtensionAPI) {
190
221
  };
191
222
  pi.registerTool(dynamicEdit as any);
192
223
 
224
+ // ── Structured LLM tools — DB-first write path (R014) ──────────────────
225
+
226
+ pi.registerTool({
227
+ name: "gsd_save_decision",
228
+ label: "Save Decision",
229
+ description:
230
+ "Record a project decision to the GSD database and regenerate DECISIONS.md. " +
231
+ "Decision IDs are auto-assigned — never provide an ID manually.",
232
+ promptSnippet: "Record a project decision to the GSD database (auto-assigns ID, regenerates DECISIONS.md)",
233
+ promptGuidelines: [
234
+ "Use gsd_save_decision when recording an architectural, pattern, library, or observability decision.",
235
+ "Decision IDs are auto-assigned (D001, D002, ...) — never guess or provide an ID.",
236
+ "All fields except revisable and when_context are required.",
237
+ "The tool writes to the DB and regenerates .gsd/DECISIONS.md automatically.",
238
+ ],
239
+ parameters: Type.Object({
240
+ scope: Type.String({ description: "Scope of the decision (e.g. 'architecture', 'library', 'observability')" }),
241
+ decision: Type.String({ description: "What is being decided" }),
242
+ choice: Type.String({ description: "The choice made" }),
243
+ rationale: Type.String({ description: "Why this choice was made" }),
244
+ revisable: Type.Optional(Type.String({ description: "Whether this can be revisited (default: 'Yes')" })),
245
+ when_context: Type.Optional(Type.String({ description: "When/context for the decision (e.g. milestone ID)" })),
246
+ }),
247
+ async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
248
+ // Check DB availability
249
+ let dbAvailable = false;
250
+ try {
251
+ const db = await import("./gsd-db.js");
252
+ dbAvailable = db.isDbAvailable();
253
+ } catch { /* dynamic import failed */ }
254
+
255
+ if (!dbAvailable) {
256
+ return {
257
+ content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot save decision." }],
258
+ isError: true,
259
+ details: { operation: "save_decision", error: "db_unavailable" },
260
+ };
261
+ }
262
+
263
+ try {
264
+ const { saveDecisionToDb } = await import("./db-writer.js");
265
+ const { id } = await saveDecisionToDb(
266
+ {
267
+ scope: params.scope,
268
+ decision: params.decision,
269
+ choice: params.choice,
270
+ rationale: params.rationale,
271
+ revisable: params.revisable,
272
+ when_context: params.when_context,
273
+ },
274
+ process.cwd(),
275
+ );
276
+ return {
277
+ content: [{ type: "text" as const, text: `Saved decision ${id}` }],
278
+ details: { operation: "save_decision", id },
279
+ };
280
+ } catch (err) {
281
+ const msg = err instanceof Error ? err.message : String(err);
282
+ process.stderr.write(`gsd-db: gsd_save_decision tool failed: ${msg}\n`);
283
+ return {
284
+ content: [{ type: "text" as const, text: `Error saving decision: ${msg}` }],
285
+ isError: true,
286
+ details: { operation: "save_decision", error: msg },
287
+ };
288
+ }
289
+ },
290
+ });
291
+
292
+ pi.registerTool({
293
+ name: "gsd_update_requirement",
294
+ label: "Update Requirement",
295
+ description:
296
+ "Update an existing requirement in the GSD database and regenerate REQUIREMENTS.md. " +
297
+ "Provide the requirement ID (e.g. R001) and any fields to update.",
298
+ promptSnippet: "Update an existing GSD requirement by ID (regenerates REQUIREMENTS.md)",
299
+ promptGuidelines: [
300
+ "Use gsd_update_requirement to change status, validation, notes, or other fields on an existing requirement.",
301
+ "The id parameter is required — it must be an existing RXXX identifier.",
302
+ "All other fields are optional — only provided fields are updated.",
303
+ "The tool verifies the requirement exists before updating.",
304
+ ],
305
+ parameters: Type.Object({
306
+ id: Type.String({ description: "The requirement ID (e.g. R001, R014)" }),
307
+ status: Type.Optional(Type.String({ description: "New status (e.g. 'active', 'validated', 'deferred')" })),
308
+ validation: Type.Optional(Type.String({ description: "Validation criteria or proof" })),
309
+ notes: Type.Optional(Type.String({ description: "Additional notes" })),
310
+ description: Type.Optional(Type.String({ description: "Updated description" })),
311
+ primary_owner: Type.Optional(Type.String({ description: "Primary owning slice" })),
312
+ supporting_slices: Type.Optional(Type.String({ description: "Supporting slices" })),
313
+ }),
314
+ async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
315
+ let dbAvailable = false;
316
+ try {
317
+ const db = await import("./gsd-db.js");
318
+ dbAvailable = db.isDbAvailable();
319
+ } catch { /* dynamic import failed */ }
320
+
321
+ if (!dbAvailable) {
322
+ return {
323
+ content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot update requirement." }],
324
+ isError: true,
325
+ details: { operation: "update_requirement", id: params.id, error: "db_unavailable" },
326
+ };
327
+ }
328
+
329
+ try {
330
+ // Verify requirement exists
331
+ const db = await import("./gsd-db.js");
332
+ const existing = db.getRequirementById(params.id);
333
+ if (!existing) {
334
+ return {
335
+ content: [{ type: "text" as const, text: `Error: Requirement ${params.id} not found.` }],
336
+ isError: true,
337
+ details: { operation: "update_requirement", id: params.id, error: "not_found" },
338
+ };
339
+ }
340
+
341
+ const { updateRequirementInDb } = await import("./db-writer.js");
342
+ const updates: Record<string, string | undefined> = {};
343
+ if (params.status !== undefined) updates.status = params.status;
344
+ if (params.validation !== undefined) updates.validation = params.validation;
345
+ if (params.notes !== undefined) updates.notes = params.notes;
346
+ if (params.description !== undefined) updates.description = params.description;
347
+ if (params.primary_owner !== undefined) updates.primary_owner = params.primary_owner;
348
+ if (params.supporting_slices !== undefined) updates.supporting_slices = params.supporting_slices;
349
+
350
+ await updateRequirementInDb(params.id, updates, process.cwd());
351
+
352
+ return {
353
+ content: [{ type: "text" as const, text: `Updated requirement ${params.id}` }],
354
+ details: { operation: "update_requirement", id: params.id },
355
+ };
356
+ } catch (err) {
357
+ const msg = err instanceof Error ? err.message : String(err);
358
+ process.stderr.write(`gsd-db: gsd_update_requirement tool failed: ${msg}\n`);
359
+ return {
360
+ content: [{ type: "text" as const, text: `Error updating requirement: ${msg}` }],
361
+ isError: true,
362
+ details: { operation: "update_requirement", id: params.id, error: msg },
363
+ };
364
+ }
365
+ },
366
+ });
367
+
368
+ pi.registerTool({
369
+ name: "gsd_save_summary",
370
+ label: "Save Summary",
371
+ description:
372
+ "Save a summary, research, context, or assessment artifact to the GSD database and write it to disk. " +
373
+ "Computes the file path from milestone/slice/task IDs automatically.",
374
+ promptSnippet: "Save a GSD artifact (summary/research/context/assessment) to DB and disk",
375
+ promptGuidelines: [
376
+ "Use gsd_save_summary to persist structured artifacts (SUMMARY, RESEARCH, CONTEXT, ASSESSMENT).",
377
+ "milestone_id is required. slice_id and task_id are optional — they determine the file path.",
378
+ "The tool computes the relative path automatically: milestones/M001/M001-SUMMARY.md, milestones/M001/slices/S01/S01-SUMMARY.md, etc.",
379
+ "artifact_type must be one of: SUMMARY, RESEARCH, CONTEXT, ASSESSMENT.",
380
+ ],
381
+ parameters: Type.Object({
382
+ milestone_id: Type.String({ description: "Milestone ID (e.g. M001)" }),
383
+ slice_id: Type.Optional(Type.String({ description: "Slice ID (e.g. S01)" })),
384
+ task_id: Type.Optional(Type.String({ description: "Task ID (e.g. T01)" })),
385
+ artifact_type: Type.String({ description: "One of: SUMMARY, RESEARCH, CONTEXT, ASSESSMENT" }),
386
+ content: Type.String({ description: "The full markdown content of the artifact" }),
387
+ }),
388
+ async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
389
+ let dbAvailable = false;
390
+ try {
391
+ const db = await import("./gsd-db.js");
392
+ dbAvailable = db.isDbAvailable();
393
+ } catch { /* dynamic import failed */ }
394
+
395
+ if (!dbAvailable) {
396
+ return {
397
+ content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot save artifact." }],
398
+ isError: true,
399
+ details: { operation: "save_summary", error: "db_unavailable" },
400
+ };
401
+ }
402
+
403
+ // Validate artifact_type
404
+ const validTypes = ["SUMMARY", "RESEARCH", "CONTEXT", "ASSESSMENT"];
405
+ if (!validTypes.includes(params.artifact_type)) {
406
+ return {
407
+ content: [{ type: "text" as const, text: `Error: Invalid artifact_type "${params.artifact_type}". Must be one of: ${validTypes.join(", ")}` }],
408
+ isError: true,
409
+ details: { operation: "save_summary", error: "invalid_artifact_type" },
410
+ };
411
+ }
412
+
413
+ try {
414
+ // Compute relative path from IDs
415
+ let relativePath: string;
416
+ if (params.task_id && params.slice_id) {
417
+ relativePath = `milestones/${params.milestone_id}/slices/${params.slice_id}/tasks/${params.task_id}-${params.artifact_type}.md`;
418
+ } else if (params.slice_id) {
419
+ relativePath = `milestones/${params.milestone_id}/slices/${params.slice_id}/${params.slice_id}-${params.artifact_type}.md`;
420
+ } else {
421
+ relativePath = `milestones/${params.milestone_id}/${params.milestone_id}-${params.artifact_type}.md`;
422
+ }
423
+
424
+ const { saveArtifactToDb } = await import("./db-writer.js");
425
+ await saveArtifactToDb(
426
+ {
427
+ path: relativePath,
428
+ artifact_type: params.artifact_type,
429
+ content: params.content,
430
+ milestone_id: params.milestone_id,
431
+ slice_id: params.slice_id,
432
+ task_id: params.task_id,
433
+ },
434
+ process.cwd(),
435
+ );
436
+
437
+ return {
438
+ content: [{ type: "text" as const, text: `Saved ${params.artifact_type} artifact to ${relativePath}` }],
439
+ details: { operation: "save_summary", path: relativePath, artifact_type: params.artifact_type },
440
+ };
441
+ } catch (err) {
442
+ const msg = err instanceof Error ? err.message : String(err);
443
+ process.stderr.write(`gsd-db: gsd_save_summary tool failed: ${msg}\n`);
444
+ return {
445
+ content: [{ type: "text" as const, text: `Error saving artifact: ${msg}` }],
446
+ isError: true,
447
+ details: { operation: "save_summary", error: msg },
448
+ };
449
+ }
450
+ },
451
+ });
452
+
193
453
  // ── session_start: render branded GSD header + load tool keys + remote status ──
194
454
  pi.on("session_start", async (_event, ctx) => {
195
455
  // Theme access throws in RPC mode (no TUI) — header is decorative, skip it
@@ -257,6 +517,7 @@ export default function (pi: ExtensionAPI) {
257
517
  pi.on("before_agent_start", async (event, ctx: ExtensionContext) => {
258
518
  if (!existsSync(join(process.cwd(), ".gsd"))) return;
259
519
 
520
+ const stopContextTimer = debugTime("context-inject");
260
521
  const systemContent = loadPrompt("system");
261
522
  const loadedPreferences = loadEffectiveGSDPreferences();
262
523
  let preferenceBlock = "";
@@ -297,6 +558,13 @@ export default function (pi: ExtensionAPI) {
297
558
  }
298
559
  }
299
560
 
561
+ // Load agent instructions (global + project)
562
+ let agentInstructionsBlock = "";
563
+ const agentInstructions = loadAgentInstructions();
564
+ if (agentInstructions) {
565
+ agentInstructionsBlock = `\n\n## Agent Instructions\n\nThe following instructions were provided by the user and must be followed in every session:\n\n${agentInstructions}`;
566
+ }
567
+
300
568
  const injection = await buildGuidedExecuteContextInjection(event.prompt, process.cwd());
301
569
 
302
570
  // Worktree context — override the static CWD in the system prompt
@@ -340,8 +608,16 @@ export default function (pi: ExtensionAPI) {
340
608
  ].join("\n");
341
609
  }
342
610
 
611
+ const fullSystem = `${event.systemPrompt}\n\n[SYSTEM CONTEXT — GSD]\n\n${systemContent}${preferenceBlock}${agentInstructionsBlock}${knowledgeBlock}${newSkillsBlock}${worktreeBlock}`;
612
+ stopContextTimer({
613
+ systemPromptSize: fullSystem.length,
614
+ injectionSize: injection?.length ?? 0,
615
+ hasPreferences: preferenceBlock.length > 0,
616
+ hasNewSkills: newSkillsBlock.length > 0,
617
+ });
618
+
343
619
  return {
344
- systemPrompt: `${event.systemPrompt}\n\n[SYSTEM CONTEXT — GSD]\n\n${systemContent}${preferenceBlock}${knowledgeBlock}${newSkillsBlock}${worktreeBlock}`,
620
+ systemPrompt: fullSystem,
345
621
  ...(injection
346
622
  ? {
347
623
  message: {