gsd-pi 2.10.12 → 2.12.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 (504) hide show
  1. package/dist/bundled-extension-paths.d.ts +2 -0
  2. package/dist/bundled-extension-paths.js +10 -0
  3. package/dist/loader.js +45 -28
  4. package/dist/onboarding.js +100 -0
  5. package/dist/resource-loader.js +12 -3
  6. package/dist/resources/GSD-WORKFLOW.md +661 -0
  7. package/dist/resources/agents/researcher.md +29 -0
  8. package/dist/resources/agents/scout.md +56 -0
  9. package/dist/resources/agents/worker.md +31 -0
  10. package/dist/resources/extensions/ask-user-questions.ts +289 -0
  11. package/dist/resources/extensions/async-jobs/async-bash-tool.ts +211 -0
  12. package/dist/resources/extensions/async-jobs/await-tool.ts +101 -0
  13. package/dist/resources/extensions/async-jobs/cancel-job-tool.ts +34 -0
  14. package/dist/resources/extensions/async-jobs/index.ts +133 -0
  15. package/dist/resources/extensions/async-jobs/job-manager.ts +211 -0
  16. package/dist/resources/extensions/bg-shell/index.ts +3179 -0
  17. package/dist/resources/extensions/browser-tools/BROWSER-TOOLS-V2-PROPOSAL.md +1277 -0
  18. package/dist/resources/extensions/browser-tools/capture.ts +165 -0
  19. package/dist/resources/extensions/browser-tools/core.d.ts +205 -0
  20. package/dist/resources/extensions/browser-tools/core.js +1057 -0
  21. package/dist/resources/extensions/browser-tools/evaluate-helpers.ts +184 -0
  22. package/dist/resources/extensions/browser-tools/index.ts +51 -0
  23. package/dist/resources/extensions/browser-tools/lifecycle.ts +270 -0
  24. package/dist/resources/extensions/browser-tools/package.json +24 -0
  25. package/dist/resources/extensions/browser-tools/refs.ts +264 -0
  26. package/dist/resources/extensions/browser-tools/settle.ts +197 -0
  27. package/dist/resources/extensions/browser-tools/state.ts +408 -0
  28. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +652 -0
  29. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +614 -0
  30. package/dist/resources/extensions/browser-tools/tools/assertions.ts +342 -0
  31. package/dist/resources/extensions/browser-tools/tools/forms.ts +801 -0
  32. package/dist/resources/extensions/browser-tools/tools/inspection.ts +492 -0
  33. package/dist/resources/extensions/browser-tools/tools/intent.ts +614 -0
  34. package/dist/resources/extensions/browser-tools/tools/interaction.ts +865 -0
  35. package/dist/resources/extensions/browser-tools/tools/navigation.ts +232 -0
  36. package/dist/resources/extensions/browser-tools/tools/pages.ts +303 -0
  37. package/dist/resources/extensions/browser-tools/tools/refs.ts +541 -0
  38. package/dist/resources/extensions/browser-tools/tools/screenshot.ts +83 -0
  39. package/dist/resources/extensions/browser-tools/tools/session.ts +400 -0
  40. package/dist/resources/extensions/browser-tools/tools/wait.ts +247 -0
  41. package/dist/resources/extensions/browser-tools/utils.ts +660 -0
  42. package/dist/resources/extensions/context7/index.ts +428 -0
  43. package/dist/resources/extensions/context7/package.json +11 -0
  44. package/dist/resources/extensions/get-secrets-from-user.ts +625 -0
  45. package/dist/resources/extensions/google-search/index.ts +336 -0
  46. package/dist/resources/extensions/google-search/package.json +9 -0
  47. package/dist/resources/extensions/gsd/activity-log.ts +116 -0
  48. package/dist/resources/extensions/gsd/auto.ts +3732 -0
  49. package/dist/resources/extensions/gsd/commands.ts +544 -0
  50. package/dist/resources/extensions/gsd/crash-recovery.ts +105 -0
  51. package/dist/resources/extensions/gsd/dashboard-overlay.ts +564 -0
  52. package/dist/resources/extensions/gsd/dispatch-guard.ts +78 -0
  53. package/dist/resources/extensions/gsd/docs/preferences-reference.md +278 -0
  54. package/dist/resources/extensions/gsd/doctor.ts +766 -0
  55. package/dist/resources/extensions/gsd/exit-command.ts +18 -0
  56. package/dist/resources/extensions/gsd/files.ts +857 -0
  57. package/dist/resources/extensions/gsd/git-service.ts +904 -0
  58. package/dist/resources/extensions/gsd/gitignore.ts +200 -0
  59. package/dist/resources/extensions/gsd/guided-flow.ts +1054 -0
  60. package/dist/resources/extensions/gsd/index.ts +735 -0
  61. package/dist/resources/extensions/gsd/metrics.ts +374 -0
  62. package/dist/resources/extensions/gsd/migrate/command.ts +218 -0
  63. package/dist/resources/extensions/gsd/migrate/index.ts +42 -0
  64. package/dist/resources/extensions/gsd/migrate/parser.ts +323 -0
  65. package/dist/resources/extensions/gsd/migrate/parsers.ts +624 -0
  66. package/dist/resources/extensions/gsd/migrate/preview.ts +48 -0
  67. package/dist/resources/extensions/gsd/migrate/transformer.ts +346 -0
  68. package/dist/resources/extensions/gsd/migrate/types.ts +370 -0
  69. package/dist/resources/extensions/gsd/migrate/validator.ts +55 -0
  70. package/dist/resources/extensions/gsd/migrate/writer.ts +539 -0
  71. package/dist/resources/extensions/gsd/native-git-bridge.ts +181 -0
  72. package/dist/resources/extensions/gsd/native-parser-bridge.ts +135 -0
  73. package/dist/resources/extensions/gsd/observability-validator.ts +408 -0
  74. package/dist/resources/extensions/gsd/package.json +11 -0
  75. package/dist/resources/extensions/gsd/paths.ts +339 -0
  76. package/dist/resources/extensions/gsd/post-unit-hooks.ts +449 -0
  77. package/dist/resources/extensions/gsd/preferences.ts +988 -0
  78. package/dist/resources/extensions/gsd/prompt-loader.ts +92 -0
  79. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +25 -0
  80. package/dist/resources/extensions/gsd/prompts/complete-slice.md +27 -0
  81. package/dist/resources/extensions/gsd/prompts/discuss.md +237 -0
  82. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +29 -0
  83. package/dist/resources/extensions/gsd/prompts/execute-task.md +63 -0
  84. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +3 -0
  85. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -0
  86. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +61 -0
  87. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +3 -0
  88. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +29 -0
  89. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +3 -0
  90. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +13 -0
  91. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -0
  92. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +78 -0
  93. package/dist/resources/extensions/gsd/prompts/plan-slice.md +55 -0
  94. package/dist/resources/extensions/gsd/prompts/queue.md +100 -0
  95. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +48 -0
  96. package/dist/resources/extensions/gsd/prompts/replan-slice.md +39 -0
  97. package/dist/resources/extensions/gsd/prompts/research-milestone.md +37 -0
  98. package/dist/resources/extensions/gsd/prompts/research-slice.md +28 -0
  99. package/dist/resources/extensions/gsd/prompts/review-migration.md +66 -0
  100. package/dist/resources/extensions/gsd/prompts/run-uat.md +109 -0
  101. package/dist/resources/extensions/gsd/prompts/system.md +190 -0
  102. package/dist/resources/extensions/gsd/prompts/worktree-merge.md +123 -0
  103. package/dist/resources/extensions/gsd/roadmap-slices.ts +50 -0
  104. package/dist/resources/extensions/gsd/session-forensics.ts +500 -0
  105. package/dist/resources/extensions/gsd/skill-discovery.ts +137 -0
  106. package/dist/resources/extensions/gsd/state.ts +569 -0
  107. package/dist/resources/extensions/gsd/templates/context.md +76 -0
  108. package/dist/resources/extensions/gsd/templates/decisions.md +8 -0
  109. package/dist/resources/extensions/gsd/templates/milestone-summary.md +73 -0
  110. package/dist/resources/extensions/gsd/templates/plan.md +131 -0
  111. package/dist/resources/extensions/gsd/templates/preferences.md +23 -0
  112. package/dist/resources/extensions/gsd/templates/project.md +31 -0
  113. package/dist/resources/extensions/gsd/templates/reassessment.md +28 -0
  114. package/dist/resources/extensions/gsd/templates/requirements.md +81 -0
  115. package/dist/resources/extensions/gsd/templates/research.md +46 -0
  116. package/dist/resources/extensions/gsd/templates/roadmap.md +118 -0
  117. package/dist/resources/extensions/gsd/templates/secrets-manifest.md +22 -0
  118. package/dist/resources/extensions/gsd/templates/slice-context.md +58 -0
  119. package/dist/resources/extensions/gsd/templates/slice-summary.md +99 -0
  120. package/dist/resources/extensions/gsd/templates/state.md +19 -0
  121. package/dist/resources/extensions/gsd/templates/task-plan.md +52 -0
  122. package/dist/resources/extensions/gsd/templates/task-summary.md +57 -0
  123. package/dist/resources/extensions/gsd/templates/uat.md +54 -0
  124. package/dist/resources/extensions/gsd/tests/activity-log-prune.test.ts +297 -0
  125. package/dist/resources/extensions/gsd/tests/activity-log-save.test.ts +127 -0
  126. package/dist/resources/extensions/gsd/tests/auto-draft-pause.test.ts +109 -0
  127. package/dist/resources/extensions/gsd/tests/auto-preflight.test.ts +45 -0
  128. package/dist/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +196 -0
  129. package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +53 -0
  130. package/dist/resources/extensions/gsd/tests/collect-from-manifest.test.ts +469 -0
  131. package/dist/resources/extensions/gsd/tests/complete-milestone.test.ts +200 -0
  132. package/dist/resources/extensions/gsd/tests/cost-projection.test.ts +134 -0
  133. package/dist/resources/extensions/gsd/tests/derive-state-deps.test.ts +312 -0
  134. package/dist/resources/extensions/gsd/tests/derive-state-draft.test.ts +299 -0
  135. package/dist/resources/extensions/gsd/tests/derive-state.test.ts +660 -0
  136. package/dist/resources/extensions/gsd/tests/discuss-prompt.test.ts +27 -0
  137. package/dist/resources/extensions/gsd/tests/dispatch-guard.test.ts +91 -0
  138. package/dist/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +170 -0
  139. package/dist/resources/extensions/gsd/tests/doctor.test.ts +594 -0
  140. package/dist/resources/extensions/gsd/tests/draft-promotion.test.ts +169 -0
  141. package/dist/resources/extensions/gsd/tests/exit-command.test.ts +50 -0
  142. package/dist/resources/extensions/gsd/tests/git-service.test.ts +1788 -0
  143. package/dist/resources/extensions/gsd/tests/idle-recovery.test.ts +577 -0
  144. package/dist/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +580 -0
  145. package/dist/resources/extensions/gsd/tests/manifest-status.test.ts +283 -0
  146. package/dist/resources/extensions/gsd/tests/metrics-io.test.ts +176 -0
  147. package/dist/resources/extensions/gsd/tests/metrics.test.ts +188 -0
  148. package/dist/resources/extensions/gsd/tests/migrate-command.test.ts +369 -0
  149. package/dist/resources/extensions/gsd/tests/migrate-parser.test.ts +757 -0
  150. package/dist/resources/extensions/gsd/tests/migrate-transformer.test.ts +635 -0
  151. package/dist/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +414 -0
  152. package/dist/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +297 -0
  153. package/dist/resources/extensions/gsd/tests/migrate-writer.test.ts +398 -0
  154. package/dist/resources/extensions/gsd/tests/must-have-parser.test.ts +291 -0
  155. package/dist/resources/extensions/gsd/tests/network-error-fallback.test.ts +54 -0
  156. package/dist/resources/extensions/gsd/tests/next-milestone-id.test.ts +66 -0
  157. package/dist/resources/extensions/gsd/tests/orphaned-branch.test.ts +353 -0
  158. package/dist/resources/extensions/gsd/tests/parsers.test.ts +1664 -0
  159. package/dist/resources/extensions/gsd/tests/plan-milestone.test.ts +133 -0
  160. package/dist/resources/extensions/gsd/tests/plan-quality-validator.test.ts +363 -0
  161. package/dist/resources/extensions/gsd/tests/post-unit-hooks.test.ts +297 -0
  162. package/dist/resources/extensions/gsd/tests/preferences-hooks.test.ts +226 -0
  163. package/dist/resources/extensions/gsd/tests/queue-draft-detection.test.ts +126 -0
  164. package/dist/resources/extensions/gsd/tests/reassess-prompt.test.ts +142 -0
  165. package/dist/resources/extensions/gsd/tests/regex-hardening.test.ts +281 -0
  166. package/dist/resources/extensions/gsd/tests/remote-questions.test.ts +155 -0
  167. package/dist/resources/extensions/gsd/tests/remote-status.test.ts +99 -0
  168. package/dist/resources/extensions/gsd/tests/replan-slice.test.ts +493 -0
  169. package/dist/resources/extensions/gsd/tests/requirements.test.ts +106 -0
  170. package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +35 -0
  171. package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +11 -0
  172. package/dist/resources/extensions/gsd/tests/roadmap-slices.test.ts +41 -0
  173. package/dist/resources/extensions/gsd/tests/run-uat.test.ts +316 -0
  174. package/dist/resources/extensions/gsd/tests/secure-env-collect.test.ts +185 -0
  175. package/dist/resources/extensions/gsd/tests/smart-entry-draft.test.ts +123 -0
  176. package/dist/resources/extensions/gsd/tests/test-helpers.ts +61 -0
  177. package/dist/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +219 -0
  178. package/dist/resources/extensions/gsd/tests/unit-runtime.test.ts +234 -0
  179. package/dist/resources/extensions/gsd/tests/workspace-index.test.ts +75 -0
  180. package/dist/resources/extensions/gsd/tests/worktree-integration.test.ts +234 -0
  181. package/dist/resources/extensions/gsd/tests/worktree-manager.test.ts +141 -0
  182. package/dist/resources/extensions/gsd/tests/worktree.test.ts +597 -0
  183. package/dist/resources/extensions/gsd/tests/write-gate.test.ts +122 -0
  184. package/dist/resources/extensions/gsd/types.ts +296 -0
  185. package/dist/resources/extensions/gsd/unit-runtime.ts +184 -0
  186. package/dist/resources/extensions/gsd/workspace-index.ts +189 -0
  187. package/dist/resources/extensions/gsd/worktree-command.ts +845 -0
  188. package/dist/resources/extensions/gsd/worktree-manager.ts +459 -0
  189. package/dist/resources/extensions/gsd/{worktree.js → worktree.ts} +92 -61
  190. package/dist/resources/extensions/mac-tools/index.ts +852 -0
  191. package/dist/resources/extensions/mac-tools/swift-cli/Package.swift +22 -0
  192. package/dist/resources/extensions/mac-tools/swift-cli/Sources/main.swift +1318 -0
  193. package/dist/resources/extensions/mcporter/index.ts +429 -0
  194. package/dist/resources/extensions/remote-questions/config.ts +81 -0
  195. package/dist/resources/extensions/remote-questions/discord-adapter.ts +128 -0
  196. package/dist/resources/extensions/remote-questions/format.ts +163 -0
  197. package/dist/resources/extensions/remote-questions/manager.ts +192 -0
  198. package/dist/resources/extensions/remote-questions/remote-command.ts +361 -0
  199. package/dist/resources/extensions/remote-questions/slack-adapter.ts +92 -0
  200. package/dist/resources/extensions/remote-questions/status.ts +31 -0
  201. package/dist/resources/extensions/remote-questions/store.ts +77 -0
  202. package/dist/resources/extensions/remote-questions/types.ts +75 -0
  203. package/dist/resources/extensions/search-the-web/cache.ts +78 -0
  204. package/dist/resources/extensions/search-the-web/command-search-provider.ts +99 -0
  205. package/dist/resources/extensions/search-the-web/format.ts +258 -0
  206. package/dist/resources/extensions/search-the-web/http.ts +238 -0
  207. package/dist/resources/extensions/search-the-web/index.ts +65 -0
  208. package/dist/resources/extensions/search-the-web/native-search.ts +165 -0
  209. package/dist/resources/extensions/search-the-web/provider.ts +136 -0
  210. package/dist/resources/extensions/search-the-web/tavily.ts +116 -0
  211. package/dist/resources/extensions/search-the-web/tool-fetch-page.ts +581 -0
  212. package/dist/resources/extensions/search-the-web/tool-llm-context.ts +620 -0
  213. package/dist/resources/extensions/search-the-web/tool-search.ts +635 -0
  214. package/dist/resources/extensions/search-the-web/url-utils.ts +91 -0
  215. package/dist/resources/extensions/shared/bundled-extension-paths.ts +11 -0
  216. package/dist/resources/extensions/shared/confirm-ui.ts +126 -0
  217. package/dist/resources/extensions/shared/interview-ui.ts +613 -0
  218. package/dist/resources/extensions/shared/next-action-ui.ts +197 -0
  219. package/dist/resources/extensions/shared/progress-widget.ts +282 -0
  220. package/dist/resources/extensions/shared/terminal.ts +23 -0
  221. package/dist/resources/extensions/shared/thinking-widget.ts +107 -0
  222. package/dist/resources/extensions/shared/ui.ts +400 -0
  223. package/dist/resources/extensions/shared/wizard-ui.ts +551 -0
  224. package/dist/resources/extensions/slash-commands/audit.ts +88 -0
  225. package/dist/resources/extensions/slash-commands/clear.ts +10 -0
  226. package/dist/resources/extensions/slash-commands/create-extension.ts +297 -0
  227. package/dist/resources/extensions/slash-commands/create-slash-command.ts +234 -0
  228. package/dist/resources/extensions/slash-commands/index.ts +12 -0
  229. package/dist/resources/extensions/subagent/agents.ts +126 -0
  230. package/dist/resources/extensions/subagent/index.ts +1072 -0
  231. package/dist/resources/extensions/subagent/isolation.ts +498 -0
  232. package/dist/resources/extensions/ttsr/index.ts +163 -0
  233. package/dist/resources/extensions/ttsr/rule-loader.ts +121 -0
  234. package/dist/resources/extensions/ttsr/ttsr-interrupt.md +6 -0
  235. package/dist/resources/extensions/ttsr/ttsr-manager.ts +430 -0
  236. package/dist/resources/extensions/universal-config/discovery.ts +78 -0
  237. package/dist/resources/extensions/universal-config/format.ts +160 -0
  238. package/dist/resources/extensions/universal-config/index.ts +118 -0
  239. package/dist/resources/extensions/universal-config/package.json +11 -0
  240. package/dist/resources/extensions/universal-config/scanners.ts +579 -0
  241. package/dist/resources/extensions/universal-config/tests/discovery.test.ts +111 -0
  242. package/dist/resources/extensions/universal-config/tests/format.test.ts +111 -0
  243. package/dist/resources/extensions/universal-config/tests/scanners.test.ts +438 -0
  244. package/dist/resources/extensions/universal-config/tools.ts +60 -0
  245. package/dist/resources/extensions/universal-config/types.ts +116 -0
  246. package/dist/resources/extensions/voice/index.ts +271 -0
  247. package/dist/resources/extensions/voice/speech-recognizer.py +504 -0
  248. package/dist/resources/extensions/voice/speech-recognizer.swift +154 -0
  249. package/dist/resources/skills/debug-like-expert/SKILL.md +231 -0
  250. package/dist/resources/skills/debug-like-expert/references/debugging-mindset.md +253 -0
  251. package/dist/resources/skills/debug-like-expert/references/hypothesis-testing.md +373 -0
  252. package/dist/resources/skills/debug-like-expert/references/investigation-techniques.md +337 -0
  253. package/dist/resources/skills/debug-like-expert/references/verification-patterns.md +425 -0
  254. package/dist/resources/skills/debug-like-expert/references/when-to-research.md +361 -0
  255. package/dist/resources/skills/frontend-design/SKILL.md +45 -0
  256. package/dist/resources/skills/github-workflows/SKILL.md +92 -0
  257. package/dist/resources/skills/github-workflows/references/gh/SKILL.md +255 -0
  258. package/dist/resources/skills/github-workflows/references/gh/references/issue-stories.md +204 -0
  259. package/dist/resources/skills/github-workflows/references/gh/references/labels.md +170 -0
  260. package/dist/resources/skills/github-workflows/references/gh/references/milestones.md +158 -0
  261. package/dist/resources/skills/github-workflows/references/gh/references/projects-v2.md +177 -0
  262. package/dist/resources/skills/github-workflows/references/gh/scripts/experiment_cleanup.py +191 -0
  263. package/dist/resources/skills/github-workflows/references/gh/scripts/github_project_setup.py +799 -0
  264. package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
  265. package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +608 -0
  266. package/dist/resources/skills/swiftui/SKILL.md +208 -0
  267. package/dist/resources/skills/swiftui/references/animations.md +921 -0
  268. package/dist/resources/skills/swiftui/references/architecture.md +1561 -0
  269. package/dist/resources/skills/swiftui/references/layout-system.md +1186 -0
  270. package/dist/resources/skills/swiftui/references/navigation.md +1492 -0
  271. package/dist/resources/skills/swiftui/references/networking-async.md +214 -0
  272. package/dist/resources/skills/swiftui/references/performance.md +1706 -0
  273. package/dist/resources/skills/swiftui/references/platform-integration.md +204 -0
  274. package/dist/resources/skills/swiftui/references/state-management.md +1443 -0
  275. package/dist/resources/skills/swiftui/references/swiftdata.md +297 -0
  276. package/dist/resources/skills/swiftui/references/testing-debugging.md +247 -0
  277. package/dist/resources/skills/swiftui/references/uikit-appkit-interop.md +218 -0
  278. package/dist/resources/skills/swiftui/workflows/add-feature.md +191 -0
  279. package/dist/resources/skills/swiftui/workflows/build-new-app.md +311 -0
  280. package/dist/resources/skills/swiftui/workflows/debug-swiftui.md +192 -0
  281. package/dist/resources/skills/swiftui/workflows/optimize-performance.md +197 -0
  282. package/dist/resources/skills/swiftui/workflows/ship-app.md +203 -0
  283. package/dist/resources/skills/swiftui/workflows/write-tests.md +235 -0
  284. package/dist/wizard.js +1 -0
  285. package/package.json +8 -6
  286. package/packages/native/dist/fd/index.d.ts +1 -0
  287. package/packages/native/dist/fd/index.js +1 -0
  288. package/packages/native/dist/grep/index.d.ts +2 -1
  289. package/packages/native/dist/grep/index.js +1 -0
  290. package/packages/native/src/__tests__/fd.test.mjs +35 -0
  291. package/packages/native/src/__tests__/grep.test.mjs +26 -9
  292. package/packages/native/src/fd/index.ts +1 -0
  293. package/packages/native/src/grep/index.ts +3 -2
  294. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  295. package/packages/pi-agent-core/dist/agent-loop.js +169 -55
  296. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  297. package/packages/pi-agent-core/dist/agent.d.ts +13 -1
  298. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  299. package/packages/pi-agent-core/dist/agent.js +16 -0
  300. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  301. package/packages/pi-agent-core/dist/types.d.ts +91 -1
  302. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  303. package/packages/pi-agent-core/dist/types.js.map +1 -1
  304. package/packages/pi-agent-core/src/agent-loop.ts +273 -63
  305. package/packages/pi-agent-core/src/agent.ts +24 -0
  306. package/packages/pi-agent-core/src/types.ts +98 -0
  307. package/packages/pi-ai/dist/env-api-keys.js +2 -0
  308. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  309. package/packages/pi-ai/dist/models.generated.d.ts +314 -0
  310. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  311. package/packages/pi-ai/dist/models.generated.js +236 -0
  312. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  313. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  314. package/packages/pi-ai/dist/providers/google-gemini-cli.js +6 -0
  315. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  316. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  317. package/packages/pi-ai/dist/providers/openai-completions.js +2 -0
  318. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  319. package/packages/pi-ai/dist/types.d.ts +1 -1
  320. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  321. package/packages/pi-ai/dist/types.js.map +1 -1
  322. package/packages/pi-ai/src/env-api-keys.ts +2 -0
  323. package/packages/pi-ai/src/models.generated.ts +236 -0
  324. package/packages/pi-ai/src/providers/google-gemini-cli.ts +8 -0
  325. package/packages/pi-ai/src/providers/openai-completions.ts +3 -0
  326. package/packages/pi-ai/src/types.ts +2 -1
  327. package/packages/pi-coding-agent/dist/cli/args.d.ts.map +1 -1
  328. package/packages/pi-coding-agent/dist/cli/args.js +1 -0
  329. package/packages/pi-coding-agent/dist/cli/args.js.map +1 -1
  330. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +26 -0
  331. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  332. package/packages/pi-coding-agent/dist/core/agent-session.js +137 -22
  333. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  334. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +20 -0
  335. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  336. package/packages/pi-coding-agent/dist/core/auth-storage.js +43 -0
  337. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  338. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts +51 -0
  339. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -0
  340. package/packages/pi-coding-agent/dist/core/fallback-resolver.js +119 -0
  341. package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -0
  342. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.d.ts +2 -0
  343. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.d.ts.map +1 -0
  344. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +183 -0
  345. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -0
  346. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
  347. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/index.js +1 -0
  349. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  351. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  352. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  353. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +12 -1
  354. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  355. package/packages/pi-coding-agent/dist/core/session-manager.js +37 -1
  356. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  357. package/packages/pi-coding-agent/dist/core/session-manager.test.d.ts +2 -0
  358. package/packages/pi-coding-agent/dist/core/session-manager.test.d.ts.map +1 -0
  359. package/packages/pi-coding-agent/dist/core/session-manager.test.js +61 -0
  360. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -0
  361. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +20 -0
  362. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  363. package/packages/pi-coding-agent/dist/core/settings-manager.js +47 -0
  364. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  365. package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
  366. package/packages/pi-coding-agent/dist/core/tools/find.js +1 -0
  367. package/packages/pi-coding-agent/dist/core/tools/find.js.map +1 -1
  368. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +6 -15
  370. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +18 -1
  372. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  373. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +46 -4
  374. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  375. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  376. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +25 -2
  377. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  378. package/packages/pi-coding-agent/src/cli/args.ts +1 -0
  379. package/packages/pi-coding-agent/src/core/agent-session.ts +167 -22
  380. package/packages/pi-coding-agent/src/core/auth-storage.ts +45 -0
  381. package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +229 -0
  382. package/packages/pi-coding-agent/src/core/fallback-resolver.ts +165 -0
  383. package/packages/pi-coding-agent/src/core/index.ts +1 -0
  384. package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
  385. package/packages/pi-coding-agent/src/core/session-manager.test.ts +65 -0
  386. package/packages/pi-coding-agent/src/core/session-manager.ts +51 -1
  387. package/packages/pi-coding-agent/src/core/settings-manager.ts +66 -0
  388. package/packages/pi-coding-agent/src/core/tools/find.ts +1 -0
  389. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +6 -16
  390. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +49 -4
  391. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +28 -2
  392. package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
  393. package/packages/pi-tui/dist/autocomplete.js +3 -4
  394. package/packages/pi-tui/dist/autocomplete.js.map +1 -1
  395. package/packages/pi-tui/dist/components/editor.d.ts +7 -0
  396. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  397. package/packages/pi-tui/dist/components/editor.js +57 -50
  398. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  399. package/packages/pi-tui/src/autocomplete.ts +3 -5
  400. package/packages/pi-tui/src/components/editor.ts +70 -49
  401. package/pkg/dist/core/export-html/ansi-to-html.d.ts +22 -0
  402. package/pkg/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
  403. package/pkg/dist/core/export-html/ansi-to-html.js +249 -0
  404. package/pkg/dist/core/export-html/ansi-to-html.js.map +1 -0
  405. package/pkg/dist/core/export-html/index.d.ts +37 -0
  406. package/pkg/dist/core/export-html/index.d.ts.map +1 -0
  407. package/pkg/dist/core/export-html/index.js +223 -0
  408. package/pkg/dist/core/export-html/index.js.map +1 -0
  409. package/pkg/dist/core/export-html/template.css +971 -0
  410. package/pkg/dist/core/export-html/template.html +54 -0
  411. package/pkg/dist/core/export-html/template.js +1583 -0
  412. package/pkg/dist/core/export-html/tool-renderer.d.ts +38 -0
  413. package/pkg/dist/core/export-html/tool-renderer.d.ts.map +1 -0
  414. package/pkg/dist/core/export-html/tool-renderer.js +70 -0
  415. package/pkg/dist/core/export-html/tool-renderer.js.map +1 -0
  416. package/pkg/dist/core/export-html/vendor/highlight.min.js +1213 -0
  417. package/pkg/dist/core/export-html/vendor/marked.min.js +6 -0
  418. package/scripts/postinstall.js +30 -17
  419. package/src/resources/extensions/bg-shell/index.ts +51 -7
  420. package/src/resources/extensions/gsd/activity-log.ts +61 -14
  421. package/src/resources/extensions/gsd/auto.ts +288 -19
  422. package/src/resources/extensions/gsd/commands.ts +9 -3
  423. package/src/resources/extensions/gsd/dashboard-overlay.ts +55 -12
  424. package/src/resources/extensions/gsd/docs/preferences-reference.md +25 -0
  425. package/src/resources/extensions/gsd/doctor.ts +60 -3
  426. package/src/resources/extensions/gsd/files.ts +45 -1
  427. package/src/resources/extensions/gsd/git-service.ts +46 -41
  428. package/src/resources/extensions/gsd/guided-flow.ts +81 -9
  429. package/src/resources/extensions/gsd/index.ts +62 -1
  430. package/src/resources/extensions/gsd/native-git-bridge.ts +181 -0
  431. package/src/resources/extensions/gsd/paths.ts +35 -4
  432. package/src/resources/extensions/gsd/post-unit-hooks.ts +449 -0
  433. package/src/resources/extensions/gsd/preferences.ts +232 -1
  434. package/src/resources/extensions/gsd/prompt-loader.ts +45 -3
  435. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  436. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -3
  437. package/src/resources/extensions/gsd/prompts/discuss.md +10 -8
  438. package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
  439. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +3 -1
  440. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +3 -1
  441. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +3 -1
  442. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +3 -1
  443. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +4 -2
  444. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +3 -1
  445. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +3 -1
  446. package/src/resources/extensions/gsd/prompts/plan-milestone.md +9 -12
  447. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -3
  448. package/src/resources/extensions/gsd/prompts/queue.md +3 -1
  449. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  450. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  451. package/src/resources/extensions/gsd/state.ts +130 -18
  452. package/src/resources/extensions/gsd/templates/context.md +1 -1
  453. package/src/resources/extensions/gsd/templates/state.md +3 -3
  454. package/src/resources/extensions/gsd/tests/activity-log-save.test.ts +127 -0
  455. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +5 -1
  456. package/src/resources/extensions/gsd/tests/doctor.test.ts +115 -1
  457. package/src/resources/extensions/gsd/tests/draft-promotion.test.ts +6 -2
  458. package/src/resources/extensions/gsd/tests/git-service.test.ts +35 -35
  459. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +8 -8
  460. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +4 -1
  461. package/src/resources/extensions/gsd/tests/network-error-fallback.test.ts +54 -0
  462. package/src/resources/extensions/gsd/tests/orphaned-branch.test.ts +5 -5
  463. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +297 -0
  464. package/src/resources/extensions/gsd/tests/preferences-hooks.test.ts +226 -0
  465. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +12 -0
  466. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +6 -0
  467. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +4 -4
  468. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +4 -4
  469. package/src/resources/extensions/gsd/tests/worktree.test.ts +19 -19
  470. package/src/resources/extensions/gsd/types.ts +109 -0
  471. package/src/resources/extensions/gsd/worktree-manager.ts +72 -13
  472. package/src/resources/extensions/gsd/worktree.ts +5 -4
  473. package/src/resources/extensions/search-the-web/command-search-provider.ts +8 -4
  474. package/src/resources/extensions/search-the-web/native-search.ts +32 -23
  475. package/src/resources/extensions/search-the-web/provider.ts +19 -2
  476. package/src/resources/extensions/search-the-web/tool-fetch-page.ts +62 -0
  477. package/src/resources/extensions/search-the-web/tool-llm-context.ts +62 -3
  478. package/src/resources/extensions/search-the-web/tool-search.ts +62 -3
  479. package/src/resources/extensions/shared/bundled-extension-paths.ts +11 -0
  480. package/src/resources/extensions/subagent/index.ts +2 -1
  481. package/src/resources/skills/github-workflows/SKILL.md +5 -0
  482. package/dist/resources/extensions/gsd/git-service.d.ts +0 -225
  483. package/dist/resources/extensions/gsd/git-service.js +0 -756
  484. package/dist/resources/extensions/gsd/preferences.d.ts +0 -122
  485. package/dist/resources/extensions/gsd/preferences.js +0 -616
  486. package/dist/resources/extensions/gsd/worktree.d.ts +0 -106
  487. package/dist/resources/extensions/remote-questions/config.d.ts +0 -14
  488. package/dist/resources/extensions/remote-questions/config.js +0 -68
  489. package/dist/resources/extensions/remote-questions/discord-adapter.d.ts +0 -17
  490. package/dist/resources/extensions/remote-questions/discord-adapter.js +0 -118
  491. package/dist/resources/extensions/remote-questions/format.d.ts +0 -38
  492. package/dist/resources/extensions/remote-questions/format.js +0 -119
  493. package/dist/resources/extensions/remote-questions/manager.d.ts +0 -23
  494. package/dist/resources/extensions/remote-questions/manager.js +0 -161
  495. package/dist/resources/extensions/remote-questions/remote-command.d.ts +0 -6
  496. package/dist/resources/extensions/remote-questions/remote-command.js +0 -358
  497. package/dist/resources/extensions/remote-questions/slack-adapter.d.ts +0 -15
  498. package/dist/resources/extensions/remote-questions/slack-adapter.js +0 -82
  499. package/dist/resources/extensions/remote-questions/status.d.ts +0 -9
  500. package/dist/resources/extensions/remote-questions/status.js +0 -25
  501. package/dist/resources/extensions/remote-questions/store.d.ts +0 -11
  502. package/dist/resources/extensions/remote-questions/store.js +0 -66
  503. package/dist/resources/extensions/remote-questions/types.d.ts +0 -68
  504. package/dist/resources/extensions/remote-questions/types.js +0 -4
@@ -16,19 +16,20 @@ import type {
16
16
  ExtensionCommandContext,
17
17
  } from "@gsd/pi-coding-agent";
18
18
 
19
- import { deriveState } from "./state.js";
19
+ import { deriveState, invalidateStateCache } from "./state.js";
20
20
  import type { GSDState } from "./types.js";
21
- import { loadFile, parseContinue, parsePlan, parseRoadmap, parseSummary, extractUatType, inlinePriorMilestoneSummary, getManifestStatus } from "./files.js";
21
+ import { loadFile, parseContinue, parsePlan, parseRoadmap, parseSummary, extractUatType, inlinePriorMilestoneSummary, getManifestStatus, clearParseCache } from "./files.js";
22
22
  export { inlinePriorMilestoneSummary };
23
23
  import type { UatType } from "./files.js";
24
24
  import { collectSecretsFromManifest } from "../get-secrets-from-user.js";
25
- import { loadPrompt } from "./prompt-loader.js";
25
+ import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
26
26
  import {
27
27
  gsdRoot, resolveMilestoneFile, resolveSliceFile, resolveSlicePath,
28
28
  resolveMilestonePath, resolveDir, resolveTasksDir, resolveTaskFiles, resolveTaskFile,
29
29
  relMilestoneFile, relSliceFile, relTaskFile, relSlicePath, relMilestonePath,
30
30
  milestonesDir, resolveGsdRootFile, relGsdRootFile,
31
31
  buildMilestoneFileName, buildSliceFileName, buildTaskFileName,
32
+ clearPathCache,
32
33
  } from "./paths.js";
33
34
  import { saveActivityLog } from "./activity-log.js";
34
35
  import { synthesizeCrashRecovery, getDeepDiagnostic } from "./session-forensics.js";
@@ -42,6 +43,18 @@ import {
42
43
  } from "./unit-runtime.js";
43
44
  import { resolveAutoSupervisorConfig, resolveModelForUnit, resolveModelWithFallbacksForUnit, resolveSkillDiscoveryMode, loadEffectiveGSDPreferences } from "./preferences.js";
44
45
  import type { GSDPreferences } from "./preferences.js";
46
+ import {
47
+ checkPostUnitHooks,
48
+ getActiveHook,
49
+ resetHookState,
50
+ isRetryPending,
51
+ consumeRetryTrigger,
52
+ runPreDispatchHooks,
53
+ persistHookState,
54
+ restoreHookState,
55
+ clearPersistedHookState,
56
+ formatHookStatus,
57
+ } from "./post-unit-hooks.js";
45
58
  import {
46
59
  validatePlanBoundary,
47
60
  validateExecuteBoundary,
@@ -71,6 +84,7 @@ import {
71
84
  mergeSliceToMain,
72
85
  } from "./worktree.js";
73
86
  import { GitServiceImpl, runGit } from "./git-service.js";
87
+ import { nativeCommitCountBetween } from "./native-git-bridge.js";
74
88
  import { getPriorSliceCompletionBlocker } from "./dispatch-guard.js";
75
89
  import type { GitPreferences } from "./git-service.js";
76
90
  import { truncateToWidth, visibleWidth } from "@gsd/pi-tui";
@@ -164,6 +178,14 @@ let unitTimeoutHandle: ReturnType<typeof setTimeout> | null = null;
164
178
  let wrapupWarningHandle: ReturnType<typeof setTimeout> | null = null;
165
179
  let idleWatchdogHandle: ReturnType<typeof setInterval> | null = null;
166
180
 
181
+ /** Dispatch gap watchdog — detects when the state machine stalls between units.
182
+ * After handleAgentEnd completes, if auto-mode is still active but no new unit
183
+ * has been dispatched (sendMessage not called), this timer fires to force a
184
+ * re-evaluation. Covers the case where dispatchNextUnit silently fails or
185
+ * an unhandled error kills the dispatch chain. */
186
+ let dispatchGapHandle: ReturnType<typeof setTimeout> | null = null;
187
+ const DISPATCH_GAP_TIMEOUT_MS = 5_000; // 5 seconds
188
+
167
189
  /** SIGTERM handler registered while auto-mode is active — cleared on stop/pause. */
168
190
  let _sigtermHandler: (() => void) | null = null;
169
191
 
@@ -269,6 +291,48 @@ function clearUnitTimeout(): void {
269
291
  clearInterval(idleWatchdogHandle);
270
292
  idleWatchdogHandle = null;
271
293
  }
294
+ clearDispatchGapWatchdog();
295
+ }
296
+
297
+ function clearDispatchGapWatchdog(): void {
298
+ if (dispatchGapHandle) {
299
+ clearTimeout(dispatchGapHandle);
300
+ dispatchGapHandle = null;
301
+ }
302
+ }
303
+
304
+ /**
305
+ * Start a watchdog that fires if no new unit is dispatched within DISPATCH_GAP_TIMEOUT_MS
306
+ * after handleAgentEnd completes. This catches the case where the dispatch chain silently
307
+ * breaks (e.g., unhandled exception in dispatchNextUnit) and auto-mode is left active but idle.
308
+ *
309
+ * The watchdog is cleared on the next successful unit dispatch (clearUnitTimeout is called
310
+ * at the start of handleAgentEnd, which calls clearDispatchGapWatchdog).
311
+ */
312
+ function startDispatchGapWatchdog(ctx: ExtensionContext, pi: ExtensionAPI): void {
313
+ clearDispatchGapWatchdog();
314
+ dispatchGapHandle = setTimeout(async () => {
315
+ dispatchGapHandle = null;
316
+ if (!active || !cmdCtx) return;
317
+
318
+ // Auto-mode is active but no unit was dispatched — the state machine stalled.
319
+ // Re-derive state and attempt a fresh dispatch.
320
+ ctx.ui.notify(
321
+ "Dispatch gap detected — no unit dispatched after previous unit completed. Re-evaluating state.",
322
+ "warning",
323
+ );
324
+
325
+ try {
326
+ await dispatchNextUnit(ctx, pi);
327
+ } catch (retryErr) {
328
+ const message = retryErr instanceof Error ? retryErr.message : String(retryErr);
329
+ ctx.ui.notify(
330
+ `Dispatch gap recovery failed: ${message}. Stopping auto-mode.`,
331
+ "error",
332
+ );
333
+ await stopAuto(ctx, pi);
334
+ }
335
+ }, DISPATCH_GAP_TIMEOUT_MS);
272
336
  }
273
337
 
274
338
  export async function stopAuto(ctx?: ExtensionContext, pi?: ExtensionAPI): Promise<void> {
@@ -296,6 +360,8 @@ export async function stopAuto(ctx?: ExtensionContext, pi?: ExtensionAPI): Promi
296
360
  }
297
361
 
298
362
  resetMetrics();
363
+ resetHookState();
364
+ if (basePath) clearPersistedHookState(basePath);
299
365
  active = false;
300
366
  paused = false;
301
367
  stepMode = false;
@@ -423,12 +489,8 @@ async function mergeOrphanedSliceBranches(
423
489
 
424
490
  // Skip if already merged (no commits ahead of main)
425
491
  const mainBranch = getMainBranch(base);
426
- const aheadCount = runGit(
427
- base,
428
- ["rev-list", "--count", `${mainBranch}..${branch}`],
429
- { allowFailure: true },
430
- );
431
- if (!aheadCount || aheadCount === "0") continue;
492
+ const aheadCount = nativeCommitCountBetween(base, mainBranch, branch);
493
+ if (aheadCount === 0) continue;
432
494
 
433
495
  // Read the roadmap from the slice branch to check if the slice is done.
434
496
  // relMilestoneFile resolves the actual directory name on disk (handles
@@ -517,6 +579,8 @@ export async function startAuto(
517
579
  ctx.ui.setStatus("gsd-auto", stepMode ? "next" : "auto");
518
580
  ctx.ui.setFooter(hideFooter);
519
581
  ctx.ui.notify(stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "info");
582
+ // Restore hook state from disk in case session was interrupted
583
+ restoreHookState(base);
520
584
  // Rebuild disk state before resuming — user interaction during pause may have changed files
521
585
  try { await rebuildState(base); } catch { /* non-fatal */ }
522
586
  try {
@@ -527,6 +591,9 @@ export async function startAuto(
527
591
  } catch { /* non-fatal */ }
528
592
  // Self-heal: clear stale runtime records where artifacts already exist
529
593
  await selfHealRuntimeRecords(base, ctx);
594
+ invalidateStateCache();
595
+ clearParseCache();
596
+ clearPathCache();
530
597
  await dispatchNextUnit(ctx, pi);
531
598
  return;
532
599
  }
@@ -622,6 +689,8 @@ export async function startAuto(
622
689
  unitRecoveryCount.clear();
623
690
  completedKeySet.clear();
624
691
  loadPersistedKeys(base, completedKeySet);
692
+ resetHookState();
693
+ restoreHookState(base);
625
694
  autoStartTime = Date.now();
626
695
  completedUnits = [];
627
696
  currentUnit = null;
@@ -716,6 +785,12 @@ export async function handleAgentEnd(
716
785
  // Unit completed — clear its timeout
717
786
  clearUnitTimeout();
718
787
 
788
+ // Invalidate deriveState() cache — the unit just completed and may have
789
+ // written planning files (task summaries, roadmap checkboxes, etc.)
790
+ invalidateStateCache();
791
+ clearParseCache();
792
+ clearPathCache();
793
+
719
794
  // Small delay to let files settle (git commits, file writes)
720
795
  await new Promise(r => setTimeout(r, 500));
721
796
 
@@ -754,13 +829,109 @@ export async function handleAgentEnd(
754
829
  }
755
830
  }
756
831
 
832
+ // ── Post-unit hooks: check if a configured hook should run before normal dispatch ──
833
+ if (currentUnit && !stepMode) {
834
+ const hookUnit = checkPostUnitHooks(currentUnit.type, currentUnit.id, basePath);
835
+ if (hookUnit) {
836
+ // Dispatch the hook unit instead of normal flow
837
+ const hookStartedAt = Date.now();
838
+ if (currentUnit) {
839
+ const modelId = ctx.model?.id ?? "unknown";
840
+ snapshotUnitMetrics(ctx, currentUnit.type, currentUnit.id, currentUnit.startedAt, modelId);
841
+ saveActivityLog(ctx, basePath, currentUnit.type, currentUnit.id);
842
+ }
843
+ currentUnit = { type: hookUnit.unitType, id: hookUnit.unitId, startedAt: hookStartedAt };
844
+ writeUnitRuntimeRecord(basePath, hookUnit.unitType, hookUnit.unitId, hookStartedAt, {
845
+ phase: "dispatched",
846
+ wrapupWarningSent: false,
847
+ timeoutAt: null,
848
+ lastProgressAt: hookStartedAt,
849
+ progressCount: 0,
850
+ lastProgressKind: "dispatch",
851
+ });
852
+
853
+ const state = await deriveState(basePath);
854
+ updateProgressWidget(ctx, hookUnit.unitType, hookUnit.unitId, state);
855
+ const hookState = getActiveHook();
856
+ ctx.ui.notify(
857
+ `Running post-unit hook: ${hookUnit.hookName} (cycle ${hookState?.cycle ?? 1})`,
858
+ "info",
859
+ );
860
+
861
+ // Switch model if the hook specifies one
862
+ if (hookUnit.model) {
863
+ const availableModels = ctx.modelRegistry.getAvailable();
864
+ const match = availableModels.find(m =>
865
+ m.id === hookUnit.model || `${m.provider}/${m.id}` === hookUnit.model,
866
+ );
867
+ if (match) {
868
+ try {
869
+ await pi.setModel(match);
870
+ } catch { /* non-fatal — use current model */ }
871
+ }
872
+ }
873
+
874
+ const result = await cmdCtx!.newSession();
875
+ if (result.cancelled) {
876
+ resetHookState();
877
+ await stopAuto(ctx, pi);
878
+ return;
879
+ }
880
+ const sessionFile = ctx.sessionManager.getSessionFile();
881
+ writeLock(basePath, hookUnit.unitType, hookUnit.unitId, completedUnits.length, sessionFile);
882
+ // Persist hook state so cycle counts survive crashes
883
+ persistHookState(basePath);
884
+ pi.sendMessage(
885
+ { customType: "gsd-auto", content: hookUnit.prompt, display: verbose },
886
+ { triggerTurn: true },
887
+ );
888
+ return; // handleAgentEnd will fire again when hook session completes
889
+ }
890
+
891
+ // Check if a hook requested a retry of the trigger unit
892
+ if (isRetryPending()) {
893
+ const trigger = consumeRetryTrigger();
894
+ if (trigger) {
895
+ ctx.ui.notify(
896
+ `Hook requested retry of ${trigger.unitType} ${trigger.unitId}.`,
897
+ "info",
898
+ );
899
+ // Fall through to normal dispatchNextUnit — state derivation will
900
+ // re-select the same unit since it hasn't been marked complete
901
+ }
902
+ }
903
+ }
904
+
757
905
  // In step mode, pause and show a wizard instead of immediately dispatching
758
906
  if (stepMode) {
759
907
  await showStepWizard(ctx, pi);
760
908
  return;
761
909
  }
762
910
 
763
- await dispatchNextUnit(ctx, pi);
911
+ try {
912
+ await dispatchNextUnit(ctx, pi);
913
+ } catch (dispatchErr) {
914
+ // dispatchNextUnit threw — without this catch the error would propagate
915
+ // to the pi event emitter which may silently swallow async rejections,
916
+ // leaving auto-mode active but permanently stalled (see #381).
917
+ const message = dispatchErr instanceof Error ? dispatchErr.message : String(dispatchErr);
918
+ ctx.ui.notify(
919
+ `Dispatch error after unit completion: ${message}. Retrying in ${DISPATCH_GAP_TIMEOUT_MS / 1000}s.`,
920
+ "error",
921
+ );
922
+
923
+ // Start the dispatch gap watchdog to retry after a delay.
924
+ // This gives transient issues (dirty working tree, branch state) time to settle.
925
+ startDispatchGapWatchdog(ctx, pi);
926
+ return;
927
+ }
928
+
929
+ // If dispatchNextUnit returned normally but auto-mode is still active and
930
+ // no new unit timeout was set (meaning sendMessage was never called), start
931
+ // the dispatch gap watchdog as a safety net.
932
+ if (active && !unitTimeoutHandle && !wrapupWarningHandle) {
933
+ startDispatchGapWatchdog(ctx, pi);
934
+ }
764
935
 
765
936
  } finally {
766
937
  _handlingAgentEnd = false;
@@ -874,6 +1045,7 @@ export function describeNextUnit(state: GSDState): { label: string; description:
874
1045
  // ─── Progress Widget ──────────────────────────────────────────────────────
875
1046
 
876
1047
  function unitVerb(unitType: string): string {
1048
+ if (unitType.startsWith("hook/")) return `hook: ${unitType.slice(5)}`;
877
1049
  switch (unitType) {
878
1050
  case "research-milestone":
879
1051
  case "research-slice": return "researching";
@@ -890,6 +1062,7 @@ function unitVerb(unitType: string): string {
890
1062
  }
891
1063
 
892
1064
  function unitPhaseLabel(unitType: string): string {
1065
+ if (unitType.startsWith("hook/")) return "HOOK";
893
1066
  switch (unitType) {
894
1067
  case "research-milestone": return "RESEARCH";
895
1068
  case "research-slice": return "RESEARCH";
@@ -906,7 +1079,14 @@ function unitPhaseLabel(unitType: string): string {
906
1079
  }
907
1080
 
908
1081
  function peekNext(unitType: string, state: GSDState): string {
1082
+ // Show active hook info in progress display
1083
+ const activeHookState = getActiveHook();
1084
+ if (activeHookState) {
1085
+ return `hook: ${activeHookState.hookName} (cycle ${activeHookState.cycle})`;
1086
+ }
1087
+
909
1088
  const sid = state.activeSlice?.id ?? "";
1089
+ if (unitType.startsWith("hook/")) return `continue ${sid}`;
910
1090
  switch (unitType) {
911
1091
  case "research-milestone": return "plan milestone roadmap";
912
1092
  case "plan-milestone": return "plan or execute first slice";
@@ -1092,7 +1272,14 @@ function updateProgressWidget(
1092
1272
  .join(theme.fg("dim", " "));
1093
1273
 
1094
1274
  const modelId = cmdCtx?.model?.id ?? "";
1095
- const sRight = modelId ? theme.fg("dim", modelId) : "";
1275
+ const modelProvider = cmdCtx?.model?.provider ?? "";
1276
+ const modelPhase = phaseLabel ? theme.fg("dim", `[${phaseLabel}] `) : "";
1277
+ const modelDisplay = modelProvider && modelId
1278
+ ? `${modelProvider}/${modelId}`
1279
+ : modelId;
1280
+ const sRight = modelDisplay
1281
+ ? `${modelPhase}${theme.fg("dim", modelDisplay)}`
1282
+ : "";
1096
1283
  lines.push(rightAlign(`${pad}${sLeft}`, sRight, width));
1097
1284
  }
1098
1285
 
@@ -1193,6 +1380,9 @@ async function dispatchNextUnit(
1193
1380
  return;
1194
1381
  }
1195
1382
 
1383
+ // Clear stale directory listing cache so deriveState sees fresh disk state (#431)
1384
+ clearPathCache();
1385
+
1196
1386
  let state = await deriveState(basePath);
1197
1387
  let mid = state.activeMilestone?.id;
1198
1388
  let midTitle = state.activeMilestone?.title;
@@ -1255,6 +1445,9 @@ async function dispatchNextUnit(
1255
1445
  }
1256
1446
  }
1257
1447
  // Re-derive state from the now-merged working tree
1448
+ invalidateStateCache();
1449
+ clearParseCache();
1450
+ clearPathCache();
1258
1451
  state = await deriveState(basePath);
1259
1452
  mid = state.activeMilestone?.id;
1260
1453
  midTitle = state.activeMilestone?.title;
@@ -1319,6 +1512,9 @@ async function dispatchNextUnit(
1319
1512
  "info",
1320
1513
  );
1321
1514
  // Re-derive state from main so downstream logic sees merged state
1515
+ invalidateStateCache();
1516
+ clearParseCache();
1517
+ clearPathCache();
1322
1518
  state = await deriveState(basePath);
1323
1519
  mid = state.activeMilestone?.id;
1324
1520
  midTitle = state.activeMilestone?.title;
@@ -1631,6 +1827,28 @@ async function dispatchNextUnit(
1631
1827
  }
1632
1828
  }
1633
1829
 
1830
+ // ── Pre-dispatch hooks: modify, skip, or replace the unit before dispatch ──
1831
+ const preDispatchResult = runPreDispatchHooks(unitType, unitId, prompt, basePath);
1832
+ if (preDispatchResult.firedHooks.length > 0) {
1833
+ ctx.ui.notify(
1834
+ `Pre-dispatch hook${preDispatchResult.firedHooks.length > 1 ? "s" : ""}: ${preDispatchResult.firedHooks.join(", ")}`,
1835
+ "info",
1836
+ );
1837
+ }
1838
+ if (preDispatchResult.action === "skip") {
1839
+ ctx.ui.notify(`Skipping ${unitType} ${unitId} (pre-dispatch hook).`, "info");
1840
+ // Yield then re-dispatch to advance to next unit
1841
+ await new Promise(r => setImmediate(r));
1842
+ await dispatchNextUnit(ctx, pi);
1843
+ return;
1844
+ }
1845
+ if (preDispatchResult.action === "replace") {
1846
+ prompt = preDispatchResult.prompt ?? prompt;
1847
+ if (preDispatchResult.unitType) unitType = preDispatchResult.unitType;
1848
+ } else if (preDispatchResult.prompt) {
1849
+ prompt = preDispatchResult.prompt;
1850
+ }
1851
+
1634
1852
  const priorSliceBlocker = getPriorSliceCompletionBlocker(basePath, getMainBranch(basePath), unitType, unitId);
1635
1853
  if (priorSliceBlocker) {
1636
1854
  await stopAuto(ctx, pi);
@@ -1870,16 +2088,37 @@ async function dispatchNextUnit(
1870
2088
  let modelSet = false;
1871
2089
 
1872
2090
  for (const modelId of modelsToTry) {
1873
- // Support "provider/model" format for explicit provider targeting
2091
+ // Resolve model from available models.
2092
+ // Handles multiple formats:
2093
+ // "provider/model" → explicit provider targeting (e.g. "anthropic/claude-opus-4-6")
2094
+ // "bare-id" → match by ID across providers
2095
+ // "org/model-name" → OpenRouter-style IDs where the full string is the model ID
2096
+ // "openrouter/org/model" → explicit provider + OpenRouter model ID
1874
2097
  const slashIdx = modelId.indexOf("/");
1875
2098
  let model;
1876
2099
  if (slashIdx !== -1) {
1877
- const provider = modelId.substring(0, slashIdx);
2100
+ const maybeProvider = modelId.substring(0, slashIdx);
1878
2101
  const id = modelId.substring(slashIdx + 1);
1879
- model = availableModels.find(
1880
- m => m.provider.toLowerCase() === provider.toLowerCase()
1881
- && m.id.toLowerCase() === id.toLowerCase(),
1882
- );
2102
+
2103
+ // Check if the prefix before the first slash is a known provider
2104
+ const knownProviders = new Set(availableModels.map(m => m.provider.toLowerCase()));
2105
+ if (knownProviders.has(maybeProvider.toLowerCase())) {
2106
+ // Explicit "provider/model" format (handles "openrouter/org/model" too)
2107
+ model = availableModels.find(
2108
+ m => m.provider.toLowerCase() === maybeProvider.toLowerCase()
2109
+ && m.id.toLowerCase() === id.toLowerCase(),
2110
+ );
2111
+ }
2112
+
2113
+ // If the prefix wasn't a known provider, or no match was found within that provider,
2114
+ // try matching the full string as a model ID (OpenRouter-style IDs like "org/model-name")
2115
+ if (!model) {
2116
+ const lower = modelId.toLowerCase();
2117
+ model = availableModels.find(
2118
+ m => m.id.toLowerCase() === lower
2119
+ || `${m.provider}/${m.id}`.toLowerCase() === lower,
2120
+ );
2121
+ }
1883
2122
  } else {
1884
2123
  // For bare IDs, prefer the current session's provider, then first available match
1885
2124
  const currentProvider = ctx.model?.provider;
@@ -1913,7 +2152,8 @@ async function dispatchNextUnit(
1913
2152
  const fallbackNote = modelId === modelConfig.primary
1914
2153
  ? ""
1915
2154
  : ` (fallback from ${modelConfig.primary})`;
1916
- ctx.ui.notify(`Model: ${modelId}${fallbackNote}`, "info");
2155
+ const phase = unitPhaseLabel(unitType);
2156
+ ctx.ui.notify(`Model [${phase}]: ${model.provider}/${model.id}${fallbackNote}`, "info");
1917
2157
  modelSet = true;
1918
2158
  break;
1919
2159
  } else {
@@ -2136,7 +2376,10 @@ async function inlineDependencySummaries(
2136
2376
  if (!sliceEntry || sliceEntry.depends.length === 0) return "- (no dependencies)";
2137
2377
 
2138
2378
  const sections: string[] = [];
2379
+ const seen = new Set<string>();
2139
2380
  for (const dep of sliceEntry.depends) {
2381
+ if (seen.has(dep)) continue;
2382
+ seen.add(dep);
2140
2383
  const summaryFile = resolveSliceFile(base, mid, dep, "SUMMARY");
2141
2384
  const summaryContent = summaryFile ? await loadFile(summaryFile) : null;
2142
2385
  const relPath = relSliceFile(base, mid, dep, "SUMMARY");
@@ -2176,6 +2419,7 @@ async function buildResearchMilestonePrompt(mid: string, midTitle: string, base:
2176
2419
  if (requirementsInline) inlined.push(requirementsInline);
2177
2420
  const decisionsInline = await inlineGsdRootFile(base, "decisions.md", "Decisions");
2178
2421
  if (decisionsInline) inlined.push(decisionsInline);
2422
+ inlined.push(inlineTemplate("research", "Research"));
2179
2423
 
2180
2424
  const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
2181
2425
 
@@ -2208,6 +2452,11 @@ async function buildPlanMilestonePrompt(mid: string, midTitle: string, base: str
2208
2452
  if (requirementsInline) inlined.push(requirementsInline);
2209
2453
  const decisionsInline = await inlineGsdRootFile(base, "decisions.md", "Decisions");
2210
2454
  if (decisionsInline) inlined.push(decisionsInline);
2455
+ inlined.push(inlineTemplate("roadmap", "Roadmap"));
2456
+ inlined.push(inlineTemplate("decisions", "Decisions"));
2457
+ inlined.push(inlineTemplate("plan", "Slice Plan"));
2458
+ inlined.push(inlineTemplate("task-plan", "Task Plan"));
2459
+ inlined.push(inlineTemplate("secrets-manifest", "Secrets Manifest"));
2211
2460
 
2212
2461
  const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
2213
2462
 
@@ -2244,6 +2493,7 @@ async function buildResearchSlicePrompt(
2244
2493
  if (decisionsInline) inlined.push(decisionsInline);
2245
2494
  const requirementsInline = await inlineGsdRootFile(base, "requirements.md", "Requirements");
2246
2495
  if (requirementsInline) inlined.push(requirementsInline);
2496
+ inlined.push(inlineTemplate("research", "Research"));
2247
2497
 
2248
2498
  const depContent = await inlineDependencySummaries(mid, sid, base);
2249
2499
 
@@ -2279,6 +2529,8 @@ async function buildPlanSlicePrompt(
2279
2529
  if (decisionsInline) inlined.push(decisionsInline);
2280
2530
  const requirementsInline = await inlineGsdRootFile(base, "requirements.md", "Requirements");
2281
2531
  if (requirementsInline) inlined.push(requirementsInline);
2532
+ inlined.push(inlineTemplate("plan", "Slice Plan"));
2533
+ inlined.push(inlineTemplate("task-plan", "Task Plan"));
2282
2534
 
2283
2535
  const depContent = await inlineDependencySummaries(mid, sid, base);
2284
2536
 
@@ -2340,6 +2592,10 @@ async function buildExecuteTaskPrompt(
2340
2592
  );
2341
2593
 
2342
2594
  const carryForwardSection = await buildCarryForwardSection(priorSummaries, base);
2595
+ const inlinedTemplates = [
2596
+ inlineTemplate("task-summary", "Task Summary"),
2597
+ inlineTemplate("decisions", "Decisions"),
2598
+ ].join("\n\n---\n\n");
2343
2599
 
2344
2600
  const taskSummaryPath = `${relSlicePath(base, mid, sid)}/tasks/${tid}-SUMMARY.md`;
2345
2601
 
@@ -2354,6 +2610,7 @@ async function buildExecuteTaskPrompt(
2354
2610
  resumeSection,
2355
2611
  priorTaskLines: priorLines,
2356
2612
  taskSummaryPath,
2613
+ inlinedTemplates,
2357
2614
  });
2358
2615
  }
2359
2616
 
@@ -2386,6 +2643,8 @@ async function buildCompleteSlicePrompt(
2386
2643
  }
2387
2644
  }
2388
2645
  }
2646
+ inlined.push(inlineTemplate("slice-summary", "Slice Summary"));
2647
+ inlined.push(inlineTemplate("uat", "UAT"));
2389
2648
 
2390
2649
  const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
2391
2650
 
@@ -2412,11 +2671,14 @@ async function buildCompleteMilestonePrompt(
2412
2671
  const inlined: string[] = [];
2413
2672
  inlined.push(await inlineFile(roadmapPath, roadmapRel, "Milestone Roadmap"));
2414
2673
 
2415
- // Inline all slice summaries
2674
+ // Inline all slice summaries (deduplicated by slice ID)
2416
2675
  const roadmapContent = roadmapPath ? await loadFile(roadmapPath) : null;
2417
2676
  if (roadmapContent) {
2418
2677
  const roadmap = parseRoadmap(roadmapContent);
2678
+ const seenSlices = new Set<string>();
2419
2679
  for (const slice of roadmap.slices) {
2680
+ if (seenSlices.has(slice.id)) continue;
2681
+ seenSlices.add(slice.id);
2420
2682
  const summaryPath = resolveSliceFile(base, mid, slice.id, "SUMMARY");
2421
2683
  const summaryRel = relSliceFile(base, mid, slice.id, "SUMMARY");
2422
2684
  inlined.push(await inlineFile(summaryPath, summaryRel, `${slice.id} Summary`));
@@ -2435,6 +2697,7 @@ async function buildCompleteMilestonePrompt(
2435
2697
  const contextRel = relMilestoneFile(base, mid, "CONTEXT");
2436
2698
  const contextInline = await inlineFileOptional(contextPath, contextRel, "Milestone Context");
2437
2699
  if (contextInline) inlined.push(contextInline);
2700
+ inlined.push(inlineTemplate("milestone-summary", "Milestone Summary"));
2438
2701
 
2439
2702
  const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
2440
2703
 
@@ -2881,6 +3144,9 @@ async function collectObservabilityWarnings(
2881
3144
  unitType: string,
2882
3145
  unitId: string,
2883
3146
  ): Promise<import("./observability-validator.ts").ValidationIssue[]> {
3147
+ // Hook units have custom artifacts — skip standard observability checks
3148
+ if (unitType.startsWith("hook/")) return [];
3149
+
2884
3150
  const parts = unitId.split("/");
2885
3151
  const mid = parts[0];
2886
3152
  const sid = parts[1];
@@ -3292,6 +3558,9 @@ export function resolveExpectedArtifactPath(unitType: string, unitId: string, ba
3292
3558
  * skipped writing the UAT file (see #176).
3293
3559
  */
3294
3560
  export function verifyExpectedArtifact(unitType: string, unitId: string, base: string): boolean {
3561
+ // Clear stale directory listing cache so artifact checks see fresh disk state (#431)
3562
+ clearPathCache();
3563
+
3295
3564
  // fix-merge has no file artifact — verify by checking git state
3296
3565
  if (unitType === "fix-merge") {
3297
3566
  const unmerged = runGit(base, ["diff", "--name-only", "--diff-filter=U"], { allowFailure: true });
@@ -53,10 +53,10 @@ function dispatchDoctorHeal(pi: ExtensionAPI, scope: string | undefined, reportT
53
53
 
54
54
  export function registerGSDCommand(pi: ExtensionAPI): void {
55
55
  pi.registerCommand("gsd", {
56
- description: "GSD — Get Shit Done: /gsd next|auto|stop|status|queue|prefs|doctor|migrate|remote",
56
+ description: "GSD — Get Shit Done: /gsd next|auto|stop|status|queue|prefs|hooks|doctor|migrate|remote",
57
57
 
58
58
  getArgumentCompletions: (prefix: string) => {
59
- const subcommands = ["next", "auto", "stop", "status", "queue", "discuss", "prefs", "doctor", "migrate", "remote"];
59
+ const subcommands = ["next", "auto", "stop", "status", "queue", "discuss", "prefs", "hooks", "doctor", "migrate", "remote"];
60
60
  const parts = prefix.trim().split(/\s+/);
61
61
 
62
62
  if (parts.length <= 1) {
@@ -151,6 +151,12 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
151
151
  return;
152
152
  }
153
153
 
154
+ if (trimmed === "hooks") {
155
+ const { formatHookStatus } = await import("./post-unit-hooks.js");
156
+ ctx.ui.notify(formatHookStatus(), "info");
157
+ return;
158
+ }
159
+
154
160
  if (trimmed === "migrate" || trimmed.startsWith("migrate ")) {
155
161
  await handleMigrate(trimmed.replace(/^migrate\s*/, "").trim(), ctx, pi);
156
162
  return;
@@ -168,7 +174,7 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
168
174
  }
169
175
 
170
176
  ctx.ui.notify(
171
- `Unknown: /gsd ${trimmed}. Use /gsd, /gsd next, /gsd auto, /gsd stop, /gsd status, /gsd queue, /gsd discuss, /gsd prefs [global|project|status|wizard|setup], /gsd doctor [audit|fix|heal] [M###/S##], /gsd migrate <path>, or /gsd remote [slack|discord|status|disconnect].`,
177
+ `Unknown: /gsd ${trimmed}. Use /gsd, /gsd next, /gsd auto, /gsd stop, /gsd status, /gsd queue, /gsd discuss, /gsd prefs [global|project|status|wizard|setup], /gsd hooks, /gsd doctor [audit|fix|heal] [M###/S##], /gsd migrate <path>, or /gsd remote [slack|discord|status|disconnect].`,
172
178
  "warning",
173
179
  );
174
180
  },