gsd-pi 2.38.0-dev.eeb3520 → 2.39.0-dev.38f11d1

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 (335) hide show
  1. package/README.md +15 -11
  2. package/dist/app-paths.js +1 -1
  3. package/dist/cli.js +9 -0
  4. package/dist/extension-discovery.d.ts +5 -3
  5. package/dist/extension-discovery.js +14 -9
  6. package/dist/extension-registry.js +2 -2
  7. package/dist/remote-questions-config.js +2 -2
  8. package/dist/resource-loader.js +34 -1
  9. package/dist/resources/extensions/async-jobs/index.js +10 -0
  10. package/dist/resources/extensions/browser-tools/index.js +3 -1
  11. package/dist/resources/extensions/browser-tools/package.json +3 -1
  12. package/dist/resources/extensions/browser-tools/tools/verify.js +97 -0
  13. package/dist/resources/extensions/cmux/index.js +55 -1
  14. package/dist/resources/extensions/context7/package.json +1 -1
  15. package/dist/resources/extensions/env-utils.js +29 -0
  16. package/dist/resources/extensions/get-secrets-from-user.js +5 -24
  17. package/dist/resources/extensions/github-sync/cli.js +284 -0
  18. package/dist/resources/extensions/github-sync/index.js +73 -0
  19. package/dist/resources/extensions/github-sync/mapping.js +67 -0
  20. package/dist/resources/extensions/github-sync/sync.js +424 -0
  21. package/dist/resources/extensions/github-sync/templates.js +118 -0
  22. package/dist/resources/extensions/github-sync/types.js +7 -0
  23. package/dist/resources/extensions/google-search/package.json +3 -1
  24. package/dist/resources/extensions/gsd/auto/session.js +6 -23
  25. package/dist/resources/extensions/gsd/auto-dashboard.js +7 -0
  26. package/dist/resources/extensions/gsd/auto-dispatch.js +8 -9
  27. package/dist/resources/extensions/gsd/auto-loop.js +923 -787
  28. package/dist/resources/extensions/gsd/auto-post-unit.js +107 -70
  29. package/dist/resources/extensions/gsd/auto-prompts.js +205 -51
  30. package/dist/resources/extensions/gsd/auto-start.js +19 -3
  31. package/dist/resources/extensions/gsd/auto-worktree-sync.js +13 -5
  32. package/dist/resources/extensions/gsd/auto-worktree.js +3 -3
  33. package/dist/resources/extensions/gsd/auto.js +147 -98
  34. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +126 -0
  35. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +233 -0
  36. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +59 -0
  37. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +38 -0
  38. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +156 -0
  39. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +46 -0
  40. package/dist/resources/extensions/gsd/bootstrap/system-context.js +300 -0
  41. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +38 -0
  42. package/dist/resources/extensions/gsd/captures.js +9 -1
  43. package/dist/resources/extensions/gsd/commands/catalog.js +278 -0
  44. package/dist/resources/extensions/gsd/commands/context.js +84 -0
  45. package/dist/resources/extensions/gsd/commands/dispatcher.js +21 -0
  46. package/dist/resources/extensions/gsd/commands/handlers/auto.js +72 -0
  47. package/dist/resources/extensions/gsd/commands/handlers/core.js +246 -0
  48. package/dist/resources/extensions/gsd/commands/handlers/ops.js +166 -0
  49. package/dist/resources/extensions/gsd/commands/handlers/parallel.js +94 -0
  50. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +102 -0
  51. package/dist/resources/extensions/gsd/commands/index.js +11 -0
  52. package/dist/resources/extensions/gsd/commands-extensions.js +3 -2
  53. package/dist/resources/extensions/gsd/commands-handlers.js +17 -4
  54. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
  55. package/dist/resources/extensions/gsd/commands.js +8 -1169
  56. package/dist/resources/extensions/gsd/context-budget.js +2 -10
  57. package/dist/resources/extensions/gsd/dashboard-overlay.js +9 -0
  58. package/dist/resources/extensions/gsd/detection.js +1 -2
  59. package/dist/resources/extensions/gsd/docs/preferences-reference.md +0 -2
  60. package/dist/resources/extensions/gsd/doctor-checks.js +82 -0
  61. package/dist/resources/extensions/gsd/doctor-environment.js +78 -0
  62. package/dist/resources/extensions/gsd/doctor-format.js +15 -0
  63. package/dist/resources/extensions/gsd/doctor-proactive.js +80 -10
  64. package/dist/resources/extensions/gsd/doctor-providers.js +30 -11
  65. package/dist/resources/extensions/gsd/doctor.js +234 -12
  66. package/dist/resources/extensions/gsd/exit-command.js +2 -1
  67. package/dist/resources/extensions/gsd/export-html.js +46 -0
  68. package/dist/resources/extensions/gsd/export.js +1 -1
  69. package/dist/resources/extensions/gsd/files.js +48 -9
  70. package/dist/resources/extensions/gsd/forensics.js +1 -1
  71. package/dist/resources/extensions/gsd/git-service.js +30 -12
  72. package/dist/resources/extensions/gsd/gitignore.js +16 -3
  73. package/dist/resources/extensions/gsd/guided-flow.js +149 -38
  74. package/dist/resources/extensions/gsd/health-widget-core.js +32 -70
  75. package/dist/resources/extensions/gsd/health-widget.js +4 -87
  76. package/dist/resources/extensions/gsd/index.js +4 -1111
  77. package/dist/resources/extensions/gsd/migrate/parsers.js +1 -1
  78. package/dist/resources/extensions/gsd/migrate-external.js +18 -1
  79. package/dist/resources/extensions/gsd/native-git-bridge.js +37 -0
  80. package/dist/resources/extensions/gsd/package.json +1 -1
  81. package/dist/resources/extensions/gsd/paths.js +3 -0
  82. package/dist/resources/extensions/gsd/preferences-models.js +0 -12
  83. package/dist/resources/extensions/gsd/preferences-types.js +1 -1
  84. package/dist/resources/extensions/gsd/preferences-validation.js +59 -11
  85. package/dist/resources/extensions/gsd/preferences.js +22 -11
  86. package/dist/resources/extensions/gsd/progress-score.js +20 -1
  87. package/dist/resources/extensions/gsd/prompt-loader.js +6 -2
  88. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  89. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  90. package/dist/resources/extensions/gsd/prompts/discuss.md +11 -14
  91. package/dist/resources/extensions/gsd/prompts/execute-task.md +5 -3
  92. package/dist/resources/extensions/gsd/prompts/forensics.md +121 -46
  93. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  94. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
  95. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
  96. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  97. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  98. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  99. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  100. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  101. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  102. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  103. package/dist/resources/extensions/gsd/prompts/queue.md +4 -8
  104. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +11 -8
  105. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  106. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  107. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  108. package/dist/resources/extensions/gsd/prompts/run-uat.md +28 -11
  109. package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -2
  110. package/dist/resources/extensions/gsd/repo-identity.js +21 -4
  111. package/dist/resources/extensions/gsd/resource-version.js +2 -1
  112. package/dist/resources/extensions/gsd/roadmap-mutations.js +24 -0
  113. package/dist/resources/extensions/gsd/state.js +42 -23
  114. package/dist/resources/extensions/gsd/templates/runtime.md +21 -0
  115. package/dist/resources/extensions/gsd/templates/task-plan.md +3 -0
  116. package/dist/resources/extensions/gsd/visualizer-data.js +27 -2
  117. package/dist/resources/extensions/gsd/visualizer-views.js +52 -0
  118. package/dist/resources/extensions/gsd/worktree.js +35 -16
  119. package/dist/resources/extensions/mcp-client/index.js +14 -1
  120. package/dist/resources/extensions/remote-questions/status.js +4 -1
  121. package/dist/resources/extensions/remote-questions/store.js +4 -1
  122. package/dist/resources/extensions/search-the-web/provider.js +2 -1
  123. package/dist/resources/extensions/shared/frontmatter.js +1 -1
  124. package/dist/resources/extensions/subagent/index.js +12 -3
  125. package/dist/resources/extensions/subagent/isolation.js +2 -1
  126. package/dist/resources/extensions/ttsr/rule-loader.js +2 -1
  127. package/dist/resources/extensions/universal-config/package.json +1 -1
  128. package/dist/welcome-screen.d.ts +12 -0
  129. package/dist/welcome-screen.js +53 -0
  130. package/package.json +1 -1
  131. package/packages/pi-ai/dist/utils/oauth/anthropic.js +2 -2
  132. package/packages/pi-ai/dist/utils/oauth/anthropic.js.map +1 -1
  133. package/packages/pi-ai/src/utils/oauth/anthropic.ts +2 -2
  134. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  135. package/packages/pi-coding-agent/dist/core/extensions/loader.js +205 -7
  136. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  137. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  138. package/packages/pi-coding-agent/dist/core/package-manager.js +8 -4
  139. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  140. package/packages/pi-coding-agent/dist/core/skills.d.ts +1 -0
  141. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  142. package/packages/pi-coding-agent/dist/core/skills.js +6 -1
  143. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  144. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  145. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  146. package/packages/pi-coding-agent/dist/index.js +1 -1
  147. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  148. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts +17 -0
  149. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -0
  150. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +244 -0
  151. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -0
  152. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.d.ts +3 -0
  153. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.d.ts.map +1 -0
  154. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js +58 -0
  155. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js.map +1 -0
  156. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts +12 -0
  157. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -0
  158. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +54 -0
  159. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -0
  160. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts +6 -0
  161. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map +1 -0
  162. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js +63 -0
  163. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js.map +1 -0
  164. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +38 -0
  165. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -0
  166. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js +2 -0
  167. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -0
  168. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  169. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -453
  170. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  171. package/packages/pi-coding-agent/package.json +1 -1
  172. package/packages/pi-coding-agent/src/core/extensions/loader.ts +223 -7
  173. package/packages/pi-coding-agent/src/core/package-manager.ts +8 -4
  174. package/packages/pi-coding-agent/src/core/skills.ts +9 -1
  175. package/packages/pi-coding-agent/src/index.ts +1 -0
  176. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +302 -0
  177. package/packages/pi-coding-agent/src/modes/interactive/controllers/extension-ui-controller.ts +59 -0
  178. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +68 -0
  179. package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +71 -0
  180. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +37 -0
  181. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +16 -506
  182. package/pkg/package.json +1 -1
  183. package/src/resources/extensions/async-jobs/index.ts +11 -0
  184. package/src/resources/extensions/browser-tools/index.ts +3 -0
  185. package/src/resources/extensions/browser-tools/tools/verify.ts +117 -0
  186. package/src/resources/extensions/cmux/index.ts +57 -1
  187. package/src/resources/extensions/env-utils.ts +31 -0
  188. package/src/resources/extensions/get-secrets-from-user.ts +5 -24
  189. package/src/resources/extensions/github-sync/cli.ts +364 -0
  190. package/src/resources/extensions/github-sync/index.ts +93 -0
  191. package/src/resources/extensions/github-sync/mapping.ts +81 -0
  192. package/src/resources/extensions/github-sync/sync.ts +556 -0
  193. package/src/resources/extensions/github-sync/templates.ts +183 -0
  194. package/src/resources/extensions/github-sync/tests/cli.test.ts +20 -0
  195. package/src/resources/extensions/github-sync/tests/commit-linking.test.ts +39 -0
  196. package/src/resources/extensions/github-sync/tests/mapping.test.ts +104 -0
  197. package/src/resources/extensions/github-sync/tests/templates.test.ts +110 -0
  198. package/src/resources/extensions/github-sync/types.ts +47 -0
  199. package/src/resources/extensions/gsd/auto/session.ts +7 -25
  200. package/src/resources/extensions/gsd/auto-dashboard.ts +10 -0
  201. package/src/resources/extensions/gsd/auto-dispatch.ts +7 -9
  202. package/src/resources/extensions/gsd/auto-loop.ts +1285 -1138
  203. package/src/resources/extensions/gsd/auto-post-unit.ts +90 -46
  204. package/src/resources/extensions/gsd/auto-prompts.ts +250 -53
  205. package/src/resources/extensions/gsd/auto-start.ts +24 -3
  206. package/src/resources/extensions/gsd/auto-worktree-sync.ts +15 -4
  207. package/src/resources/extensions/gsd/auto-worktree.ts +3 -3
  208. package/src/resources/extensions/gsd/auto.ts +143 -102
  209. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +142 -0
  210. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +238 -0
  211. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +90 -0
  212. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +46 -0
  213. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +167 -0
  214. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +55 -0
  215. package/src/resources/extensions/gsd/bootstrap/system-context.ts +340 -0
  216. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +51 -0
  217. package/src/resources/extensions/gsd/captures.ts +10 -1
  218. package/src/resources/extensions/gsd/commands/catalog.ts +301 -0
  219. package/src/resources/extensions/gsd/commands/context.ts +101 -0
  220. package/src/resources/extensions/gsd/commands/dispatcher.ts +32 -0
  221. package/src/resources/extensions/gsd/commands/handlers/auto.ts +74 -0
  222. package/src/resources/extensions/gsd/commands/handlers/core.ts +274 -0
  223. package/src/resources/extensions/gsd/commands/handlers/ops.ts +169 -0
  224. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +118 -0
  225. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +109 -0
  226. package/src/resources/extensions/gsd/commands/index.ts +14 -0
  227. package/src/resources/extensions/gsd/commands-extensions.ts +4 -2
  228. package/src/resources/extensions/gsd/commands-handlers.ts +18 -3
  229. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
  230. package/src/resources/extensions/gsd/commands.ts +10 -1307
  231. package/src/resources/extensions/gsd/context-budget.ts +2 -12
  232. package/src/resources/extensions/gsd/dashboard-overlay.ts +10 -0
  233. package/src/resources/extensions/gsd/detection.ts +2 -2
  234. package/src/resources/extensions/gsd/docs/preferences-reference.md +0 -2
  235. package/src/resources/extensions/gsd/doctor-checks.ts +75 -0
  236. package/src/resources/extensions/gsd/doctor-environment.ts +82 -1
  237. package/src/resources/extensions/gsd/doctor-format.ts +20 -0
  238. package/src/resources/extensions/gsd/doctor-proactive.ts +106 -10
  239. package/src/resources/extensions/gsd/doctor-providers.ts +30 -9
  240. package/src/resources/extensions/gsd/doctor-types.ts +16 -1
  241. package/src/resources/extensions/gsd/doctor.ts +243 -14
  242. package/src/resources/extensions/gsd/exit-command.ts +2 -2
  243. package/src/resources/extensions/gsd/export-html.ts +51 -0
  244. package/src/resources/extensions/gsd/export.ts +1 -1
  245. package/src/resources/extensions/gsd/files.ts +51 -11
  246. package/src/resources/extensions/gsd/forensics.ts +1 -1
  247. package/src/resources/extensions/gsd/git-service.ts +44 -10
  248. package/src/resources/extensions/gsd/gitignore.ts +17 -3
  249. package/src/resources/extensions/gsd/guided-flow.ts +177 -44
  250. package/src/resources/extensions/gsd/health-widget-core.ts +28 -80
  251. package/src/resources/extensions/gsd/health-widget.ts +4 -89
  252. package/src/resources/extensions/gsd/index.ts +12 -1307
  253. package/src/resources/extensions/gsd/migrate/parsers.ts +1 -1
  254. package/src/resources/extensions/gsd/migrate-external.ts +18 -1
  255. package/src/resources/extensions/gsd/native-git-bridge.ts +37 -0
  256. package/src/resources/extensions/gsd/paths.ts +4 -0
  257. package/src/resources/extensions/gsd/preferences-models.ts +0 -12
  258. package/src/resources/extensions/gsd/preferences-types.ts +4 -4
  259. package/src/resources/extensions/gsd/preferences-validation.ts +51 -11
  260. package/src/resources/extensions/gsd/preferences.ts +25 -11
  261. package/src/resources/extensions/gsd/progress-score.ts +23 -0
  262. package/src/resources/extensions/gsd/prompt-loader.ts +7 -2
  263. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  264. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  265. package/src/resources/extensions/gsd/prompts/discuss.md +11 -14
  266. package/src/resources/extensions/gsd/prompts/execute-task.md +5 -3
  267. package/src/resources/extensions/gsd/prompts/forensics.md +121 -46
  268. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  269. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
  270. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
  271. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  272. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  273. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  274. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  275. package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  276. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  277. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  278. package/src/resources/extensions/gsd/prompts/queue.md +4 -8
  279. package/src/resources/extensions/gsd/prompts/reactive-execute.md +11 -8
  280. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  281. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  282. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  283. package/src/resources/extensions/gsd/prompts/run-uat.md +28 -11
  284. package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -2
  285. package/src/resources/extensions/gsd/repo-identity.ts +23 -4
  286. package/src/resources/extensions/gsd/resource-version.ts +3 -1
  287. package/src/resources/extensions/gsd/roadmap-mutations.ts +29 -0
  288. package/src/resources/extensions/gsd/state.ts +39 -21
  289. package/src/resources/extensions/gsd/templates/runtime.md +21 -0
  290. package/src/resources/extensions/gsd/templates/task-plan.md +3 -0
  291. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +21 -18
  292. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +135 -77
  293. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +4 -3
  294. package/src/resources/extensions/gsd/tests/cmux.test.ts +93 -0
  295. package/src/resources/extensions/gsd/tests/derive-state.test.ts +43 -0
  296. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +266 -0
  297. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +3 -3
  298. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +86 -3
  299. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +50 -0
  300. package/src/resources/extensions/gsd/tests/health-widget.test.ts +16 -54
  301. package/src/resources/extensions/gsd/tests/parsers.test.ts +131 -14
  302. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +209 -0
  303. package/src/resources/extensions/gsd/tests/preferences.test.ts +2 -7
  304. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +59 -0
  305. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +16 -16
  306. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +21 -1
  307. package/src/resources/extensions/gsd/tests/run-uat.test.ts +16 -4
  308. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +140 -0
  309. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +10 -10
  310. package/src/resources/extensions/gsd/tests/worktree.test.ts +47 -0
  311. package/src/resources/extensions/gsd/types.ts +18 -1
  312. package/src/resources/extensions/gsd/verification-evidence.ts +16 -0
  313. package/src/resources/extensions/gsd/visualizer-data.ts +52 -2
  314. package/src/resources/extensions/gsd/visualizer-views.ts +58 -0
  315. package/src/resources/extensions/gsd/worktree.ts +35 -15
  316. package/src/resources/extensions/mcp-client/index.ts +17 -1
  317. package/src/resources/extensions/remote-questions/status.ts +5 -1
  318. package/src/resources/extensions/remote-questions/store.ts +5 -1
  319. package/src/resources/extensions/search-the-web/provider.ts +2 -1
  320. package/src/resources/extensions/shared/frontmatter.ts +1 -1
  321. package/src/resources/extensions/subagent/index.ts +12 -3
  322. package/src/resources/extensions/subagent/isolation.ts +3 -1
  323. package/src/resources/extensions/ttsr/rule-loader.ts +3 -1
  324. package/dist/resources/extensions/gsd/prompt-compressor.js +0 -393
  325. package/dist/resources/extensions/gsd/semantic-chunker.js +0 -254
  326. package/dist/resources/extensions/gsd/summary-distiller.js +0 -212
  327. package/src/resources/extensions/gsd/prompt-compressor.ts +0 -508
  328. package/src/resources/extensions/gsd/semantic-chunker.ts +0 -336
  329. package/src/resources/extensions/gsd/summary-distiller.ts +0 -258
  330. package/src/resources/extensions/gsd/tests/context-compression.test.ts +0 -193
  331. package/src/resources/extensions/gsd/tests/prompt-compressor.test.ts +0 -529
  332. package/src/resources/extensions/gsd/tests/semantic-chunker.test.ts +0 -426
  333. package/src/resources/extensions/gsd/tests/summary-distiller.test.ts +0 -323
  334. package/src/resources/extensions/gsd/tests/token-optimization-benchmark.test.ts +0 -1272
  335. package/src/resources/extensions/gsd/tests/token-optimization-prefs.test.ts +0 -164
@@ -0,0 +1,556 @@
1
+ /**
2
+ * Core GitHub sync engine.
3
+ *
4
+ * Entry point: `runGitHubSync()` — called from the GSD post-unit pipeline.
5
+ * Routes to per-event sync functions based on the unit type, reads GSD
6
+ * files to build GitHub entities, and persists the sync mapping.
7
+ *
8
+ * All errors are caught internally — sync failures never block execution.
9
+ */
10
+
11
+ import { existsSync, readdirSync } from "node:fs";
12
+ import { join } from "node:path";
13
+ import { loadFile, parseRoadmap, parsePlan, parseSummary } from "../gsd/files.js";
14
+ import {
15
+ resolveMilestoneFile,
16
+ resolveSliceFile,
17
+ resolveTaskFile,
18
+ } from "../gsd/paths.js";
19
+ import { debugLog } from "../gsd/debug-logger.js";
20
+ import { loadEffectiveGSDPreferences } from "../gsd/preferences.js";
21
+
22
+ import type { GitHubSyncConfig, SyncMapping } from "./types.js";
23
+ import {
24
+ loadSyncMapping,
25
+ saveSyncMapping,
26
+ createEmptyMapping,
27
+ getMilestoneRecord,
28
+ getSliceRecord,
29
+ getTaskRecord,
30
+ setMilestoneRecord,
31
+ setSliceRecord,
32
+ setTaskRecord,
33
+ } from "./mapping.js";
34
+ import {
35
+ ghIsAvailable,
36
+ ghHasRateLimit,
37
+ ghDetectRepo,
38
+ ghCreateIssue,
39
+ ghCloseIssue,
40
+ ghAddComment,
41
+ ghCreateMilestone,
42
+ ghCloseMilestone,
43
+ ghCreatePR,
44
+ ghMarkPRReady,
45
+ ghMergePR,
46
+ ghCreateBranch,
47
+ ghPushBranch,
48
+ ghAddToProject,
49
+ } from "./cli.js";
50
+ import {
51
+ formatMilestoneIssueBody,
52
+ formatSlicePRBody,
53
+ formatTaskIssueBody,
54
+ formatSummaryComment,
55
+ } from "./templates.js";
56
+
57
+ // ─── Entry Point ────────────────────────────────────────────────────────────
58
+
59
+ /**
60
+ * Main sync entry point — called from GSD post-unit pipeline.
61
+ * Routes to the appropriate sync function based on unit type.
62
+ */
63
+ export async function runGitHubSync(
64
+ basePath: string,
65
+ unitType: string,
66
+ unitId: string,
67
+ ): Promise<void> {
68
+ try {
69
+ const config = loadGitHubSyncConfig(basePath);
70
+ if (!config?.enabled) return;
71
+ if (!ghIsAvailable()) {
72
+ debugLog("github-sync", { skip: "gh CLI not available" });
73
+ return;
74
+ }
75
+
76
+ // Resolve repo
77
+ const repo = config.repo ?? resolveRepo(basePath);
78
+ if (!repo) {
79
+ debugLog("github-sync", { skip: "could not detect repo" });
80
+ return;
81
+ }
82
+
83
+ // Rate limit check
84
+ if (!ghHasRateLimit(basePath)) {
85
+ debugLog("github-sync", { skip: "rate limit low" });
86
+ return;
87
+ }
88
+
89
+ // Load or init mapping
90
+ let mapping = loadSyncMapping(basePath) ?? createEmptyMapping(repo);
91
+ mapping.repo = repo;
92
+
93
+ // Parse unit ID parts
94
+ const parts = unitId.split("/");
95
+ const [mid, sid, tid] = parts;
96
+
97
+ // Route by unit type
98
+ switch (unitType) {
99
+ case "plan-milestone":
100
+ if (mid) await syncMilestonePlan(basePath, mapping, config, mid);
101
+ break;
102
+ case "plan-slice":
103
+ case "research-slice":
104
+ if (mid && sid) await syncSlicePlan(basePath, mapping, config, mid, sid);
105
+ break;
106
+ case "execute-task":
107
+ case "reactive-execute":
108
+ if (mid && sid && tid) await syncTaskComplete(basePath, mapping, config, mid, sid, tid);
109
+ break;
110
+ case "complete-slice":
111
+ if (mid && sid) await syncSliceComplete(basePath, mapping, config, mid, sid);
112
+ break;
113
+ case "complete-milestone":
114
+ if (mid) await syncMilestoneComplete(basePath, mapping, config, mid);
115
+ break;
116
+ }
117
+
118
+ saveSyncMapping(basePath, mapping);
119
+ } catch (err) {
120
+ debugLog("github-sync", { error: String(err) });
121
+ }
122
+ }
123
+
124
+ // ─── Per-Event Sync Functions ───────────────────────────────────────────────
125
+
126
+ async function syncMilestonePlan(
127
+ basePath: string,
128
+ mapping: SyncMapping,
129
+ config: GitHubSyncConfig,
130
+ mid: string,
131
+ ): Promise<void> {
132
+ // Skip if already synced
133
+ if (getMilestoneRecord(mapping, mid)) return;
134
+
135
+ // Load roadmap data
136
+ const roadmapPath = resolveMilestoneFile(basePath, mid, "ROADMAP");
137
+ if (!roadmapPath) return;
138
+ const content = await loadFile(roadmapPath);
139
+ if (!content) return;
140
+
141
+ const roadmap = parseRoadmap(content);
142
+ const title = `${mid}: ${roadmap.title || "Milestone"}`;
143
+
144
+ // Create GitHub Milestone
145
+ const milestoneResult = ghCreateMilestone(
146
+ basePath,
147
+ mapping.repo,
148
+ title,
149
+ roadmap.vision || "",
150
+ );
151
+ if (!milestoneResult.ok) {
152
+ debugLog("github-sync", { phase: "create-milestone", error: milestoneResult.error });
153
+ return;
154
+ }
155
+ const ghMilestoneNumber = milestoneResult.data!;
156
+
157
+ // Create tracking issue
158
+ const issueBody = formatMilestoneIssueBody({
159
+ id: mid,
160
+ title: roadmap.title || "Milestone",
161
+ vision: roadmap.vision,
162
+ successCriteria: roadmap.successCriteria,
163
+ slices: roadmap.slices?.map(s => ({
164
+ id: s.id,
165
+ title: s.title,
166
+ })),
167
+ });
168
+
169
+ const issueResult = ghCreateIssue(basePath, {
170
+ repo: mapping.repo,
171
+ title: `${mid}: ${roadmap.title || "Milestone"} — Tracking`,
172
+ body: issueBody,
173
+ labels: config.labels,
174
+ milestone: ghMilestoneNumber,
175
+ });
176
+ if (!issueResult.ok) {
177
+ debugLog("github-sync", { phase: "create-tracking-issue", error: issueResult.error });
178
+ return;
179
+ }
180
+
181
+ // Add to project if configured
182
+ if (config.project) {
183
+ ghAddToProject(basePath, mapping.repo, config.project, issueResult.data!);
184
+ }
185
+
186
+ setMilestoneRecord(mapping, mid, {
187
+ issueNumber: issueResult.data!,
188
+ ghMilestoneNumber,
189
+ lastSyncedAt: new Date().toISOString(),
190
+ state: "open",
191
+ });
192
+
193
+ debugLog("github-sync", {
194
+ phase: "milestone-synced",
195
+ mid,
196
+ milestone: ghMilestoneNumber,
197
+ issue: issueResult.data,
198
+ });
199
+ }
200
+
201
+ async function syncSlicePlan(
202
+ basePath: string,
203
+ mapping: SyncMapping,
204
+ config: GitHubSyncConfig,
205
+ mid: string,
206
+ sid: string,
207
+ ): Promise<void> {
208
+ // Skip if already synced
209
+ if (getSliceRecord(mapping, mid, sid)) return;
210
+
211
+ // Ensure milestone is synced first
212
+ if (!getMilestoneRecord(mapping, mid)) {
213
+ await syncMilestonePlan(basePath, mapping, config, mid);
214
+ }
215
+ const milestoneRecord = getMilestoneRecord(mapping, mid);
216
+
217
+ // Load slice plan
218
+ const planPath = resolveSliceFile(basePath, mid, sid, "PLAN");
219
+ if (!planPath) return;
220
+ const content = await loadFile(planPath);
221
+ if (!content) return;
222
+
223
+ const plan = parsePlan(content);
224
+ const sliceBranch = `milestone/${mid}/${sid}`;
225
+ const milestoneBranch = `milestone/${mid}`;
226
+
227
+ // Create task sub-issues first (so we can link them in the PR body)
228
+ const taskIssueNumbers: Array<{ id: string; title: string; issueNumber?: number }> = [];
229
+
230
+ if (plan.tasks) {
231
+ for (const task of plan.tasks) {
232
+ // Skip if already synced
233
+ if (getTaskRecord(mapping, mid, sid, task.id)) {
234
+ const existing = getTaskRecord(mapping, mid, sid, task.id)!;
235
+ taskIssueNumbers.push({ id: task.id, title: task.title, issueNumber: existing.issueNumber });
236
+ continue;
237
+ }
238
+
239
+ const taskBody = formatTaskIssueBody({
240
+ id: task.id,
241
+ title: task.title,
242
+ description: task.description,
243
+ files: task.files,
244
+ verifyCriteria: task.verify ? [task.verify] : undefined,
245
+ });
246
+
247
+ const taskResult = ghCreateIssue(basePath, {
248
+ repo: mapping.repo,
249
+ title: `${mid}/${sid}/${task.id}: ${task.title}`,
250
+ body: taskBody,
251
+ labels: config.labels,
252
+ milestone: milestoneRecord?.ghMilestoneNumber,
253
+ parentIssue: milestoneRecord?.issueNumber,
254
+ });
255
+
256
+ if (taskResult.ok) {
257
+ setTaskRecord(mapping, mid, sid, task.id, {
258
+ issueNumber: taskResult.data!,
259
+ lastSyncedAt: new Date().toISOString(),
260
+ state: "open",
261
+ });
262
+ taskIssueNumbers.push({ id: task.id, title: task.title, issueNumber: taskResult.data! });
263
+
264
+ if (config.project) {
265
+ ghAddToProject(basePath, mapping.repo, config.project, taskResult.data!);
266
+ }
267
+ } else {
268
+ taskIssueNumbers.push({ id: task.id, title: task.title });
269
+ }
270
+ }
271
+ }
272
+
273
+ if (config.slice_prs === false) {
274
+ // Slice PRs disabled — just record without PR
275
+ setSliceRecord(mapping, mid, sid, {
276
+ issueNumber: 0,
277
+ prNumber: 0,
278
+ branch: sliceBranch,
279
+ lastSyncedAt: new Date().toISOString(),
280
+ state: "open",
281
+ });
282
+ return;
283
+ }
284
+
285
+ // Create slice branch from milestone branch
286
+ const branchResult = ghCreateBranch(basePath, sliceBranch, milestoneBranch);
287
+ if (!branchResult.ok) {
288
+ debugLog("github-sync", { phase: "create-slice-branch", error: branchResult.error });
289
+ // Branch might already exist — continue anyway
290
+ }
291
+
292
+ // Push the slice branch
293
+ const pushResult = ghPushBranch(basePath, sliceBranch);
294
+ if (!pushResult.ok) {
295
+ debugLog("github-sync", { phase: "push-slice-branch", error: pushResult.error });
296
+ }
297
+
298
+ // Create draft PR
299
+ const prBody = formatSlicePRBody({
300
+ id: sid,
301
+ title: plan.title || sid,
302
+ goal: plan.goal,
303
+ mustHaves: plan.mustHaves,
304
+ demoCriterion: plan.demo,
305
+ tasks: taskIssueNumbers,
306
+ });
307
+
308
+ const prResult = ghCreatePR(basePath, {
309
+ repo: mapping.repo,
310
+ base: milestoneBranch,
311
+ head: sliceBranch,
312
+ title: `${sid}: ${plan.title || sid}`,
313
+ body: prBody,
314
+ draft: true,
315
+ });
316
+
317
+ const prNumber = prResult.ok ? prResult.data! : 0;
318
+ if (!prResult.ok) {
319
+ debugLog("github-sync", { phase: "create-slice-pr", error: prResult.error });
320
+ }
321
+
322
+ setSliceRecord(mapping, mid, sid, {
323
+ issueNumber: 0, // Slice doesn't get its own issue — tracked via PR
324
+ prNumber,
325
+ branch: sliceBranch,
326
+ lastSyncedAt: new Date().toISOString(),
327
+ state: "open",
328
+ });
329
+
330
+ debugLog("github-sync", {
331
+ phase: "slice-synced",
332
+ mid,
333
+ sid,
334
+ pr: prNumber,
335
+ taskIssues: taskIssueNumbers.filter(t => t.issueNumber).length,
336
+ });
337
+ }
338
+
339
+ async function syncTaskComplete(
340
+ basePath: string,
341
+ mapping: SyncMapping,
342
+ config: GitHubSyncConfig,
343
+ mid: string,
344
+ sid: string,
345
+ tid: string,
346
+ ): Promise<void> {
347
+ const taskRecord = getTaskRecord(mapping, mid, sid, tid);
348
+ if (!taskRecord || taskRecord.state === "closed") return;
349
+
350
+ // Load task summary
351
+ const summaryPath = resolveTaskFile(basePath, mid, sid, tid, "SUMMARY");
352
+ if (summaryPath) {
353
+ const content = await loadFile(summaryPath);
354
+ if (content) {
355
+ const summary = parseSummary(content);
356
+ const comment = formatSummaryComment({
357
+ oneLiner: summary.oneLiner,
358
+ body: summary.whatHappened,
359
+ frontmatter: summary.frontmatter as unknown as Record<string, unknown>,
360
+ });
361
+ ghAddComment(basePath, mapping.repo, taskRecord.issueNumber, comment);
362
+ }
363
+ }
364
+
365
+ // Close the task issue
366
+ ghCloseIssue(basePath, mapping.repo, taskRecord.issueNumber);
367
+
368
+ taskRecord.state = "closed";
369
+ taskRecord.lastSyncedAt = new Date().toISOString();
370
+ setTaskRecord(mapping, mid, sid, tid, taskRecord);
371
+
372
+ debugLog("github-sync", { phase: "task-closed", mid, sid, tid, issue: taskRecord.issueNumber });
373
+ }
374
+
375
+ async function syncSliceComplete(
376
+ basePath: string,
377
+ mapping: SyncMapping,
378
+ config: GitHubSyncConfig,
379
+ mid: string,
380
+ sid: string,
381
+ ): Promise<void> {
382
+ const sliceRecord = getSliceRecord(mapping, mid, sid);
383
+ if (!sliceRecord || sliceRecord.state === "closed") return;
384
+
385
+ // Post slice summary as PR comment
386
+ const summaryPath = resolveSliceFile(basePath, mid, sid, "SUMMARY");
387
+ if (summaryPath && sliceRecord.prNumber) {
388
+ const content = await loadFile(summaryPath);
389
+ if (content) {
390
+ const summary = parseSummary(content);
391
+ const comment = formatSummaryComment({
392
+ oneLiner: summary.oneLiner,
393
+ body: summary.whatHappened,
394
+ frontmatter: summary.frontmatter as unknown as Record<string, unknown>,
395
+ });
396
+ ghAddComment(basePath, mapping.repo, sliceRecord.prNumber, comment);
397
+ }
398
+ }
399
+
400
+ // Mark PR ready for review, then merge
401
+ if (sliceRecord.prNumber) {
402
+ ghMarkPRReady(basePath, mapping.repo, sliceRecord.prNumber);
403
+ // Squash-merge into milestone branch
404
+ ghMergePR(basePath, mapping.repo, sliceRecord.prNumber, "squash");
405
+ }
406
+
407
+ sliceRecord.state = "closed";
408
+ sliceRecord.lastSyncedAt = new Date().toISOString();
409
+ setSliceRecord(mapping, mid, sid, sliceRecord);
410
+
411
+ debugLog("github-sync", { phase: "slice-completed", mid, sid, pr: sliceRecord.prNumber });
412
+ }
413
+
414
+ async function syncMilestoneComplete(
415
+ basePath: string,
416
+ mapping: SyncMapping,
417
+ config: GitHubSyncConfig,
418
+ mid: string,
419
+ ): Promise<void> {
420
+ const record = getMilestoneRecord(mapping, mid);
421
+ if (!record || record.state === "closed") return;
422
+
423
+ // Close tracking issue
424
+ ghCloseIssue(
425
+ basePath,
426
+ mapping.repo,
427
+ record.issueNumber,
428
+ `Milestone ${mid} completed.`,
429
+ );
430
+
431
+ // Close GitHub milestone
432
+ ghCloseMilestone(basePath, mapping.repo, record.ghMilestoneNumber);
433
+
434
+ record.state = "closed";
435
+ record.lastSyncedAt = new Date().toISOString();
436
+ setMilestoneRecord(mapping, mid, record);
437
+
438
+ debugLog("github-sync", { phase: "milestone-completed", mid });
439
+ }
440
+
441
+ // ─── Bootstrap ──────────────────────────────────────────────────────────────
442
+
443
+ /**
444
+ * Walk the `.gsd/milestones/` tree and create GitHub entities for any
445
+ * that are missing from the sync mapping. Safe to run multiple times.
446
+ */
447
+ export async function bootstrapSync(basePath: string): Promise<{
448
+ milestones: number;
449
+ slices: number;
450
+ tasks: number;
451
+ }> {
452
+ const config = loadGitHubSyncConfig(basePath);
453
+ if (!config?.enabled) return { milestones: 0, slices: 0, tasks: 0 };
454
+ if (!ghIsAvailable()) return { milestones: 0, slices: 0, tasks: 0 };
455
+
456
+ const repo = config.repo ?? resolveRepo(basePath);
457
+ if (!repo) return { milestones: 0, slices: 0, tasks: 0 };
458
+
459
+ let mapping = loadSyncMapping(basePath) ?? createEmptyMapping(repo);
460
+ mapping.repo = repo;
461
+
462
+ const taskCountBefore = Object.keys(mapping.tasks).length;
463
+ const counts = { milestones: 0, slices: 0, tasks: 0 };
464
+ const milestonesDir = join(basePath, ".gsd", "milestones");
465
+ if (!existsSync(milestonesDir)) return counts;
466
+
467
+ const milestoneIds = readdirSync(milestonesDir, { withFileTypes: true })
468
+ .filter(d => d.isDirectory())
469
+ .map(d => d.name)
470
+ .sort();
471
+
472
+ for (const mid of milestoneIds) {
473
+ if (!getMilestoneRecord(mapping, mid)) {
474
+ await syncMilestonePlan(basePath, mapping, config, mid);
475
+ counts.milestones++;
476
+ }
477
+
478
+ // Find slices
479
+ const slicesDir = join(milestonesDir, mid, "slices");
480
+ if (!existsSync(slicesDir)) continue;
481
+
482
+ const sliceIds = readdirSync(slicesDir, { withFileTypes: true })
483
+ .filter(d => d.isDirectory())
484
+ .map(d => d.name)
485
+ .sort();
486
+
487
+ for (const sid of sliceIds) {
488
+ if (!getSliceRecord(mapping, mid, sid)) {
489
+ await syncSlicePlan(basePath, mapping, config, mid, sid);
490
+ counts.slices++;
491
+ }
492
+ }
493
+ }
494
+
495
+ counts.tasks = Object.keys(mapping.tasks).length - taskCountBefore;
496
+ saveSyncMapping(basePath, mapping);
497
+ return counts;
498
+ }
499
+
500
+ // ─── Config Loading ─────────────────────────────────────────────────────────
501
+
502
+ let _cachedConfig: GitHubSyncConfig | null | undefined;
503
+
504
+ function loadGitHubSyncConfig(_basePath: string): GitHubSyncConfig | null {
505
+ if (_cachedConfig !== undefined) return _cachedConfig;
506
+ try {
507
+ const prefs = loadEffectiveGSDPreferences();
508
+ const github = (prefs?.preferences as Record<string, unknown>)?.github;
509
+ if (!github || typeof github !== "object") {
510
+ _cachedConfig = null;
511
+ return null;
512
+ }
513
+ _cachedConfig = github as GitHubSyncConfig;
514
+ return _cachedConfig;
515
+ } catch {
516
+ _cachedConfig = null;
517
+ return null;
518
+ }
519
+ }
520
+
521
+ /** Reset config cache (for testing). */
522
+ export function _resetConfigCache(): void {
523
+ _cachedConfig = undefined;
524
+ }
525
+
526
+ function resolveRepo(basePath: string): string | null {
527
+ const result = ghDetectRepo(basePath);
528
+ return result.ok ? result.data! : null;
529
+ }
530
+
531
+ // ─── Commit Linking ─────────────────────────────────────────────────────────
532
+
533
+ /**
534
+ * Look up the GitHub issue number for a task so the commit message
535
+ * can include `Resolves #N`. Called from git-service commit building.
536
+ */
537
+ export function getTaskIssueNumberForCommit(
538
+ basePath: string,
539
+ mid: string,
540
+ sid: string,
541
+ tid: string,
542
+ ): number | null {
543
+ try {
544
+ const config = loadGitHubSyncConfig(basePath);
545
+ if (!config?.enabled) return null;
546
+ if (config.auto_link_commits === false) return null;
547
+
548
+ const mapping = loadSyncMapping(basePath);
549
+ if (!mapping) return null;
550
+
551
+ const record = getTaskRecord(mapping, mid, sid, tid);
552
+ return record?.issueNumber ?? null;
553
+ } catch {
554
+ return null;
555
+ }
556
+ }