gsd-pi 2.28.0 → 2.29.0-dev.23d50d0

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 (1321) hide show
  1. package/README.md +34 -4
  2. package/dist/cli.js +20 -21
  3. package/dist/extension-discovery.d.ts +16 -0
  4. package/dist/extension-discovery.js +66 -0
  5. package/dist/headless-answers.d.ts +51 -0
  6. package/dist/headless-answers.js +224 -0
  7. package/dist/headless-context.d.ts +18 -0
  8. package/dist/headless-context.js +44 -0
  9. package/dist/headless-events.d.ts +28 -0
  10. package/dist/headless-events.js +59 -0
  11. package/dist/headless-query.d.ts +4 -0
  12. package/dist/headless-query.js +22 -4
  13. package/dist/headless-ui.d.ts +23 -0
  14. package/dist/headless-ui.js +103 -0
  15. package/dist/headless.d.ts +2 -0
  16. package/dist/headless.js +65 -183
  17. package/dist/help-text.js +4 -0
  18. package/dist/loader.js +18 -59
  19. package/dist/onboarding.js +8 -7
  20. package/dist/remote-questions-config.js +8 -3
  21. package/dist/resource-loader.d.ts +1 -6
  22. package/dist/resource-loader.js +125 -96
  23. package/dist/resources/extensions/ask-user-questions.ts +3 -2
  24. package/dist/resources/extensions/bg-shell/bg-shell-command.ts +219 -0
  25. package/dist/resources/extensions/bg-shell/bg-shell-lifecycle.ts +400 -0
  26. package/dist/resources/extensions/bg-shell/bg-shell-tool.ts +985 -0
  27. package/dist/resources/extensions/bg-shell/index.ts +17 -1561
  28. package/dist/resources/extensions/bg-shell/overlay.ts +4 -0
  29. package/dist/resources/extensions/bg-shell/process-manager.ts +13 -0
  30. package/dist/resources/extensions/bg-shell/utilities.ts +4 -16
  31. package/dist/resources/extensions/browser-tools/capture.ts +34 -2
  32. package/dist/resources/extensions/browser-tools/lifecycle.ts +5 -5
  33. package/dist/resources/extensions/browser-tools/settle.ts +1 -1
  34. package/dist/resources/extensions/browser-tools/state.ts +5 -5
  35. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +1 -1
  36. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +3 -3
  37. package/dist/resources/extensions/browser-tools/tools/assertions.ts +1 -1
  38. package/dist/resources/extensions/browser-tools/tools/device.ts +1 -1
  39. package/dist/resources/extensions/browser-tools/tools/extract.ts +1 -1
  40. package/dist/resources/extensions/browser-tools/tools/navigation.ts +6 -6
  41. package/dist/resources/extensions/browser-tools/tools/network-mock.ts +1 -1
  42. package/dist/resources/extensions/browser-tools/tools/pages.ts +1 -1
  43. package/dist/resources/extensions/browser-tools/tools/screenshot.ts +28 -10
  44. package/dist/resources/extensions/browser-tools/tools/state-persistence.ts +1 -1
  45. package/dist/resources/extensions/browser-tools/tools/visual-diff.ts +1 -1
  46. package/dist/resources/extensions/browser-tools/utils.ts +5 -5
  47. package/dist/resources/extensions/get-secrets-from-user.ts +1 -1
  48. package/dist/resources/extensions/google-search/index.ts +21 -8
  49. package/dist/resources/extensions/gsd/activity-log.ts +2 -1
  50. package/dist/resources/extensions/gsd/atomic-write.ts +35 -0
  51. package/dist/resources/extensions/gsd/auto/session.ts +12 -0
  52. package/dist/resources/extensions/gsd/auto-dashboard.ts +295 -62
  53. package/dist/resources/extensions/gsd/auto-dispatch.ts +2 -2
  54. package/dist/resources/extensions/gsd/auto-idempotency.ts +150 -0
  55. package/dist/resources/extensions/gsd/auto-post-unit.ts +633 -0
  56. package/dist/resources/extensions/gsd/auto-prompts.ts +139 -32
  57. package/dist/resources/extensions/gsd/auto-recovery.ts +36 -31
  58. package/dist/resources/extensions/gsd/auto-start.ts +500 -0
  59. package/dist/resources/extensions/gsd/auto-stuck-detection.ts +220 -0
  60. package/dist/resources/extensions/gsd/auto-timers.ts +223 -0
  61. package/dist/resources/extensions/gsd/auto-unit-closeout.ts +3 -1
  62. package/dist/resources/extensions/gsd/auto-verification.ts +229 -0
  63. package/dist/resources/extensions/gsd/auto-worktree-sync.ts +29 -37
  64. package/dist/resources/extensions/gsd/auto-worktree.ts +92 -67
  65. package/dist/resources/extensions/gsd/auto.ts +375 -1890
  66. package/dist/resources/extensions/gsd/commands-config.ts +102 -0
  67. package/dist/resources/extensions/gsd/commands-handlers.ts +394 -0
  68. package/dist/resources/extensions/gsd/commands-inspect.ts +90 -0
  69. package/dist/resources/extensions/gsd/commands-logs.ts +536 -0
  70. package/dist/resources/extensions/gsd/commands-maintenance.ts +206 -0
  71. package/dist/resources/extensions/gsd/commands-prefs-wizard.ts +790 -0
  72. package/dist/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
  73. package/dist/resources/extensions/gsd/commands.ts +417 -1495
  74. package/dist/resources/extensions/gsd/constants.ts +21 -0
  75. package/dist/resources/extensions/gsd/context-budget.ts +25 -2
  76. package/dist/resources/extensions/gsd/crash-recovery.ts +3 -4
  77. package/dist/resources/extensions/gsd/dashboard-overlay.ts +15 -5
  78. package/dist/resources/extensions/gsd/db-writer.ts +21 -2
  79. package/dist/resources/extensions/gsd/detection.ts +469 -0
  80. package/dist/resources/extensions/gsd/diff-context.ts +2 -1
  81. package/dist/resources/extensions/gsd/dispatch-guard.ts +4 -0
  82. package/dist/resources/extensions/gsd/doctor-checks.ts +564 -0
  83. package/dist/resources/extensions/gsd/doctor-format.ts +78 -0
  84. package/dist/resources/extensions/gsd/doctor-types.ts +72 -0
  85. package/dist/resources/extensions/gsd/doctor.ts +64 -701
  86. package/dist/resources/extensions/gsd/errors.ts +0 -2
  87. package/dist/resources/extensions/gsd/export-html.ts +367 -11
  88. package/dist/resources/extensions/gsd/export.ts +31 -5
  89. package/dist/resources/extensions/gsd/files.ts +8 -126
  90. package/dist/resources/extensions/gsd/forensics.ts +2 -12
  91. package/dist/resources/extensions/gsd/git-constants.ts +11 -0
  92. package/dist/resources/extensions/gsd/git-service.ts +13 -9
  93. package/dist/resources/extensions/gsd/gsd-db.ts +26 -6
  94. package/dist/resources/extensions/gsd/guided-flow-queue.ts +451 -0
  95. package/dist/resources/extensions/gsd/guided-flow.ts +231 -514
  96. package/dist/resources/extensions/gsd/history.ts +2 -20
  97. package/dist/resources/extensions/gsd/index.ts +208 -46
  98. package/dist/resources/extensions/gsd/init-wizard.ts +615 -0
  99. package/dist/resources/extensions/gsd/json-persistence.ts +67 -0
  100. package/dist/resources/extensions/gsd/jsonl-utils.ts +21 -0
  101. package/dist/resources/extensions/gsd/key-manager.ts +995 -0
  102. package/dist/resources/extensions/gsd/mechanical-completion.ts +430 -0
  103. package/dist/resources/extensions/gsd/metrics.ts +49 -36
  104. package/dist/resources/extensions/gsd/migrate/command.ts +1 -1
  105. package/dist/resources/extensions/gsd/migrate/parsers.ts +10 -95
  106. package/dist/resources/extensions/gsd/milestone-actions.ts +126 -0
  107. package/dist/resources/extensions/gsd/milestone-ids.ts +95 -0
  108. package/dist/resources/extensions/gsd/native-git-bridge.ts +5 -10
  109. package/dist/resources/extensions/gsd/parallel-eligibility.ts +3 -3
  110. package/dist/resources/extensions/gsd/paths.ts +18 -11
  111. package/dist/resources/extensions/gsd/plugin-importer.ts +3 -2
  112. package/dist/resources/extensions/gsd/preferences-models.ts +329 -0
  113. package/dist/resources/extensions/gsd/preferences-skills.ts +169 -0
  114. package/dist/resources/extensions/gsd/preferences-types.ts +223 -0
  115. package/dist/resources/extensions/gsd/preferences-validation.ts +598 -0
  116. package/dist/resources/extensions/gsd/preferences.ts +219 -1305
  117. package/dist/resources/extensions/gsd/prompt-cache-optimizer.ts +213 -0
  118. package/dist/resources/extensions/gsd/prompt-compressor.ts +508 -0
  119. package/dist/resources/extensions/gsd/prompt-loader.ts +4 -2
  120. package/dist/resources/extensions/gsd/prompt-ordering.ts +200 -0
  121. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -2
  122. package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -4
  123. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +6 -6
  124. package/dist/resources/extensions/gsd/prompts/discuss.md +13 -5
  125. package/dist/resources/extensions/gsd/prompts/execute-task.md +0 -1
  126. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  127. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  128. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +0 -1
  129. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +26 -3
  130. package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  131. package/dist/resources/extensions/gsd/prompts/queue.md +30 -0
  132. package/dist/resources/extensions/gsd/prompts/quick-task.md +0 -6
  133. package/dist/resources/extensions/gsd/prompts/replan-slice.md +0 -1
  134. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +0 -1
  135. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  136. package/dist/resources/extensions/gsd/prompts/workflow-start.md +28 -0
  137. package/dist/resources/extensions/gsd/provider-error-pause.ts +59 -10
  138. package/dist/resources/extensions/gsd/queue-order.ts +11 -12
  139. package/dist/resources/extensions/gsd/queue-reorder-ui.ts +15 -2
  140. package/dist/resources/extensions/gsd/quick.ts +18 -15
  141. package/dist/resources/extensions/gsd/reports.ts +1 -7
  142. package/dist/resources/extensions/gsd/routing-history.ts +13 -17
  143. package/dist/resources/extensions/gsd/safe-fs.ts +47 -0
  144. package/dist/resources/extensions/gsd/semantic-chunker.ts +336 -0
  145. package/dist/resources/extensions/gsd/session-forensics.ts +8 -23
  146. package/dist/resources/extensions/gsd/session-lock.ts +284 -0
  147. package/dist/resources/extensions/gsd/session-status-io.ts +23 -41
  148. package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +38 -1
  149. package/dist/resources/extensions/gsd/skills/gsd-headless/references/answer-injection.md +35 -6
  150. package/dist/resources/extensions/gsd/state.ts +54 -2
  151. package/dist/resources/extensions/gsd/structured-data-formatter.ts +144 -0
  152. package/dist/resources/extensions/gsd/summary-distiller.ts +258 -0
  153. package/dist/resources/extensions/gsd/tests/activity-log.test.ts +213 -0
  154. package/dist/resources/extensions/gsd/tests/agent-end-retry.test.ts +107 -0
  155. package/dist/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +197 -0
  156. package/dist/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  157. package/dist/resources/extensions/gsd/tests/auto-preflight.test.ts +33 -39
  158. package/dist/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +108 -2
  159. package/dist/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +257 -0
  160. package/dist/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
  161. package/dist/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +3 -0
  162. package/dist/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
  163. package/dist/resources/extensions/gsd/tests/context-budget.test.ts +69 -0
  164. package/dist/resources/extensions/gsd/tests/detection.test.ts +398 -0
  165. package/dist/resources/extensions/gsd/tests/discuss-prompt.test.ts +12 -24
  166. package/dist/resources/extensions/gsd/tests/dispatch-guard.test.ts +118 -94
  167. package/dist/resources/extensions/gsd/tests/dispatch-stall-guard.test.ts +126 -0
  168. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +7 -3
  169. package/dist/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +75 -0
  170. package/dist/resources/extensions/gsd/tests/doctor-git.test.ts +17 -55
  171. package/dist/resources/extensions/gsd/tests/export-html-enhancements.test.ts +375 -0
  172. package/dist/resources/extensions/gsd/tests/extension-selector-separator.test.ts +144 -0
  173. package/dist/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +3 -0
  174. package/dist/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
  175. package/dist/resources/extensions/gsd/tests/headless-answers.test.ts +340 -0
  176. package/dist/resources/extensions/gsd/tests/in-flight-tool-tracking.test.ts +24 -82
  177. package/dist/resources/extensions/gsd/tests/init-wizard.test.ts +197 -0
  178. package/dist/resources/extensions/gsd/tests/key-manager.test.ts +414 -0
  179. package/dist/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
  180. package/dist/resources/extensions/gsd/tests/metrics.test.ts +173 -305
  181. package/dist/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +3 -0
  182. package/dist/resources/extensions/gsd/tests/model-isolation.test.ts +59 -1
  183. package/dist/resources/extensions/gsd/tests/next-milestone-id.test.ts +18 -61
  184. package/dist/resources/extensions/gsd/tests/none-mode-gates.test.ts +17 -8
  185. package/dist/resources/extensions/gsd/tests/parallel-merge.test.ts +3 -0
  186. package/dist/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
  187. package/dist/resources/extensions/gsd/tests/park-edge-cases.test.ts +276 -0
  188. package/dist/resources/extensions/gsd/tests/park-milestone.test.ts +401 -0
  189. package/dist/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +24 -47
  190. package/dist/resources/extensions/gsd/tests/preferences.test.ts +284 -0
  191. package/dist/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +314 -0
  192. package/dist/resources/extensions/gsd/tests/prompt-compressor.test.ts +529 -0
  193. package/dist/resources/extensions/gsd/tests/prompt-ordering.test.ts +296 -0
  194. package/dist/resources/extensions/gsd/tests/provider-errors.test.ts +338 -0
  195. package/dist/resources/extensions/gsd/tests/reassess-detection.test.ts +154 -0
  196. package/dist/resources/extensions/gsd/tests/remote-questions.test.ts +1 -1
  197. package/dist/resources/extensions/gsd/tests/remote-status.test.ts +2 -2
  198. package/dist/resources/extensions/gsd/tests/roadmap-slices.test.ts +43 -60
  199. package/dist/resources/extensions/gsd/tests/semantic-chunker.test.ts +426 -0
  200. package/dist/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
  201. package/dist/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +3 -0
  202. package/dist/resources/extensions/gsd/tests/stop-auto-remote.test.ts +8 -5
  203. package/dist/resources/extensions/gsd/tests/structured-data-formatter.test.ts +365 -0
  204. package/dist/resources/extensions/gsd/tests/summary-distiller.test.ts +323 -0
  205. package/dist/resources/extensions/gsd/tests/token-counter.test.ts +129 -0
  206. package/dist/resources/extensions/gsd/tests/token-optimization-benchmark.test.ts +1272 -0
  207. package/dist/resources/extensions/gsd/tests/token-optimization-prefs.test.ts +164 -0
  208. package/dist/resources/extensions/gsd/tests/token-profile.test.ts +22 -17
  209. package/dist/resources/extensions/gsd/tests/triage-dispatch.test.ts +69 -73
  210. package/dist/resources/extensions/gsd/tests/validate-directory.test.ts +222 -0
  211. package/dist/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
  212. package/dist/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
  213. package/dist/resources/extensions/gsd/tests/verification-gate.test.ts +251 -8
  214. package/dist/resources/extensions/gsd/tests/visualizer-overlay.test.ts +2 -2
  215. package/dist/resources/extensions/gsd/tests/visualizer-views.test.ts +2 -1
  216. package/dist/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
  217. package/dist/resources/extensions/gsd/tests/workspace-index.test.ts +24 -61
  218. package/dist/resources/extensions/gsd/tests/worktree-e2e.test.ts +5 -2
  219. package/dist/resources/extensions/gsd/tests/write-gate.test.ts +132 -43
  220. package/dist/resources/extensions/gsd/token-counter.ts +20 -0
  221. package/dist/resources/extensions/gsd/triage-ui.ts +1 -1
  222. package/dist/resources/extensions/gsd/types.ts +7 -1
  223. package/dist/resources/extensions/gsd/unit-runtime.ts +16 -13
  224. package/dist/resources/extensions/gsd/validate-directory.ts +164 -0
  225. package/dist/resources/extensions/gsd/verification-evidence.ts +9 -4
  226. package/dist/resources/extensions/gsd/verification-gate.ts +83 -7
  227. package/dist/resources/extensions/gsd/visualizer-data.ts +1 -1
  228. package/dist/resources/extensions/gsd/visualizer-overlay.ts +5 -2
  229. package/dist/resources/extensions/gsd/visualizer-views.ts +2 -3
  230. package/dist/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
  231. package/dist/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
  232. package/dist/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
  233. package/dist/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
  234. package/dist/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
  235. package/dist/resources/extensions/gsd/workflow-templates/registry.json +85 -0
  236. package/dist/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
  237. package/dist/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
  238. package/dist/resources/extensions/gsd/workflow-templates/spike.md +69 -0
  239. package/dist/resources/extensions/gsd/workflow-templates.ts +241 -0
  240. package/dist/resources/extensions/gsd/worktree-command.ts +4 -51
  241. package/dist/resources/extensions/gsd/worktree-manager.ts +7 -9
  242. package/dist/resources/extensions/gsd/worktree.ts +41 -1
  243. package/dist/resources/extensions/mcp-client/index.ts +459 -0
  244. package/dist/resources/extensions/remote-questions/discord-adapter.ts +9 -20
  245. package/dist/resources/extensions/remote-questions/http-client.ts +76 -0
  246. package/dist/resources/extensions/remote-questions/manager.ts +6 -24
  247. package/dist/resources/extensions/remote-questions/mod.ts +16 -0
  248. package/dist/resources/extensions/remote-questions/notify.ts +90 -0
  249. package/dist/resources/extensions/remote-questions/remote-command.ts +1 -1
  250. package/dist/resources/extensions/remote-questions/slack-adapter.ts +11 -18
  251. package/dist/resources/extensions/remote-questions/store.ts +5 -1
  252. package/dist/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
  253. package/dist/resources/extensions/remote-questions/types.ts +29 -3
  254. package/dist/resources/extensions/search-the-web/native-search.ts +7 -0
  255. package/dist/resources/extensions/search-the-web/provider.ts +15 -3
  256. package/dist/resources/extensions/search-the-web/tool-llm-context.ts +1 -13
  257. package/dist/resources/extensions/search-the-web/tool-search.ts +1 -13
  258. package/dist/resources/extensions/shared/format-utils.ts +53 -0
  259. package/dist/resources/extensions/shared/frontmatter.ts +117 -0
  260. package/dist/resources/extensions/shared/mod.ts +33 -0
  261. package/dist/resources/extensions/shared/sanitize.ts +19 -0
  262. package/dist/resources/extensions/slash-commands/create-extension.ts +1 -1
  263. package/dist/resources/extensions/slash-commands/create-slash-command.ts +1 -1
  264. package/dist/resources/extensions/subagent/index.ts +1 -2
  265. package/dist/resources/extensions/ttsr/index.ts +5 -0
  266. package/dist/resources/extensions/ttsr/rule-loader.ts +4 -51
  267. package/dist/resources/extensions/universal-config/discovery.ts +37 -15
  268. package/dist/resources/extensions/voice/index.ts +1 -1
  269. package/dist/resources/skills/accessibility/SKILL.md +522 -0
  270. package/dist/resources/skills/accessibility/references/WCAG.md +162 -0
  271. package/dist/resources/skills/agent-browser/SKILL.md +517 -0
  272. package/dist/resources/skills/agent-browser/references/authentication.md +202 -0
  273. package/dist/resources/skills/agent-browser/references/commands.md +263 -0
  274. package/dist/resources/skills/agent-browser/references/profiling.md +120 -0
  275. package/dist/resources/skills/agent-browser/references/proxy-support.md +194 -0
  276. package/dist/resources/skills/agent-browser/references/session-management.md +193 -0
  277. package/dist/resources/skills/agent-browser/references/snapshot-refs.md +194 -0
  278. package/dist/resources/skills/agent-browser/references/video-recording.md +173 -0
  279. package/dist/resources/skills/agent-browser/templates/authenticated-session.sh +105 -0
  280. package/dist/resources/skills/agent-browser/templates/capture-workflow.sh +69 -0
  281. package/dist/resources/skills/agent-browser/templates/form-automation.sh +62 -0
  282. package/dist/resources/skills/best-practices/SKILL.md +583 -0
  283. package/dist/resources/skills/code-optimizer/SKILL.md +160 -0
  284. package/dist/resources/skills/code-optimizer/references/algorithmic-complexity.md +66 -0
  285. package/dist/resources/skills/code-optimizer/references/build-compilation.md +90 -0
  286. package/dist/resources/skills/code-optimizer/references/bundle-dependencies.md +82 -0
  287. package/dist/resources/skills/code-optimizer/references/caching-memoization.md +76 -0
  288. package/dist/resources/skills/code-optimizer/references/concurrency-async.md +80 -0
  289. package/dist/resources/skills/code-optimizer/references/config-infra.md +71 -0
  290. package/dist/resources/skills/code-optimizer/references/data-structures.md +80 -0
  291. package/dist/resources/skills/code-optimizer/references/database-queries.md +76 -0
  292. package/dist/resources/skills/code-optimizer/references/dead-code-redundancy.md +84 -0
  293. package/dist/resources/skills/code-optimizer/references/error-resilience.md +80 -0
  294. package/dist/resources/skills/code-optimizer/references/io-network.md +89 -0
  295. package/dist/resources/skills/code-optimizer/references/logging-observability.md +64 -0
  296. package/dist/resources/skills/code-optimizer/references/memory-resources.md +66 -0
  297. package/dist/resources/skills/code-optimizer/references/rendering-ui.md +90 -0
  298. package/dist/resources/skills/code-optimizer/references/security-performance.md +68 -0
  299. package/dist/resources/skills/core-web-vitals/SKILL.md +441 -0
  300. package/dist/resources/skills/core-web-vitals/references/LCP.md +208 -0
  301. package/dist/resources/skills/create-gsd-extension/SKILL.md +87 -0
  302. package/dist/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
  303. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
  304. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
  305. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
  306. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
  307. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
  308. package/dist/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
  309. package/dist/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
  310. package/dist/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
  311. package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
  312. package/dist/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
  313. package/dist/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
  314. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
  315. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
  316. package/dist/resources/skills/create-gsd-extension/references/state-management.md +70 -0
  317. package/dist/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
  318. package/dist/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
  319. package/dist/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
  320. package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
  321. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
  322. package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
  323. package/dist/resources/skills/create-skill/SKILL.md +184 -0
  324. package/dist/resources/skills/create-skill/references/api-security.md +226 -0
  325. package/dist/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
  326. package/dist/resources/skills/create-skill/references/common-patterns.md +595 -0
  327. package/dist/resources/skills/create-skill/references/core-principles.md +437 -0
  328. package/dist/resources/skills/create-skill/references/executable-code.md +175 -0
  329. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
  330. package/dist/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
  331. package/dist/resources/skills/create-skill/references/recommended-structure.md +168 -0
  332. package/dist/resources/skills/create-skill/references/skill-structure.md +372 -0
  333. package/dist/resources/skills/create-skill/references/use-xml-tags.md +466 -0
  334. package/dist/resources/skills/create-skill/references/using-scripts.md +113 -0
  335. package/dist/resources/skills/create-skill/references/using-templates.md +112 -0
  336. package/dist/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
  337. package/dist/resources/skills/create-skill/templates/router-skill.md +73 -0
  338. package/dist/resources/skills/create-skill/templates/simple-skill.md +33 -0
  339. package/dist/resources/skills/create-skill/workflows/add-reference.md +96 -0
  340. package/dist/resources/skills/create-skill/workflows/add-script.md +93 -0
  341. package/dist/resources/skills/create-skill/workflows/add-template.md +74 -0
  342. package/dist/resources/skills/create-skill/workflows/add-workflow.md +120 -0
  343. package/dist/resources/skills/create-skill/workflows/audit-skill.md +148 -0
  344. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
  345. package/dist/resources/skills/create-skill/workflows/get-guidance.md +121 -0
  346. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
  347. package/dist/resources/skills/create-skill/workflows/verify-skill.md +204 -0
  348. package/dist/resources/skills/make-interfaces-feel-better/SKILL.md +122 -0
  349. package/dist/resources/skills/make-interfaces-feel-better/animations.md +379 -0
  350. package/dist/resources/skills/make-interfaces-feel-better/performance.md +88 -0
  351. package/dist/resources/skills/make-interfaces-feel-better/surfaces.md +247 -0
  352. package/dist/resources/skills/make-interfaces-feel-better/typography.md +123 -0
  353. package/dist/resources/skills/react-best-practices/README.md +123 -0
  354. package/dist/resources/skills/react-best-practices/SKILL.md +136 -0
  355. package/dist/resources/skills/react-best-practices/metadata.json +15 -0
  356. package/dist/resources/skills/react-best-practices/rules/_sections.md +46 -0
  357. package/dist/resources/skills/react-best-practices/rules/_template.md +28 -0
  358. package/dist/resources/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  359. package/dist/resources/skills/react-best-practices/rules/advanced-init-once.md +42 -0
  360. package/dist/resources/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
  361. package/dist/resources/skills/react-best-practices/rules/async-api-routes.md +38 -0
  362. package/dist/resources/skills/react-best-practices/rules/async-defer-await.md +80 -0
  363. package/dist/resources/skills/react-best-practices/rules/async-dependencies.md +51 -0
  364. package/dist/resources/skills/react-best-practices/rules/async-parallel.md +28 -0
  365. package/dist/resources/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  366. package/dist/resources/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  367. package/dist/resources/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  368. package/dist/resources/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  369. package/dist/resources/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  370. package/dist/resources/skills/react-best-practices/rules/bundle-preload.md +50 -0
  371. package/dist/resources/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  372. package/dist/resources/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
  373. package/dist/resources/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  374. package/dist/resources/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  375. package/dist/resources/skills/react-best-practices/rules/js-batch-dom-css.md +107 -0
  376. package/dist/resources/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  377. package/dist/resources/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  378. package/dist/resources/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  379. package/dist/resources/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  380. package/dist/resources/skills/react-best-practices/rules/js-early-exit.md +50 -0
  381. package/dist/resources/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  382. package/dist/resources/skills/react-best-practices/rules/js-index-maps.md +37 -0
  383. package/dist/resources/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  384. package/dist/resources/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  385. package/dist/resources/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  386. package/dist/resources/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  387. package/dist/resources/skills/react-best-practices/rules/rendering-activity.md +26 -0
  388. package/dist/resources/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  389. package/dist/resources/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  390. package/dist/resources/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  391. package/dist/resources/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  392. package/dist/resources/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  393. package/dist/resources/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  394. package/dist/resources/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  395. package/dist/resources/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  396. package/dist/resources/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  397. package/dist/resources/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  398. package/dist/resources/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  399. package/dist/resources/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  400. package/dist/resources/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  401. package/dist/resources/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  402. package/dist/resources/skills/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  403. package/dist/resources/skills/react-best-practices/rules/rerender-memo.md +44 -0
  404. package/dist/resources/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  405. package/dist/resources/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  406. package/dist/resources/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  407. package/dist/resources/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  408. package/dist/resources/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  409. package/dist/resources/skills/react-best-practices/rules/server-auth-actions.md +96 -0
  410. package/dist/resources/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  411. package/dist/resources/skills/react-best-practices/rules/server-cache-react.md +76 -0
  412. package/dist/resources/skills/react-best-practices/rules/server-dedup-props.md +65 -0
  413. package/dist/resources/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  414. package/dist/resources/skills/react-best-practices/rules/server-serialization.md +38 -0
  415. package/dist/resources/skills/userinterface-wiki/SKILL.md +253 -0
  416. package/dist/resources/skills/userinterface-wiki/rules/_sections.md +66 -0
  417. package/dist/resources/skills/userinterface-wiki/rules/_template.md +24 -0
  418. package/dist/resources/skills/userinterface-wiki/rules/a11y-reduced-motion-check.md +30 -0
  419. package/dist/resources/skills/userinterface-wiki/rules/a11y-toggle-setting.md +30 -0
  420. package/dist/resources/skills/userinterface-wiki/rules/a11y-visual-equivalent.md +36 -0
  421. package/dist/resources/skills/userinterface-wiki/rules/a11y-volume-control.md +28 -0
  422. package/dist/resources/skills/userinterface-wiki/rules/appropriate-confirmations-only.md +19 -0
  423. package/dist/resources/skills/userinterface-wiki/rules/appropriate-errors-warnings.md +18 -0
  424. package/dist/resources/skills/userinterface-wiki/rules/appropriate-no-decorative.md +21 -0
  425. package/dist/resources/skills/userinterface-wiki/rules/appropriate-no-high-frequency.md +28 -0
  426. package/dist/resources/skills/userinterface-wiki/rules/appropriate-no-punishing.md +27 -0
  427. package/dist/resources/skills/userinterface-wiki/rules/container-callback-ref.md +31 -0
  428. package/dist/resources/skills/userinterface-wiki/rules/container-guard-initial-zero.md +25 -0
  429. package/dist/resources/skills/userinterface-wiki/rules/container-no-excessive-use.md +13 -0
  430. package/dist/resources/skills/userinterface-wiki/rules/container-overflow-hidden.md +25 -0
  431. package/dist/resources/skills/userinterface-wiki/rules/container-transition-delay.md +21 -0
  432. package/dist/resources/skills/userinterface-wiki/rules/container-two-div-pattern.md +35 -0
  433. package/dist/resources/skills/userinterface-wiki/rules/container-use-resize-observer.md +48 -0
  434. package/dist/resources/skills/userinterface-wiki/rules/context-cleanup-nodes.md +25 -0
  435. package/dist/resources/skills/userinterface-wiki/rules/context-resume-suspended.md +28 -0
  436. package/dist/resources/skills/userinterface-wiki/rules/context-reuse-single.md +30 -0
  437. package/dist/resources/skills/userinterface-wiki/rules/design-filter-for-character.md +25 -0
  438. package/dist/resources/skills/userinterface-wiki/rules/design-noise-for-percussion.md +26 -0
  439. package/dist/resources/skills/userinterface-wiki/rules/design-oscillator-for-tonal.md +22 -0
  440. package/dist/resources/skills/userinterface-wiki/rules/duration-max-300ms.md +21 -0
  441. package/dist/resources/skills/userinterface-wiki/rules/duration-press-hover.md +21 -0
  442. package/dist/resources/skills/userinterface-wiki/rules/duration-shorten-before-curve.md +21 -0
  443. package/dist/resources/skills/userinterface-wiki/rules/duration-small-state.md +15 -0
  444. package/dist/resources/skills/userinterface-wiki/rules/easing-entrance-ease-out.md +21 -0
  445. package/dist/resources/skills/userinterface-wiki/rules/easing-exit-ease-in.md +21 -0
  446. package/dist/resources/skills/userinterface-wiki/rules/easing-for-state-change.md +27 -0
  447. package/dist/resources/skills/userinterface-wiki/rules/easing-linear-only-progress.md +21 -0
  448. package/dist/resources/skills/userinterface-wiki/rules/easing-natural-decay.md +22 -0
  449. package/dist/resources/skills/userinterface-wiki/rules/easing-no-linear-motion.md +22 -0
  450. package/dist/resources/skills/userinterface-wiki/rules/easing-transition-ease-in-out.md +15 -0
  451. package/dist/resources/skills/userinterface-wiki/rules/envelope-exponential-decay.md +21 -0
  452. package/dist/resources/skills/userinterface-wiki/rules/envelope-no-zero-target.md +21 -0
  453. package/dist/resources/skills/userinterface-wiki/rules/envelope-set-initial-value.md +22 -0
  454. package/dist/resources/skills/userinterface-wiki/rules/exit-key-required.md +29 -0
  455. package/dist/resources/skills/userinterface-wiki/rules/exit-matches-initial.md +29 -0
  456. package/dist/resources/skills/userinterface-wiki/rules/exit-prop-required.md +33 -0
  457. package/dist/resources/skills/userinterface-wiki/rules/exit-requires-wrapper.md +27 -0
  458. package/dist/resources/skills/userinterface-wiki/rules/impl-default-subtle.md +21 -0
  459. package/dist/resources/skills/userinterface-wiki/rules/impl-preload-audio.md +34 -0
  460. package/dist/resources/skills/userinterface-wiki/rules/impl-reset-current-time.md +26 -0
  461. package/dist/resources/skills/userinterface-wiki/rules/mode-pop-layout-for-lists.md +25 -0
  462. package/dist/resources/skills/userinterface-wiki/rules/mode-sync-layout-conflict.md +29 -0
  463. package/dist/resources/skills/userinterface-wiki/rules/mode-wait-doubles-duration.md +25 -0
  464. package/dist/resources/skills/userinterface-wiki/rules/morphing-aria-hidden.md +21 -0
  465. package/dist/resources/skills/userinterface-wiki/rules/morphing-consistent-viewbox.md +23 -0
  466. package/dist/resources/skills/userinterface-wiki/rules/morphing-group-variants.md +33 -0
  467. package/dist/resources/skills/userinterface-wiki/rules/morphing-jump-non-grouped.md +29 -0
  468. package/dist/resources/skills/userinterface-wiki/rules/morphing-reduced-motion.md +28 -0
  469. package/dist/resources/skills/userinterface-wiki/rules/morphing-spring-rotation.md +23 -0
  470. package/dist/resources/skills/userinterface-wiki/rules/morphing-strokelinecap-round.md +21 -0
  471. package/dist/resources/skills/userinterface-wiki/rules/morphing-three-lines.md +32 -0
  472. package/dist/resources/skills/userinterface-wiki/rules/morphing-use-collapsed.md +33 -0
  473. package/dist/resources/skills/userinterface-wiki/rules/native-backdrop-styling.md +27 -0
  474. package/dist/resources/skills/userinterface-wiki/rules/native-placeholder-styling.md +27 -0
  475. package/dist/resources/skills/userinterface-wiki/rules/native-selection-styling.md +18 -0
  476. package/dist/resources/skills/userinterface-wiki/rules/nested-consistent-timing.md +25 -0
  477. package/dist/resources/skills/userinterface-wiki/rules/nested-propagate-required.md +41 -0
  478. package/dist/resources/skills/userinterface-wiki/rules/none-context-menu-entrance.md +25 -0
  479. package/dist/resources/skills/userinterface-wiki/rules/none-high-frequency.md +29 -0
  480. package/dist/resources/skills/userinterface-wiki/rules/none-keyboard-navigation.md +32 -0
  481. package/dist/resources/skills/userinterface-wiki/rules/param-click-duration.md +21 -0
  482. package/dist/resources/skills/userinterface-wiki/rules/param-filter-frequency-range.md +21 -0
  483. package/dist/resources/skills/userinterface-wiki/rules/param-q-value-range.md +21 -0
  484. package/dist/resources/skills/userinterface-wiki/rules/param-reasonable-gain.md +21 -0
  485. package/dist/resources/skills/userinterface-wiki/rules/physics-active-state.md +23 -0
  486. package/dist/resources/skills/userinterface-wiki/rules/physics-no-excessive-stagger.md +22 -0
  487. package/dist/resources/skills/userinterface-wiki/rules/physics-spring-for-overshoot.md +23 -0
  488. package/dist/resources/skills/userinterface-wiki/rules/physics-subtle-deformation.md +22 -0
  489. package/dist/resources/skills/userinterface-wiki/rules/prefetch-hit-slop.md +27 -0
  490. package/dist/resources/skills/userinterface-wiki/rules/prefetch-keyboard-tab.md +19 -0
  491. package/dist/resources/skills/userinterface-wiki/rules/prefetch-not-everything.md +22 -0
  492. package/dist/resources/skills/userinterface-wiki/rules/prefetch-touch-fallback.md +34 -0
  493. package/dist/resources/skills/userinterface-wiki/rules/prefetch-trajectory-over-hover.md +32 -0
  494. package/dist/resources/skills/userinterface-wiki/rules/prefetch-use-selectively.md +13 -0
  495. package/dist/resources/skills/userinterface-wiki/rules/presence-disable-interactions.md +31 -0
  496. package/dist/resources/skills/userinterface-wiki/rules/presence-hook-in-child.md +31 -0
  497. package/dist/resources/skills/userinterface-wiki/rules/presence-safe-to-remove.md +37 -0
  498. package/dist/resources/skills/userinterface-wiki/rules/pseudo-content-required.md +28 -0
  499. package/dist/resources/skills/userinterface-wiki/rules/pseudo-first-line-styling.md +27 -0
  500. package/dist/resources/skills/userinterface-wiki/rules/pseudo-hit-target-expansion.md +31 -0
  501. package/dist/resources/skills/userinterface-wiki/rules/pseudo-marker-styling.md +28 -0
  502. package/dist/resources/skills/userinterface-wiki/rules/pseudo-over-dom-node.md +32 -0
  503. package/dist/resources/skills/userinterface-wiki/rules/pseudo-position-relative-parent.md +33 -0
  504. package/dist/resources/skills/userinterface-wiki/rules/pseudo-z-index-layering.md +37 -0
  505. package/dist/resources/skills/userinterface-wiki/rules/spring-for-gestures.md +27 -0
  506. package/dist/resources/skills/userinterface-wiki/rules/spring-for-interruptible.md +27 -0
  507. package/dist/resources/skills/userinterface-wiki/rules/spring-params-balanced.md +29 -0
  508. package/dist/resources/skills/userinterface-wiki/rules/spring-preserves-velocity.md +28 -0
  509. package/dist/resources/skills/userinterface-wiki/rules/staging-dim-background.md +22 -0
  510. package/dist/resources/skills/userinterface-wiki/rules/staging-one-focal-point.md +24 -0
  511. package/dist/resources/skills/userinterface-wiki/rules/staging-z-index-hierarchy.md +22 -0
  512. package/dist/resources/skills/userinterface-wiki/rules/timing-consistent.md +24 -0
  513. package/dist/resources/skills/userinterface-wiki/rules/timing-no-entrance-context-menu.md +22 -0
  514. package/dist/resources/skills/userinterface-wiki/rules/timing-under-300ms.md +22 -0
  515. package/dist/resources/skills/userinterface-wiki/rules/transition-name-cleanup.md +28 -0
  516. package/dist/resources/skills/userinterface-wiki/rules/transition-name-required.md +27 -0
  517. package/dist/resources/skills/userinterface-wiki/rules/transition-name-unique.md +24 -0
  518. package/dist/resources/skills/userinterface-wiki/rules/transition-over-js-library.md +32 -0
  519. package/dist/resources/skills/userinterface-wiki/rules/transition-style-pseudo-elements.md +24 -0
  520. package/dist/resources/skills/userinterface-wiki/rules/type-antialiased-on-retina.md +18 -0
  521. package/dist/resources/skills/userinterface-wiki/rules/type-disambiguation-stylistic-set.md +15 -0
  522. package/dist/resources/skills/userinterface-wiki/rules/type-font-display-swap.md +28 -0
  523. package/dist/resources/skills/userinterface-wiki/rules/type-justify-with-hyphens.md +24 -0
  524. package/dist/resources/skills/userinterface-wiki/rules/type-letter-spacing-uppercase.md +28 -0
  525. package/dist/resources/skills/userinterface-wiki/rules/type-no-font-synthesis.md +18 -0
  526. package/dist/resources/skills/userinterface-wiki/rules/type-oldstyle-nums-for-prose.md +21 -0
  527. package/dist/resources/skills/userinterface-wiki/rules/type-opentype-contextual-alternates.md +15 -0
  528. package/dist/resources/skills/userinterface-wiki/rules/type-optical-sizing-auto.md +25 -0
  529. package/dist/resources/skills/userinterface-wiki/rules/type-proper-fractions.md +15 -0
  530. package/dist/resources/skills/userinterface-wiki/rules/type-slashed-zero.md +17 -0
  531. package/dist/resources/skills/userinterface-wiki/rules/type-tabular-nums-for-data.md +21 -0
  532. package/dist/resources/skills/userinterface-wiki/rules/type-text-wrap-balance-headings.md +21 -0
  533. package/dist/resources/skills/userinterface-wiki/rules/type-text-wrap-pretty.md +16 -0
  534. package/dist/resources/skills/userinterface-wiki/rules/type-underline-offset.md +25 -0
  535. package/dist/resources/skills/userinterface-wiki/rules/type-variable-weight-continuous.md +23 -0
  536. package/dist/resources/skills/userinterface-wiki/rules/ux-aesthetic-usability.md +32 -0
  537. package/dist/resources/skills/userinterface-wiki/rules/ux-cognitive-load-reduce.md +49 -0
  538. package/dist/resources/skills/userinterface-wiki/rules/ux-common-region-boundaries.md +50 -0
  539. package/dist/resources/skills/userinterface-wiki/rules/ux-doherty-perceived-speed.md +29 -0
  540. package/dist/resources/skills/userinterface-wiki/rules/ux-doherty-under-400ms.md +30 -0
  541. package/dist/resources/skills/userinterface-wiki/rules/ux-fitts-hit-area.md +32 -0
  542. package/dist/resources/skills/userinterface-wiki/rules/ux-fitts-target-size.md +31 -0
  543. package/dist/resources/skills/userinterface-wiki/rules/ux-goal-gradient-progress.md +33 -0
  544. package/dist/resources/skills/userinterface-wiki/rules/ux-hicks-minimize-choices.md +45 -0
  545. package/dist/resources/skills/userinterface-wiki/rules/ux-jakobs-familiar-patterns.md +37 -0
  546. package/dist/resources/skills/userinterface-wiki/rules/ux-millers-chunking.md +23 -0
  547. package/dist/resources/skills/userinterface-wiki/rules/ux-pareto-prioritize-features.md +36 -0
  548. package/dist/resources/skills/userinterface-wiki/rules/ux-peak-end-finish-strong.md +35 -0
  549. package/dist/resources/skills/userinterface-wiki/rules/ux-postels-accept-messy-input.md +45 -0
  550. package/dist/resources/skills/userinterface-wiki/rules/ux-pragnanz-simplify.md +33 -0
  551. package/dist/resources/skills/userinterface-wiki/rules/ux-progressive-disclosure.md +41 -0
  552. package/dist/resources/skills/userinterface-wiki/rules/ux-proximity-grouping.md +38 -0
  553. package/dist/resources/skills/userinterface-wiki/rules/ux-serial-position.md +31 -0
  554. package/dist/resources/skills/userinterface-wiki/rules/ux-similarity-consistency.md +35 -0
  555. package/dist/resources/skills/userinterface-wiki/rules/ux-teslers-complexity.md +28 -0
  556. package/dist/resources/skills/userinterface-wiki/rules/ux-uniform-connectedness.md +43 -0
  557. package/dist/resources/skills/userinterface-wiki/rules/ux-von-restorff-emphasis.md +29 -0
  558. package/dist/resources/skills/userinterface-wiki/rules/ux-zeigarnik-show-incomplete.md +36 -0
  559. package/dist/resources/skills/userinterface-wiki/rules/visual-animate-shadow-pseudo.md +49 -0
  560. package/dist/resources/skills/userinterface-wiki/rules/visual-border-alpha-colors.md +25 -0
  561. package/dist/resources/skills/userinterface-wiki/rules/visual-button-shadow-anatomy.md +49 -0
  562. package/dist/resources/skills/userinterface-wiki/rules/visual-concentric-radius.md +40 -0
  563. package/dist/resources/skills/userinterface-wiki/rules/visual-consistent-spacing-scale.md +35 -0
  564. package/dist/resources/skills/userinterface-wiki/rules/visual-layered-shadows.md +30 -0
  565. package/dist/resources/skills/userinterface-wiki/rules/visual-no-pure-black-shadow.md +25 -0
  566. package/dist/resources/skills/userinterface-wiki/rules/visual-shadow-direction.md +25 -0
  567. package/dist/resources/skills/userinterface-wiki/rules/visual-shadow-matches-elevation.md +23 -0
  568. package/dist/resources/skills/userinterface-wiki/rules/weight-duration-matches-action.md +29 -0
  569. package/dist/resources/skills/userinterface-wiki/rules/weight-match-action.md +32 -0
  570. package/dist/resources/skills/web-design-guidelines/SKILL.md +39 -0
  571. package/dist/resources/skills/web-quality-audit/SKILL.md +170 -0
  572. package/dist/resources/skills/web-quality-audit/scripts/analyze.sh +91 -0
  573. package/package.json +22 -8
  574. package/packages/native/dist/native.d.ts +2 -0
  575. package/packages/native/dist/native.js +19 -5
  576. package/packages/native/package.json +28 -0
  577. package/packages/native/src/native.ts +23 -9
  578. package/packages/pi-agent-core/package.json +6 -0
  579. package/packages/pi-ai/dist/models.generated.d.ts +43 -11
  580. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  581. package/packages/pi-ai/dist/models.generated.js +34 -26
  582. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  583. package/packages/pi-ai/dist/providers/anthropic.js +3 -2
  584. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  585. package/packages/pi-ai/dist/providers/openai-codex-responses.js +14 -4
  586. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  587. package/packages/pi-ai/oauth.d.ts +1 -0
  588. package/packages/pi-ai/oauth.js +1 -0
  589. package/packages/pi-ai/package.json +2 -2
  590. package/packages/pi-ai/src/models.generated.ts +42 -34
  591. package/packages/pi-ai/src/providers/anthropic.ts +3 -2
  592. package/packages/pi-ai/src/providers/openai-codex-responses.ts +15 -4
  593. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  594. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  595. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  596. package/packages/pi-coding-agent/dist/core/auth-storage.js +2 -1
  597. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  598. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  599. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js +2 -1
  600. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
  601. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  602. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +3 -2
  603. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  604. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts.map +1 -1
  605. package/packages/pi-coding-agent/dist/core/compaction/utils.js +2 -2
  606. package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
  607. package/packages/pi-coding-agent/dist/core/constants.d.ts +29 -0
  608. package/packages/pi-coding-agent/dist/core/constants.d.ts.map +1 -0
  609. package/packages/pi-coding-agent/dist/core/constants.js +44 -0
  610. package/packages/pi-coding-agent/dist/core/constants.js.map +1 -0
  611. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  612. package/packages/pi-coding-agent/dist/core/extensions/loader.js +14 -1
  613. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  614. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  615. package/packages/pi-coding-agent/dist/core/lsp/client.js +3 -0
  616. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  617. package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
  618. package/packages/pi-coding-agent/dist/core/lsp/index.js +30 -4
  619. package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
  620. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
  621. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +13 -5
  622. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
  623. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  624. package/packages/pi-coding-agent/dist/core/model-resolver.js +14 -0
  625. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  626. package/packages/pi-coding-agent/dist/core/resolve-config-value.d.ts.map +1 -1
  627. package/packages/pi-coding-agent/dist/core/resolve-config-value.js +12 -4
  628. package/packages/pi-coding-agent/dist/core/resolve-config-value.js.map +1 -1
  629. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +49 -0
  630. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  631. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  632. package/packages/pi-coding-agent/dist/core/session-manager.js +25 -2
  633. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  634. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +6 -0
  635. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  636. package/packages/pi-coding-agent/dist/core/settings-manager.js +22 -5
  637. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  638. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  639. package/packages/pi-coding-agent/dist/core/system-prompt.js +10 -0
  640. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  641. package/packages/pi-coding-agent/dist/core/tools/edit-diff.js +2 -2
  642. package/packages/pi-coding-agent/dist/core/tools/edit-diff.js.map +1 -1
  643. package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
  644. package/packages/pi-coding-agent/dist/core/tools/find.js +2 -1
  645. package/packages/pi-coding-agent/dist/core/tools/find.js.map +1 -1
  646. package/packages/pi-coding-agent/dist/core/tools/hashline-edit.js +4 -4
  647. package/packages/pi-coding-agent/dist/core/tools/hashline-edit.js.map +1 -1
  648. package/packages/pi-coding-agent/dist/core/tools/hashline.d.ts +1 -1
  649. package/packages/pi-coding-agent/dist/core/tools/hashline.js +1 -1
  650. package/packages/pi-coding-agent/dist/core/tools/hashline.js.map +1 -1
  651. package/packages/pi-coding-agent/dist/core/tools/hashline.test.js +8 -8
  652. package/packages/pi-coding-agent/dist/core/tools/hashline.test.js.map +1 -1
  653. package/packages/pi-coding-agent/dist/core/tools/index.d.ts +1 -1
  654. package/packages/pi-coding-agent/dist/core/tools/index.js +1 -1
  655. package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
  656. package/packages/pi-coding-agent/dist/core/tools/path-utils.d.ts +1 -0
  657. package/packages/pi-coding-agent/dist/core/tools/path-utils.d.ts.map +1 -1
  658. package/packages/pi-coding-agent/dist/core/tools/path-utils.js +1 -1
  659. package/packages/pi-coding-agent/dist/core/tools/path-utils.js.map +1 -1
  660. package/packages/pi-coding-agent/dist/core/tools/truncate.d.ts.map +1 -1
  661. package/packages/pi-coding-agent/dist/core/tools/truncate.js +2 -1
  662. package/packages/pi-coding-agent/dist/core/tools/truncate.js.map +1 -1
  663. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-selector.d.ts +9 -0
  664. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  665. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-selector.js +47 -5
  666. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-selector.js.map +1 -1
  667. package/packages/pi-coding-agent/dist/modes/interactive/components/index.d.ts +1 -1
  668. package/packages/pi-coding-agent/dist/modes/interactive/components/index.d.ts.map +1 -1
  669. package/packages/pi-coding-agent/dist/modes/interactive/components/index.js +1 -1
  670. package/packages/pi-coding-agent/dist/modes/interactive/components/index.js.map +1 -1
  671. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +4 -4
  672. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  673. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  674. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  675. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
  676. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  677. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  678. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +25 -1
  679. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  680. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  681. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +12 -2
  682. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  683. package/packages/pi-coding-agent/dist/resources/extensions/memory/pipeline.d.ts.map +1 -1
  684. package/packages/pi-coding-agent/dist/resources/extensions/memory/pipeline.js +25 -3
  685. package/packages/pi-coding-agent/dist/resources/extensions/memory/pipeline.js.map +1 -1
  686. package/packages/pi-coding-agent/package.json +1 -5
  687. package/packages/pi-coding-agent/scripts/copy-assets.cjs +39 -8
  688. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  689. package/packages/pi-coding-agent/src/core/auth-storage.ts +2 -1
  690. package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +2 -1
  691. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +3 -2
  692. package/packages/pi-coding-agent/src/core/compaction/utils.ts +2 -2
  693. package/packages/pi-coding-agent/src/core/constants.ts +59 -0
  694. package/packages/pi-coding-agent/src/core/extensions/loader.ts +14 -1
  695. package/packages/pi-coding-agent/src/core/lsp/client.ts +3 -0
  696. package/packages/pi-coding-agent/src/core/lsp/index.ts +31 -5
  697. package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +13 -5
  698. package/packages/pi-coding-agent/src/core/model-resolver.ts +14 -0
  699. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +58 -0
  700. package/packages/pi-coding-agent/src/core/resolve-config-value.ts +14 -4
  701. package/packages/pi-coding-agent/src/core/session-manager.ts +29 -6
  702. package/packages/pi-coding-agent/src/core/settings-manager.ts +33 -5
  703. package/packages/pi-coding-agent/src/core/system-prompt.ts +11 -0
  704. package/packages/pi-coding-agent/src/core/tools/edit-diff.ts +2 -2
  705. package/packages/pi-coding-agent/src/core/tools/find.ts +2 -1
  706. package/packages/pi-coding-agent/src/core/tools/hashline-edit.ts +4 -4
  707. package/packages/pi-coding-agent/src/core/tools/hashline.test.ts +8 -8
  708. package/packages/pi-coding-agent/src/core/tools/hashline.ts +1 -1
  709. package/packages/pi-coding-agent/src/core/tools/index.ts +1 -1
  710. package/packages/pi-coding-agent/src/core/tools/path-utils.ts +1 -1
  711. package/packages/pi-coding-agent/src/core/tools/truncate.ts +3 -1
  712. package/packages/pi-coding-agent/src/modes/interactive/components/extension-selector.ts +49 -5
  713. package/packages/pi-coding-agent/src/modes/interactive/components/index.ts +1 -1
  714. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +4 -4
  715. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  716. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +26 -0
  717. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +11 -2
  718. package/packages/pi-coding-agent/src/resources/extensions/memory/pipeline.ts +23 -3
  719. package/packages/pi-tui/dist/__tests__/autocomplete.test.d.ts +2 -0
  720. package/packages/pi-tui/dist/__tests__/autocomplete.test.d.ts.map +1 -0
  721. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +149 -0
  722. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -0
  723. package/packages/pi-tui/dist/__tests__/fuzzy.test.d.ts +2 -0
  724. package/packages/pi-tui/dist/__tests__/fuzzy.test.d.ts.map +1 -0
  725. package/packages/pi-tui/dist/__tests__/fuzzy.test.js +94 -0
  726. package/packages/pi-tui/dist/__tests__/fuzzy.test.js.map +1 -0
  727. package/packages/pi-tui/dist/autocomplete.d.ts +8 -1
  728. package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
  729. package/packages/pi-tui/dist/autocomplete.js +20 -2
  730. package/packages/pi-tui/dist/autocomplete.js.map +1 -1
  731. package/packages/pi-tui/package.json +8 -2
  732. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +186 -0
  733. package/packages/pi-tui/src/__tests__/fuzzy.test.ts +112 -0
  734. package/packages/pi-tui/src/autocomplete.ts +26 -1
  735. package/pkg/package.json +1 -1
  736. package/src/resources/extensions/ask-user-questions.ts +3 -2
  737. package/src/resources/extensions/bg-shell/bg-shell-command.ts +219 -0
  738. package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +400 -0
  739. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +985 -0
  740. package/src/resources/extensions/bg-shell/index.ts +17 -1561
  741. package/src/resources/extensions/bg-shell/overlay.ts +4 -0
  742. package/src/resources/extensions/bg-shell/process-manager.ts +13 -0
  743. package/src/resources/extensions/bg-shell/utilities.ts +4 -16
  744. package/src/resources/extensions/browser-tools/capture.ts +34 -2
  745. package/src/resources/extensions/browser-tools/lifecycle.ts +5 -5
  746. package/src/resources/extensions/browser-tools/settle.ts +1 -1
  747. package/src/resources/extensions/browser-tools/state.ts +5 -5
  748. package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +1 -1
  749. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +3 -3
  750. package/src/resources/extensions/browser-tools/tools/assertions.ts +1 -1
  751. package/src/resources/extensions/browser-tools/tools/device.ts +1 -1
  752. package/src/resources/extensions/browser-tools/tools/extract.ts +1 -1
  753. package/src/resources/extensions/browser-tools/tools/navigation.ts +6 -6
  754. package/src/resources/extensions/browser-tools/tools/network-mock.ts +1 -1
  755. package/src/resources/extensions/browser-tools/tools/pages.ts +1 -1
  756. package/src/resources/extensions/browser-tools/tools/screenshot.ts +28 -10
  757. package/src/resources/extensions/browser-tools/tools/state-persistence.ts +1 -1
  758. package/src/resources/extensions/browser-tools/tools/visual-diff.ts +1 -1
  759. package/src/resources/extensions/browser-tools/utils.ts +5 -5
  760. package/src/resources/extensions/get-secrets-from-user.ts +1 -1
  761. package/src/resources/extensions/google-search/index.ts +21 -8
  762. package/src/resources/extensions/gsd/activity-log.ts +2 -1
  763. package/src/resources/extensions/gsd/atomic-write.ts +35 -0
  764. package/src/resources/extensions/gsd/auto/session.ts +12 -0
  765. package/src/resources/extensions/gsd/auto-dashboard.ts +295 -62
  766. package/src/resources/extensions/gsd/auto-dispatch.ts +2 -2
  767. package/src/resources/extensions/gsd/auto-idempotency.ts +150 -0
  768. package/src/resources/extensions/gsd/auto-post-unit.ts +633 -0
  769. package/src/resources/extensions/gsd/auto-prompts.ts +139 -32
  770. package/src/resources/extensions/gsd/auto-recovery.ts +36 -31
  771. package/src/resources/extensions/gsd/auto-start.ts +500 -0
  772. package/src/resources/extensions/gsd/auto-stuck-detection.ts +220 -0
  773. package/src/resources/extensions/gsd/auto-timers.ts +223 -0
  774. package/src/resources/extensions/gsd/auto-unit-closeout.ts +3 -1
  775. package/src/resources/extensions/gsd/auto-verification.ts +229 -0
  776. package/src/resources/extensions/gsd/auto-worktree-sync.ts +29 -37
  777. package/src/resources/extensions/gsd/auto-worktree.ts +92 -67
  778. package/src/resources/extensions/gsd/auto.ts +375 -1890
  779. package/src/resources/extensions/gsd/commands-config.ts +102 -0
  780. package/src/resources/extensions/gsd/commands-handlers.ts +394 -0
  781. package/src/resources/extensions/gsd/commands-inspect.ts +90 -0
  782. package/src/resources/extensions/gsd/commands-logs.ts +536 -0
  783. package/src/resources/extensions/gsd/commands-maintenance.ts +206 -0
  784. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +790 -0
  785. package/src/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
  786. package/src/resources/extensions/gsd/commands.ts +417 -1495
  787. package/src/resources/extensions/gsd/constants.ts +21 -0
  788. package/src/resources/extensions/gsd/context-budget.ts +25 -2
  789. package/src/resources/extensions/gsd/crash-recovery.ts +3 -4
  790. package/src/resources/extensions/gsd/dashboard-overlay.ts +15 -5
  791. package/src/resources/extensions/gsd/db-writer.ts +21 -2
  792. package/src/resources/extensions/gsd/detection.ts +469 -0
  793. package/src/resources/extensions/gsd/diff-context.ts +2 -1
  794. package/src/resources/extensions/gsd/dispatch-guard.ts +4 -0
  795. package/src/resources/extensions/gsd/doctor-checks.ts +564 -0
  796. package/src/resources/extensions/gsd/doctor-format.ts +78 -0
  797. package/src/resources/extensions/gsd/doctor-types.ts +72 -0
  798. package/src/resources/extensions/gsd/doctor.ts +64 -701
  799. package/src/resources/extensions/gsd/errors.ts +0 -2
  800. package/src/resources/extensions/gsd/export-html.ts +367 -11
  801. package/src/resources/extensions/gsd/export.ts +31 -5
  802. package/src/resources/extensions/gsd/files.ts +8 -126
  803. package/src/resources/extensions/gsd/forensics.ts +2 -12
  804. package/src/resources/extensions/gsd/git-constants.ts +11 -0
  805. package/src/resources/extensions/gsd/git-service.ts +13 -9
  806. package/src/resources/extensions/gsd/gsd-db.ts +26 -6
  807. package/src/resources/extensions/gsd/guided-flow-queue.ts +451 -0
  808. package/src/resources/extensions/gsd/guided-flow.ts +231 -514
  809. package/src/resources/extensions/gsd/history.ts +2 -20
  810. package/src/resources/extensions/gsd/index.ts +208 -46
  811. package/src/resources/extensions/gsd/init-wizard.ts +615 -0
  812. package/src/resources/extensions/gsd/json-persistence.ts +67 -0
  813. package/src/resources/extensions/gsd/jsonl-utils.ts +21 -0
  814. package/src/resources/extensions/gsd/key-manager.ts +995 -0
  815. package/src/resources/extensions/gsd/mechanical-completion.ts +430 -0
  816. package/src/resources/extensions/gsd/metrics.ts +49 -36
  817. package/src/resources/extensions/gsd/migrate/command.ts +1 -1
  818. package/src/resources/extensions/gsd/migrate/parsers.ts +10 -95
  819. package/src/resources/extensions/gsd/milestone-actions.ts +126 -0
  820. package/src/resources/extensions/gsd/milestone-ids.ts +95 -0
  821. package/src/resources/extensions/gsd/native-git-bridge.ts +5 -10
  822. package/src/resources/extensions/gsd/parallel-eligibility.ts +3 -3
  823. package/src/resources/extensions/gsd/paths.ts +18 -11
  824. package/src/resources/extensions/gsd/plugin-importer.ts +3 -2
  825. package/src/resources/extensions/gsd/preferences-models.ts +329 -0
  826. package/src/resources/extensions/gsd/preferences-skills.ts +169 -0
  827. package/src/resources/extensions/gsd/preferences-types.ts +223 -0
  828. package/src/resources/extensions/gsd/preferences-validation.ts +598 -0
  829. package/src/resources/extensions/gsd/preferences.ts +219 -1305
  830. package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +213 -0
  831. package/src/resources/extensions/gsd/prompt-compressor.ts +508 -0
  832. package/src/resources/extensions/gsd/prompt-loader.ts +4 -2
  833. package/src/resources/extensions/gsd/prompt-ordering.ts +200 -0
  834. package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -2
  835. package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -4
  836. package/src/resources/extensions/gsd/prompts/discuss-headless.md +6 -6
  837. package/src/resources/extensions/gsd/prompts/discuss.md +13 -5
  838. package/src/resources/extensions/gsd/prompts/execute-task.md +0 -1
  839. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  840. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  841. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +0 -1
  842. package/src/resources/extensions/gsd/prompts/plan-milestone.md +26 -3
  843. package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  844. package/src/resources/extensions/gsd/prompts/queue.md +30 -0
  845. package/src/resources/extensions/gsd/prompts/quick-task.md +0 -6
  846. package/src/resources/extensions/gsd/prompts/replan-slice.md +0 -1
  847. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +0 -1
  848. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  849. package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
  850. package/src/resources/extensions/gsd/provider-error-pause.ts +59 -10
  851. package/src/resources/extensions/gsd/queue-order.ts +11 -12
  852. package/src/resources/extensions/gsd/queue-reorder-ui.ts +15 -2
  853. package/src/resources/extensions/gsd/quick.ts +18 -15
  854. package/src/resources/extensions/gsd/reports.ts +1 -7
  855. package/src/resources/extensions/gsd/routing-history.ts +13 -17
  856. package/src/resources/extensions/gsd/safe-fs.ts +47 -0
  857. package/src/resources/extensions/gsd/semantic-chunker.ts +336 -0
  858. package/src/resources/extensions/gsd/session-forensics.ts +8 -23
  859. package/src/resources/extensions/gsd/session-lock.ts +284 -0
  860. package/src/resources/extensions/gsd/session-status-io.ts +23 -41
  861. package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +38 -1
  862. package/src/resources/extensions/gsd/skills/gsd-headless/references/answer-injection.md +35 -6
  863. package/src/resources/extensions/gsd/state.ts +54 -2
  864. package/src/resources/extensions/gsd/structured-data-formatter.ts +144 -0
  865. package/src/resources/extensions/gsd/summary-distiller.ts +258 -0
  866. package/src/resources/extensions/gsd/tests/activity-log.test.ts +213 -0
  867. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +107 -0
  868. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +197 -0
  869. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  870. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +33 -39
  871. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +108 -2
  872. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +257 -0
  873. package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
  874. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +3 -0
  875. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
  876. package/src/resources/extensions/gsd/tests/context-budget.test.ts +69 -0
  877. package/src/resources/extensions/gsd/tests/detection.test.ts +398 -0
  878. package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +12 -24
  879. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +118 -94
  880. package/src/resources/extensions/gsd/tests/dispatch-stall-guard.test.ts +126 -0
  881. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +7 -3
  882. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +75 -0
  883. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +17 -55
  884. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +375 -0
  885. package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +144 -0
  886. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +3 -0
  887. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
  888. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +340 -0
  889. package/src/resources/extensions/gsd/tests/in-flight-tool-tracking.test.ts +24 -82
  890. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +197 -0
  891. package/src/resources/extensions/gsd/tests/key-manager.test.ts +414 -0
  892. package/src/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
  893. package/src/resources/extensions/gsd/tests/metrics.test.ts +173 -305
  894. package/src/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +3 -0
  895. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +59 -1
  896. package/src/resources/extensions/gsd/tests/next-milestone-id.test.ts +18 -61
  897. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +17 -8
  898. package/src/resources/extensions/gsd/tests/parallel-merge.test.ts +3 -0
  899. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
  900. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +276 -0
  901. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +401 -0
  902. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +24 -47
  903. package/src/resources/extensions/gsd/tests/preferences.test.ts +284 -0
  904. package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +314 -0
  905. package/src/resources/extensions/gsd/tests/prompt-compressor.test.ts +529 -0
  906. package/src/resources/extensions/gsd/tests/prompt-ordering.test.ts +296 -0
  907. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +338 -0
  908. package/src/resources/extensions/gsd/tests/reassess-detection.test.ts +154 -0
  909. package/src/resources/extensions/gsd/tests/remote-questions.test.ts +1 -1
  910. package/src/resources/extensions/gsd/tests/remote-status.test.ts +2 -2
  911. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +43 -60
  912. package/src/resources/extensions/gsd/tests/semantic-chunker.test.ts +426 -0
  913. package/src/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
  914. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +3 -0
  915. package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +8 -5
  916. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +365 -0
  917. package/src/resources/extensions/gsd/tests/summary-distiller.test.ts +323 -0
  918. package/src/resources/extensions/gsd/tests/token-counter.test.ts +129 -0
  919. package/src/resources/extensions/gsd/tests/token-optimization-benchmark.test.ts +1272 -0
  920. package/src/resources/extensions/gsd/tests/token-optimization-prefs.test.ts +164 -0
  921. package/src/resources/extensions/gsd/tests/token-profile.test.ts +22 -17
  922. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +69 -73
  923. package/src/resources/extensions/gsd/tests/validate-directory.test.ts +222 -0
  924. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
  925. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
  926. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +251 -8
  927. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +2 -2
  928. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +2 -1
  929. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
  930. package/src/resources/extensions/gsd/tests/workspace-index.test.ts +24 -61
  931. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +5 -2
  932. package/src/resources/extensions/gsd/tests/write-gate.test.ts +132 -43
  933. package/src/resources/extensions/gsd/token-counter.ts +20 -0
  934. package/src/resources/extensions/gsd/triage-ui.ts +1 -1
  935. package/src/resources/extensions/gsd/types.ts +7 -1
  936. package/src/resources/extensions/gsd/unit-runtime.ts +16 -13
  937. package/src/resources/extensions/gsd/validate-directory.ts +164 -0
  938. package/src/resources/extensions/gsd/verification-evidence.ts +9 -4
  939. package/src/resources/extensions/gsd/verification-gate.ts +83 -7
  940. package/src/resources/extensions/gsd/visualizer-data.ts +1 -1
  941. package/src/resources/extensions/gsd/visualizer-overlay.ts +5 -2
  942. package/src/resources/extensions/gsd/visualizer-views.ts +2 -3
  943. package/src/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
  944. package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
  945. package/src/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
  946. package/src/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
  947. package/src/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
  948. package/src/resources/extensions/gsd/workflow-templates/registry.json +85 -0
  949. package/src/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
  950. package/src/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
  951. package/src/resources/extensions/gsd/workflow-templates/spike.md +69 -0
  952. package/src/resources/extensions/gsd/workflow-templates.ts +241 -0
  953. package/src/resources/extensions/gsd/worktree-command.ts +4 -51
  954. package/src/resources/extensions/gsd/worktree-manager.ts +7 -9
  955. package/src/resources/extensions/gsd/worktree.ts +41 -1
  956. package/src/resources/extensions/mcp-client/index.ts +459 -0
  957. package/src/resources/extensions/remote-questions/discord-adapter.ts +9 -20
  958. package/src/resources/extensions/remote-questions/http-client.ts +76 -0
  959. package/src/resources/extensions/remote-questions/manager.ts +6 -24
  960. package/src/resources/extensions/remote-questions/mod.ts +16 -0
  961. package/src/resources/extensions/remote-questions/notify.ts +90 -0
  962. package/src/resources/extensions/remote-questions/remote-command.ts +1 -1
  963. package/src/resources/extensions/remote-questions/slack-adapter.ts +11 -18
  964. package/src/resources/extensions/remote-questions/store.ts +5 -1
  965. package/src/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
  966. package/src/resources/extensions/remote-questions/types.ts +29 -3
  967. package/src/resources/extensions/search-the-web/native-search.ts +7 -0
  968. package/src/resources/extensions/search-the-web/provider.ts +15 -3
  969. package/src/resources/extensions/search-the-web/tool-llm-context.ts +1 -13
  970. package/src/resources/extensions/search-the-web/tool-search.ts +1 -13
  971. package/src/resources/extensions/shared/format-utils.ts +53 -0
  972. package/src/resources/extensions/shared/frontmatter.ts +117 -0
  973. package/src/resources/extensions/shared/mod.ts +33 -0
  974. package/src/resources/extensions/shared/sanitize.ts +19 -0
  975. package/src/resources/extensions/slash-commands/create-extension.ts +1 -1
  976. package/src/resources/extensions/slash-commands/create-slash-command.ts +1 -1
  977. package/src/resources/extensions/subagent/index.ts +1 -2
  978. package/src/resources/extensions/ttsr/index.ts +5 -0
  979. package/src/resources/extensions/ttsr/rule-loader.ts +4 -51
  980. package/src/resources/extensions/universal-config/discovery.ts +37 -15
  981. package/src/resources/extensions/voice/index.ts +1 -1
  982. package/src/resources/skills/accessibility/SKILL.md +522 -0
  983. package/src/resources/skills/accessibility/references/WCAG.md +162 -0
  984. package/src/resources/skills/agent-browser/SKILL.md +517 -0
  985. package/src/resources/skills/agent-browser/references/authentication.md +202 -0
  986. package/src/resources/skills/agent-browser/references/commands.md +263 -0
  987. package/src/resources/skills/agent-browser/references/profiling.md +120 -0
  988. package/src/resources/skills/agent-browser/references/proxy-support.md +194 -0
  989. package/src/resources/skills/agent-browser/references/session-management.md +193 -0
  990. package/src/resources/skills/agent-browser/references/snapshot-refs.md +194 -0
  991. package/src/resources/skills/agent-browser/references/video-recording.md +173 -0
  992. package/src/resources/skills/agent-browser/templates/authenticated-session.sh +105 -0
  993. package/src/resources/skills/agent-browser/templates/capture-workflow.sh +69 -0
  994. package/src/resources/skills/agent-browser/templates/form-automation.sh +62 -0
  995. package/src/resources/skills/best-practices/SKILL.md +583 -0
  996. package/src/resources/skills/code-optimizer/SKILL.md +160 -0
  997. package/src/resources/skills/code-optimizer/references/algorithmic-complexity.md +66 -0
  998. package/src/resources/skills/code-optimizer/references/build-compilation.md +90 -0
  999. package/src/resources/skills/code-optimizer/references/bundle-dependencies.md +82 -0
  1000. package/src/resources/skills/code-optimizer/references/caching-memoization.md +76 -0
  1001. package/src/resources/skills/code-optimizer/references/concurrency-async.md +80 -0
  1002. package/src/resources/skills/code-optimizer/references/config-infra.md +71 -0
  1003. package/src/resources/skills/code-optimizer/references/data-structures.md +80 -0
  1004. package/src/resources/skills/code-optimizer/references/database-queries.md +76 -0
  1005. package/src/resources/skills/code-optimizer/references/dead-code-redundancy.md +84 -0
  1006. package/src/resources/skills/code-optimizer/references/error-resilience.md +80 -0
  1007. package/src/resources/skills/code-optimizer/references/io-network.md +89 -0
  1008. package/src/resources/skills/code-optimizer/references/logging-observability.md +64 -0
  1009. package/src/resources/skills/code-optimizer/references/memory-resources.md +66 -0
  1010. package/src/resources/skills/code-optimizer/references/rendering-ui.md +90 -0
  1011. package/src/resources/skills/code-optimizer/references/security-performance.md +68 -0
  1012. package/src/resources/skills/core-web-vitals/SKILL.md +441 -0
  1013. package/src/resources/skills/core-web-vitals/references/LCP.md +208 -0
  1014. package/src/resources/skills/create-gsd-extension/SKILL.md +87 -0
  1015. package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
  1016. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
  1017. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
  1018. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
  1019. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
  1020. package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
  1021. package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
  1022. package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
  1023. package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
  1024. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
  1025. package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
  1026. package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
  1027. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
  1028. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
  1029. package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
  1030. package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
  1031. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
  1032. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
  1033. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
  1034. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
  1035. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
  1036. package/src/resources/skills/create-skill/SKILL.md +184 -0
  1037. package/src/resources/skills/create-skill/references/api-security.md +226 -0
  1038. package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
  1039. package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
  1040. package/src/resources/skills/create-skill/references/core-principles.md +437 -0
  1041. package/src/resources/skills/create-skill/references/executable-code.md +175 -0
  1042. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
  1043. package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
  1044. package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
  1045. package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
  1046. package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
  1047. package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
  1048. package/src/resources/skills/create-skill/references/using-templates.md +112 -0
  1049. package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
  1050. package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
  1051. package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
  1052. package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
  1053. package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
  1054. package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
  1055. package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
  1056. package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
  1057. package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
  1058. package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
  1059. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
  1060. package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
  1061. package/src/resources/skills/make-interfaces-feel-better/SKILL.md +122 -0
  1062. package/src/resources/skills/make-interfaces-feel-better/animations.md +379 -0
  1063. package/src/resources/skills/make-interfaces-feel-better/performance.md +88 -0
  1064. package/src/resources/skills/make-interfaces-feel-better/surfaces.md +247 -0
  1065. package/src/resources/skills/make-interfaces-feel-better/typography.md +123 -0
  1066. package/src/resources/skills/react-best-practices/README.md +123 -0
  1067. package/src/resources/skills/react-best-practices/SKILL.md +136 -0
  1068. package/src/resources/skills/react-best-practices/metadata.json +15 -0
  1069. package/src/resources/skills/react-best-practices/rules/_sections.md +46 -0
  1070. package/src/resources/skills/react-best-practices/rules/_template.md +28 -0
  1071. package/src/resources/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  1072. package/src/resources/skills/react-best-practices/rules/advanced-init-once.md +42 -0
  1073. package/src/resources/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
  1074. package/src/resources/skills/react-best-practices/rules/async-api-routes.md +38 -0
  1075. package/src/resources/skills/react-best-practices/rules/async-defer-await.md +80 -0
  1076. package/src/resources/skills/react-best-practices/rules/async-dependencies.md +51 -0
  1077. package/src/resources/skills/react-best-practices/rules/async-parallel.md +28 -0
  1078. package/src/resources/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  1079. package/src/resources/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  1080. package/src/resources/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  1081. package/src/resources/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  1082. package/src/resources/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  1083. package/src/resources/skills/react-best-practices/rules/bundle-preload.md +50 -0
  1084. package/src/resources/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  1085. package/src/resources/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
  1086. package/src/resources/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  1087. package/src/resources/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  1088. package/src/resources/skills/react-best-practices/rules/js-batch-dom-css.md +107 -0
  1089. package/src/resources/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  1090. package/src/resources/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  1091. package/src/resources/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  1092. package/src/resources/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  1093. package/src/resources/skills/react-best-practices/rules/js-early-exit.md +50 -0
  1094. package/src/resources/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  1095. package/src/resources/skills/react-best-practices/rules/js-index-maps.md +37 -0
  1096. package/src/resources/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  1097. package/src/resources/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  1098. package/src/resources/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  1099. package/src/resources/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  1100. package/src/resources/skills/react-best-practices/rules/rendering-activity.md +26 -0
  1101. package/src/resources/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  1102. package/src/resources/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  1103. package/src/resources/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  1104. package/src/resources/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  1105. package/src/resources/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  1106. package/src/resources/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  1107. package/src/resources/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  1108. package/src/resources/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  1109. package/src/resources/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  1110. package/src/resources/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  1111. package/src/resources/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  1112. package/src/resources/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  1113. package/src/resources/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  1114. package/src/resources/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  1115. package/src/resources/skills/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  1116. package/src/resources/skills/react-best-practices/rules/rerender-memo.md +44 -0
  1117. package/src/resources/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  1118. package/src/resources/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  1119. package/src/resources/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  1120. package/src/resources/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  1121. package/src/resources/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  1122. package/src/resources/skills/react-best-practices/rules/server-auth-actions.md +96 -0
  1123. package/src/resources/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  1124. package/src/resources/skills/react-best-practices/rules/server-cache-react.md +76 -0
  1125. package/src/resources/skills/react-best-practices/rules/server-dedup-props.md +65 -0
  1126. package/src/resources/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  1127. package/src/resources/skills/react-best-practices/rules/server-serialization.md +38 -0
  1128. package/src/resources/skills/userinterface-wiki/SKILL.md +253 -0
  1129. package/src/resources/skills/userinterface-wiki/rules/_sections.md +66 -0
  1130. package/src/resources/skills/userinterface-wiki/rules/_template.md +24 -0
  1131. package/src/resources/skills/userinterface-wiki/rules/a11y-reduced-motion-check.md +30 -0
  1132. package/src/resources/skills/userinterface-wiki/rules/a11y-toggle-setting.md +30 -0
  1133. package/src/resources/skills/userinterface-wiki/rules/a11y-visual-equivalent.md +36 -0
  1134. package/src/resources/skills/userinterface-wiki/rules/a11y-volume-control.md +28 -0
  1135. package/src/resources/skills/userinterface-wiki/rules/appropriate-confirmations-only.md +19 -0
  1136. package/src/resources/skills/userinterface-wiki/rules/appropriate-errors-warnings.md +18 -0
  1137. package/src/resources/skills/userinterface-wiki/rules/appropriate-no-decorative.md +21 -0
  1138. package/src/resources/skills/userinterface-wiki/rules/appropriate-no-high-frequency.md +28 -0
  1139. package/src/resources/skills/userinterface-wiki/rules/appropriate-no-punishing.md +27 -0
  1140. package/src/resources/skills/userinterface-wiki/rules/container-callback-ref.md +31 -0
  1141. package/src/resources/skills/userinterface-wiki/rules/container-guard-initial-zero.md +25 -0
  1142. package/src/resources/skills/userinterface-wiki/rules/container-no-excessive-use.md +13 -0
  1143. package/src/resources/skills/userinterface-wiki/rules/container-overflow-hidden.md +25 -0
  1144. package/src/resources/skills/userinterface-wiki/rules/container-transition-delay.md +21 -0
  1145. package/src/resources/skills/userinterface-wiki/rules/container-two-div-pattern.md +35 -0
  1146. package/src/resources/skills/userinterface-wiki/rules/container-use-resize-observer.md +48 -0
  1147. package/src/resources/skills/userinterface-wiki/rules/context-cleanup-nodes.md +25 -0
  1148. package/src/resources/skills/userinterface-wiki/rules/context-resume-suspended.md +28 -0
  1149. package/src/resources/skills/userinterface-wiki/rules/context-reuse-single.md +30 -0
  1150. package/src/resources/skills/userinterface-wiki/rules/design-filter-for-character.md +25 -0
  1151. package/src/resources/skills/userinterface-wiki/rules/design-noise-for-percussion.md +26 -0
  1152. package/src/resources/skills/userinterface-wiki/rules/design-oscillator-for-tonal.md +22 -0
  1153. package/src/resources/skills/userinterface-wiki/rules/duration-max-300ms.md +21 -0
  1154. package/src/resources/skills/userinterface-wiki/rules/duration-press-hover.md +21 -0
  1155. package/src/resources/skills/userinterface-wiki/rules/duration-shorten-before-curve.md +21 -0
  1156. package/src/resources/skills/userinterface-wiki/rules/duration-small-state.md +15 -0
  1157. package/src/resources/skills/userinterface-wiki/rules/easing-entrance-ease-out.md +21 -0
  1158. package/src/resources/skills/userinterface-wiki/rules/easing-exit-ease-in.md +21 -0
  1159. package/src/resources/skills/userinterface-wiki/rules/easing-for-state-change.md +27 -0
  1160. package/src/resources/skills/userinterface-wiki/rules/easing-linear-only-progress.md +21 -0
  1161. package/src/resources/skills/userinterface-wiki/rules/easing-natural-decay.md +22 -0
  1162. package/src/resources/skills/userinterface-wiki/rules/easing-no-linear-motion.md +22 -0
  1163. package/src/resources/skills/userinterface-wiki/rules/easing-transition-ease-in-out.md +15 -0
  1164. package/src/resources/skills/userinterface-wiki/rules/envelope-exponential-decay.md +21 -0
  1165. package/src/resources/skills/userinterface-wiki/rules/envelope-no-zero-target.md +21 -0
  1166. package/src/resources/skills/userinterface-wiki/rules/envelope-set-initial-value.md +22 -0
  1167. package/src/resources/skills/userinterface-wiki/rules/exit-key-required.md +29 -0
  1168. package/src/resources/skills/userinterface-wiki/rules/exit-matches-initial.md +29 -0
  1169. package/src/resources/skills/userinterface-wiki/rules/exit-prop-required.md +33 -0
  1170. package/src/resources/skills/userinterface-wiki/rules/exit-requires-wrapper.md +27 -0
  1171. package/src/resources/skills/userinterface-wiki/rules/impl-default-subtle.md +21 -0
  1172. package/src/resources/skills/userinterface-wiki/rules/impl-preload-audio.md +34 -0
  1173. package/src/resources/skills/userinterface-wiki/rules/impl-reset-current-time.md +26 -0
  1174. package/src/resources/skills/userinterface-wiki/rules/mode-pop-layout-for-lists.md +25 -0
  1175. package/src/resources/skills/userinterface-wiki/rules/mode-sync-layout-conflict.md +29 -0
  1176. package/src/resources/skills/userinterface-wiki/rules/mode-wait-doubles-duration.md +25 -0
  1177. package/src/resources/skills/userinterface-wiki/rules/morphing-aria-hidden.md +21 -0
  1178. package/src/resources/skills/userinterface-wiki/rules/morphing-consistent-viewbox.md +23 -0
  1179. package/src/resources/skills/userinterface-wiki/rules/morphing-group-variants.md +33 -0
  1180. package/src/resources/skills/userinterface-wiki/rules/morphing-jump-non-grouped.md +29 -0
  1181. package/src/resources/skills/userinterface-wiki/rules/morphing-reduced-motion.md +28 -0
  1182. package/src/resources/skills/userinterface-wiki/rules/morphing-spring-rotation.md +23 -0
  1183. package/src/resources/skills/userinterface-wiki/rules/morphing-strokelinecap-round.md +21 -0
  1184. package/src/resources/skills/userinterface-wiki/rules/morphing-three-lines.md +32 -0
  1185. package/src/resources/skills/userinterface-wiki/rules/morphing-use-collapsed.md +33 -0
  1186. package/src/resources/skills/userinterface-wiki/rules/native-backdrop-styling.md +27 -0
  1187. package/src/resources/skills/userinterface-wiki/rules/native-placeholder-styling.md +27 -0
  1188. package/src/resources/skills/userinterface-wiki/rules/native-selection-styling.md +18 -0
  1189. package/src/resources/skills/userinterface-wiki/rules/nested-consistent-timing.md +25 -0
  1190. package/src/resources/skills/userinterface-wiki/rules/nested-propagate-required.md +41 -0
  1191. package/src/resources/skills/userinterface-wiki/rules/none-context-menu-entrance.md +25 -0
  1192. package/src/resources/skills/userinterface-wiki/rules/none-high-frequency.md +29 -0
  1193. package/src/resources/skills/userinterface-wiki/rules/none-keyboard-navigation.md +32 -0
  1194. package/src/resources/skills/userinterface-wiki/rules/param-click-duration.md +21 -0
  1195. package/src/resources/skills/userinterface-wiki/rules/param-filter-frequency-range.md +21 -0
  1196. package/src/resources/skills/userinterface-wiki/rules/param-q-value-range.md +21 -0
  1197. package/src/resources/skills/userinterface-wiki/rules/param-reasonable-gain.md +21 -0
  1198. package/src/resources/skills/userinterface-wiki/rules/physics-active-state.md +23 -0
  1199. package/src/resources/skills/userinterface-wiki/rules/physics-no-excessive-stagger.md +22 -0
  1200. package/src/resources/skills/userinterface-wiki/rules/physics-spring-for-overshoot.md +23 -0
  1201. package/src/resources/skills/userinterface-wiki/rules/physics-subtle-deformation.md +22 -0
  1202. package/src/resources/skills/userinterface-wiki/rules/prefetch-hit-slop.md +27 -0
  1203. package/src/resources/skills/userinterface-wiki/rules/prefetch-keyboard-tab.md +19 -0
  1204. package/src/resources/skills/userinterface-wiki/rules/prefetch-not-everything.md +22 -0
  1205. package/src/resources/skills/userinterface-wiki/rules/prefetch-touch-fallback.md +34 -0
  1206. package/src/resources/skills/userinterface-wiki/rules/prefetch-trajectory-over-hover.md +32 -0
  1207. package/src/resources/skills/userinterface-wiki/rules/prefetch-use-selectively.md +13 -0
  1208. package/src/resources/skills/userinterface-wiki/rules/presence-disable-interactions.md +31 -0
  1209. package/src/resources/skills/userinterface-wiki/rules/presence-hook-in-child.md +31 -0
  1210. package/src/resources/skills/userinterface-wiki/rules/presence-safe-to-remove.md +37 -0
  1211. package/src/resources/skills/userinterface-wiki/rules/pseudo-content-required.md +28 -0
  1212. package/src/resources/skills/userinterface-wiki/rules/pseudo-first-line-styling.md +27 -0
  1213. package/src/resources/skills/userinterface-wiki/rules/pseudo-hit-target-expansion.md +31 -0
  1214. package/src/resources/skills/userinterface-wiki/rules/pseudo-marker-styling.md +28 -0
  1215. package/src/resources/skills/userinterface-wiki/rules/pseudo-over-dom-node.md +32 -0
  1216. package/src/resources/skills/userinterface-wiki/rules/pseudo-position-relative-parent.md +33 -0
  1217. package/src/resources/skills/userinterface-wiki/rules/pseudo-z-index-layering.md +37 -0
  1218. package/src/resources/skills/userinterface-wiki/rules/spring-for-gestures.md +27 -0
  1219. package/src/resources/skills/userinterface-wiki/rules/spring-for-interruptible.md +27 -0
  1220. package/src/resources/skills/userinterface-wiki/rules/spring-params-balanced.md +29 -0
  1221. package/src/resources/skills/userinterface-wiki/rules/spring-preserves-velocity.md +28 -0
  1222. package/src/resources/skills/userinterface-wiki/rules/staging-dim-background.md +22 -0
  1223. package/src/resources/skills/userinterface-wiki/rules/staging-one-focal-point.md +24 -0
  1224. package/src/resources/skills/userinterface-wiki/rules/staging-z-index-hierarchy.md +22 -0
  1225. package/src/resources/skills/userinterface-wiki/rules/timing-consistent.md +24 -0
  1226. package/src/resources/skills/userinterface-wiki/rules/timing-no-entrance-context-menu.md +22 -0
  1227. package/src/resources/skills/userinterface-wiki/rules/timing-under-300ms.md +22 -0
  1228. package/src/resources/skills/userinterface-wiki/rules/transition-name-cleanup.md +28 -0
  1229. package/src/resources/skills/userinterface-wiki/rules/transition-name-required.md +27 -0
  1230. package/src/resources/skills/userinterface-wiki/rules/transition-name-unique.md +24 -0
  1231. package/src/resources/skills/userinterface-wiki/rules/transition-over-js-library.md +32 -0
  1232. package/src/resources/skills/userinterface-wiki/rules/transition-style-pseudo-elements.md +24 -0
  1233. package/src/resources/skills/userinterface-wiki/rules/type-antialiased-on-retina.md +18 -0
  1234. package/src/resources/skills/userinterface-wiki/rules/type-disambiguation-stylistic-set.md +15 -0
  1235. package/src/resources/skills/userinterface-wiki/rules/type-font-display-swap.md +28 -0
  1236. package/src/resources/skills/userinterface-wiki/rules/type-justify-with-hyphens.md +24 -0
  1237. package/src/resources/skills/userinterface-wiki/rules/type-letter-spacing-uppercase.md +28 -0
  1238. package/src/resources/skills/userinterface-wiki/rules/type-no-font-synthesis.md +18 -0
  1239. package/src/resources/skills/userinterface-wiki/rules/type-oldstyle-nums-for-prose.md +21 -0
  1240. package/src/resources/skills/userinterface-wiki/rules/type-opentype-contextual-alternates.md +15 -0
  1241. package/src/resources/skills/userinterface-wiki/rules/type-optical-sizing-auto.md +25 -0
  1242. package/src/resources/skills/userinterface-wiki/rules/type-proper-fractions.md +15 -0
  1243. package/src/resources/skills/userinterface-wiki/rules/type-slashed-zero.md +17 -0
  1244. package/src/resources/skills/userinterface-wiki/rules/type-tabular-nums-for-data.md +21 -0
  1245. package/src/resources/skills/userinterface-wiki/rules/type-text-wrap-balance-headings.md +21 -0
  1246. package/src/resources/skills/userinterface-wiki/rules/type-text-wrap-pretty.md +16 -0
  1247. package/src/resources/skills/userinterface-wiki/rules/type-underline-offset.md +25 -0
  1248. package/src/resources/skills/userinterface-wiki/rules/type-variable-weight-continuous.md +23 -0
  1249. package/src/resources/skills/userinterface-wiki/rules/ux-aesthetic-usability.md +32 -0
  1250. package/src/resources/skills/userinterface-wiki/rules/ux-cognitive-load-reduce.md +49 -0
  1251. package/src/resources/skills/userinterface-wiki/rules/ux-common-region-boundaries.md +50 -0
  1252. package/src/resources/skills/userinterface-wiki/rules/ux-doherty-perceived-speed.md +29 -0
  1253. package/src/resources/skills/userinterface-wiki/rules/ux-doherty-under-400ms.md +30 -0
  1254. package/src/resources/skills/userinterface-wiki/rules/ux-fitts-hit-area.md +32 -0
  1255. package/src/resources/skills/userinterface-wiki/rules/ux-fitts-target-size.md +31 -0
  1256. package/src/resources/skills/userinterface-wiki/rules/ux-goal-gradient-progress.md +33 -0
  1257. package/src/resources/skills/userinterface-wiki/rules/ux-hicks-minimize-choices.md +45 -0
  1258. package/src/resources/skills/userinterface-wiki/rules/ux-jakobs-familiar-patterns.md +37 -0
  1259. package/src/resources/skills/userinterface-wiki/rules/ux-millers-chunking.md +23 -0
  1260. package/src/resources/skills/userinterface-wiki/rules/ux-pareto-prioritize-features.md +36 -0
  1261. package/src/resources/skills/userinterface-wiki/rules/ux-peak-end-finish-strong.md +35 -0
  1262. package/src/resources/skills/userinterface-wiki/rules/ux-postels-accept-messy-input.md +45 -0
  1263. package/src/resources/skills/userinterface-wiki/rules/ux-pragnanz-simplify.md +33 -0
  1264. package/src/resources/skills/userinterface-wiki/rules/ux-progressive-disclosure.md +41 -0
  1265. package/src/resources/skills/userinterface-wiki/rules/ux-proximity-grouping.md +38 -0
  1266. package/src/resources/skills/userinterface-wiki/rules/ux-serial-position.md +31 -0
  1267. package/src/resources/skills/userinterface-wiki/rules/ux-similarity-consistency.md +35 -0
  1268. package/src/resources/skills/userinterface-wiki/rules/ux-teslers-complexity.md +28 -0
  1269. package/src/resources/skills/userinterface-wiki/rules/ux-uniform-connectedness.md +43 -0
  1270. package/src/resources/skills/userinterface-wiki/rules/ux-von-restorff-emphasis.md +29 -0
  1271. package/src/resources/skills/userinterface-wiki/rules/ux-zeigarnik-show-incomplete.md +36 -0
  1272. package/src/resources/skills/userinterface-wiki/rules/visual-animate-shadow-pseudo.md +49 -0
  1273. package/src/resources/skills/userinterface-wiki/rules/visual-border-alpha-colors.md +25 -0
  1274. package/src/resources/skills/userinterface-wiki/rules/visual-button-shadow-anatomy.md +49 -0
  1275. package/src/resources/skills/userinterface-wiki/rules/visual-concentric-radius.md +40 -0
  1276. package/src/resources/skills/userinterface-wiki/rules/visual-consistent-spacing-scale.md +35 -0
  1277. package/src/resources/skills/userinterface-wiki/rules/visual-layered-shadows.md +30 -0
  1278. package/src/resources/skills/userinterface-wiki/rules/visual-no-pure-black-shadow.md +25 -0
  1279. package/src/resources/skills/userinterface-wiki/rules/visual-shadow-direction.md +25 -0
  1280. package/src/resources/skills/userinterface-wiki/rules/visual-shadow-matches-elevation.md +23 -0
  1281. package/src/resources/skills/userinterface-wiki/rules/weight-duration-matches-action.md +29 -0
  1282. package/src/resources/skills/userinterface-wiki/rules/weight-match-action.md +32 -0
  1283. package/src/resources/skills/web-design-guidelines/SKILL.md +39 -0
  1284. package/src/resources/skills/web-quality-audit/SKILL.md +170 -0
  1285. package/src/resources/skills/web-quality-audit/scripts/analyze.sh +91 -0
  1286. package/dist/resources/extensions/gsd/complexity.ts +0 -237
  1287. package/dist/resources/extensions/gsd/github-client.ts +0 -235
  1288. package/dist/resources/extensions/gsd/tests/activity-log-prune.test.ts +0 -297
  1289. package/dist/resources/extensions/gsd/tests/activity-log-save.test.ts +0 -127
  1290. package/dist/resources/extensions/gsd/tests/agent-end-provider-error.test.ts +0 -110
  1291. package/dist/resources/extensions/gsd/tests/auto-draft-pause.test.ts +0 -115
  1292. package/dist/resources/extensions/gsd/tests/complexity-routing.test.ts +0 -294
  1293. package/dist/resources/extensions/gsd/tests/metrics-io.test.ts +0 -176
  1294. package/dist/resources/extensions/gsd/tests/network-error-fallback.test.ts +0 -104
  1295. package/dist/resources/extensions/gsd/tests/preferences-git.test.ts +0 -120
  1296. package/dist/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -226
  1297. package/dist/resources/extensions/gsd/tests/preferences-mode.test.ts +0 -110
  1298. package/dist/resources/extensions/gsd/tests/preferences-models.test.ts +0 -207
  1299. package/dist/resources/extensions/gsd/tests/preferences-schema-validation.test.ts +0 -183
  1300. package/dist/resources/extensions/gsd/tests/preferences-wizard-fields.test.ts +0 -168
  1301. package/dist/resources/extensions/mcporter/index.ts +0 -512
  1302. package/dist/resources/extensions/shared/progress-widget.ts +0 -282
  1303. package/dist/resources/extensions/shared/thinking-widget.ts +0 -107
  1304. package/src/resources/extensions/gsd/complexity.ts +0 -237
  1305. package/src/resources/extensions/gsd/github-client.ts +0 -235
  1306. package/src/resources/extensions/gsd/tests/activity-log-prune.test.ts +0 -297
  1307. package/src/resources/extensions/gsd/tests/activity-log-save.test.ts +0 -127
  1308. package/src/resources/extensions/gsd/tests/agent-end-provider-error.test.ts +0 -110
  1309. package/src/resources/extensions/gsd/tests/auto-draft-pause.test.ts +0 -115
  1310. package/src/resources/extensions/gsd/tests/complexity-routing.test.ts +0 -294
  1311. package/src/resources/extensions/gsd/tests/metrics-io.test.ts +0 -176
  1312. package/src/resources/extensions/gsd/tests/network-error-fallback.test.ts +0 -104
  1313. package/src/resources/extensions/gsd/tests/preferences-git.test.ts +0 -120
  1314. package/src/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -226
  1315. package/src/resources/extensions/gsd/tests/preferences-mode.test.ts +0 -110
  1316. package/src/resources/extensions/gsd/tests/preferences-models.test.ts +0 -207
  1317. package/src/resources/extensions/gsd/tests/preferences-schema-validation.test.ts +0 -183
  1318. package/src/resources/extensions/gsd/tests/preferences-wizard-fields.test.ts +0 -168
  1319. package/src/resources/extensions/mcporter/index.ts +0 -512
  1320. package/src/resources/extensions/shared/progress-widget.ts +0 -282
  1321. package/src/resources/extensions/shared/thinking-widget.ts +0 -107
@@ -5,39 +5,24 @@
5
5
  */
6
6
 
7
7
  import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent";
8
- import { AuthStorage } from "@gsd/pi-coding-agent";
9
- import { existsSync, readFileSync, mkdirSync, unlinkSync } from "node:fs";
10
- import { join, dirname } from "node:path";
11
- import { enableDebug, isDebugEnabled } from "./debug-logger.js";
12
- import { fileURLToPath } from "node:url";
8
+ import type { GSDState } from "./types.js";
9
+ import { existsSync, readFileSync, unlinkSync } from "node:fs";
10
+ import { join } from "node:path";
11
+ import { enableDebug } from "./debug-logger.js";
13
12
  import { deriveState } from "./state.js";
14
13
  import { GSDDashboardOverlay } from "./dashboard-overlay.js";
15
14
  import { GSDVisualizerOverlay } from "./visualizer-overlay.js";
16
15
  import { showQueue, showDiscuss, showHeadlessMilestoneCreation } from "./guided-flow.js";
17
- import { startAuto, stopAuto, pauseAuto, isAutoActive, isAutoPaused, isStepMode, stopAutoRemote, dispatchDirectPhase } from "./auto.js";
16
+ import { startAuto, stopAuto, pauseAuto, isAutoActive, isAutoPaused, isStepMode, stopAutoRemote } from "./auto.js";
17
+ import { dispatchDirectPhase } from "./auto-direct-dispatch.js";
18
18
  import { resolveProjectRoot } from "./worktree.js";
19
- import { appendCapture, hasPendingCaptures, loadPendingCaptures } from "./captures.js";
19
+ import { assertSafeDirectory } from "./validate-directory.js";
20
20
  import {
21
21
  getGlobalGSDPreferencesPath,
22
- getLegacyGlobalGSDPreferencesPath,
23
22
  getProjectGSDPreferencesPath,
24
- loadGlobalGSDPreferences,
25
- loadProjectGSDPreferences,
26
23
  loadEffectiveGSDPreferences,
27
- resolveAllSkillReferences,
28
24
  } from "./preferences.js";
29
- import { loadFile, saveFile, appendOverride, appendKnowledge, splitFrontmatter, parseFrontmatterMap } from "./files.js";
30
- import { runClaudeImportFlow } from "./claude-import.js";
31
- import {
32
- formatDoctorIssuesForPrompt,
33
- formatDoctorReport,
34
- runGSDDoctor,
35
- selectDoctorScope,
36
- filterDoctorIssues,
37
- } from "./doctor.js";
38
- import { loadPrompt } from "./prompt-loader.js";
39
-
40
- import { handleRemote } from "../remote-questions/remote-command.js";
25
+ import { handleRemote } from "../remote-questions/mod.js";
41
26
  import { handleQuick } from "./quick.js";
42
27
  import { handleHistory } from "./history.js";
43
28
  import { handleUndo } from "./undo.js";
@@ -50,34 +35,27 @@ import {
50
35
  import { formatEligibilityReport } from "./parallel-eligibility.js";
51
36
  import { mergeAllCompleted, mergeCompletedMilestone, formatMergeResults } from "./parallel-merge.js";
52
37
  import { resolveParallelConfig } from "./preferences.js";
53
- import { nativeBranchList, nativeDetectMainBranch, nativeBranchListMerged, nativeBranchDelete, nativeForEachRef, nativeUpdateRef } from "./native-git-bridge.js";
54
-
55
- export function dispatchDoctorHeal(pi: ExtensionAPI, scope: string | undefined, reportText: string, structuredIssues: string): void {
56
- const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".pi", "GSD-WORKFLOW.md");
57
- const workflow = readFileSync(workflowPath, "utf-8");
58
- const prompt = loadPrompt("doctor-heal", {
59
- doctorSummary: reportText,
60
- structuredIssues,
61
- scopeLabel: scope ?? "active milestone / blocking scope",
62
- doctorCommandSuffix: scope ? ` ${scope}` : "",
63
- });
64
38
 
65
- const content = `Read the following GSD workflow protocol and execute exactly.\n\n${workflow}\n\n## Your Task\n\n${prompt}`;
39
+ // ─── Imports from extracted modules ──────────────────────────────────────────
40
+ import { handlePrefs, handlePrefsMode, handlePrefsWizard, ensurePreferencesFile } from "./commands-prefs-wizard.js";
41
+ import { handleConfig } from "./commands-config.js";
42
+ import { handleInspect } from "./commands-inspect.js";
43
+ import { handleCleanupBranches, handleCleanupSnapshots, handleSkip, handleDryRun } from "./commands-maintenance.js";
44
+ import { handleDoctor, handleSteer, handleCapture, handleTriage, handleKnowledge, handleRunHook, handleUpdate, handleSkillHealth } from "./commands-handlers.js";
45
+ import { handleLogs } from "./commands-logs.js";
46
+ import { handleStart, handleTemplates, getTemplateCompletions } from "./commands-workflow-templates.js";
66
47
 
67
- pi.sendMessage(
68
- { customType: "gsd-doctor-heal", content, display: false },
69
- { triggerTurn: true },
70
- );
71
- }
72
48
 
73
49
  /** Resolve the effective project root, accounting for worktree paths. */
74
- function projectRoot(): string {
75
- return resolveProjectRoot(process.cwd());
50
+ export function projectRoot(): string {
51
+ const root = resolveProjectRoot(process.cwd());
52
+ assertSafeDirectory(root);
53
+ return root;
76
54
  }
77
55
 
78
56
  export function registerGSDCommand(pi: ExtensionAPI): void {
79
57
  pi.registerCommand("gsd", {
80
- description: "GSD — Get Shit Done: /gsd help|next|auto|stop|pause|status|visualize|queue|quick|capture|triage|dispatch|history|undo|skip|export|cleanup|mode|prefs|config|hooks|run-hook|skill-health|doctor|forensics|migrate|remote|steer|knowledge|new-milestone|parallel|update",
58
+ description: "GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|visualize|queue|quick|capture|triage|dispatch|history|undo|skip|export|cleanup|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|forensics|migrate|remote|steer|knowledge|new-milestone|parallel|update",
81
59
  getArgumentCompletions: (prefix: string) => {
82
60
  const subcommands = [
83
61
  { cmd: "help", desc: "Categorized command reference with descriptions" },
@@ -101,11 +79,15 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
101
79
  { cmd: "mode", desc: "Switch workflow mode (solo/team)" },
102
80
  { cmd: "prefs", desc: "Manage preferences (model selection, timeouts, etc.)" },
103
81
  { cmd: "config", desc: "Set API keys for external tools" },
82
+ { cmd: "keys", desc: "API key manager — list, add, remove, test, rotate, doctor" },
104
83
  { cmd: "hooks", desc: "Show configured post-unit and pre-dispatch hooks" },
105
84
  { cmd: "run-hook", desc: "Manually trigger a specific hook" },
106
85
  { cmd: "skill-health", desc: "Skill lifecycle dashboard" },
107
86
  { cmd: "doctor", desc: "Runtime health checks with auto-fix" },
87
+ { cmd: "logs", desc: "Browse activity logs, debug logs, and metrics" },
108
88
  { cmd: "forensics", desc: "Examine execution logs" },
89
+ { cmd: "init", desc: "Project init wizard — detect, configure, bootstrap .gsd/" },
90
+ { cmd: "setup", desc: "Global setup status and configuration" },
109
91
  { cmd: "migrate", desc: "Migrate a v1 .planning directory to .gsd format" },
110
92
  { cmd: "remote", desc: "Control remote auto-mode" },
111
93
  { cmd: "steer", desc: "Hard-steer plan documents during execution" },
@@ -113,102 +95,244 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
113
95
  { cmd: "knowledge", desc: "Add persistent project knowledge (rule, pattern, or lesson)" },
114
96
  { cmd: "new-milestone", desc: "Create a milestone from a specification document (headless)" },
115
97
  { cmd: "parallel", desc: "Parallel milestone orchestration (start, status, stop, merge)" },
98
+ { cmd: "park", desc: "Park a milestone — skip without deleting" },
99
+ { cmd: "unpark", desc: "Reactivate a parked milestone" },
116
100
  { cmd: "update", desc: "Update GSD to the latest version" },
101
+ { cmd: "start", desc: "Start a workflow template (bugfix, spike, feature, etc.)" },
102
+ { cmd: "templates", desc: "List available workflow templates" },
117
103
  ];
118
104
  const parts = prefix.trim().split(/\s+/);
119
105
 
120
106
  if (parts.length <= 1) {
121
107
  return subcommands
122
108
  .filter((item) => item.cmd.startsWith(parts[0] ?? ""))
123
- .map((item) => ({
124
- value: item.cmd,
125
- label: item.cmd,
126
- description: item.desc
109
+ .map((item) => ({
110
+ value: item.cmd,
111
+ label: item.cmd,
112
+ description: item.desc
127
113
  }));
128
114
  }
129
115
 
130
116
  if (parts[0] === "auto" && parts.length <= 2) {
131
117
  const flagPrefix = parts[1] ?? "";
132
- return ["--verbose", "--debug"]
133
- .filter((f) => f.startsWith(flagPrefix))
134
- .map((f) => ({ value: `auto ${f}`, label: f }));
118
+ const flags = [
119
+ { flag: "--verbose", desc: "Show detailed execution output" },
120
+ { flag: "--debug", desc: "Enable debug logging" },
121
+ ];
122
+ return flags
123
+ .filter((f) => f.flag.startsWith(flagPrefix))
124
+ .map((f) => ({ value: `auto ${f.flag}`, label: f.flag, description: f.desc }));
135
125
  }
136
126
 
137
127
  if (parts[0] === "mode" && parts.length <= 2) {
138
128
  const subPrefix = parts[1] ?? "";
139
- return ["global", "project"]
140
- .filter((cmd) => cmd.startsWith(subPrefix))
141
- .map((cmd) => ({ value: `mode ${cmd}`, label: cmd }));
129
+ const modes = [
130
+ { cmd: "global", desc: "Edit global workflow mode" },
131
+ { cmd: "project", desc: "Edit project-specific workflow mode" },
132
+ ];
133
+ return modes
134
+ .filter((m) => m.cmd.startsWith(subPrefix))
135
+ .map((m) => ({ value: `mode ${m.cmd}`, label: m.cmd, description: m.desc }));
142
136
  }
143
137
 
144
138
  if (parts[0] === "parallel" && parts.length <= 2) {
145
139
  const subPrefix = parts[1] ?? "";
146
- return ["start", "status", "stop", "pause", "resume", "merge"]
147
- .filter((cmd) => cmd.startsWith(subPrefix))
148
- .map((cmd) => ({ value: `parallel ${cmd}`, label: cmd }));
140
+ const subs = [
141
+ { cmd: "start", desc: "Start parallel milestone orchestration" },
142
+ { cmd: "status", desc: "Show parallel worker statuses" },
143
+ { cmd: "stop", desc: "Stop all parallel workers" },
144
+ { cmd: "pause", desc: "Pause a specific worker" },
145
+ { cmd: "resume", desc: "Resume a paused worker" },
146
+ { cmd: "merge", desc: "Merge completed milestone branches" },
147
+ ];
148
+ return subs
149
+ .filter((s) => s.cmd.startsWith(subPrefix))
150
+ .map((s) => ({ value: `parallel ${s.cmd}`, label: s.cmd, description: s.desc }));
151
+ }
152
+
153
+ if (parts[0] === "setup" && parts.length <= 2) {
154
+ const subPrefix = parts[1] ?? "";
155
+ const subs = [
156
+ { cmd: "llm", desc: "Configure LLM provider settings" },
157
+ { cmd: "search", desc: "Configure web search provider" },
158
+ { cmd: "remote", desc: "Configure remote integrations" },
159
+ { cmd: "keys", desc: "Manage API keys" },
160
+ { cmd: "prefs", desc: "Configure global preferences" },
161
+ ];
162
+ return subs
163
+ .filter((s) => s.cmd.startsWith(subPrefix))
164
+ .map((s) => ({ value: `setup ${s.cmd}`, label: s.cmd, description: s.desc }));
165
+ }
166
+
167
+ if (parts[0] === "logs" && parts.length <= 2) {
168
+ const subPrefix = parts[1] ?? "";
169
+ const subs = [
170
+ { cmd: "debug", desc: "List or view debug log files" },
171
+ { cmd: "tail", desc: "Show last N activity log summaries" },
172
+ { cmd: "clear", desc: "Remove old activity and debug logs" },
173
+ ];
174
+ return subs
175
+ .filter((s) => s.cmd.startsWith(subPrefix))
176
+ .map((s) => ({ value: `logs ${s.cmd}`, label: s.cmd, description: s.desc }));
177
+ }
178
+
179
+ if (parts[0] === "keys" && parts.length <= 2) {
180
+ const subPrefix = parts[1] ?? "";
181
+ const subs = [
182
+ { cmd: "list", desc: "Show key status dashboard" },
183
+ { cmd: "add", desc: "Add a key for a provider" },
184
+ { cmd: "remove", desc: "Remove a key" },
185
+ { cmd: "test", desc: "Validate key(s) with API call" },
186
+ { cmd: "rotate", desc: "Replace an existing key" },
187
+ { cmd: "doctor", desc: "Health check all keys" },
188
+ ];
189
+ return subs
190
+ .filter((s) => s.cmd.startsWith(subPrefix))
191
+ .map((s) => ({ value: `keys ${s.cmd}`, label: s.cmd, description: s.desc }));
149
192
  }
150
193
 
151
194
  if (parts[0] === "prefs" && parts.length <= 2) {
152
195
  const subPrefix = parts[1] ?? "";
153
- return ["global", "project", "status", "wizard", "setup", "import-claude"]
154
- .filter((cmd) => cmd.startsWith(subPrefix))
155
- .map((cmd) => ({ value: `prefs ${cmd}`, label: cmd }));
196
+ const subs = [
197
+ { cmd: "global", desc: "Edit global preferences file" },
198
+ { cmd: "project", desc: "Edit project preferences file" },
199
+ { cmd: "status", desc: "Show effective preferences" },
200
+ { cmd: "wizard", desc: "Interactive preferences wizard" },
201
+ { cmd: "setup", desc: "First-time preferences setup" },
202
+ { cmd: "import-claude", desc: "Import settings from Claude Code" },
203
+ ];
204
+ return subs
205
+ .filter((s) => s.cmd.startsWith(subPrefix))
206
+ .map((s) => ({ value: `prefs ${s.cmd}`, label: s.cmd, description: s.desc }));
156
207
  }
157
208
 
158
209
  if (parts[0] === "remote" && parts.length <= 2) {
159
210
  const subPrefix = parts[1] ?? "";
160
- return ["slack", "discord", "status", "disconnect"]
161
- .filter((cmd) => cmd.startsWith(subPrefix))
162
- .map((cmd) => ({ value: `remote ${cmd}`, label: cmd }));
211
+ const subs = [
212
+ { cmd: "slack", desc: "Configure Slack integration" },
213
+ { cmd: "discord", desc: "Configure Discord integration" },
214
+ { cmd: "status", desc: "Show remote connection status" },
215
+ { cmd: "disconnect", desc: "Disconnect remote integrations" },
216
+ ];
217
+ return subs
218
+ .filter((s) => s.cmd.startsWith(subPrefix))
219
+ .map((s) => ({ value: `remote ${s.cmd}`, label: s.cmd, description: s.desc }));
163
220
  }
164
221
 
165
222
  if (parts[0] === "next" && parts.length <= 2) {
166
223
  const flagPrefix = parts[1] ?? "";
167
- return ["--verbose", "--dry-run"]
168
- .filter((f) => f.startsWith(flagPrefix))
169
- .map((f) => ({ value: `next ${f}`, label: f }));
224
+ const flags = [
225
+ { flag: "--verbose", desc: "Show detailed step output" },
226
+ { flag: "--dry-run", desc: "Preview next step without executing" },
227
+ ];
228
+ return flags
229
+ .filter((f) => f.flag.startsWith(flagPrefix))
230
+ .map((f) => ({ value: `next ${f.flag}`, label: f.flag, description: f.desc }));
170
231
  }
171
232
 
172
233
  if (parts[0] === "history" && parts.length <= 2) {
173
234
  const flagPrefix = parts[1] ?? "";
174
- return ["--cost", "--phase", "--model", "10", "20", "50"]
175
- .filter((f) => f.startsWith(flagPrefix))
176
- .map((f) => ({ value: `history ${f}`, label: f }));
235
+ const flags = [
236
+ { flag: "--cost", desc: "Show cost breakdown per entry" },
237
+ { flag: "--phase", desc: "Filter by phase type" },
238
+ { flag: "--model", desc: "Filter by model used" },
239
+ { flag: "10", desc: "Show last 10 entries" },
240
+ { flag: "20", desc: "Show last 20 entries" },
241
+ { flag: "50", desc: "Show last 50 entries" },
242
+ ];
243
+ return flags
244
+ .filter((f) => f.flag.startsWith(flagPrefix))
245
+ .map((f) => ({ value: `history ${f.flag}`, label: f.flag, description: f.desc }));
177
246
  }
178
247
 
179
248
  if (parts[0] === "undo" && parts.length <= 2) {
180
- return [{ value: "undo --force", label: "--force" }];
249
+ return [{ value: "undo --force", label: "--force", description: "Skip confirmation prompt" }];
181
250
  }
182
251
 
183
252
  if (parts[0] === "export" && parts.length <= 2) {
184
253
  const flagPrefix = parts[1] ?? "";
185
- return ["--json", "--markdown", "--html", "--html --all"]
186
- .filter((f) => f.startsWith(flagPrefix))
187
- .map((f) => ({ value: `export ${f}`, label: f }));
254
+ const flags = [
255
+ { flag: "--json", desc: "Export as JSON" },
256
+ { flag: "--markdown", desc: "Export as Markdown" },
257
+ { flag: "--html", desc: "Export as HTML" },
258
+ { flag: "--html --all", desc: "Export all milestones as HTML" },
259
+ ];
260
+ return flags
261
+ .filter((f) => f.flag.startsWith(flagPrefix))
262
+ .map((f) => ({ value: `export ${f.flag}`, label: f.flag, description: f.desc }));
188
263
  }
189
264
 
190
265
  if (parts[0] === "cleanup" && parts.length <= 2) {
191
266
  const subPrefix = parts[1] ?? "";
192
- return ["branches", "snapshots"]
193
- .filter((cmd) => cmd.startsWith(subPrefix))
194
- .map((cmd) => ({ value: `cleanup ${cmd}`, label: cmd }));
267
+ const subs = [
268
+ { cmd: "branches", desc: "Remove merged milestone branches" },
269
+ { cmd: "snapshots", desc: "Remove old execution snapshots" },
270
+ ];
271
+ return subs
272
+ .filter((s) => s.cmd.startsWith(subPrefix))
273
+ .map((s) => ({ value: `cleanup ${s.cmd}`, label: s.cmd, description: s.desc }));
195
274
  }
196
275
 
197
276
  if (parts[0] === "knowledge" && parts.length <= 2) {
198
277
  const subPrefix = parts[1] ?? "";
199
- return ["rule", "pattern", "lesson"]
200
- .filter((cmd) => cmd.startsWith(subPrefix))
201
- .map((cmd) => ({ value: `knowledge ${cmd}`, label: cmd }));
278
+ const subs = [
279
+ { cmd: "rule", desc: "Add a project rule (always/never do X)" },
280
+ { cmd: "pattern", desc: "Add a code pattern to follow" },
281
+ { cmd: "lesson", desc: "Record a lesson learned" },
282
+ ];
283
+ return subs
284
+ .filter((s) => s.cmd.startsWith(subPrefix))
285
+ .map((s) => ({ value: `knowledge ${s.cmd}`, label: s.cmd, description: s.desc }));
286
+ }
287
+
288
+ if (parts[0] === "start" && parts.length <= 2) {
289
+ const subPrefix = parts[1] ?? "";
290
+ const subs = [
291
+ { cmd: "bugfix", desc: "Triage, fix, test, and ship a bug fix" },
292
+ { cmd: "small-feature", desc: "Lightweight feature with optional discussion" },
293
+ { cmd: "spike", desc: "Research, prototype, and document findings" },
294
+ { cmd: "hotfix", desc: "Minimal: fix it, test it, ship it" },
295
+ { cmd: "refactor", desc: "Inventory, plan waves, migrate, verify" },
296
+ { cmd: "security-audit", desc: "Scan, triage, remediate, re-scan" },
297
+ { cmd: "dep-upgrade", desc: "Assess, upgrade, fix breaks, verify" },
298
+ { cmd: "full-project", desc: "Complete GSD workflow with full ceremony" },
299
+ { cmd: "resume", desc: "Resume an in-progress workflow" },
300
+ { cmd: "--list", desc: "List all available templates" },
301
+ { cmd: "--dry-run", desc: "Preview workflow without executing" },
302
+ ];
303
+ return subs
304
+ .filter((s) => s.cmd.startsWith(subPrefix))
305
+ .map((s) => ({ value: `start ${s.cmd}`, label: s.cmd, description: s.desc }));
306
+ }
307
+
308
+ if (parts[0] === "templates" && parts.length <= 2) {
309
+ const subPrefix = parts[1] ?? "";
310
+ const subs = [
311
+ { cmd: "info", desc: "Show detailed template info" },
312
+ ];
313
+ return subs
314
+ .filter((s) => s.cmd.startsWith(subPrefix))
315
+ .map((s) => ({ value: `templates ${s.cmd}`, label: s.cmd, description: s.desc }));
316
+ }
317
+
318
+ if (parts[0] === "templates" && parts[1] === "info" && parts.length <= 3) {
319
+ const namePrefix = parts[2] ?? "";
320
+ return getTemplateCompletions(namePrefix)
321
+ .map((c) => ({ value: `templates ${c.value}`, label: c.label, description: c.description }));
202
322
  }
203
323
 
204
324
  if (parts[0] === "doctor") {
205
325
  const modePrefix = parts[1] ?? "";
206
- const modes = ["fix", "heal", "audit"];
326
+ const modes = [
327
+ { cmd: "fix", desc: "Auto-fix detected issues" },
328
+ { cmd: "heal", desc: "AI-driven deep healing" },
329
+ { cmd: "audit", desc: "Run health audit without fixing" },
330
+ ];
207
331
 
208
332
  if (parts.length <= 2) {
209
333
  return modes
210
- .filter((cmd) => cmd.startsWith(modePrefix))
211
- .map((cmd) => ({ value: `doctor ${cmd}`, label: cmd }));
334
+ .filter((m) => m.cmd.startsWith(modePrefix))
335
+ .map((m) => ({ value: `doctor ${m.cmd}`, label: m.cmd, description: m.desc }));
212
336
  }
213
337
 
214
338
  return [];
@@ -216,9 +340,18 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
216
340
 
217
341
  if (parts[0] === "dispatch" && parts.length <= 2) {
218
342
  const phasePrefix = parts[1] ?? "";
219
- return ["research", "plan", "execute", "complete", "reassess", "uat", "replan"]
220
- .filter((cmd) => cmd.startsWith(phasePrefix))
221
- .map((cmd) => ({ value: `dispatch ${cmd}`, label: cmd }));
343
+ const phases = [
344
+ { cmd: "research", desc: "Run research phase" },
345
+ { cmd: "plan", desc: "Run planning phase" },
346
+ { cmd: "execute", desc: "Run execution phase" },
347
+ { cmd: "complete", desc: "Run completion phase" },
348
+ { cmd: "reassess", desc: "Reassess current progress" },
349
+ { cmd: "uat", desc: "Run user acceptance testing" },
350
+ { cmd: "replan", desc: "Replan the current slice" },
351
+ ];
352
+ return phases
353
+ .filter((p) => p.cmd.startsWith(phasePrefix))
354
+ .map((p) => ({ value: `dispatch ${p.cmd}`, label: p.cmd, description: p.desc }));
222
355
  }
223
356
 
224
357
  return [];
@@ -256,11 +389,42 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
256
389
  return;
257
390
  }
258
391
 
392
+ if (trimmed === "init") {
393
+ const { detectProjectState } = await import("./detection.js");
394
+ const { showProjectInit, handleReinit } = await import("./init-wizard.js");
395
+ const basePath = projectRoot();
396
+ const detection = detectProjectState(basePath);
397
+ if (detection.state === "v2-gsd" || detection.state === "v2-gsd-empty") {
398
+ await handleReinit(ctx, detection);
399
+ } else {
400
+ await showProjectInit(ctx, pi, basePath, detection);
401
+ }
402
+ return;
403
+ }
404
+
405
+ if (trimmed === "keys" || trimmed.startsWith("keys ")) {
406
+ const { handleKeys } = await import("./key-manager.js");
407
+ const keysArgs = trimmed.replace(/^keys\s*/, "").trim();
408
+ await handleKeys(keysArgs, ctx);
409
+ return;
410
+ }
411
+
412
+ if (trimmed === "setup" || trimmed.startsWith("setup ")) {
413
+ const setupArgs = trimmed.replace(/^setup\s*/, "").trim();
414
+ await handleSetup(setupArgs, ctx);
415
+ return;
416
+ }
417
+
259
418
  if (trimmed === "doctor" || trimmed.startsWith("doctor ")) {
260
419
  await handleDoctor(trimmed.replace(/^doctor\s*/, "").trim(), ctx, pi);
261
420
  return;
262
421
  }
263
422
 
423
+ if (trimmed === "logs" || trimmed.startsWith("logs ")) {
424
+ await handleLogs(trimmed.replace(/^logs\s*/, "").trim(), ctx);
425
+ return;
426
+ }
427
+
264
428
  if (trimmed === "forensics" || trimmed.startsWith("forensics ")) {
265
429
  const { handleForensics } = await import("./forensics.js");
266
430
  await handleForensics(trimmed.replace(/^forensics\s*/, "").trim(), ctx, pi);
@@ -465,6 +629,73 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
465
629
  return;
466
630
  }
467
631
 
632
+ if (trimmed === "park" || trimmed.startsWith("park ")) {
633
+ const basePath = projectRoot();
634
+ const arg = trimmed.replace(/^park\s*/, "").trim();
635
+ const { parkMilestone, isParked } = await import("./milestone-actions.js");
636
+ const { deriveState } = await import("./state.js");
637
+
638
+ let targetId = arg;
639
+ if (!targetId) {
640
+ // Park the current active milestone
641
+ const state = await deriveState(basePath);
642
+ if (!state.activeMilestone) {
643
+ ctx.ui.notify("No active milestone to park.", "warning");
644
+ return;
645
+ }
646
+ targetId = state.activeMilestone.id;
647
+ }
648
+
649
+ if (isParked(basePath, targetId)) {
650
+ ctx.ui.notify(`${targetId} is already parked. Use /gsd unpark ${targetId} to reactivate.`, "info");
651
+ return;
652
+ }
653
+
654
+ // Extract reason from remaining args (e.g., /gsd park M002 "reason here")
655
+ const reasonParts = arg.replace(targetId, "").trim().replace(/^["']|["']$/g, "");
656
+ const reason = reasonParts || "Parked via /gsd park";
657
+
658
+ const success = parkMilestone(basePath, targetId, reason);
659
+ if (success) {
660
+ ctx.ui.notify(`Parked ${targetId}. Run /gsd unpark ${targetId} to reactivate.`, "info");
661
+ } else {
662
+ ctx.ui.notify(`Could not park ${targetId} — milestone not found.`, "warning");
663
+ }
664
+ return;
665
+ }
666
+
667
+ if (trimmed === "unpark" || trimmed.startsWith("unpark ")) {
668
+ const basePath = projectRoot();
669
+ const arg = trimmed.replace(/^unpark\s*/, "").trim();
670
+ const { unparkMilestone } = await import("./milestone-actions.js");
671
+ const { deriveState } = await import("./state.js");
672
+
673
+ let targetId = arg;
674
+ if (!targetId) {
675
+ // List parked milestones and let user pick
676
+ const state = await deriveState(basePath);
677
+ const parkedEntries = state.registry.filter(e => e.status === "parked");
678
+ if (parkedEntries.length === 0) {
679
+ ctx.ui.notify("No parked milestones.", "info");
680
+ return;
681
+ }
682
+ if (parkedEntries.length === 1) {
683
+ targetId = parkedEntries[0].id;
684
+ } else {
685
+ ctx.ui.notify(`Parked milestones: ${parkedEntries.map(e => e.id).join(", ")}. Specify which to unpark: /gsd unpark <id>`, "info");
686
+ return;
687
+ }
688
+ }
689
+
690
+ const success = unparkMilestone(basePath, targetId);
691
+ if (success) {
692
+ ctx.ui.notify(`Unparked ${targetId}. It will resume its normal position in the queue.`, "info");
693
+ } else {
694
+ ctx.ui.notify(`Could not unpark ${targetId} — milestone not found or not parked.`, "warning");
695
+ }
696
+ return;
697
+ }
698
+
468
699
  if (trimmed === "new-milestone") {
469
700
  const basePath = projectRoot();
470
701
  const headlessContextPath = join(basePath, ".gsd", "runtime", "headless-context.md");
@@ -581,6 +812,17 @@ Examples:
581
812
  return;
582
813
  }
583
814
 
815
+ // ─── Workflow Templates ────────────────────────────────────────
816
+ if (trimmed === "start" || trimmed.startsWith("start ")) {
817
+ await handleStart(trimmed.replace(/^start\s*/, "").trim(), ctx, pi);
818
+ return;
819
+ }
820
+
821
+ if (trimmed === "templates" || trimmed.startsWith("templates ")) {
822
+ await handleTemplates(trimmed.replace(/^templates\s*/, "").trim(), ctx);
823
+ return;
824
+ }
825
+
584
826
  if (trimmed === "") {
585
827
  // Bare /gsd defaults to step mode
586
828
  await startAuto(ctx, pi, projectRoot(), false, { step: true });
@@ -599,6 +841,8 @@ function showHelp(ctx: ExtensionCommandContext): void {
599
841
  const lines = [
600
842
  "GSD — Get Shit Done\n",
601
843
  "WORKFLOW",
844
+ " /gsd start <tpl> Start a workflow template (bugfix, spike, feature, hotfix, etc.)",
845
+ " /gsd templates List available workflow templates [info <name>]",
602
846
  " /gsd Run next unit in step mode (same as /gsd next)",
603
847
  " /gsd next Execute next task, then pause [--dry-run] [--verbose]",
604
848
  " /gsd auto Run all queued units continuously [--verbose]",
@@ -619,21 +863,26 @@ function showHelp(ctx: ExtensionCommandContext): void {
619
863
  " /gsd triage Classify and route pending captures",
620
864
  " /gsd skip <unit> Prevent a unit from auto-mode dispatch",
621
865
  " /gsd undo Revert last completed unit [--force]",
866
+ " /gsd park [id] Park a milestone — skip without deleting [reason]",
867
+ " /gsd unpark [id] Reactivate a parked milestone",
622
868
  "",
623
869
  "PROJECT KNOWLEDGE",
624
870
  " /gsd knowledge <type> <text> Add rule, pattern, or lesson to KNOWLEDGE.md",
625
871
  "",
626
- "CONFIGURATION",
872
+ "SETUP & CONFIGURATION",
873
+ " /gsd init Project init wizard — detect, configure, bootstrap .gsd/",
874
+ " /gsd setup Global setup status [llm|search|remote|keys|prefs]",
627
875
  " /gsd mode Set workflow mode (solo/team) [global|project]",
628
- " /gsd prefs Manage preferences [global|project|status|wizard|setup]",
876
+ " /gsd prefs Manage preferences [global|project|status|wizard|setup|import-claude]",
629
877
  " /gsd config Set API keys for external tools",
878
+ " /gsd keys API key manager [list|add|remove|test|rotate|doctor]",
630
879
  " /gsd hooks Show post-unit hook configuration",
631
880
  "",
632
881
  "MAINTENANCE",
633
882
  " /gsd doctor Diagnose and repair .gsd/ state [audit|fix|heal] [scope]",
634
883
  " /gsd export Export milestone/slice results [--json|--markdown|--html] [--all]",
635
884
  " /gsd cleanup Remove merged branches or snapshots [branches|snapshots]",
636
- " /gsd migrate Upgrade .gsd/ structures to new format",
885
+ " /gsd migrate Migrate .planning/ (v1) to .gsd/ (v2) format",
637
886
  " /gsd remote Control remote auto-mode [slack|discord|status|disconnect]",
638
887
  " /gsd inspect Show SQLite DB diagnostics (schema, row counts, recent entries)",
639
888
  " /gsd update Update GSD to the latest version via npm",
@@ -650,7 +899,7 @@ async function handleStatus(ctx: ExtensionCommandContext): Promise<void> {
650
899
  return;
651
900
  }
652
901
 
653
- await ctx.ui.custom<void>(
902
+ const result = await ctx.ui.custom<void>(
654
903
  (tui, theme, _kb, done) => {
655
904
  return new GSDDashboardOverlay(tui, theme, () => done());
656
905
  },
@@ -664,6 +913,12 @@ async function handleStatus(ctx: ExtensionCommandContext): Promise<void> {
664
913
  },
665
914
  },
666
915
  );
916
+
917
+ // Fallback for RPC mode where ctx.ui.custom() returns undefined.
918
+ // Produce a text-based status summary so the turn is not empty.
919
+ if (result === undefined) {
920
+ ctx.ui.notify(formatTextStatus(state), "info");
921
+ }
667
922
  }
668
923
 
669
924
  export async function fireStatusViaCommand(
@@ -678,7 +933,7 @@ async function handleVisualize(ctx: ExtensionCommandContext): Promise<void> {
678
933
  return;
679
934
  }
680
935
 
681
- await ctx.ui.custom<void>(
936
+ const result = await ctx.ui.custom<void>(
682
937
  (tui, theme, _kb, done) => {
683
938
  return new GSDVisualizerOverlay(tui, theme, () => done());
684
939
  },
@@ -692,1454 +947,121 @@ async function handleVisualize(ctx: ExtensionCommandContext): Promise<void> {
692
947
  },
693
948
  },
694
949
  );
950
+
951
+ // Fallback for RPC mode where ctx.ui.custom() returns undefined.
952
+ if (result === undefined) {
953
+ ctx.ui.notify("Visualizer requires an interactive terminal. Use /gsd status for a text-based overview.", "warning");
954
+ }
695
955
  }
696
956
 
697
- async function handlePrefs(args: string, ctx: ExtensionCommandContext): Promise<void> {
698
- const trimmed = args.trim();
957
+ async function handleSetup(args: string, ctx: ExtensionCommandContext): Promise<void> {
958
+ const { detectProjectState, hasGlobalSetup } = await import("./detection.js");
699
959
 
700
- if (trimmed === "" || trimmed === "global" || trimmed === "wizard" || trimmed === "setup"
701
- || trimmed === "wizard global" || trimmed === "setup global") {
702
- await ensurePreferencesFile(getGlobalGSDPreferencesPath(), ctx, "global");
703
- await handlePrefsWizard(ctx, "global");
704
- return;
705
- }
960
+ // Show current global setup status
961
+ const globalConfigured = hasGlobalSetup();
962
+ const detection = detectProjectState(projectRoot());
706
963
 
707
- if (trimmed === "project" || trimmed === "wizard project" || trimmed === "setup project") {
708
- await ensurePreferencesFile(getProjectGSDPreferencesPath(), ctx, "project");
709
- await handlePrefsWizard(ctx, "project");
710
- return;
964
+ const statusLines = ["GSD Setup Status\n"];
965
+ statusLines.push(` Global preferences: ${globalConfigured ? "configured" : "not set"}`);
966
+ statusLines.push(` Project state: ${detection.state}`);
967
+ if (detection.projectSignals.primaryLanguage) {
968
+ statusLines.push(` Detected: ${detection.projectSignals.primaryLanguage}`);
711
969
  }
712
970
 
713
- if (trimmed === "import-claude" || trimmed === "import-claude global") {
714
- await handleImportClaude(ctx, "global");
971
+ if (args === "llm" || args === "auth") {
972
+ ctx.ui.notify("Use /login to configure LLM authentication.", "info");
715
973
  return;
716
974
  }
717
975
 
718
- if (trimmed === "import-claude project") {
719
- await handleImportClaude(ctx, "project");
976
+ if (args === "search") {
977
+ ctx.ui.notify("Use /search-provider to configure web search.", "info");
720
978
  return;
721
979
  }
722
- if (trimmed === "status") {
723
- const globalPrefs = loadGlobalGSDPreferences();
724
- const projectPrefs = loadProjectGSDPreferences();
725
- const canonicalGlobal = getGlobalGSDPreferencesPath();
726
- const legacyGlobal = getLegacyGlobalGSDPreferencesPath();
727
- const globalStatus = globalPrefs
728
- ? `present: ${globalPrefs.path}${globalPrefs.path === legacyGlobal ? " (legacy fallback)" : ""}`
729
- : `missing: ${canonicalGlobal}`;
730
- const projectStatus = projectPrefs ? `present: ${projectPrefs.path}` : `missing: ${getProjectGSDPreferencesPath()}`;
731
-
732
- const lines = [`GSD skill prefs — global ${globalStatus}; project ${projectStatus}`];
733
-
734
- const effective = loadEffectiveGSDPreferences();
735
- let hasUnresolved = false;
736
- if (effective) {
737
- const report = resolveAllSkillReferences(effective.preferences, process.cwd());
738
- const resolved = [...report.resolutions.values()].filter(r => r.method !== "unresolved");
739
- hasUnresolved = report.warnings.length > 0;
740
- if (resolved.length > 0 || hasUnresolved) {
741
- lines.push(`Skills: ${resolved.length} resolved, ${report.warnings.length} unresolved`);
742
- }
743
- if (hasUnresolved) {
744
- lines.push(`Unresolved: ${report.warnings.join(", ")}`);
745
- }
746
- }
747
980
 
748
- ctx.ui.notify(lines.join("\n"), hasUnresolved ? "warning" : "info");
981
+ if (args === "remote") {
982
+ ctx.ui.notify("Use /gsd remote to configure remote questions.", "info");
749
983
  return;
750
984
  }
751
985
 
752
- ctx.ui.notify("Usage: /gsd prefs [global|project|status|wizard|setup|import-claude [global|project]]", "info");
753
- }
754
-
755
- async function handleImportClaude(ctx: ExtensionCommandContext, scope: "global" | "project"): Promise<void> {
756
- const path = scope === "project" ? getProjectGSDPreferencesPath() : getGlobalGSDPreferencesPath();
757
- if (!existsSync(path)) {
758
- await ensurePreferencesFile(path, ctx, scope);
759
- }
760
-
761
- const readPrefs = (): Record<string, unknown> => {
762
- if (!existsSync(path)) return { version: 1 };
763
- const content = readFileSync(path, "utf-8");
764
- const [frontmatterLines] = splitFrontmatter(content);
765
- return frontmatterLines ? parseFrontmatterMap(frontmatterLines) : { version: 1 };
766
- };
767
-
768
- const writePrefs = async (prefs: Record<string, unknown>): Promise<void> => {
769
- prefs.version = prefs.version || 1;
770
- const frontmatter = serializePreferencesToFrontmatter(prefs);
771
- let body = "\n# GSD Skill Preferences\n\nSee `~/.gsd/agent/extensions/gsd/docs/preferences-reference.md` for full field documentation and examples.\n";
772
- if (existsSync(path)) {
773
- const existingContent = readFileSync(path, "utf-8");
774
- const closingIdx = existingContent.indexOf("\n---", existingContent.indexOf("---"));
775
- if (closingIdx !== -1) {
776
- const afterFrontmatter = existingContent.slice(closingIdx + 4);
777
- if (afterFrontmatter.trim()) body = afterFrontmatter;
778
- }
779
- }
780
- await saveFile(path, `---\n${frontmatter}---${body}`);
781
- };
782
-
783
- await runClaudeImportFlow(ctx, scope, readPrefs, writePrefs);
784
- }
785
-
786
- async function handlePrefsMode(ctx: ExtensionCommandContext, scope: "global" | "project"): Promise<void> {
787
- const path = scope === "project" ? getProjectGSDPreferencesPath() : getGlobalGSDPreferencesPath();
788
- const existing = scope === "project" ? loadProjectGSDPreferences() : loadGlobalGSDPreferences();
789
- const prefs: Record<string, unknown> = existing?.preferences ? { ...existing.preferences } : {};
790
-
791
- await configureMode(ctx, prefs);
792
-
793
- // Serialize and save
794
- prefs.version = prefs.version || 1;
795
- const frontmatter = serializePreferencesToFrontmatter(prefs);
796
-
797
- let body = "\n# GSD Skill Preferences\n\nSee `~/.gsd/agent/extensions/gsd/docs/preferences-reference.md` for full field documentation and examples.\n";
798
- if (existsSync(path)) {
799
- const existingContent = readFileSync(path, "utf-8");
800
- const closingIdx = existingContent.indexOf("\n---", existingContent.indexOf("---"));
801
- if (closingIdx !== -1) {
802
- const afterFrontmatter = existingContent.slice(closingIdx + 4);
803
- if (afterFrontmatter.trim()) {
804
- body = afterFrontmatter;
805
- }
806
- }
807
- }
808
-
809
- const content = `---\n${frontmatter}---${body}`;
810
- await saveFile(path, content);
811
- await ctx.waitForIdle();
812
- await ctx.reload();
813
- ctx.ui.notify(`Saved ${scope} preferences to ${path}`, "info");
814
- }
815
-
816
- async function handleDoctor(args: string, ctx: ExtensionCommandContext, pi: ExtensionAPI): Promise<void> {
817
- const trimmed = args.trim();
818
- const parts = trimmed ? trimmed.split(/\s+/) : [];
819
- const mode = parts[0] === "fix" || parts[0] === "heal" || parts[0] === "audit" ? parts[0] : "doctor";
820
- const requestedScope = mode === "doctor" ? parts[0] : parts[1];
821
- const scope = await selectDoctorScope(projectRoot(), requestedScope);
822
- const effectiveScope = mode === "audit" ? requestedScope : scope;
823
- const report = await runGSDDoctor(projectRoot(), {
824
- fix: mode === "fix" || mode === "heal",
825
- scope: effectiveScope,
826
- });
827
-
828
- const reportText = formatDoctorReport(report, {
829
- scope: effectiveScope,
830
- includeWarnings: mode === "audit",
831
- maxIssues: mode === "audit" ? 50 : 12,
832
- title: mode === "audit" ? "GSD doctor audit." : mode === "heal" ? "GSD doctor heal prep." : undefined,
833
- });
834
-
835
- ctx.ui.notify(reportText, report.ok ? "info" : "warning");
836
-
837
- if (mode === "heal") {
838
- const unresolved = filterDoctorIssues(report.issues, {
839
- scope: effectiveScope,
840
- includeWarnings: true,
841
- });
842
- const actionable = unresolved.filter(issue => issue.severity === "error" || issue.code === "all_tasks_done_missing_slice_uat" || issue.code === "slice_checked_missing_uat");
843
- if (actionable.length === 0) {
844
- ctx.ui.notify("Doctor heal found nothing actionable to hand off to the LLM.", "info");
845
- return;
846
- }
847
-
848
- const structuredIssues = formatDoctorIssuesForPrompt(actionable);
849
- dispatchDoctorHeal(pi, effectiveScope, reportText, structuredIssues);
850
- ctx.ui.notify(`Doctor heal dispatched ${actionable.length} issue(s) to the LLM.`, "info");
851
- }
852
- }
853
-
854
- // ─── Inspect ──────────────────────────────────────────────────────────────────
855
-
856
- export interface InspectData {
857
- schemaVersion: number | null;
858
- counts: { decisions: number; requirements: number; artifacts: number };
859
- recentDecisions: Array<{ id: string; decision: string; choice: string }>;
860
- recentRequirements: Array<{ id: string; status: string; description: string }>;
861
- }
862
-
863
- export function formatInspectOutput(data: InspectData): string {
864
- const lines: string[] = [];
865
- lines.push("=== GSD Database Inspect ===");
866
- lines.push(`Schema version: ${data.schemaVersion ?? "unknown"}`);
867
- lines.push("");
868
- lines.push(`Decisions: ${data.counts.decisions}`);
869
- lines.push(`Requirements: ${data.counts.requirements}`);
870
- lines.push(`Artifacts: ${data.counts.artifacts}`);
871
-
872
- if (data.recentDecisions.length > 0) {
873
- lines.push("");
874
- lines.push("Recent decisions:");
875
- for (const d of data.recentDecisions) {
876
- lines.push(` ${d.id}: ${d.decision} → ${d.choice}`);
877
- }
878
- }
879
-
880
- if (data.recentRequirements.length > 0) {
881
- lines.push("");
882
- lines.push("Recent requirements:");
883
- for (const r of data.recentRequirements) {
884
- lines.push(` ${r.id} [${r.status}]: ${r.description}`);
885
- }
886
- }
887
-
888
- return lines.join("\n");
889
- }
890
-
891
- async function handleInspect(ctx: ExtensionCommandContext): Promise<void> {
892
- try {
893
- const { isDbAvailable, _getAdapter } = await import("./gsd-db.js");
894
-
895
- if (!isDbAvailable()) {
896
- ctx.ui.notify("No GSD database available. Run /gsd auto to create one.", "info");
897
- return;
898
- }
899
-
900
- const adapter = _getAdapter();
901
- if (!adapter) {
902
- ctx.ui.notify("No GSD database available. Run /gsd auto to create one.", "info");
903
- return;
904
- }
905
-
906
- const versionRow = adapter.prepare("SELECT MAX(version) as v FROM schema_version").get();
907
- const schemaVersion = versionRow ? (versionRow["v"] as number | null) : null;
908
-
909
- const dCount = adapter.prepare("SELECT count(*) as cnt FROM decisions").get();
910
- const rCount = adapter.prepare("SELECT count(*) as cnt FROM requirements").get();
911
- const aCount = adapter.prepare("SELECT count(*) as cnt FROM artifacts").get();
912
-
913
- const recentDecisions = adapter
914
- .prepare("SELECT id, decision, choice FROM decisions ORDER BY seq DESC LIMIT 5")
915
- .all() as Array<{ id: string; decision: string; choice: string }>;
916
-
917
- const recentRequirements = adapter
918
- .prepare("SELECT id, status, description FROM requirements ORDER BY id DESC LIMIT 5")
919
- .all() as Array<{ id: string; status: string; description: string }>;
920
-
921
- const data: InspectData = {
922
- schemaVersion,
923
- counts: {
924
- decisions: (dCount?.["cnt"] as number) ?? 0,
925
- requirements: (rCount?.["cnt"] as number) ?? 0,
926
- artifacts: (aCount?.["cnt"] as number) ?? 0,
927
- },
928
- recentDecisions,
929
- recentRequirements,
930
- };
931
-
932
- ctx.ui.notify(formatInspectOutput(data), "info");
933
- } catch (err) {
934
- process.stderr.write(`gsd-db: /gsd inspect failed: ${err instanceof Error ? err.message : String(err)}\n`);
935
- ctx.ui.notify("Failed to inspect GSD database. Check stderr for details.", "error");
936
- }
937
- }
938
-
939
- // ─── Skill Health ─────────────────────────────────────────────────────────────
940
-
941
- async function handleSkillHealth(args: string, ctx: ExtensionCommandContext): Promise<void> {
942
- const {
943
- generateSkillHealthReport,
944
- formatSkillHealthReport,
945
- formatSkillDetail,
946
- } = await import("./skill-health.js");
947
-
948
- const basePath = projectRoot();
949
-
950
- // /gsd skill-health <skill-name> — detail view
951
- if (args && !args.startsWith("--")) {
952
- const detail = formatSkillDetail(basePath, args);
953
- ctx.ui.notify(detail, "info");
986
+ if (args === "keys") {
987
+ const { handleKeys } = await import("./key-manager.js");
988
+ await handleKeys("", ctx);
954
989
  return;
955
990
  }
956
991
 
957
- // Parse flags
958
- const staleMatch = args.match(/--stale\s+(\d+)/);
959
- const staleDays = staleMatch ? parseInt(staleMatch[1], 10) : undefined;
960
- const decliningOnly = args.includes("--declining");
961
-
962
- const report = generateSkillHealthReport(basePath, staleDays);
963
-
964
- if (decliningOnly) {
965
- if (report.decliningSkills.length === 0) {
966
- ctx.ui.notify("No skills flagged for declining performance.", "info");
967
- return;
968
- }
969
- const filtered = {
970
- ...report,
971
- skills: report.skills.filter(s => s.flagged),
972
- };
973
- ctx.ui.notify(formatSkillHealthReport(filtered), "info");
992
+ if (args === "prefs") {
993
+ await ensurePreferencesFile(getGlobalGSDPreferencesPath(), ctx, "global");
994
+ await handlePrefsWizard(ctx, "global");
974
995
  return;
975
996
  }
976
997
 
977
- ctx.ui.notify(formatSkillHealthReport(report), "info");
978
- }
979
-
980
- // ─── Preferences Wizard ───────────────────────────────────────────────────────
981
-
982
- /** Build short summary strings for each preference category. */
983
- function buildCategorySummaries(prefs: Record<string, unknown>): Record<string, string> {
984
- // Mode
985
- const mode = prefs.mode as string | undefined;
986
- const modeSummary = mode ?? "(not set)";
987
-
988
- // Models
989
- const models = prefs.models as Record<string, string> | undefined;
990
- let modelsSummary = "(not configured)";
991
- if (models && Object.keys(models).length > 0) {
992
- const parts = Object.entries(models).map(([phase, model]) => `${phase}: ${model}`);
993
- modelsSummary = parts.join(", ");
994
- }
995
-
996
- // Timeouts
997
- const autoSup = prefs.auto_supervisor as Record<string, unknown> | undefined;
998
- let timeoutsSummary = "(defaults)";
999
- if (autoSup && Object.keys(autoSup).length > 0) {
1000
- const soft = autoSup.soft_timeout_minutes ?? "20";
1001
- const idle = autoSup.idle_timeout_minutes ?? "10";
1002
- const hard = autoSup.hard_timeout_minutes ?? "30";
1003
- timeoutsSummary = `soft: ${soft}m, idle: ${idle}m, hard: ${hard}m`;
1004
- }
1005
-
1006
- // Git
1007
- const git = prefs.git as Record<string, unknown> | undefined;
1008
- let gitSummary = "(defaults)";
1009
- if (git && Object.keys(git).length > 0) {
1010
- const branch = git.main_branch ?? "main";
1011
- const push = git.auto_push ? "on" : "off";
1012
- gitSummary = `main: ${branch}, push: ${push}`;
1013
- }
1014
-
1015
- // Skills
1016
- const discovery = prefs.skill_discovery as string | undefined;
1017
- const uat = prefs.uat_dispatch;
1018
- let skillsSummary = "(not configured)";
1019
- if (discovery || uat !== undefined) {
1020
- const parts: string[] = [];
1021
- if (discovery) parts.push(`discovery: ${discovery}`);
1022
- if (uat !== undefined) parts.push(`uat: ${uat}`);
1023
- skillsSummary = parts.join(", ");
1024
- }
1025
-
1026
- // Budget
1027
- const ceiling = prefs.budget_ceiling;
1028
- const enforcement = prefs.budget_enforcement as string | undefined;
1029
- let budgetSummary = "(no limit)";
1030
- if (ceiling !== undefined) {
1031
- budgetSummary = `$${ceiling}`;
1032
- if (enforcement) budgetSummary += ` / ${enforcement}`;
1033
- } else if (enforcement) {
1034
- budgetSummary = enforcement;
1035
- }
1036
-
1037
- // Notifications
1038
- const notif = prefs.notifications as Record<string, boolean> | undefined;
1039
- let notifSummary = "(defaults)";
1040
- if (notif && Object.keys(notif).length > 0) {
1041
- const allKeys = ["enabled", "on_complete", "on_error", "on_budget", "on_milestone", "on_attention"];
1042
- const enabledCount = allKeys.filter(k => notif[k] !== false).length;
1043
- notifSummary = `${enabledCount}/${allKeys.length} enabled`;
1044
- }
1045
-
1046
- // Advanced
1047
- const uniqueIds = prefs.unique_milestone_ids;
1048
- let advancedSummary = "(defaults)";
1049
- if (uniqueIds !== undefined) {
1050
- advancedSummary = `unique IDs: ${uniqueIds ? "on" : "off"}`;
1051
- }
1052
-
1053
- return {
1054
- mode: modeSummary,
1055
- models: modelsSummary,
1056
- timeouts: timeoutsSummary,
1057
- git: gitSummary,
1058
- skills: skillsSummary,
1059
- budget: budgetSummary,
1060
- notifications: notifSummary,
1061
- advanced: advancedSummary,
1062
- };
1063
- }
1064
-
1065
- // ─── Category configuration functions ────────────────────────────────────────
1066
-
1067
- async function configureModels(ctx: ExtensionCommandContext, prefs: Record<string, unknown>): Promise<void> {
1068
- const modelPhases = ["research", "planning", "execution", "completion"] as const;
1069
- const models: Record<string, string> = (prefs.models as Record<string, string>) ?? {};
1070
-
1071
- const availableModels = ctx.modelRegistry.getAvailable();
1072
- if (availableModels.length > 0) {
1073
- const modelOptions = availableModels.map(m => `${m.id} · ${m.provider}`);
1074
- modelOptions.push("(keep current)", "(clear)");
1075
-
1076
- for (const phase of modelPhases) {
1077
- const current = models[phase] ?? "";
1078
- const title = `Model for ${phase} phase${current ? ` (current: ${current})` : ""}:`;
1079
- const choice = await ctx.ui.select(title, modelOptions);
1080
-
1081
- if (choice && typeof choice === "string" && choice !== "(keep current)") {
1082
- if (choice === "(clear)") {
1083
- delete models[phase];
1084
- } else {
1085
- models[phase] = choice.split(" · ")[0];
1086
- }
1087
- }
1088
- }
1089
- } else {
1090
- for (const phase of modelPhases) {
1091
- const current = models[phase] ?? "";
1092
- const input = await ctx.ui.input(
1093
- `Model for ${phase} phase${current ? ` (current: ${current})` : ""}:`,
1094
- current || "e.g. claude-sonnet-4-20250514",
1095
- );
1096
- if (input !== null && input !== undefined) {
1097
- const val = input.trim();
1098
- if (val) {
1099
- models[phase] = val;
1100
- } else if (current) {
1101
- delete models[phase];
1102
- }
1103
- }
1104
- }
1105
- }
1106
- if (Object.keys(models).length > 0) {
1107
- prefs.models = models;
1108
- }
1109
- }
1110
-
1111
- async function configureTimeouts(ctx: ExtensionCommandContext, prefs: Record<string, unknown>): Promise<void> {
1112
- const autoSup: Record<string, unknown> = (prefs.auto_supervisor as Record<string, unknown>) ?? {};
1113
- const timeoutFields = [
1114
- { key: "soft_timeout_minutes", label: "Soft timeout (minutes)", defaultVal: "20" },
1115
- { key: "idle_timeout_minutes", label: "Idle timeout (minutes)", defaultVal: "10" },
1116
- { key: "hard_timeout_minutes", label: "Hard timeout (minutes)", defaultVal: "30" },
1117
- ] as const;
1118
-
1119
- for (const field of timeoutFields) {
1120
- const current = autoSup[field.key];
1121
- const currentStr = current !== undefined && current !== null ? String(current) : "";
1122
- const input = await ctx.ui.input(
1123
- `${field.label}${currentStr ? ` (current: ${currentStr})` : ` (default: ${field.defaultVal})`}:`,
1124
- currentStr || field.defaultVal,
1125
- );
1126
- if (input !== null && input !== undefined) {
1127
- const val = input.trim();
1128
- if (val && /^\d+$/.test(val)) {
1129
- autoSup[field.key] = Number(val);
1130
- } else if (val && !/^\d+$/.test(val)) {
1131
- ctx.ui.notify(`Invalid value "${val}" for ${field.label} — must be a whole number. Keeping previous value.`, "warning");
1132
- } else if (!val && currentStr) {
1133
- delete autoSup[field.key];
1134
- }
1135
- }
1136
- }
1137
- if (Object.keys(autoSup).length > 0) {
1138
- prefs.auto_supervisor = autoSup;
1139
- }
1140
- }
1141
-
1142
- async function configureGit(ctx: ExtensionCommandContext, prefs: Record<string, unknown>): Promise<void> {
1143
- const git: Record<string, unknown> = (prefs.git as Record<string, unknown>) ?? {};
1144
-
1145
- // main_branch
1146
- const currentBranch = git.main_branch ? String(git.main_branch) : "";
1147
- const branchInput = await ctx.ui.input(
1148
- `Git main branch${currentBranch ? ` (current: ${currentBranch})` : ""}:`,
1149
- currentBranch || "main",
1150
- );
1151
- if (branchInput !== null && branchInput !== undefined) {
1152
- const val = branchInput.trim();
1153
- if (val) {
1154
- git.main_branch = val;
1155
- } else if (currentBranch) {
1156
- delete git.main_branch;
1157
- }
1158
- }
1159
-
1160
- // Boolean git toggles
1161
- const gitBooleanFields = [
1162
- { key: "auto_push", label: "Auto-push commits after committing", defaultVal: false },
1163
- { key: "push_branches", label: "Push milestone branches to remote", defaultVal: false },
1164
- { key: "snapshots", label: "Create WIP snapshot commits during long tasks", defaultVal: false },
1165
- ] as const;
1166
-
1167
- for (const field of gitBooleanFields) {
1168
- const current = git[field.key];
1169
- const currentStr = current !== undefined ? String(current) : "";
1170
- const choice = await ctx.ui.select(
1171
- `${field.label}${currentStr ? ` (current: ${currentStr})` : ` (default: ${field.defaultVal})`}:`,
1172
- ["true", "false", "(keep current)"],
1173
- );
1174
- if (choice && choice !== "(keep current)") {
1175
- git[field.key] = choice === "true";
1176
- }
1177
- }
1178
-
1179
- // remote
1180
- const currentRemote = git.remote ? String(git.remote) : "";
1181
- const remoteInput = await ctx.ui.input(
1182
- `Git remote name${currentRemote ? ` (current: ${currentRemote})` : " (default: origin)"}:`,
1183
- currentRemote || "origin",
1184
- );
1185
- if (remoteInput !== null && remoteInput !== undefined) {
1186
- const val = remoteInput.trim();
1187
- if (val && val !== "origin") {
1188
- git.remote = val;
1189
- } else if (!val && currentRemote) {
1190
- delete git.remote;
1191
- }
1192
- }
1193
-
1194
- // pre_merge_check
1195
- const currentPreMerge = git.pre_merge_check !== undefined ? String(git.pre_merge_check) : "";
1196
- const preMergeChoice = await ctx.ui.select(
1197
- `Pre-merge check${currentPreMerge ? ` (current: ${currentPreMerge})` : " (default: false)"}:`,
1198
- ["true", "false", "auto", "(keep current)"],
1199
- );
1200
- if (preMergeChoice && preMergeChoice !== "(keep current)") {
1201
- if (preMergeChoice === "auto") {
1202
- git.pre_merge_check = "auto";
1203
- } else {
1204
- git.pre_merge_check = preMergeChoice === "true";
1205
- }
1206
- }
1207
-
1208
- // commit_type
1209
- const currentCommitType = git.commit_type ? String(git.commit_type) : "";
1210
- const commitTypes = ["feat", "fix", "refactor", "docs", "test", "chore", "perf", "ci", "build", "style", "(inferred — default)", "(keep current)"];
1211
- const commitChoice = await ctx.ui.select(
1212
- `Default commit type${currentCommitType ? ` (current: ${currentCommitType})` : ""}:`,
1213
- commitTypes,
1214
- );
1215
- if (commitChoice && typeof commitChoice === "string" && commitChoice !== "(keep current)") {
1216
- if ((commitChoice as string).startsWith("(inferred")) {
1217
- delete git.commit_type;
1218
- } else {
1219
- git.commit_type = commitChoice;
1220
- }
1221
- }
1222
-
1223
- // merge_strategy
1224
- const currentMerge = git.merge_strategy ? String(git.merge_strategy) : "";
1225
- const mergeChoice = await ctx.ui.select(
1226
- `Merge strategy${currentMerge ? ` (current: ${currentMerge})` : ""}:`,
1227
- ["squash", "merge", "(keep current)"],
1228
- );
1229
- if (mergeChoice && mergeChoice !== "(keep current)") {
1230
- git.merge_strategy = mergeChoice;
1231
- }
1232
-
1233
- // isolation
1234
- const currentIsolation = git.isolation ? String(git.isolation) : "";
1235
- const isolationChoice = await ctx.ui.select(
1236
- `Git isolation strategy${currentIsolation ? ` (current: ${currentIsolation})` : " (default: worktree)"}:`,
1237
- ["worktree", "branch", "none", "(keep current)"],
1238
- );
1239
- if (isolationChoice && isolationChoice !== "(keep current)") {
1240
- git.isolation = isolationChoice;
1241
- }
1242
-
1243
- // commit_docs
1244
- const currentCommitDocs = git.commit_docs;
1245
- const commitDocsChoice = await ctx.ui.select(
1246
- `Track .gsd/ planning docs in git${currentCommitDocs !== undefined ? ` (current: ${currentCommitDocs})` : ""}:`,
1247
- ["true", "false", "(keep current)"],
1248
- );
1249
- if (commitDocsChoice && commitDocsChoice !== "(keep current)") {
1250
- git.commit_docs = commitDocsChoice === "true";
1251
- }
1252
-
1253
- if (Object.keys(git).length > 0) {
1254
- prefs.git = git;
1255
- }
1256
- }
1257
-
1258
- async function configureSkills(ctx: ExtensionCommandContext, prefs: Record<string, unknown>): Promise<void> {
1259
- // Skill discovery mode
1260
- const currentDiscovery = (prefs.skill_discovery as string) ?? "";
1261
- const discoveryChoice = await ctx.ui.select(
1262
- `Skill discovery mode${currentDiscovery ? ` (current: ${currentDiscovery})` : ""}:`,
1263
- ["auto", "suggest", "off", "(keep current)"],
1264
- );
1265
- if (discoveryChoice && discoveryChoice !== "(keep current)") {
1266
- prefs.skill_discovery = discoveryChoice;
1267
- }
1268
-
1269
- // UAT dispatch
1270
- const currentUat = prefs.uat_dispatch;
1271
- const uatChoice = await ctx.ui.select(
1272
- `UAT dispatch mode${currentUat !== undefined ? ` (current: ${currentUat})` : " (default: false)"}:`,
1273
- ["true", "false", "(keep current)"],
1274
- );
1275
- if (uatChoice && uatChoice !== "(keep current)") {
1276
- prefs.uat_dispatch = uatChoice === "true";
1277
- }
1278
- }
1279
-
1280
- async function configureBudget(ctx: ExtensionCommandContext, prefs: Record<string, unknown>): Promise<void> {
1281
- const currentCeiling = prefs.budget_ceiling;
1282
- const ceilingStr = currentCeiling !== undefined ? String(currentCeiling) : "";
1283
- const ceilingInput = await ctx.ui.input(
1284
- `Budget ceiling (USD)${ceilingStr ? ` (current: $${ceilingStr})` : " (default: no limit)"}:`,
1285
- ceilingStr || "",
1286
- );
1287
- if (ceilingInput !== null && ceilingInput !== undefined) {
1288
- const val = ceilingInput.trim().replace(/^\$/, "");
1289
- if (val && !isNaN(Number(val)) && isFinite(Number(val))) {
1290
- prefs.budget_ceiling = Number(val);
1291
- } else if (val && (isNaN(Number(val)) || !isFinite(Number(val)))) {
1292
- ctx.ui.notify(`Invalid budget ceiling "${val}" — must be a number. Keeping previous value.`, "warning");
1293
- } else if (!val && ceilingStr) {
1294
- delete prefs.budget_ceiling;
1295
- }
1296
- }
1297
-
1298
- const currentEnforcement = (prefs.budget_enforcement as string) ?? "";
1299
- const enforcementChoice = await ctx.ui.select(
1300
- `Budget enforcement${currentEnforcement ? ` (current: ${currentEnforcement})` : " (default: pause)"}:`,
1301
- ["warn", "pause", "halt", "(keep current)"],
1302
- );
1303
- if (enforcementChoice && enforcementChoice !== "(keep current)") {
1304
- prefs.budget_enforcement = enforcementChoice;
1305
- }
1306
-
1307
- const currentContextPause = prefs.context_pause_threshold;
1308
- const contextPauseStr = currentContextPause !== undefined ? String(currentContextPause) : "";
1309
- const contextPauseInput = await ctx.ui.input(
1310
- `Context pause threshold (0-100%, 0=disabled)${contextPauseStr ? ` (current: ${contextPauseStr}%)` : " (default: 0)"}:`,
1311
- contextPauseStr || "0",
1312
- );
1313
- if (contextPauseInput !== null && contextPauseInput !== undefined) {
1314
- const val = contextPauseInput.trim().replace(/%$/, "");
1315
- if (val && !isNaN(Number(val)) && Number(val) >= 0 && Number(val) <= 100) {
1316
- const num = Number(val);
1317
- if (num === 0) {
1318
- delete prefs.context_pause_threshold;
1319
- } else {
1320
- prefs.context_pause_threshold = num;
1321
- }
1322
- } else if (val && (isNaN(Number(val)) || Number(val) < 0 || Number(val) > 100)) {
1323
- ctx.ui.notify(`Invalid context pause threshold "${val}" — must be 0-100. Keeping previous value.`, "warning");
1324
- }
1325
- }
1326
- }
1327
-
1328
- async function configureNotifications(ctx: ExtensionCommandContext, prefs: Record<string, unknown>): Promise<void> {
1329
- const notif: Record<string, boolean> = (prefs.notifications as Record<string, boolean>) ?? {};
1330
- const notifFields = [
1331
- { key: "enabled", label: "Notifications enabled (master toggle)", defaultVal: true },
1332
- { key: "on_complete", label: "Notify on unit completion", defaultVal: true },
1333
- { key: "on_error", label: "Notify on errors", defaultVal: true },
1334
- { key: "on_budget", label: "Notify on budget thresholds", defaultVal: true },
1335
- { key: "on_milestone", label: "Notify on milestone completion", defaultVal: true },
1336
- { key: "on_attention", label: "Notify when manual attention needed", defaultVal: true },
1337
- ] as const;
1338
-
1339
- for (const field of notifFields) {
1340
- const current = notif[field.key];
1341
- const currentStr = current !== undefined && typeof current === "boolean" ? String(current) : "";
1342
- const choice = await ctx.ui.select(
1343
- `${field.label}${currentStr ? ` (current: ${currentStr})` : ` (default: ${field.defaultVal})`}:`,
1344
- ["true", "false", "(keep current)"],
1345
- );
1346
- if (choice && choice !== "(keep current)") {
1347
- notif[field.key] = choice === "true";
1348
- }
1349
- }
1350
- if (Object.keys(notif).length > 0) {
1351
- prefs.notifications = notif;
1352
- }
1353
- }
1354
-
1355
- async function configureMode(ctx: ExtensionCommandContext, prefs: Record<string, unknown>): Promise<void> {
1356
- const currentMode = prefs.mode as string | undefined;
1357
- const modeChoice = await ctx.ui.select(
1358
- `Workflow mode${currentMode ? ` (current: ${currentMode})` : ""}:`,
1359
- [
1360
- "solo — auto-push, squash, simple IDs (personal projects)",
1361
- "team — unique IDs, push branches, pre-merge checks (shared repos)",
1362
- "(none) — configure everything manually",
1363
- "(keep current)",
1364
- ],
1365
- );
1366
- const modeStr = typeof modeChoice === "string" ? modeChoice : "";
1367
- if (modeStr && modeStr !== "(keep current)") {
1368
- if (modeStr.startsWith("solo")) {
1369
- prefs.mode = "solo";
1370
- ctx.ui.notify(
1371
- "Mode: solo — defaults: auto_push=true, push_branches=false, pre_merge_check=false, merge_strategy=squash, isolation=worktree, commit_docs=true, unique_milestone_ids=false",
1372
- "info",
1373
- );
1374
- } else if (modeStr.startsWith("team")) {
1375
- prefs.mode = "team";
1376
- ctx.ui.notify(
1377
- "Mode: team — defaults: auto_push=false, push_branches=true, pre_merge_check=true, merge_strategy=squash, isolation=worktree, commit_docs=true, unique_milestone_ids=true",
1378
- "info",
1379
- );
1380
- } else {
1381
- delete prefs.mode;
1382
- }
1383
- }
1384
- }
1385
-
1386
- async function configureAdvanced(ctx: ExtensionCommandContext, prefs: Record<string, unknown>): Promise<void> {
1387
- const currentUnique = prefs.unique_milestone_ids;
1388
- const uniqueChoice = await ctx.ui.select(
1389
- `Unique milestone IDs${currentUnique !== undefined ? ` (current: ${currentUnique})` : ""}:`,
1390
- ["true", "false", "(keep current)"],
998
+ // Full setup summary
999
+ ctx.ui.notify(statusLines.join("\n"), "info");
1000
+ ctx.ui.notify(
1001
+ "Available setup commands:\n" +
1002
+ " /gsd setup llm — LLM authentication\n" +
1003
+ " /gsd setup search — Web search provider\n" +
1004
+ " /gsd setup remote — Remote questions (Discord/Slack/Telegram)\n" +
1005
+ " /gsd setup keys — Tool API keys\n" +
1006
+ " /gsd setup prefs Global preferences wizard",
1007
+ "info",
1391
1008
  );
1392
- if (uniqueChoice && uniqueChoice !== "(keep current)") {
1393
- prefs.unique_milestone_ids = uniqueChoice === "true";
1394
- }
1395
- }
1396
-
1397
- // ─── Main wizard with category menu ─────────────────────────────────────────
1398
-
1399
- async function handlePrefsWizard(
1400
- ctx: ExtensionCommandContext,
1401
- scope: "global" | "project",
1402
- ): Promise<void> {
1403
- const path = scope === "project" ? getProjectGSDPreferencesPath() : getGlobalGSDPreferencesPath();
1404
- const existing = scope === "project" ? loadProjectGSDPreferences() : loadGlobalGSDPreferences();
1405
- const prefs: Record<string, unknown> = existing?.preferences ? { ...existing.preferences } : {};
1406
-
1407
- ctx.ui.notify(`GSD preferences (${scope}) — pick a category to configure.`, "info");
1408
-
1409
- while (true) {
1410
- const summaries = buildCategorySummaries(prefs);
1411
- const options = [
1412
- `Workflow Mode ${summaries.mode}`,
1413
- `Models ${summaries.models}`,
1414
- `Timeouts ${summaries.timeouts}`,
1415
- `Git ${summaries.git}`,
1416
- `Skills ${summaries.skills}`,
1417
- `Budget ${summaries.budget}`,
1418
- `Notifications ${summaries.notifications}`,
1419
- `Advanced ${summaries.advanced}`,
1420
- `── Save & Exit ──`,
1421
- ];
1422
-
1423
- const raw = await ctx.ui.select("GSD Preferences", options);
1424
- const choice = typeof raw === "string" ? raw : "";
1425
- if (!choice || choice.includes("Save & Exit")) break;
1426
-
1427
- if (choice.startsWith("Workflow Mode")) await configureMode(ctx, prefs);
1428
- else if (choice.startsWith("Models")) await configureModels(ctx, prefs);
1429
- else if (choice.startsWith("Timeouts")) await configureTimeouts(ctx, prefs);
1430
- else if (choice.startsWith("Git")) await configureGit(ctx, prefs);
1431
- else if (choice.startsWith("Skills")) await configureSkills(ctx, prefs);
1432
- else if (choice.startsWith("Budget")) await configureBudget(ctx, prefs);
1433
- else if (choice.startsWith("Notifications")) await configureNotifications(ctx, prefs);
1434
- else if (choice.startsWith("Advanced")) await configureAdvanced(ctx, prefs);
1435
- }
1436
-
1437
- // ─── Serialize to frontmatter ───────────────────────────────────────────
1438
- prefs.version = prefs.version || 1;
1439
- const frontmatter = serializePreferencesToFrontmatter(prefs);
1440
-
1441
- // Preserve existing body content (everything after closing ---)
1442
- let body = "\n# GSD Skill Preferences\n\nSee `~/.gsd/agent/extensions/gsd/docs/preferences-reference.md` for full field documentation and examples.\n";
1443
- if (existsSync(path)) {
1444
- const existingContent = readFileSync(path, "utf-8");
1445
- const closingIdx = existingContent.indexOf("\n---", existingContent.indexOf("---"));
1446
- if (closingIdx !== -1) {
1447
- const afterFrontmatter = existingContent.slice(closingIdx + 4); // skip past "\n---"
1448
- if (afterFrontmatter.trim()) {
1449
- body = afterFrontmatter;
1450
- }
1451
- }
1452
- }
1453
-
1454
- const content = `---\n${frontmatter}---${body}`;
1455
-
1456
- await saveFile(path, content);
1457
- await ctx.waitForIdle();
1458
- await ctx.reload();
1459
- ctx.ui.notify(`Saved ${scope} preferences to ${path}`, "info");
1460
- }
1461
-
1462
- /** Wrap a YAML value in double quotes if it contains special characters. */
1463
- function yamlSafeString(val: unknown): string {
1464
- if (typeof val !== "string") return String(val);
1465
- if (/[:#{\[\]'"`,|>&*!?@%]/.test(val) || val.trim() !== val || val === "") {
1466
- return `"${val.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
1467
- }
1468
- return val;
1469
- }
1470
-
1471
- function serializePreferencesToFrontmatter(prefs: Record<string, unknown>): string {
1472
- const lines: string[] = [];
1473
-
1474
- function serializeValue(key: string, value: unknown, indent: number): void {
1475
- const prefix = " ".repeat(indent);
1476
- if (value === null || value === undefined) return;
1477
-
1478
- if (Array.isArray(value)) {
1479
- if (value.length === 0) {
1480
- return; // Omit empty arrays — avoids parse/serialize cycle bug with "[]" strings
1481
- }
1482
- lines.push(`${prefix}${key}:`);
1483
- for (const item of value) {
1484
- if (typeof item === "object" && item !== null) {
1485
- const entries = Object.entries(item as Record<string, unknown>);
1486
- if (entries.length > 0) {
1487
- const [firstKey, firstVal] = entries[0];
1488
- lines.push(`${prefix} - ${firstKey}: ${yamlSafeString(firstVal)}`);
1489
- for (let i = 1; i < entries.length; i++) {
1490
- const [k, v] = entries[i];
1491
- if (Array.isArray(v)) {
1492
- lines.push(`${prefix} ${k}:`);
1493
- for (const arrItem of v) {
1494
- lines.push(`${prefix} - ${yamlSafeString(arrItem)}`);
1495
- }
1496
- } else {
1497
- lines.push(`${prefix} ${k}: ${yamlSafeString(v)}`);
1498
- }
1499
- }
1500
- }
1501
- } else {
1502
- lines.push(`${prefix} - ${yamlSafeString(item)}`);
1503
- }
1504
- }
1505
- return;
1506
- }
1507
-
1508
- if (typeof value === "object") {
1509
- const entries = Object.entries(value as Record<string, unknown>);
1510
- if (entries.length === 0) {
1511
- return; // Omit empty objects — avoids parse/serialize cycle bug with "{}" strings
1512
- }
1513
- lines.push(`${prefix}${key}:`);
1514
- for (const [k, v] of entries) {
1515
- serializeValue(k, v, indent + 1);
1516
- }
1517
- return;
1518
- }
1519
-
1520
- lines.push(`${prefix}${key}: ${yamlSafeString(value)}`);
1521
- }
1522
-
1523
- // Ordered keys for consistent output
1524
- const orderedKeys = [
1525
- "version", "mode", "always_use_skills", "prefer_skills", "avoid_skills",
1526
- "skill_rules", "custom_instructions", "models", "skill_discovery",
1527
- "auto_supervisor", "uat_dispatch", "unique_milestone_ids",
1528
- "budget_ceiling", "budget_enforcement", "context_pause_threshold",
1529
- "notifications", "remote_questions", "git",
1530
- "post_unit_hooks", "pre_dispatch_hooks",
1531
- ];
1532
-
1533
- const seen = new Set<string>();
1534
- for (const key of orderedKeys) {
1535
- if (key in prefs) {
1536
- serializeValue(key, prefs[key], 0);
1537
- seen.add(key);
1538
- }
1539
- }
1540
- // Any remaining keys not in the ordered list
1541
- for (const [key, value] of Object.entries(prefs)) {
1542
- if (!seen.has(key)) {
1543
- serializeValue(key, value, 0);
1544
- }
1545
- }
1546
-
1547
- return lines.join("\n") + "\n";
1548
1009
  }
1549
1010
 
1550
- // ─── Tool Config Wizard ───────────────────────────────────────────────────────
1011
+ // ─── Text-based status for RPC mode ────────────────────────────────────────
1551
1012
 
1552
1013
  /**
1553
- * Tool API key configurations.
1554
- * This is the source of truth for tool credentials - used by both the config wizard
1555
- * and session startup to load keys from auth.json into environment variables.
1014
+ * Generate a text-based status summary for non-TUI environments (RPC mode).
1015
+ * Used as a fallback when the interactive dashboard overlay is unavailable.
1556
1016
  */
1557
- export const TOOL_KEYS = [
1558
- { id: "tavily", env: "TAVILY_API_KEY", label: "Tavily Search", hint: "tavily.com/app/api-keys" },
1559
- { id: "brave", env: "BRAVE_API_KEY", label: "Brave Search", hint: "brave.com/search/api" },
1560
- { id: "context7", env: "CONTEXT7_API_KEY", label: "Context7 Docs", hint: "context7.com/dashboard" },
1561
- { id: "jina", env: "JINA_API_KEY", label: "Jina Page Extract", hint: "jina.ai/api" },
1562
- { id: "groq", env: "GROQ_API_KEY", label: "Groq Voice", hint: "console.groq.com" },
1563
- ] as const;
1017
+ function formatTextStatus(state: GSDState): string {
1018
+ const lines: string[] = ["GSD Status\n"];
1564
1019
 
1565
- /**
1566
- * Load tool API keys from auth.json into environment variables.
1567
- * Called at session startup to ensure tools have access to their credentials.
1568
- */
1569
- export function loadToolApiKeys(): void {
1570
- try {
1571
- const authPath = join(process.env.HOME ?? "", ".gsd", "agent", "auth.json");
1572
- if (!existsSync(authPath)) return;
1020
+ // Phase
1021
+ lines.push(`Phase: ${state.phase}`);
1573
1022
 
1574
- const auth = AuthStorage.create(authPath);
1575
- for (const tool of TOOL_KEYS) {
1576
- const cred = auth.get(tool.id);
1577
- if (cred && cred.type === "api_key" && cred.key && !process.env[tool.env]) {
1578
- process.env[tool.env] = cred.key;
1579
- }
1580
- }
1581
- } catch {
1582
- // Failed to load tool keys — ignore, they can still be set via env vars
1023
+ // Active milestone
1024
+ if (state.activeMilestone) {
1025
+ lines.push(`Active milestone: ${state.activeMilestone.id} — ${state.activeMilestone.title}`);
1583
1026
  }
1584
- }
1585
-
1586
- function getConfigAuthStorage(): AuthStorage {
1587
- const authPath = join(process.env.HOME ?? "", ".gsd", "agent", "auth.json");
1588
- mkdirSync(dirname(authPath), { recursive: true });
1589
- return AuthStorage.create(authPath);
1590
- }
1591
-
1592
- async function handleConfig(ctx: ExtensionCommandContext): Promise<void> {
1593
- const auth = getConfigAuthStorage();
1594
1027
 
1595
- // Show current status
1596
- const statusLines = ["GSD Tool Configuration\n"];
1597
- for (const tool of TOOL_KEYS) {
1598
- const hasKey = !!process.env[tool.env] || !!(auth.get(tool.id) as { key?: string })?.key;
1599
- statusLines.push(` ${hasKey ? "✓" : "✗"} ${tool.label}${hasKey ? "" : ` — get key at ${tool.hint}`}`);
1028
+ // Active slice / task
1029
+ if (state.activeSlice) {
1030
+ lines.push(`Active slice: ${state.activeSlice.id} ${state.activeSlice.title}`);
1600
1031
  }
1601
- ctx.ui.notify(statusLines.join("\n"), "info");
1602
-
1603
- // Ask which tools to configure
1604
- const options = TOOL_KEYS.map(t => {
1605
- const hasKey = !!process.env[t.env] || !!(auth.get(t.id) as { key?: string })?.key;
1606
- return `${t.label} ${hasKey ? "(configured ✓)" : "(not set)"}`;
1607
- });
1608
- options.push("(done)");
1609
-
1610
- let changed = false;
1611
- while (true) {
1612
- const choice = await ctx.ui.select("Configure which tool? Press Escape when done.", options);
1613
- if (!choice || typeof choice !== "string" || choice === "(done)") break;
1614
-
1615
- const toolIdx = TOOL_KEYS.findIndex(t => choice.startsWith(t.label));
1616
- if (toolIdx === -1) break;
1617
-
1618
- const tool = TOOL_KEYS[toolIdx];
1619
- const input = await ctx.ui.input(
1620
- `API key for ${tool.label} (${tool.hint}):`,
1621
- "paste your key here",
1622
- );
1623
-
1624
- if (input !== null && input !== undefined) {
1625
- const key = input.trim();
1626
- if (key) {
1627
- auth.set(tool.id, { type: "api_key", key });
1628
- process.env[tool.env] = key;
1629
- ctx.ui.notify(`${tool.label} key saved and activated.`, "info");
1630
- // Update option label
1631
- options[toolIdx] = `${tool.label} (configured ✓)`;
1632
- changed = true;
1633
- }
1634
- }
1032
+ if (state.activeTask) {
1033
+ lines.push(`Active task: ${state.activeTask.id} — ${state.activeTask.title}`);
1635
1034
  }
1636
1035
 
1637
- if (changed) {
1638
- await ctx.waitForIdle();
1639
- await ctx.reload();
1640
- ctx.ui.notify("Configuration saved. Extensions reloaded with new keys.", "info");
1641
- }
1642
- }
1643
-
1644
- async function ensurePreferencesFile(
1645
- path: string,
1646
- ctx: ExtensionCommandContext,
1647
- scope: "global" | "project",
1648
- ): Promise<void> {
1649
- if (!existsSync(path)) {
1650
- const template = await loadFile(join(dirname(fileURLToPath(import.meta.url)), "templates", "preferences.md"));
1651
- if (!template) {
1652
- ctx.ui.notify("Could not load GSD preferences template.", "error");
1653
- return;
1654
- }
1655
- await saveFile(path, template);
1656
- ctx.ui.notify(`Created ${scope} GSD skill preferences at ${path}`, "info");
1657
- } else {
1658
- ctx.ui.notify(`Using existing ${scope} GSD skill preferences at ${path}`, "info");
1659
- }
1660
-
1661
- }
1662
-
1663
- // ─── Skip handler ─────────────────────────────────────────────────────────────
1664
-
1665
- async function handleSkip(unitArg: string, ctx: ExtensionCommandContext, basePath: string): Promise<void> {
1666
- if (!unitArg) {
1667
- ctx.ui.notify("Usage: /gsd skip <unit-id> (e.g., /gsd skip execute-task/M001/S01/T03 or /gsd skip T03)", "info");
1668
- return;
1669
- }
1670
-
1671
- const { existsSync: fileExists, writeFileSync: writeFile, mkdirSync: mkDir, readFileSync: readFile } = await import("node:fs");
1672
- const { join: pathJoin } = await import("node:path");
1673
-
1674
- const completedKeysFile = pathJoin(basePath, ".gsd", "completed-units.json");
1675
- let keys: string[] = [];
1676
- try {
1677
- if (fileExists(completedKeysFile)) {
1678
- keys = JSON.parse(readFile(completedKeysFile, "utf-8"));
1679
- }
1680
- } catch { /* start fresh */ }
1681
-
1682
- // Normalize: accept "execute-task/M001/S01/T03", "M001/S01/T03", or just "T03"
1683
- let skipKey = unitArg;
1684
-
1685
- if (!skipKey.includes("execute-task") && !skipKey.includes("plan-") && !skipKey.includes("research-") && !skipKey.includes("complete-")) {
1686
- const state = await deriveState(basePath);
1687
- const mid = state.activeMilestone?.id;
1688
- const sid = state.activeSlice?.id;
1689
-
1690
- if (unitArg.match(/^T\d+$/i) && mid && sid) {
1691
- skipKey = `execute-task/${mid}/${sid}/${unitArg.toUpperCase()}`;
1692
- } else if (unitArg.match(/^S\d+$/i) && mid) {
1693
- skipKey = `plan-slice/${mid}/${unitArg.toUpperCase()}`;
1694
- } else if (unitArg.includes("/")) {
1695
- skipKey = `execute-task/${unitArg}`;
1696
- }
1697
- }
1698
-
1699
- if (keys.includes(skipKey)) {
1700
- ctx.ui.notify(`Already skipped: ${skipKey}`, "info");
1701
- return;
1702
- }
1703
-
1704
- keys.push(skipKey);
1705
- mkDir(pathJoin(basePath, ".gsd"), { recursive: true });
1706
- writeFile(completedKeysFile, JSON.stringify(keys), "utf-8");
1707
-
1708
- ctx.ui.notify(`Skipped: ${skipKey}. Will not be dispatched in auto-mode.`, "success");
1709
- }
1710
-
1711
- // ─── Dry-run handler ──────────────────────────────────────────────────────────
1712
-
1713
- async function handleDryRun(ctx: ExtensionCommandContext, basePath: string): Promise<void> {
1714
- const state = await deriveState(basePath);
1715
-
1716
- if (!state.activeMilestone) {
1717
- ctx.ui.notify("No active milestone — nothing to dispatch.", "info");
1718
- return;
1719
- }
1720
-
1721
- const { getLedger, getProjectTotals, formatCost, formatTokenCount, loadLedgerFromDisk } = await import("./metrics.js");
1722
- const { loadEffectiveGSDPreferences: loadPrefs } = await import("./preferences.js");
1723
- const { formatDuration } = await import("./history.js");
1724
-
1725
- const ledger = getLedger();
1726
- const units = ledger?.units ?? loadLedgerFromDisk(basePath)?.units ?? [];
1727
- const prefs = loadPrefs()?.preferences;
1728
-
1729
- let nextType = "unknown";
1730
- let nextId = "unknown";
1731
-
1732
- const mid = state.activeMilestone.id;
1733
- const midTitle = state.activeMilestone.title;
1734
-
1735
- if (state.phase === "pre-planning") {
1736
- nextType = "research-milestone";
1737
- nextId = mid;
1738
- } else if (state.phase === "planning" && state.activeSlice) {
1739
- nextType = "plan-slice";
1740
- nextId = `${mid}/${state.activeSlice.id}`;
1741
- } else if (state.phase === "executing" && state.activeTask && state.activeSlice) {
1742
- nextType = "execute-task";
1743
- nextId = `${mid}/${state.activeSlice.id}/${state.activeTask.id}`;
1744
- } else if (state.phase === "summarizing" && state.activeSlice) {
1745
- nextType = "complete-slice";
1746
- nextId = `${mid}/${state.activeSlice.id}`;
1747
- } else if (state.phase === "completing-milestone") {
1748
- nextType = "complete-milestone";
1749
- nextId = mid;
1750
- } else {
1751
- nextType = state.phase;
1752
- nextId = mid;
1753
- }
1754
-
1755
- const sameTypeUnits = units.filter(u => u.type === nextType);
1756
- const avgCost = sameTypeUnits.length > 0
1757
- ? sameTypeUnits.reduce((s, u) => s + u.cost, 0) / sameTypeUnits.length
1758
- : null;
1759
- const avgDuration = sameTypeUnits.length > 0
1760
- ? sameTypeUnits.reduce((s, u) => s + (u.finishedAt - u.startedAt), 0) / sameTypeUnits.length
1761
- : null;
1762
-
1763
- const totals = units.length > 0 ? getProjectTotals(units) : null;
1764
- const budgetRemaining = prefs?.budget_ceiling && totals
1765
- ? prefs.budget_ceiling - totals.cost
1766
- : null;
1767
-
1768
- const lines = [
1769
- `Dry-run preview:`,
1770
- ``,
1771
- ` Next unit: ${nextType}`,
1772
- ` ID: ${nextId}`,
1773
- ` Milestone: ${mid}: ${midTitle}`,
1774
- ` Phase: ${state.phase}`,
1775
- ` Est. cost: ${avgCost !== null ? `${formatCost(avgCost)} (avg of ${sameTypeUnits.length} similar)` : "unknown (first of this type)"}`,
1776
- ` Est. duration: ${avgDuration !== null ? formatDuration(avgDuration) : "unknown"}`,
1777
- ` Spent so far: ${totals ? formatCost(totals.cost) : "$0"}`,
1778
- ` Budget left: ${budgetRemaining !== null ? formatCost(budgetRemaining) : "no ceiling set"}`,
1779
- ];
1780
-
1036
+ // Progress
1781
1037
  if (state.progress) {
1782
- const p = state.progress;
1783
- lines.push(` Progress: ${p.tasks?.done ?? 0}/${p.tasks?.total ?? "?"} tasks, ${p.slices?.done ?? 0}/${p.slices?.total ?? "?"} slices`);
1784
- }
1785
-
1786
- ctx.ui.notify(lines.join("\n"), "info");
1787
- }
1788
-
1789
- // ─── Branch cleanup handler ──────────────────────────────────────────────────
1790
-
1791
- async function handleCleanupBranches(ctx: ExtensionCommandContext, basePath: string): Promise<void> {
1792
- let branches: string[];
1793
- try {
1794
- branches = nativeBranchList(basePath, "gsd/*");
1795
- } catch {
1796
- ctx.ui.notify("No GSD branches found.", "info");
1797
- return;
1798
- }
1799
-
1800
- if (branches.length === 0) {
1801
- ctx.ui.notify("No GSD branches to clean up.", "info");
1802
- return;
1803
- }
1804
-
1805
- const mainBranch = nativeDetectMainBranch(basePath);
1806
-
1807
- let merged: string[];
1808
- try {
1809
- merged = nativeBranchListMerged(basePath, mainBranch, "gsd/*");
1810
- } catch {
1811
- merged = [];
1812
- }
1813
-
1814
- if (merged.length === 0) {
1815
- ctx.ui.notify(`${branches.length} GSD branches found, none are merged into ${mainBranch} yet.`, "info");
1816
- return;
1817
- }
1818
-
1819
- let deleted = 0;
1820
- for (const branch of merged) {
1821
- try {
1822
- nativeBranchDelete(basePath, branch, false);
1823
- deleted++;
1824
- } catch { /* skip branches that can't be deleted */ }
1825
- }
1826
-
1827
- ctx.ui.notify(`Cleaned up ${deleted} merged branches. ${branches.length - deleted} remain.`, "success");
1828
- }
1829
-
1830
- // ─── Snapshot cleanup handler ─────────────────────────────────────────────────
1831
-
1832
- async function handleCleanupSnapshots(ctx: ExtensionCommandContext, basePath: string): Promise<void> {
1833
- let refs: string[];
1834
- try {
1835
- refs = nativeForEachRef(basePath, "refs/gsd/snapshots/");
1836
- } catch {
1837
- ctx.ui.notify("No snapshot refs found.", "info");
1838
- return;
1839
- }
1840
-
1841
- if (refs.length === 0) {
1842
- ctx.ui.notify("No snapshot refs to clean up.", "info");
1843
- return;
1844
- }
1845
-
1846
- const byLabel = new Map<string, string[]>();
1847
- for (const ref of refs) {
1848
- const parts = ref.split("/");
1849
- const label = parts.slice(0, -1).join("/");
1850
- if (!byLabel.has(label)) byLabel.set(label, []);
1851
- byLabel.get(label)!.push(ref);
1852
- }
1853
-
1854
- let pruned = 0;
1855
- for (const [, labelRefs] of byLabel) {
1856
- const sorted = labelRefs.sort();
1857
- for (const old of sorted.slice(0, -5)) {
1858
- try {
1859
- nativeUpdateRef(basePath, old);
1860
- pruned++;
1861
- } catch { /* skip */ }
1862
- }
1863
- }
1864
-
1865
- ctx.ui.notify(`Pruned ${pruned} old snapshot refs. ${refs.length - pruned} remain.`, "success");
1866
- }
1867
-
1868
- async function handleKnowledge(args: string, ctx: ExtensionCommandContext): Promise<void> {
1869
- const parts = args.split(/\s+/);
1870
- const typeArg = parts[0]?.toLowerCase();
1871
-
1872
- if (!typeArg || !["rule", "pattern", "lesson"].includes(typeArg)) {
1873
- ctx.ui.notify(
1874
- "Usage: /gsd knowledge <rule|pattern|lesson> <description>\nExample: /gsd knowledge rule Use real DB for integration tests",
1875
- "warning",
1876
- );
1877
- return;
1878
- }
1879
-
1880
- const entryText = parts.slice(1).join(" ").trim();
1881
- if (!entryText) {
1882
- ctx.ui.notify(`Usage: /gsd knowledge ${typeArg} <description>`, "warning");
1883
- return;
1884
- }
1885
-
1886
- const type = typeArg as "rule" | "pattern" | "lesson";
1887
- const basePath = process.cwd();
1888
- const state = await deriveState(basePath);
1889
- const scope = state.activeMilestone?.id
1890
- ? `${state.activeMilestone.id}${state.activeSlice ? `/${state.activeSlice.id}` : ""}`
1891
- : "global";
1892
-
1893
- await appendKnowledge(basePath, type, entryText, scope);
1894
- ctx.ui.notify(`Added ${type} to KNOWLEDGE.md: "${entryText}"`, "success");
1895
- }
1896
-
1897
- // ─── Capture Command ──────────────────────────────────────────────────────────
1898
-
1899
- /**
1900
- * Handle `/gsd capture "..."` — fire-and-forget thought capture.
1901
- * Appends to `.gsd/CAPTURES.md` without interrupting auto-mode.
1902
- * Works in all modes: auto running, paused, stopped, no project.
1903
- */
1904
- async function handleCapture(args: string, ctx: ExtensionCommandContext): Promise<void> {
1905
- // Strip surrounding quotes from the argument
1906
- let text = args.trim();
1907
- if (!text) {
1908
- ctx.ui.notify('Usage: /gsd capture "your thought here"', "warning");
1909
- return;
1910
- }
1911
- // Remove wrapping quotes (single or double)
1912
- if ((text.startsWith('"') && text.endsWith('"')) || (text.startsWith("'") && text.endsWith("'"))) {
1913
- text = text.slice(1, -1);
1914
- }
1915
- if (!text) {
1916
- ctx.ui.notify('Usage: /gsd capture "your thought here"', "warning");
1917
- return;
1038
+ const { milestones, slices, tasks } = state.progress;
1039
+ const parts: string[] = [];
1040
+ parts.push(`milestones ${milestones.done}/${milestones.total}`);
1041
+ if (slices) parts.push(`slices ${slices.done}/${slices.total}`);
1042
+ if (tasks) parts.push(`tasks ${tasks.done}/${tasks.total}`);
1043
+ lines.push(`Progress: ${parts.join(", ")}`);
1918
1044
  }
1919
1045
 
1920
- const basePath = process.cwd();
1921
-
1922
- // Ensure .gsd/ exists — capture should work even without a milestone
1923
- const gsdDir = join(basePath, ".gsd");
1924
- if (!existsSync(gsdDir)) {
1925
- mkdirSync(gsdDir, { recursive: true });
1046
+ // Next action
1047
+ if (state.nextAction) {
1048
+ lines.push(`Next: ${state.nextAction}`);
1926
1049
  }
1927
1050
 
1928
- const id = appendCapture(basePath, text);
1929
- ctx.ui.notify(`Captured: ${id} — "${text.length > 60 ? text.slice(0, 57) + "..." : text}"`, "info");
1930
- }
1931
-
1932
- // ─── Triage Command ───────────────────────────────────────────────────────────
1933
-
1934
- /**
1935
- * Handle `/gsd triage` — manually trigger triage of pending captures.
1936
- * Dispatches the triage prompt to the LLM for classification.
1937
- * Triage result handling (confirmation UI) is wired in T03.
1938
- */
1939
- async function handleTriage(ctx: ExtensionCommandContext, pi: ExtensionAPI, basePath: string): Promise<void> {
1940
- if (!hasPendingCaptures(basePath)) {
1941
- ctx.ui.notify("No pending captures to triage.", "info");
1942
- return;
1051
+ // Blockers
1052
+ if (state.blockers.length > 0) {
1053
+ lines.push(`Blockers: ${state.blockers.join("; ")}`);
1943
1054
  }
1944
1055
 
1945
- const pending = loadPendingCaptures(basePath);
1946
- ctx.ui.notify(`Triaging ${pending.length} pending capture${pending.length === 1 ? "" : "s"}...`, "info");
1947
-
1948
- // Build context for the triage prompt
1949
- const state = await deriveState(basePath);
1950
- let currentPlan = "";
1951
- let roadmapContext = "";
1952
-
1953
- if (state.activeMilestone && state.activeSlice) {
1954
- const { resolveSliceFile, resolveMilestoneFile } = await import("./paths.js");
1955
- const planFile = resolveSliceFile(basePath, state.activeMilestone.id, state.activeSlice.id, "PLAN");
1956
- if (planFile) {
1957
- const { loadFile: load } = await import("./files.js");
1958
- currentPlan = (await load(planFile)) ?? "";
1959
- }
1960
- const roadmapFile = resolveMilestoneFile(basePath, state.activeMilestone.id, "ROADMAP");
1961
- if (roadmapFile) {
1962
- const { loadFile: load } = await import("./files.js");
1963
- roadmapContext = (await load(roadmapFile)) ?? "";
1056
+ // Milestone registry summary
1057
+ if (state.registry.length > 0) {
1058
+ lines.push("");
1059
+ lines.push("Milestones:");
1060
+ for (const m of state.registry) {
1061
+ const statusIcon = m.status === "complete" ? "✓" : m.status === "active" ? "▶" : m.status === "parked" ? "⏸" : "○";
1062
+ lines.push(` ${statusIcon} ${m.id}: ${m.title} (${m.status})`);
1964
1063
  }
1965
1064
  }
1966
1065
 
1967
- // Format pending captures for the prompt
1968
- const capturesList = pending.map(c =>
1969
- `- **${c.id}**: "${c.text}" (captured: ${c.timestamp})`
1970
- ).join("\n");
1971
-
1972
- // Dispatch triage prompt
1973
- const { loadPrompt } = await import("./prompt-loader.js");
1974
- const prompt = loadPrompt("triage-captures", {
1975
- pendingCaptures: capturesList,
1976
- currentPlan: currentPlan || "(no active slice plan)",
1977
- roadmapContext: roadmapContext || "(no active roadmap)",
1978
- });
1979
-
1980
- const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".pi", "GSD-WORKFLOW.md");
1981
- const workflow = readFileSync(workflowPath, "utf-8");
1982
-
1983
- pi.sendMessage(
1984
- {
1985
- customType: "gsd-triage",
1986
- content: `Read the following GSD workflow protocol and execute exactly.\n\n${workflow}\n\n## Your Task\n\n${prompt}`,
1987
- display: false,
1988
- },
1989
- { triggerTurn: true },
1990
- );
1991
- }
1992
-
1993
- async function handleSteer(change: string, ctx: ExtensionCommandContext, pi: ExtensionAPI): Promise<void> {
1994
- const basePath = process.cwd();
1995
- const state = await deriveState(basePath);
1996
- const mid = state.activeMilestone?.id ?? "none";
1997
- const sid = state.activeSlice?.id ?? "none";
1998
- const tid = state.activeTask?.id ?? "none";
1999
- const appliedAt = `${mid}/${sid}/${tid}`;
2000
- await appendOverride(basePath, change, appliedAt);
2001
-
2002
- if (isAutoActive()) {
2003
- pi.sendMessage({
2004
- customType: "gsd-hard-steer",
2005
- content: [
2006
- "HARD STEER — User override registered.",
2007
- "",
2008
- `**Override:** ${change}`,
2009
- "",
2010
- "This override has been saved to `.gsd/OVERRIDES.md` and will be injected into all future task prompts.",
2011
- "A document rewrite unit will run before the next task to propagate this change across all active plan documents.",
2012
- "",
2013
- "If you are mid-task, finish your current work respecting this override. The next dispatched unit will be a document rewrite.",
2014
- ].join("\n"),
2015
- display: false,
2016
- }, { triggerTurn: true });
2017
- ctx.ui.notify(`Override registered: "${change}". Will be applied before next task dispatch.`, "info");
2018
- } else {
2019
- pi.sendMessage({
2020
- customType: "gsd-hard-steer",
2021
- content: [
2022
- "HARD STEER — User override registered.",
2023
- "",
2024
- `**Override:** ${change}`,
2025
- "",
2026
- "This override has been saved to `.gsd/OVERRIDES.md`.",
2027
- "Before continuing, read `.gsd/OVERRIDES.md` and update the current plan documents to reflect this change.",
2028
- "Focus on: active slice plan, incomplete task plans, and DECISIONS.md.",
2029
- ].join("\n"),
2030
- display: false,
2031
- }, { triggerTurn: true });
2032
- ctx.ui.notify(`Override registered: "${change}". Update plan documents to reflect this change.`, "info");
2033
- }
2034
- }
2035
-
2036
- async function handleRunHook(args: string, ctx: ExtensionCommandContext, pi: ExtensionAPI): Promise<void> {
2037
- const parts = args.trim().split(/\s+/);
2038
- if (parts.length < 3) {
2039
- ctx.ui.notify(`Usage: /gsd run-hook <hook-name> <unit-type> <unit-id>
2040
-
2041
- Unit types:
2042
- execute-task - Task execution (unit-id: M001/S01/T01)
2043
- plan-slice - Slice planning (unit-id: M001/S01)
2044
- research-milestone - Milestone research (unit-id: M001)
2045
- complete-slice - Slice completion (unit-id: M001/S01)
2046
- complete-milestone - Milestone completion (unit-id: M001)
2047
-
2048
- Examples:
2049
- /gsd run-hook code-review execute-task M001/S01/T01
2050
- /gsd run-hook lint-check plan-slice M001/S01`, "warning");
2051
- return;
2052
- }
2053
-
2054
- const [hookName, unitType, unitId] = parts;
2055
- const basePath = projectRoot();
2056
-
2057
- // Import the hook trigger function
2058
- const { triggerHookManually, formatHookStatus, getHookStatus } = await import("./post-unit-hooks.js");
2059
- const { dispatchHookUnit } = await import("./auto.js");
2060
-
2061
- // Check if the hook exists
2062
- const hooks = getHookStatus();
2063
- const hookExists = hooks.some(h => h.name === hookName);
2064
- if (!hookExists) {
2065
- ctx.ui.notify(`Hook "${hookName}" not found. Configured hooks:\n${formatHookStatus()}`, "error");
2066
- return;
2067
- }
2068
-
2069
- // Validate unit ID format
2070
- const unitIdPattern = /^M\d{3}\/S\d{2,3}\/T\d{2,3}$/;
2071
- if (!unitIdPattern.test(unitId)) {
2072
- ctx.ui.notify(`Invalid unit ID format: "${unitId}". Expected format: M004/S04/T03`, "warning");
2073
- return;
2074
- }
2075
-
2076
- // Trigger the hook manually
2077
- const hookUnit = triggerHookManually(hookName, unitType, unitId, basePath);
2078
- if (!hookUnit) {
2079
- ctx.ui.notify(`Failed to trigger hook "${hookName}". The hook may be disabled or not configured for unit type "${unitType}".`, "error");
2080
- return;
2081
- }
2082
-
2083
- ctx.ui.notify(`Manually triggering hook: ${hookName} for ${unitType} ${unitId}`, "info");
2084
-
2085
- // Dispatch the hook unit directly, bypassing normal pre-dispatch hooks
2086
- const success = await dispatchHookUnit(
2087
- ctx,
2088
- pi,
2089
- hookName,
2090
- unitType,
2091
- unitId,
2092
- hookUnit.prompt,
2093
- hookUnit.model,
2094
- basePath,
2095
- );
2096
-
2097
- if (!success) {
2098
- ctx.ui.notify("Failed to dispatch hook. Auto-mode may have been cancelled.", "error");
2099
- }
2100
- }
2101
-
2102
- // ─── Self-update handler ────────────────────────────────────────────────────
2103
-
2104
- async function handleUpdate(ctx: ExtensionCommandContext): Promise<void> {
2105
- const { execSync } = await import("node:child_process");
2106
- const { compareSemver } = await import("../../../update-check.js");
2107
-
2108
- const NPM_PACKAGE = "gsd-pi";
2109
- const current = process.env.GSD_VERSION || "0.0.0";
2110
-
2111
- ctx.ui.notify(`Current version: v${current}\nChecking npm registry...`, "info");
2112
-
2113
- let latest: string;
2114
- try {
2115
- latest = execSync(`npm view ${NPM_PACKAGE} version`, {
2116
- encoding: "utf-8",
2117
- stdio: ["ignore", "pipe", "ignore"],
2118
- }).trim();
2119
- } catch {
2120
- ctx.ui.notify("Failed to reach npm registry. Check your network connection.", "error");
2121
- return;
2122
- }
2123
-
2124
- if (compareSemver(latest, current) <= 0) {
2125
- ctx.ui.notify(`Already up to date (v${current}).`, "info");
2126
- return;
2127
- }
2128
-
2129
- ctx.ui.notify(`Updating: v${current} → v${latest}...`, "info");
2130
-
2131
- try {
2132
- execSync(`npm install -g ${NPM_PACKAGE}@latest`, {
2133
- stdio: ["ignore", "pipe", "ignore"],
2134
- });
2135
- ctx.ui.notify(
2136
- `Updated to v${latest}. Restart your GSD session to use the new version.`,
2137
- "info",
2138
- );
2139
- } catch {
2140
- ctx.ui.notify(
2141
- `Update failed. Try manually: npm install -g ${NPM_PACKAGE}@latest`,
2142
- "error",
2143
- );
2144
- }
1066
+ return lines.join("\n");
2145
1067
  }