gsd-pi 2.28.0 → 2.29.0-dev.2ccf3fb

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 (1311) 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 +61 -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 +264 -62
  53. package/dist/resources/extensions/gsd/auto-idempotency.ts +150 -0
  54. package/dist/resources/extensions/gsd/auto-post-unit.ts +594 -0
  55. package/dist/resources/extensions/gsd/auto-prompts.ts +116 -22
  56. package/dist/resources/extensions/gsd/auto-recovery.ts +36 -31
  57. package/dist/resources/extensions/gsd/auto-start.ts +500 -0
  58. package/dist/resources/extensions/gsd/auto-stuck-detection.ts +220 -0
  59. package/dist/resources/extensions/gsd/auto-timers.ts +223 -0
  60. package/dist/resources/extensions/gsd/auto-unit-closeout.ts +3 -1
  61. package/dist/resources/extensions/gsd/auto-verification.ts +229 -0
  62. package/dist/resources/extensions/gsd/auto-worktree-sync.ts +29 -37
  63. package/dist/resources/extensions/gsd/auto-worktree.ts +83 -67
  64. package/dist/resources/extensions/gsd/auto.ts +375 -1890
  65. package/dist/resources/extensions/gsd/commands-config.ts +102 -0
  66. package/dist/resources/extensions/gsd/commands-handlers.ts +394 -0
  67. package/dist/resources/extensions/gsd/commands-inspect.ts +90 -0
  68. package/dist/resources/extensions/gsd/commands-logs.ts +536 -0
  69. package/dist/resources/extensions/gsd/commands-maintenance.ts +206 -0
  70. package/dist/resources/extensions/gsd/commands-prefs-wizard.ts +790 -0
  71. package/dist/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
  72. package/dist/resources/extensions/gsd/commands.ts +417 -1495
  73. package/dist/resources/extensions/gsd/constants.ts +21 -0
  74. package/dist/resources/extensions/gsd/context-budget.ts +25 -2
  75. package/dist/resources/extensions/gsd/crash-recovery.ts +3 -4
  76. package/dist/resources/extensions/gsd/dashboard-overlay.ts +15 -5
  77. package/dist/resources/extensions/gsd/db-writer.ts +21 -2
  78. package/dist/resources/extensions/gsd/detection.ts +469 -0
  79. package/dist/resources/extensions/gsd/diff-context.ts +2 -1
  80. package/dist/resources/extensions/gsd/dispatch-guard.ts +4 -0
  81. package/dist/resources/extensions/gsd/doctor-checks.ts +564 -0
  82. package/dist/resources/extensions/gsd/doctor-format.ts +78 -0
  83. package/dist/resources/extensions/gsd/doctor-types.ts +72 -0
  84. package/dist/resources/extensions/gsd/doctor.ts +64 -701
  85. package/dist/resources/extensions/gsd/errors.ts +0 -2
  86. package/dist/resources/extensions/gsd/export-html.ts +367 -11
  87. package/dist/resources/extensions/gsd/export.ts +31 -5
  88. package/dist/resources/extensions/gsd/files.ts +8 -126
  89. package/dist/resources/extensions/gsd/forensics.ts +2 -12
  90. package/dist/resources/extensions/gsd/git-constants.ts +11 -0
  91. package/dist/resources/extensions/gsd/git-service.ts +13 -9
  92. package/dist/resources/extensions/gsd/gsd-db.ts +26 -6
  93. package/dist/resources/extensions/gsd/guided-flow-queue.ts +451 -0
  94. package/dist/resources/extensions/gsd/guided-flow.ts +231 -514
  95. package/dist/resources/extensions/gsd/history.ts +2 -20
  96. package/dist/resources/extensions/gsd/index.ts +208 -46
  97. package/dist/resources/extensions/gsd/init-wizard.ts +615 -0
  98. package/dist/resources/extensions/gsd/json-persistence.ts +67 -0
  99. package/dist/resources/extensions/gsd/jsonl-utils.ts +21 -0
  100. package/dist/resources/extensions/gsd/key-manager.ts +995 -0
  101. package/dist/resources/extensions/gsd/metrics.ts +49 -36
  102. package/dist/resources/extensions/gsd/migrate/command.ts +1 -1
  103. package/dist/resources/extensions/gsd/migrate/parsers.ts +10 -95
  104. package/dist/resources/extensions/gsd/milestone-actions.ts +126 -0
  105. package/dist/resources/extensions/gsd/milestone-ids.ts +95 -0
  106. package/dist/resources/extensions/gsd/native-git-bridge.ts +5 -10
  107. package/dist/resources/extensions/gsd/parallel-eligibility.ts +3 -3
  108. package/dist/resources/extensions/gsd/paths.ts +1 -11
  109. package/dist/resources/extensions/gsd/plugin-importer.ts +3 -2
  110. package/dist/resources/extensions/gsd/preferences-models.ts +323 -0
  111. package/dist/resources/extensions/gsd/preferences-skills.ts +169 -0
  112. package/dist/resources/extensions/gsd/preferences-types.ts +223 -0
  113. package/dist/resources/extensions/gsd/preferences-validation.ts +597 -0
  114. package/dist/resources/extensions/gsd/preferences.ts +219 -1305
  115. package/dist/resources/extensions/gsd/prompt-cache-optimizer.ts +213 -0
  116. package/dist/resources/extensions/gsd/prompt-compressor.ts +508 -0
  117. package/dist/resources/extensions/gsd/prompt-loader.ts +4 -2
  118. package/dist/resources/extensions/gsd/prompt-ordering.ts +200 -0
  119. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -2
  120. package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -4
  121. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +2 -4
  122. package/dist/resources/extensions/gsd/prompts/discuss.md +13 -5
  123. package/dist/resources/extensions/gsd/prompts/execute-task.md +0 -1
  124. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  125. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  126. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +0 -1
  127. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +0 -1
  128. package/dist/resources/extensions/gsd/prompts/plan-slice.md +0 -1
  129. package/dist/resources/extensions/gsd/prompts/queue.md +30 -0
  130. package/dist/resources/extensions/gsd/prompts/quick-task.md +0 -6
  131. package/dist/resources/extensions/gsd/prompts/replan-slice.md +0 -1
  132. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +0 -1
  133. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  134. package/dist/resources/extensions/gsd/prompts/workflow-start.md +28 -0
  135. package/dist/resources/extensions/gsd/provider-error-pause.ts +59 -10
  136. package/dist/resources/extensions/gsd/queue-order.ts +11 -12
  137. package/dist/resources/extensions/gsd/queue-reorder-ui.ts +15 -2
  138. package/dist/resources/extensions/gsd/quick.ts +18 -15
  139. package/dist/resources/extensions/gsd/reports.ts +1 -7
  140. package/dist/resources/extensions/gsd/routing-history.ts +13 -17
  141. package/dist/resources/extensions/gsd/safe-fs.ts +47 -0
  142. package/dist/resources/extensions/gsd/semantic-chunker.ts +336 -0
  143. package/dist/resources/extensions/gsd/session-forensics.ts +8 -23
  144. package/dist/resources/extensions/gsd/session-lock.ts +284 -0
  145. package/dist/resources/extensions/gsd/session-status-io.ts +23 -41
  146. package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +38 -1
  147. package/dist/resources/extensions/gsd/skills/gsd-headless/references/answer-injection.md +35 -6
  148. package/dist/resources/extensions/gsd/state.ts +54 -2
  149. package/dist/resources/extensions/gsd/structured-data-formatter.ts +144 -0
  150. package/dist/resources/extensions/gsd/summary-distiller.ts +258 -0
  151. package/dist/resources/extensions/gsd/tests/activity-log.test.ts +213 -0
  152. package/dist/resources/extensions/gsd/tests/agent-end-retry.test.ts +107 -0
  153. package/dist/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +197 -0
  154. package/dist/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  155. package/dist/resources/extensions/gsd/tests/auto-preflight.test.ts +33 -39
  156. package/dist/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +108 -2
  157. package/dist/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +257 -0
  158. package/dist/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
  159. package/dist/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +3 -0
  160. package/dist/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
  161. package/dist/resources/extensions/gsd/tests/context-budget.test.ts +69 -0
  162. package/dist/resources/extensions/gsd/tests/detection.test.ts +398 -0
  163. package/dist/resources/extensions/gsd/tests/discuss-prompt.test.ts +12 -24
  164. package/dist/resources/extensions/gsd/tests/dispatch-guard.test.ts +118 -94
  165. package/dist/resources/extensions/gsd/tests/dispatch-stall-guard.test.ts +126 -0
  166. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +7 -3
  167. package/dist/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +75 -0
  168. package/dist/resources/extensions/gsd/tests/doctor-git.test.ts +17 -55
  169. package/dist/resources/extensions/gsd/tests/export-html-enhancements.test.ts +375 -0
  170. package/dist/resources/extensions/gsd/tests/extension-selector-separator.test.ts +144 -0
  171. package/dist/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +3 -0
  172. package/dist/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
  173. package/dist/resources/extensions/gsd/tests/headless-answers.test.ts +340 -0
  174. package/dist/resources/extensions/gsd/tests/in-flight-tool-tracking.test.ts +24 -82
  175. package/dist/resources/extensions/gsd/tests/init-wizard.test.ts +197 -0
  176. package/dist/resources/extensions/gsd/tests/key-manager.test.ts +414 -0
  177. package/dist/resources/extensions/gsd/tests/metrics.test.ts +173 -305
  178. package/dist/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +3 -0
  179. package/dist/resources/extensions/gsd/tests/model-isolation.test.ts +59 -1
  180. package/dist/resources/extensions/gsd/tests/next-milestone-id.test.ts +18 -61
  181. package/dist/resources/extensions/gsd/tests/none-mode-gates.test.ts +17 -8
  182. package/dist/resources/extensions/gsd/tests/parallel-merge.test.ts +3 -0
  183. package/dist/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
  184. package/dist/resources/extensions/gsd/tests/park-edge-cases.test.ts +276 -0
  185. package/dist/resources/extensions/gsd/tests/park-milestone.test.ts +401 -0
  186. package/dist/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +23 -47
  187. package/dist/resources/extensions/gsd/tests/preferences.test.ts +284 -0
  188. package/dist/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +314 -0
  189. package/dist/resources/extensions/gsd/tests/prompt-compressor.test.ts +529 -0
  190. package/dist/resources/extensions/gsd/tests/prompt-ordering.test.ts +296 -0
  191. package/dist/resources/extensions/gsd/tests/provider-errors.test.ts +338 -0
  192. package/dist/resources/extensions/gsd/tests/reassess-detection.test.ts +154 -0
  193. package/dist/resources/extensions/gsd/tests/remote-questions.test.ts +1 -1
  194. package/dist/resources/extensions/gsd/tests/remote-status.test.ts +2 -2
  195. package/dist/resources/extensions/gsd/tests/roadmap-slices.test.ts +43 -60
  196. package/dist/resources/extensions/gsd/tests/semantic-chunker.test.ts +426 -0
  197. package/dist/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
  198. package/dist/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +3 -0
  199. package/dist/resources/extensions/gsd/tests/stop-auto-remote.test.ts +8 -5
  200. package/dist/resources/extensions/gsd/tests/structured-data-formatter.test.ts +365 -0
  201. package/dist/resources/extensions/gsd/tests/summary-distiller.test.ts +323 -0
  202. package/dist/resources/extensions/gsd/tests/token-counter.test.ts +129 -0
  203. package/dist/resources/extensions/gsd/tests/token-optimization-benchmark.test.ts +1272 -0
  204. package/dist/resources/extensions/gsd/tests/token-optimization-prefs.test.ts +164 -0
  205. package/dist/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
  206. package/dist/resources/extensions/gsd/tests/triage-dispatch.test.ts +69 -73
  207. package/dist/resources/extensions/gsd/tests/validate-directory.test.ts +222 -0
  208. package/dist/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
  209. package/dist/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
  210. package/dist/resources/extensions/gsd/tests/verification-gate.test.ts +251 -8
  211. package/dist/resources/extensions/gsd/tests/visualizer-overlay.test.ts +2 -2
  212. package/dist/resources/extensions/gsd/tests/visualizer-views.test.ts +2 -1
  213. package/dist/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
  214. package/dist/resources/extensions/gsd/tests/workspace-index.test.ts +24 -61
  215. package/dist/resources/extensions/gsd/tests/worktree-e2e.test.ts +5 -2
  216. package/dist/resources/extensions/gsd/tests/write-gate.test.ts +132 -43
  217. package/dist/resources/extensions/gsd/token-counter.ts +20 -0
  218. package/dist/resources/extensions/gsd/triage-ui.ts +1 -1
  219. package/dist/resources/extensions/gsd/types.ts +5 -1
  220. package/dist/resources/extensions/gsd/unit-runtime.ts +16 -13
  221. package/dist/resources/extensions/gsd/validate-directory.ts +164 -0
  222. package/dist/resources/extensions/gsd/verification-evidence.ts +9 -4
  223. package/dist/resources/extensions/gsd/verification-gate.ts +83 -7
  224. package/dist/resources/extensions/gsd/visualizer-data.ts +1 -1
  225. package/dist/resources/extensions/gsd/visualizer-overlay.ts +5 -2
  226. package/dist/resources/extensions/gsd/visualizer-views.ts +2 -3
  227. package/dist/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
  228. package/dist/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
  229. package/dist/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
  230. package/dist/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
  231. package/dist/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
  232. package/dist/resources/extensions/gsd/workflow-templates/registry.json +85 -0
  233. package/dist/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
  234. package/dist/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
  235. package/dist/resources/extensions/gsd/workflow-templates/spike.md +69 -0
  236. package/dist/resources/extensions/gsd/workflow-templates.ts +241 -0
  237. package/dist/resources/extensions/gsd/worktree-command.ts +4 -51
  238. package/dist/resources/extensions/gsd/worktree-manager.ts +7 -9
  239. package/dist/resources/extensions/gsd/worktree.ts +41 -1
  240. package/dist/resources/extensions/mcp-client/index.ts +459 -0
  241. package/dist/resources/extensions/remote-questions/discord-adapter.ts +9 -20
  242. package/dist/resources/extensions/remote-questions/http-client.ts +76 -0
  243. package/dist/resources/extensions/remote-questions/manager.ts +6 -24
  244. package/dist/resources/extensions/remote-questions/mod.ts +16 -0
  245. package/dist/resources/extensions/remote-questions/notify.ts +90 -0
  246. package/dist/resources/extensions/remote-questions/remote-command.ts +1 -1
  247. package/dist/resources/extensions/remote-questions/slack-adapter.ts +11 -18
  248. package/dist/resources/extensions/remote-questions/store.ts +5 -1
  249. package/dist/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
  250. package/dist/resources/extensions/remote-questions/types.ts +29 -3
  251. package/dist/resources/extensions/search-the-web/native-search.ts +7 -0
  252. package/dist/resources/extensions/search-the-web/provider.ts +15 -3
  253. package/dist/resources/extensions/search-the-web/tool-llm-context.ts +1 -13
  254. package/dist/resources/extensions/search-the-web/tool-search.ts +1 -13
  255. package/dist/resources/extensions/shared/format-utils.ts +53 -0
  256. package/dist/resources/extensions/shared/frontmatter.ts +117 -0
  257. package/dist/resources/extensions/shared/mod.ts +33 -0
  258. package/dist/resources/extensions/shared/sanitize.ts +19 -0
  259. package/dist/resources/extensions/slash-commands/create-extension.ts +1 -1
  260. package/dist/resources/extensions/slash-commands/create-slash-command.ts +1 -1
  261. package/dist/resources/extensions/subagent/index.ts +1 -2
  262. package/dist/resources/extensions/ttsr/index.ts +5 -0
  263. package/dist/resources/extensions/ttsr/rule-loader.ts +4 -51
  264. package/dist/resources/extensions/universal-config/discovery.ts +37 -15
  265. package/dist/resources/extensions/voice/index.ts +1 -1
  266. package/dist/resources/skills/accessibility/SKILL.md +522 -0
  267. package/dist/resources/skills/accessibility/references/WCAG.md +162 -0
  268. package/dist/resources/skills/agent-browser/SKILL.md +517 -0
  269. package/dist/resources/skills/agent-browser/references/authentication.md +202 -0
  270. package/dist/resources/skills/agent-browser/references/commands.md +263 -0
  271. package/dist/resources/skills/agent-browser/references/profiling.md +120 -0
  272. package/dist/resources/skills/agent-browser/references/proxy-support.md +194 -0
  273. package/dist/resources/skills/agent-browser/references/session-management.md +193 -0
  274. package/dist/resources/skills/agent-browser/references/snapshot-refs.md +194 -0
  275. package/dist/resources/skills/agent-browser/references/video-recording.md +173 -0
  276. package/dist/resources/skills/agent-browser/templates/authenticated-session.sh +105 -0
  277. package/dist/resources/skills/agent-browser/templates/capture-workflow.sh +69 -0
  278. package/dist/resources/skills/agent-browser/templates/form-automation.sh +62 -0
  279. package/dist/resources/skills/best-practices/SKILL.md +583 -0
  280. package/dist/resources/skills/code-optimizer/SKILL.md +160 -0
  281. package/dist/resources/skills/code-optimizer/references/algorithmic-complexity.md +66 -0
  282. package/dist/resources/skills/code-optimizer/references/build-compilation.md +90 -0
  283. package/dist/resources/skills/code-optimizer/references/bundle-dependencies.md +82 -0
  284. package/dist/resources/skills/code-optimizer/references/caching-memoization.md +76 -0
  285. package/dist/resources/skills/code-optimizer/references/concurrency-async.md +80 -0
  286. package/dist/resources/skills/code-optimizer/references/config-infra.md +71 -0
  287. package/dist/resources/skills/code-optimizer/references/data-structures.md +80 -0
  288. package/dist/resources/skills/code-optimizer/references/database-queries.md +76 -0
  289. package/dist/resources/skills/code-optimizer/references/dead-code-redundancy.md +84 -0
  290. package/dist/resources/skills/code-optimizer/references/error-resilience.md +80 -0
  291. package/dist/resources/skills/code-optimizer/references/io-network.md +89 -0
  292. package/dist/resources/skills/code-optimizer/references/logging-observability.md +64 -0
  293. package/dist/resources/skills/code-optimizer/references/memory-resources.md +66 -0
  294. package/dist/resources/skills/code-optimizer/references/rendering-ui.md +90 -0
  295. package/dist/resources/skills/code-optimizer/references/security-performance.md +68 -0
  296. package/dist/resources/skills/core-web-vitals/SKILL.md +441 -0
  297. package/dist/resources/skills/core-web-vitals/references/LCP.md +208 -0
  298. package/dist/resources/skills/create-gsd-extension/SKILL.md +87 -0
  299. package/dist/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
  300. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
  301. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
  302. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
  303. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
  304. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
  305. package/dist/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
  306. package/dist/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
  307. package/dist/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
  308. package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
  309. package/dist/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
  310. package/dist/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
  311. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
  312. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
  313. package/dist/resources/skills/create-gsd-extension/references/state-management.md +70 -0
  314. package/dist/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
  315. package/dist/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
  316. package/dist/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
  317. package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
  318. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
  319. package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
  320. package/dist/resources/skills/create-skill/SKILL.md +184 -0
  321. package/dist/resources/skills/create-skill/references/api-security.md +226 -0
  322. package/dist/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
  323. package/dist/resources/skills/create-skill/references/common-patterns.md +595 -0
  324. package/dist/resources/skills/create-skill/references/core-principles.md +437 -0
  325. package/dist/resources/skills/create-skill/references/executable-code.md +175 -0
  326. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
  327. package/dist/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
  328. package/dist/resources/skills/create-skill/references/recommended-structure.md +168 -0
  329. package/dist/resources/skills/create-skill/references/skill-structure.md +372 -0
  330. package/dist/resources/skills/create-skill/references/use-xml-tags.md +466 -0
  331. package/dist/resources/skills/create-skill/references/using-scripts.md +113 -0
  332. package/dist/resources/skills/create-skill/references/using-templates.md +112 -0
  333. package/dist/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
  334. package/dist/resources/skills/create-skill/templates/router-skill.md +73 -0
  335. package/dist/resources/skills/create-skill/templates/simple-skill.md +33 -0
  336. package/dist/resources/skills/create-skill/workflows/add-reference.md +96 -0
  337. package/dist/resources/skills/create-skill/workflows/add-script.md +93 -0
  338. package/dist/resources/skills/create-skill/workflows/add-template.md +74 -0
  339. package/dist/resources/skills/create-skill/workflows/add-workflow.md +120 -0
  340. package/dist/resources/skills/create-skill/workflows/audit-skill.md +148 -0
  341. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
  342. package/dist/resources/skills/create-skill/workflows/get-guidance.md +121 -0
  343. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
  344. package/dist/resources/skills/create-skill/workflows/verify-skill.md +204 -0
  345. package/dist/resources/skills/make-interfaces-feel-better/SKILL.md +122 -0
  346. package/dist/resources/skills/make-interfaces-feel-better/animations.md +379 -0
  347. package/dist/resources/skills/make-interfaces-feel-better/performance.md +88 -0
  348. package/dist/resources/skills/make-interfaces-feel-better/surfaces.md +247 -0
  349. package/dist/resources/skills/make-interfaces-feel-better/typography.md +123 -0
  350. package/dist/resources/skills/react-best-practices/README.md +123 -0
  351. package/dist/resources/skills/react-best-practices/SKILL.md +136 -0
  352. package/dist/resources/skills/react-best-practices/metadata.json +15 -0
  353. package/dist/resources/skills/react-best-practices/rules/_sections.md +46 -0
  354. package/dist/resources/skills/react-best-practices/rules/_template.md +28 -0
  355. package/dist/resources/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  356. package/dist/resources/skills/react-best-practices/rules/advanced-init-once.md +42 -0
  357. package/dist/resources/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
  358. package/dist/resources/skills/react-best-practices/rules/async-api-routes.md +38 -0
  359. package/dist/resources/skills/react-best-practices/rules/async-defer-await.md +80 -0
  360. package/dist/resources/skills/react-best-practices/rules/async-dependencies.md +51 -0
  361. package/dist/resources/skills/react-best-practices/rules/async-parallel.md +28 -0
  362. package/dist/resources/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  363. package/dist/resources/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  364. package/dist/resources/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  365. package/dist/resources/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  366. package/dist/resources/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  367. package/dist/resources/skills/react-best-practices/rules/bundle-preload.md +50 -0
  368. package/dist/resources/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  369. package/dist/resources/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
  370. package/dist/resources/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  371. package/dist/resources/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  372. package/dist/resources/skills/react-best-practices/rules/js-batch-dom-css.md +107 -0
  373. package/dist/resources/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  374. package/dist/resources/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  375. package/dist/resources/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  376. package/dist/resources/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  377. package/dist/resources/skills/react-best-practices/rules/js-early-exit.md +50 -0
  378. package/dist/resources/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  379. package/dist/resources/skills/react-best-practices/rules/js-index-maps.md +37 -0
  380. package/dist/resources/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  381. package/dist/resources/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  382. package/dist/resources/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  383. package/dist/resources/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  384. package/dist/resources/skills/react-best-practices/rules/rendering-activity.md +26 -0
  385. package/dist/resources/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  386. package/dist/resources/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  387. package/dist/resources/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  388. package/dist/resources/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  389. package/dist/resources/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  390. package/dist/resources/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  391. package/dist/resources/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  392. package/dist/resources/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  393. package/dist/resources/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  394. package/dist/resources/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  395. package/dist/resources/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  396. package/dist/resources/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  397. package/dist/resources/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  398. package/dist/resources/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  399. package/dist/resources/skills/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  400. package/dist/resources/skills/react-best-practices/rules/rerender-memo.md +44 -0
  401. package/dist/resources/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  402. package/dist/resources/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  403. package/dist/resources/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  404. package/dist/resources/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  405. package/dist/resources/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  406. package/dist/resources/skills/react-best-practices/rules/server-auth-actions.md +96 -0
  407. package/dist/resources/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  408. package/dist/resources/skills/react-best-practices/rules/server-cache-react.md +76 -0
  409. package/dist/resources/skills/react-best-practices/rules/server-dedup-props.md +65 -0
  410. package/dist/resources/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  411. package/dist/resources/skills/react-best-practices/rules/server-serialization.md +38 -0
  412. package/dist/resources/skills/userinterface-wiki/SKILL.md +253 -0
  413. package/dist/resources/skills/userinterface-wiki/rules/_sections.md +66 -0
  414. package/dist/resources/skills/userinterface-wiki/rules/_template.md +24 -0
  415. package/dist/resources/skills/userinterface-wiki/rules/a11y-reduced-motion-check.md +30 -0
  416. package/dist/resources/skills/userinterface-wiki/rules/a11y-toggle-setting.md +30 -0
  417. package/dist/resources/skills/userinterface-wiki/rules/a11y-visual-equivalent.md +36 -0
  418. package/dist/resources/skills/userinterface-wiki/rules/a11y-volume-control.md +28 -0
  419. package/dist/resources/skills/userinterface-wiki/rules/appropriate-confirmations-only.md +19 -0
  420. package/dist/resources/skills/userinterface-wiki/rules/appropriate-errors-warnings.md +18 -0
  421. package/dist/resources/skills/userinterface-wiki/rules/appropriate-no-decorative.md +21 -0
  422. package/dist/resources/skills/userinterface-wiki/rules/appropriate-no-high-frequency.md +28 -0
  423. package/dist/resources/skills/userinterface-wiki/rules/appropriate-no-punishing.md +27 -0
  424. package/dist/resources/skills/userinterface-wiki/rules/container-callback-ref.md +31 -0
  425. package/dist/resources/skills/userinterface-wiki/rules/container-guard-initial-zero.md +25 -0
  426. package/dist/resources/skills/userinterface-wiki/rules/container-no-excessive-use.md +13 -0
  427. package/dist/resources/skills/userinterface-wiki/rules/container-overflow-hidden.md +25 -0
  428. package/dist/resources/skills/userinterface-wiki/rules/container-transition-delay.md +21 -0
  429. package/dist/resources/skills/userinterface-wiki/rules/container-two-div-pattern.md +35 -0
  430. package/dist/resources/skills/userinterface-wiki/rules/container-use-resize-observer.md +48 -0
  431. package/dist/resources/skills/userinterface-wiki/rules/context-cleanup-nodes.md +25 -0
  432. package/dist/resources/skills/userinterface-wiki/rules/context-resume-suspended.md +28 -0
  433. package/dist/resources/skills/userinterface-wiki/rules/context-reuse-single.md +30 -0
  434. package/dist/resources/skills/userinterface-wiki/rules/design-filter-for-character.md +25 -0
  435. package/dist/resources/skills/userinterface-wiki/rules/design-noise-for-percussion.md +26 -0
  436. package/dist/resources/skills/userinterface-wiki/rules/design-oscillator-for-tonal.md +22 -0
  437. package/dist/resources/skills/userinterface-wiki/rules/duration-max-300ms.md +21 -0
  438. package/dist/resources/skills/userinterface-wiki/rules/duration-press-hover.md +21 -0
  439. package/dist/resources/skills/userinterface-wiki/rules/duration-shorten-before-curve.md +21 -0
  440. package/dist/resources/skills/userinterface-wiki/rules/duration-small-state.md +15 -0
  441. package/dist/resources/skills/userinterface-wiki/rules/easing-entrance-ease-out.md +21 -0
  442. package/dist/resources/skills/userinterface-wiki/rules/easing-exit-ease-in.md +21 -0
  443. package/dist/resources/skills/userinterface-wiki/rules/easing-for-state-change.md +27 -0
  444. package/dist/resources/skills/userinterface-wiki/rules/easing-linear-only-progress.md +21 -0
  445. package/dist/resources/skills/userinterface-wiki/rules/easing-natural-decay.md +22 -0
  446. package/dist/resources/skills/userinterface-wiki/rules/easing-no-linear-motion.md +22 -0
  447. package/dist/resources/skills/userinterface-wiki/rules/easing-transition-ease-in-out.md +15 -0
  448. package/dist/resources/skills/userinterface-wiki/rules/envelope-exponential-decay.md +21 -0
  449. package/dist/resources/skills/userinterface-wiki/rules/envelope-no-zero-target.md +21 -0
  450. package/dist/resources/skills/userinterface-wiki/rules/envelope-set-initial-value.md +22 -0
  451. package/dist/resources/skills/userinterface-wiki/rules/exit-key-required.md +29 -0
  452. package/dist/resources/skills/userinterface-wiki/rules/exit-matches-initial.md +29 -0
  453. package/dist/resources/skills/userinterface-wiki/rules/exit-prop-required.md +33 -0
  454. package/dist/resources/skills/userinterface-wiki/rules/exit-requires-wrapper.md +27 -0
  455. package/dist/resources/skills/userinterface-wiki/rules/impl-default-subtle.md +21 -0
  456. package/dist/resources/skills/userinterface-wiki/rules/impl-preload-audio.md +34 -0
  457. package/dist/resources/skills/userinterface-wiki/rules/impl-reset-current-time.md +26 -0
  458. package/dist/resources/skills/userinterface-wiki/rules/mode-pop-layout-for-lists.md +25 -0
  459. package/dist/resources/skills/userinterface-wiki/rules/mode-sync-layout-conflict.md +29 -0
  460. package/dist/resources/skills/userinterface-wiki/rules/mode-wait-doubles-duration.md +25 -0
  461. package/dist/resources/skills/userinterface-wiki/rules/morphing-aria-hidden.md +21 -0
  462. package/dist/resources/skills/userinterface-wiki/rules/morphing-consistent-viewbox.md +23 -0
  463. package/dist/resources/skills/userinterface-wiki/rules/morphing-group-variants.md +33 -0
  464. package/dist/resources/skills/userinterface-wiki/rules/morphing-jump-non-grouped.md +29 -0
  465. package/dist/resources/skills/userinterface-wiki/rules/morphing-reduced-motion.md +28 -0
  466. package/dist/resources/skills/userinterface-wiki/rules/morphing-spring-rotation.md +23 -0
  467. package/dist/resources/skills/userinterface-wiki/rules/morphing-strokelinecap-round.md +21 -0
  468. package/dist/resources/skills/userinterface-wiki/rules/morphing-three-lines.md +32 -0
  469. package/dist/resources/skills/userinterface-wiki/rules/morphing-use-collapsed.md +33 -0
  470. package/dist/resources/skills/userinterface-wiki/rules/native-backdrop-styling.md +27 -0
  471. package/dist/resources/skills/userinterface-wiki/rules/native-placeholder-styling.md +27 -0
  472. package/dist/resources/skills/userinterface-wiki/rules/native-selection-styling.md +18 -0
  473. package/dist/resources/skills/userinterface-wiki/rules/nested-consistent-timing.md +25 -0
  474. package/dist/resources/skills/userinterface-wiki/rules/nested-propagate-required.md +41 -0
  475. package/dist/resources/skills/userinterface-wiki/rules/none-context-menu-entrance.md +25 -0
  476. package/dist/resources/skills/userinterface-wiki/rules/none-high-frequency.md +29 -0
  477. package/dist/resources/skills/userinterface-wiki/rules/none-keyboard-navigation.md +32 -0
  478. package/dist/resources/skills/userinterface-wiki/rules/param-click-duration.md +21 -0
  479. package/dist/resources/skills/userinterface-wiki/rules/param-filter-frequency-range.md +21 -0
  480. package/dist/resources/skills/userinterface-wiki/rules/param-q-value-range.md +21 -0
  481. package/dist/resources/skills/userinterface-wiki/rules/param-reasonable-gain.md +21 -0
  482. package/dist/resources/skills/userinterface-wiki/rules/physics-active-state.md +23 -0
  483. package/dist/resources/skills/userinterface-wiki/rules/physics-no-excessive-stagger.md +22 -0
  484. package/dist/resources/skills/userinterface-wiki/rules/physics-spring-for-overshoot.md +23 -0
  485. package/dist/resources/skills/userinterface-wiki/rules/physics-subtle-deformation.md +22 -0
  486. package/dist/resources/skills/userinterface-wiki/rules/prefetch-hit-slop.md +27 -0
  487. package/dist/resources/skills/userinterface-wiki/rules/prefetch-keyboard-tab.md +19 -0
  488. package/dist/resources/skills/userinterface-wiki/rules/prefetch-not-everything.md +22 -0
  489. package/dist/resources/skills/userinterface-wiki/rules/prefetch-touch-fallback.md +34 -0
  490. package/dist/resources/skills/userinterface-wiki/rules/prefetch-trajectory-over-hover.md +32 -0
  491. package/dist/resources/skills/userinterface-wiki/rules/prefetch-use-selectively.md +13 -0
  492. package/dist/resources/skills/userinterface-wiki/rules/presence-disable-interactions.md +31 -0
  493. package/dist/resources/skills/userinterface-wiki/rules/presence-hook-in-child.md +31 -0
  494. package/dist/resources/skills/userinterface-wiki/rules/presence-safe-to-remove.md +37 -0
  495. package/dist/resources/skills/userinterface-wiki/rules/pseudo-content-required.md +28 -0
  496. package/dist/resources/skills/userinterface-wiki/rules/pseudo-first-line-styling.md +27 -0
  497. package/dist/resources/skills/userinterface-wiki/rules/pseudo-hit-target-expansion.md +31 -0
  498. package/dist/resources/skills/userinterface-wiki/rules/pseudo-marker-styling.md +28 -0
  499. package/dist/resources/skills/userinterface-wiki/rules/pseudo-over-dom-node.md +32 -0
  500. package/dist/resources/skills/userinterface-wiki/rules/pseudo-position-relative-parent.md +33 -0
  501. package/dist/resources/skills/userinterface-wiki/rules/pseudo-z-index-layering.md +37 -0
  502. package/dist/resources/skills/userinterface-wiki/rules/spring-for-gestures.md +27 -0
  503. package/dist/resources/skills/userinterface-wiki/rules/spring-for-interruptible.md +27 -0
  504. package/dist/resources/skills/userinterface-wiki/rules/spring-params-balanced.md +29 -0
  505. package/dist/resources/skills/userinterface-wiki/rules/spring-preserves-velocity.md +28 -0
  506. package/dist/resources/skills/userinterface-wiki/rules/staging-dim-background.md +22 -0
  507. package/dist/resources/skills/userinterface-wiki/rules/staging-one-focal-point.md +24 -0
  508. package/dist/resources/skills/userinterface-wiki/rules/staging-z-index-hierarchy.md +22 -0
  509. package/dist/resources/skills/userinterface-wiki/rules/timing-consistent.md +24 -0
  510. package/dist/resources/skills/userinterface-wiki/rules/timing-no-entrance-context-menu.md +22 -0
  511. package/dist/resources/skills/userinterface-wiki/rules/timing-under-300ms.md +22 -0
  512. package/dist/resources/skills/userinterface-wiki/rules/transition-name-cleanup.md +28 -0
  513. package/dist/resources/skills/userinterface-wiki/rules/transition-name-required.md +27 -0
  514. package/dist/resources/skills/userinterface-wiki/rules/transition-name-unique.md +24 -0
  515. package/dist/resources/skills/userinterface-wiki/rules/transition-over-js-library.md +32 -0
  516. package/dist/resources/skills/userinterface-wiki/rules/transition-style-pseudo-elements.md +24 -0
  517. package/dist/resources/skills/userinterface-wiki/rules/type-antialiased-on-retina.md +18 -0
  518. package/dist/resources/skills/userinterface-wiki/rules/type-disambiguation-stylistic-set.md +15 -0
  519. package/dist/resources/skills/userinterface-wiki/rules/type-font-display-swap.md +28 -0
  520. package/dist/resources/skills/userinterface-wiki/rules/type-justify-with-hyphens.md +24 -0
  521. package/dist/resources/skills/userinterface-wiki/rules/type-letter-spacing-uppercase.md +28 -0
  522. package/dist/resources/skills/userinterface-wiki/rules/type-no-font-synthesis.md +18 -0
  523. package/dist/resources/skills/userinterface-wiki/rules/type-oldstyle-nums-for-prose.md +21 -0
  524. package/dist/resources/skills/userinterface-wiki/rules/type-opentype-contextual-alternates.md +15 -0
  525. package/dist/resources/skills/userinterface-wiki/rules/type-optical-sizing-auto.md +25 -0
  526. package/dist/resources/skills/userinterface-wiki/rules/type-proper-fractions.md +15 -0
  527. package/dist/resources/skills/userinterface-wiki/rules/type-slashed-zero.md +17 -0
  528. package/dist/resources/skills/userinterface-wiki/rules/type-tabular-nums-for-data.md +21 -0
  529. package/dist/resources/skills/userinterface-wiki/rules/type-text-wrap-balance-headings.md +21 -0
  530. package/dist/resources/skills/userinterface-wiki/rules/type-text-wrap-pretty.md +16 -0
  531. package/dist/resources/skills/userinterface-wiki/rules/type-underline-offset.md +25 -0
  532. package/dist/resources/skills/userinterface-wiki/rules/type-variable-weight-continuous.md +23 -0
  533. package/dist/resources/skills/userinterface-wiki/rules/ux-aesthetic-usability.md +32 -0
  534. package/dist/resources/skills/userinterface-wiki/rules/ux-cognitive-load-reduce.md +49 -0
  535. package/dist/resources/skills/userinterface-wiki/rules/ux-common-region-boundaries.md +50 -0
  536. package/dist/resources/skills/userinterface-wiki/rules/ux-doherty-perceived-speed.md +29 -0
  537. package/dist/resources/skills/userinterface-wiki/rules/ux-doherty-under-400ms.md +30 -0
  538. package/dist/resources/skills/userinterface-wiki/rules/ux-fitts-hit-area.md +32 -0
  539. package/dist/resources/skills/userinterface-wiki/rules/ux-fitts-target-size.md +31 -0
  540. package/dist/resources/skills/userinterface-wiki/rules/ux-goal-gradient-progress.md +33 -0
  541. package/dist/resources/skills/userinterface-wiki/rules/ux-hicks-minimize-choices.md +45 -0
  542. package/dist/resources/skills/userinterface-wiki/rules/ux-jakobs-familiar-patterns.md +37 -0
  543. package/dist/resources/skills/userinterface-wiki/rules/ux-millers-chunking.md +23 -0
  544. package/dist/resources/skills/userinterface-wiki/rules/ux-pareto-prioritize-features.md +36 -0
  545. package/dist/resources/skills/userinterface-wiki/rules/ux-peak-end-finish-strong.md +35 -0
  546. package/dist/resources/skills/userinterface-wiki/rules/ux-postels-accept-messy-input.md +45 -0
  547. package/dist/resources/skills/userinterface-wiki/rules/ux-pragnanz-simplify.md +33 -0
  548. package/dist/resources/skills/userinterface-wiki/rules/ux-progressive-disclosure.md +41 -0
  549. package/dist/resources/skills/userinterface-wiki/rules/ux-proximity-grouping.md +38 -0
  550. package/dist/resources/skills/userinterface-wiki/rules/ux-serial-position.md +31 -0
  551. package/dist/resources/skills/userinterface-wiki/rules/ux-similarity-consistency.md +35 -0
  552. package/dist/resources/skills/userinterface-wiki/rules/ux-teslers-complexity.md +28 -0
  553. package/dist/resources/skills/userinterface-wiki/rules/ux-uniform-connectedness.md +43 -0
  554. package/dist/resources/skills/userinterface-wiki/rules/ux-von-restorff-emphasis.md +29 -0
  555. package/dist/resources/skills/userinterface-wiki/rules/ux-zeigarnik-show-incomplete.md +36 -0
  556. package/dist/resources/skills/userinterface-wiki/rules/visual-animate-shadow-pseudo.md +49 -0
  557. package/dist/resources/skills/userinterface-wiki/rules/visual-border-alpha-colors.md +25 -0
  558. package/dist/resources/skills/userinterface-wiki/rules/visual-button-shadow-anatomy.md +49 -0
  559. package/dist/resources/skills/userinterface-wiki/rules/visual-concentric-radius.md +40 -0
  560. package/dist/resources/skills/userinterface-wiki/rules/visual-consistent-spacing-scale.md +35 -0
  561. package/dist/resources/skills/userinterface-wiki/rules/visual-layered-shadows.md +30 -0
  562. package/dist/resources/skills/userinterface-wiki/rules/visual-no-pure-black-shadow.md +25 -0
  563. package/dist/resources/skills/userinterface-wiki/rules/visual-shadow-direction.md +25 -0
  564. package/dist/resources/skills/userinterface-wiki/rules/visual-shadow-matches-elevation.md +23 -0
  565. package/dist/resources/skills/userinterface-wiki/rules/weight-duration-matches-action.md +29 -0
  566. package/dist/resources/skills/userinterface-wiki/rules/weight-match-action.md +32 -0
  567. package/dist/resources/skills/web-design-guidelines/SKILL.md +39 -0
  568. package/dist/resources/skills/web-quality-audit/SKILL.md +170 -0
  569. package/dist/resources/skills/web-quality-audit/scripts/analyze.sh +91 -0
  570. package/package.json +22 -8
  571. package/packages/native/dist/native.d.ts +2 -0
  572. package/packages/native/dist/native.js +19 -5
  573. package/packages/native/package.json +28 -0
  574. package/packages/native/src/native.ts +23 -9
  575. package/packages/pi-agent-core/package.json +6 -0
  576. package/packages/pi-ai/dist/models.generated.d.ts +43 -11
  577. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  578. package/packages/pi-ai/dist/models.generated.js +34 -26
  579. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  580. package/packages/pi-ai/dist/providers/anthropic.js +3 -2
  581. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  582. package/packages/pi-ai/dist/providers/openai-codex-responses.js +14 -4
  583. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  584. package/packages/pi-ai/oauth.d.ts +1 -0
  585. package/packages/pi-ai/oauth.js +1 -0
  586. package/packages/pi-ai/package.json +2 -2
  587. package/packages/pi-ai/src/models.generated.ts +42 -34
  588. package/packages/pi-ai/src/providers/anthropic.ts +3 -2
  589. package/packages/pi-ai/src/providers/openai-codex-responses.ts +15 -4
  590. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  591. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  592. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  593. package/packages/pi-coding-agent/dist/core/auth-storage.js +2 -1
  594. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  595. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  596. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js +2 -1
  597. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
  598. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  599. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +3 -2
  600. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  601. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts.map +1 -1
  602. package/packages/pi-coding-agent/dist/core/compaction/utils.js +2 -2
  603. package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
  604. package/packages/pi-coding-agent/dist/core/constants.d.ts +29 -0
  605. package/packages/pi-coding-agent/dist/core/constants.d.ts.map +1 -0
  606. package/packages/pi-coding-agent/dist/core/constants.js +44 -0
  607. package/packages/pi-coding-agent/dist/core/constants.js.map +1 -0
  608. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  609. package/packages/pi-coding-agent/dist/core/extensions/loader.js +14 -1
  610. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  611. package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
  612. package/packages/pi-coding-agent/dist/core/lsp/index.js +30 -4
  613. package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
  614. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
  615. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +13 -5
  616. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
  617. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  618. package/packages/pi-coding-agent/dist/core/model-resolver.js +14 -0
  619. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  620. package/packages/pi-coding-agent/dist/core/resolve-config-value.d.ts.map +1 -1
  621. package/packages/pi-coding-agent/dist/core/resolve-config-value.js +12 -4
  622. package/packages/pi-coding-agent/dist/core/resolve-config-value.js.map +1 -1
  623. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +49 -0
  624. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  625. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  626. package/packages/pi-coding-agent/dist/core/session-manager.js +25 -2
  627. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  628. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +6 -0
  629. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  630. package/packages/pi-coding-agent/dist/core/settings-manager.js +22 -5
  631. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  632. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  633. package/packages/pi-coding-agent/dist/core/system-prompt.js +10 -0
  634. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  635. package/packages/pi-coding-agent/dist/core/tools/edit-diff.js +2 -2
  636. package/packages/pi-coding-agent/dist/core/tools/edit-diff.js.map +1 -1
  637. package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
  638. package/packages/pi-coding-agent/dist/core/tools/find.js +2 -1
  639. package/packages/pi-coding-agent/dist/core/tools/find.js.map +1 -1
  640. package/packages/pi-coding-agent/dist/core/tools/hashline-edit.js +4 -4
  641. package/packages/pi-coding-agent/dist/core/tools/hashline-edit.js.map +1 -1
  642. package/packages/pi-coding-agent/dist/core/tools/hashline.d.ts +1 -1
  643. package/packages/pi-coding-agent/dist/core/tools/hashline.js +1 -1
  644. package/packages/pi-coding-agent/dist/core/tools/hashline.js.map +1 -1
  645. package/packages/pi-coding-agent/dist/core/tools/hashline.test.js +8 -8
  646. package/packages/pi-coding-agent/dist/core/tools/hashline.test.js.map +1 -1
  647. package/packages/pi-coding-agent/dist/core/tools/index.d.ts +1 -1
  648. package/packages/pi-coding-agent/dist/core/tools/index.js +1 -1
  649. package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
  650. package/packages/pi-coding-agent/dist/core/tools/path-utils.d.ts +1 -0
  651. package/packages/pi-coding-agent/dist/core/tools/path-utils.d.ts.map +1 -1
  652. package/packages/pi-coding-agent/dist/core/tools/path-utils.js +1 -1
  653. package/packages/pi-coding-agent/dist/core/tools/path-utils.js.map +1 -1
  654. package/packages/pi-coding-agent/dist/core/tools/truncate.d.ts.map +1 -1
  655. package/packages/pi-coding-agent/dist/core/tools/truncate.js +2 -1
  656. package/packages/pi-coding-agent/dist/core/tools/truncate.js.map +1 -1
  657. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-selector.d.ts +9 -0
  658. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  659. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-selector.js +47 -5
  660. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-selector.js.map +1 -1
  661. package/packages/pi-coding-agent/dist/modes/interactive/components/index.d.ts +1 -1
  662. package/packages/pi-coding-agent/dist/modes/interactive/components/index.d.ts.map +1 -1
  663. package/packages/pi-coding-agent/dist/modes/interactive/components/index.js +1 -1
  664. package/packages/pi-coding-agent/dist/modes/interactive/components/index.js.map +1 -1
  665. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +4 -4
  666. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  667. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  668. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  669. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
  670. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  671. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  672. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +25 -1
  673. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  674. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  675. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +12 -2
  676. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  677. package/packages/pi-coding-agent/dist/resources/extensions/memory/pipeline.d.ts.map +1 -1
  678. package/packages/pi-coding-agent/dist/resources/extensions/memory/pipeline.js +25 -3
  679. package/packages/pi-coding-agent/dist/resources/extensions/memory/pipeline.js.map +1 -1
  680. package/packages/pi-coding-agent/package.json +1 -5
  681. package/packages/pi-coding-agent/scripts/copy-assets.cjs +39 -8
  682. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  683. package/packages/pi-coding-agent/src/core/auth-storage.ts +2 -1
  684. package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +2 -1
  685. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +3 -2
  686. package/packages/pi-coding-agent/src/core/compaction/utils.ts +2 -2
  687. package/packages/pi-coding-agent/src/core/constants.ts +59 -0
  688. package/packages/pi-coding-agent/src/core/extensions/loader.ts +14 -1
  689. package/packages/pi-coding-agent/src/core/lsp/index.ts +31 -5
  690. package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +13 -5
  691. package/packages/pi-coding-agent/src/core/model-resolver.ts +14 -0
  692. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +58 -0
  693. package/packages/pi-coding-agent/src/core/resolve-config-value.ts +14 -4
  694. package/packages/pi-coding-agent/src/core/session-manager.ts +29 -6
  695. package/packages/pi-coding-agent/src/core/settings-manager.ts +33 -5
  696. package/packages/pi-coding-agent/src/core/system-prompt.ts +11 -0
  697. package/packages/pi-coding-agent/src/core/tools/edit-diff.ts +2 -2
  698. package/packages/pi-coding-agent/src/core/tools/find.ts +2 -1
  699. package/packages/pi-coding-agent/src/core/tools/hashline-edit.ts +4 -4
  700. package/packages/pi-coding-agent/src/core/tools/hashline.test.ts +8 -8
  701. package/packages/pi-coding-agent/src/core/tools/hashline.ts +1 -1
  702. package/packages/pi-coding-agent/src/core/tools/index.ts +1 -1
  703. package/packages/pi-coding-agent/src/core/tools/path-utils.ts +1 -1
  704. package/packages/pi-coding-agent/src/core/tools/truncate.ts +3 -1
  705. package/packages/pi-coding-agent/src/modes/interactive/components/extension-selector.ts +49 -5
  706. package/packages/pi-coding-agent/src/modes/interactive/components/index.ts +1 -1
  707. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +4 -4
  708. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  709. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +26 -0
  710. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +11 -2
  711. package/packages/pi-coding-agent/src/resources/extensions/memory/pipeline.ts +23 -3
  712. package/packages/pi-tui/dist/__tests__/autocomplete.test.d.ts +2 -0
  713. package/packages/pi-tui/dist/__tests__/autocomplete.test.d.ts.map +1 -0
  714. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +149 -0
  715. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -0
  716. package/packages/pi-tui/dist/__tests__/fuzzy.test.d.ts +2 -0
  717. package/packages/pi-tui/dist/__tests__/fuzzy.test.d.ts.map +1 -0
  718. package/packages/pi-tui/dist/__tests__/fuzzy.test.js +94 -0
  719. package/packages/pi-tui/dist/__tests__/fuzzy.test.js.map +1 -0
  720. package/packages/pi-tui/dist/autocomplete.d.ts +8 -1
  721. package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
  722. package/packages/pi-tui/dist/autocomplete.js +20 -2
  723. package/packages/pi-tui/dist/autocomplete.js.map +1 -1
  724. package/packages/pi-tui/package.json +8 -2
  725. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +186 -0
  726. package/packages/pi-tui/src/__tests__/fuzzy.test.ts +112 -0
  727. package/packages/pi-tui/src/autocomplete.ts +26 -1
  728. package/pkg/package.json +1 -1
  729. package/src/resources/extensions/ask-user-questions.ts +3 -2
  730. package/src/resources/extensions/bg-shell/bg-shell-command.ts +219 -0
  731. package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +400 -0
  732. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +985 -0
  733. package/src/resources/extensions/bg-shell/index.ts +17 -1561
  734. package/src/resources/extensions/bg-shell/overlay.ts +4 -0
  735. package/src/resources/extensions/bg-shell/process-manager.ts +13 -0
  736. package/src/resources/extensions/bg-shell/utilities.ts +4 -16
  737. package/src/resources/extensions/browser-tools/capture.ts +34 -2
  738. package/src/resources/extensions/browser-tools/lifecycle.ts +5 -5
  739. package/src/resources/extensions/browser-tools/settle.ts +1 -1
  740. package/src/resources/extensions/browser-tools/state.ts +5 -5
  741. package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +1 -1
  742. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +3 -3
  743. package/src/resources/extensions/browser-tools/tools/assertions.ts +1 -1
  744. package/src/resources/extensions/browser-tools/tools/device.ts +1 -1
  745. package/src/resources/extensions/browser-tools/tools/extract.ts +1 -1
  746. package/src/resources/extensions/browser-tools/tools/navigation.ts +6 -6
  747. package/src/resources/extensions/browser-tools/tools/network-mock.ts +1 -1
  748. package/src/resources/extensions/browser-tools/tools/pages.ts +1 -1
  749. package/src/resources/extensions/browser-tools/tools/screenshot.ts +28 -10
  750. package/src/resources/extensions/browser-tools/tools/state-persistence.ts +1 -1
  751. package/src/resources/extensions/browser-tools/tools/visual-diff.ts +1 -1
  752. package/src/resources/extensions/browser-tools/utils.ts +5 -5
  753. package/src/resources/extensions/get-secrets-from-user.ts +1 -1
  754. package/src/resources/extensions/google-search/index.ts +21 -8
  755. package/src/resources/extensions/gsd/activity-log.ts +2 -1
  756. package/src/resources/extensions/gsd/atomic-write.ts +35 -0
  757. package/src/resources/extensions/gsd/auto/session.ts +12 -0
  758. package/src/resources/extensions/gsd/auto-dashboard.ts +264 -62
  759. package/src/resources/extensions/gsd/auto-idempotency.ts +150 -0
  760. package/src/resources/extensions/gsd/auto-post-unit.ts +594 -0
  761. package/src/resources/extensions/gsd/auto-prompts.ts +116 -22
  762. package/src/resources/extensions/gsd/auto-recovery.ts +36 -31
  763. package/src/resources/extensions/gsd/auto-start.ts +500 -0
  764. package/src/resources/extensions/gsd/auto-stuck-detection.ts +220 -0
  765. package/src/resources/extensions/gsd/auto-timers.ts +223 -0
  766. package/src/resources/extensions/gsd/auto-unit-closeout.ts +3 -1
  767. package/src/resources/extensions/gsd/auto-verification.ts +229 -0
  768. package/src/resources/extensions/gsd/auto-worktree-sync.ts +29 -37
  769. package/src/resources/extensions/gsd/auto-worktree.ts +83 -67
  770. package/src/resources/extensions/gsd/auto.ts +375 -1890
  771. package/src/resources/extensions/gsd/commands-config.ts +102 -0
  772. package/src/resources/extensions/gsd/commands-handlers.ts +394 -0
  773. package/src/resources/extensions/gsd/commands-inspect.ts +90 -0
  774. package/src/resources/extensions/gsd/commands-logs.ts +536 -0
  775. package/src/resources/extensions/gsd/commands-maintenance.ts +206 -0
  776. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +790 -0
  777. package/src/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
  778. package/src/resources/extensions/gsd/commands.ts +417 -1495
  779. package/src/resources/extensions/gsd/constants.ts +21 -0
  780. package/src/resources/extensions/gsd/context-budget.ts +25 -2
  781. package/src/resources/extensions/gsd/crash-recovery.ts +3 -4
  782. package/src/resources/extensions/gsd/dashboard-overlay.ts +15 -5
  783. package/src/resources/extensions/gsd/db-writer.ts +21 -2
  784. package/src/resources/extensions/gsd/detection.ts +469 -0
  785. package/src/resources/extensions/gsd/diff-context.ts +2 -1
  786. package/src/resources/extensions/gsd/dispatch-guard.ts +4 -0
  787. package/src/resources/extensions/gsd/doctor-checks.ts +564 -0
  788. package/src/resources/extensions/gsd/doctor-format.ts +78 -0
  789. package/src/resources/extensions/gsd/doctor-types.ts +72 -0
  790. package/src/resources/extensions/gsd/doctor.ts +64 -701
  791. package/src/resources/extensions/gsd/errors.ts +0 -2
  792. package/src/resources/extensions/gsd/export-html.ts +367 -11
  793. package/src/resources/extensions/gsd/export.ts +31 -5
  794. package/src/resources/extensions/gsd/files.ts +8 -126
  795. package/src/resources/extensions/gsd/forensics.ts +2 -12
  796. package/src/resources/extensions/gsd/git-constants.ts +11 -0
  797. package/src/resources/extensions/gsd/git-service.ts +13 -9
  798. package/src/resources/extensions/gsd/gsd-db.ts +26 -6
  799. package/src/resources/extensions/gsd/guided-flow-queue.ts +451 -0
  800. package/src/resources/extensions/gsd/guided-flow.ts +231 -514
  801. package/src/resources/extensions/gsd/history.ts +2 -20
  802. package/src/resources/extensions/gsd/index.ts +208 -46
  803. package/src/resources/extensions/gsd/init-wizard.ts +615 -0
  804. package/src/resources/extensions/gsd/json-persistence.ts +67 -0
  805. package/src/resources/extensions/gsd/jsonl-utils.ts +21 -0
  806. package/src/resources/extensions/gsd/key-manager.ts +995 -0
  807. package/src/resources/extensions/gsd/metrics.ts +49 -36
  808. package/src/resources/extensions/gsd/migrate/command.ts +1 -1
  809. package/src/resources/extensions/gsd/migrate/parsers.ts +10 -95
  810. package/src/resources/extensions/gsd/milestone-actions.ts +126 -0
  811. package/src/resources/extensions/gsd/milestone-ids.ts +95 -0
  812. package/src/resources/extensions/gsd/native-git-bridge.ts +5 -10
  813. package/src/resources/extensions/gsd/parallel-eligibility.ts +3 -3
  814. package/src/resources/extensions/gsd/paths.ts +1 -11
  815. package/src/resources/extensions/gsd/plugin-importer.ts +3 -2
  816. package/src/resources/extensions/gsd/preferences-models.ts +323 -0
  817. package/src/resources/extensions/gsd/preferences-skills.ts +169 -0
  818. package/src/resources/extensions/gsd/preferences-types.ts +223 -0
  819. package/src/resources/extensions/gsd/preferences-validation.ts +597 -0
  820. package/src/resources/extensions/gsd/preferences.ts +219 -1305
  821. package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +213 -0
  822. package/src/resources/extensions/gsd/prompt-compressor.ts +508 -0
  823. package/src/resources/extensions/gsd/prompt-loader.ts +4 -2
  824. package/src/resources/extensions/gsd/prompt-ordering.ts +200 -0
  825. package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -2
  826. package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -4
  827. package/src/resources/extensions/gsd/prompts/discuss-headless.md +2 -4
  828. package/src/resources/extensions/gsd/prompts/discuss.md +13 -5
  829. package/src/resources/extensions/gsd/prompts/execute-task.md +0 -1
  830. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  831. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  832. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +0 -1
  833. package/src/resources/extensions/gsd/prompts/plan-milestone.md +0 -1
  834. package/src/resources/extensions/gsd/prompts/plan-slice.md +0 -1
  835. package/src/resources/extensions/gsd/prompts/queue.md +30 -0
  836. package/src/resources/extensions/gsd/prompts/quick-task.md +0 -6
  837. package/src/resources/extensions/gsd/prompts/replan-slice.md +0 -1
  838. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +0 -1
  839. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  840. package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
  841. package/src/resources/extensions/gsd/provider-error-pause.ts +59 -10
  842. package/src/resources/extensions/gsd/queue-order.ts +11 -12
  843. package/src/resources/extensions/gsd/queue-reorder-ui.ts +15 -2
  844. package/src/resources/extensions/gsd/quick.ts +18 -15
  845. package/src/resources/extensions/gsd/reports.ts +1 -7
  846. package/src/resources/extensions/gsd/routing-history.ts +13 -17
  847. package/src/resources/extensions/gsd/safe-fs.ts +47 -0
  848. package/src/resources/extensions/gsd/semantic-chunker.ts +336 -0
  849. package/src/resources/extensions/gsd/session-forensics.ts +8 -23
  850. package/src/resources/extensions/gsd/session-lock.ts +284 -0
  851. package/src/resources/extensions/gsd/session-status-io.ts +23 -41
  852. package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +38 -1
  853. package/src/resources/extensions/gsd/skills/gsd-headless/references/answer-injection.md +35 -6
  854. package/src/resources/extensions/gsd/state.ts +54 -2
  855. package/src/resources/extensions/gsd/structured-data-formatter.ts +144 -0
  856. package/src/resources/extensions/gsd/summary-distiller.ts +258 -0
  857. package/src/resources/extensions/gsd/tests/activity-log.test.ts +213 -0
  858. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +107 -0
  859. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +197 -0
  860. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  861. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +33 -39
  862. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +108 -2
  863. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +257 -0
  864. package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
  865. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +3 -0
  866. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
  867. package/src/resources/extensions/gsd/tests/context-budget.test.ts +69 -0
  868. package/src/resources/extensions/gsd/tests/detection.test.ts +398 -0
  869. package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +12 -24
  870. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +118 -94
  871. package/src/resources/extensions/gsd/tests/dispatch-stall-guard.test.ts +126 -0
  872. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +7 -3
  873. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +75 -0
  874. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +17 -55
  875. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +375 -0
  876. package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +144 -0
  877. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +3 -0
  878. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
  879. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +340 -0
  880. package/src/resources/extensions/gsd/tests/in-flight-tool-tracking.test.ts +24 -82
  881. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +197 -0
  882. package/src/resources/extensions/gsd/tests/key-manager.test.ts +414 -0
  883. package/src/resources/extensions/gsd/tests/metrics.test.ts +173 -305
  884. package/src/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +3 -0
  885. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +59 -1
  886. package/src/resources/extensions/gsd/tests/next-milestone-id.test.ts +18 -61
  887. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +17 -8
  888. package/src/resources/extensions/gsd/tests/parallel-merge.test.ts +3 -0
  889. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
  890. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +276 -0
  891. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +401 -0
  892. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +23 -47
  893. package/src/resources/extensions/gsd/tests/preferences.test.ts +284 -0
  894. package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +314 -0
  895. package/src/resources/extensions/gsd/tests/prompt-compressor.test.ts +529 -0
  896. package/src/resources/extensions/gsd/tests/prompt-ordering.test.ts +296 -0
  897. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +338 -0
  898. package/src/resources/extensions/gsd/tests/reassess-detection.test.ts +154 -0
  899. package/src/resources/extensions/gsd/tests/remote-questions.test.ts +1 -1
  900. package/src/resources/extensions/gsd/tests/remote-status.test.ts +2 -2
  901. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +43 -60
  902. package/src/resources/extensions/gsd/tests/semantic-chunker.test.ts +426 -0
  903. package/src/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
  904. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +3 -0
  905. package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +8 -5
  906. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +365 -0
  907. package/src/resources/extensions/gsd/tests/summary-distiller.test.ts +323 -0
  908. package/src/resources/extensions/gsd/tests/token-counter.test.ts +129 -0
  909. package/src/resources/extensions/gsd/tests/token-optimization-benchmark.test.ts +1272 -0
  910. package/src/resources/extensions/gsd/tests/token-optimization-prefs.test.ts +164 -0
  911. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
  912. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +69 -73
  913. package/src/resources/extensions/gsd/tests/validate-directory.test.ts +222 -0
  914. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
  915. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
  916. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +251 -8
  917. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +2 -2
  918. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +2 -1
  919. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
  920. package/src/resources/extensions/gsd/tests/workspace-index.test.ts +24 -61
  921. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +5 -2
  922. package/src/resources/extensions/gsd/tests/write-gate.test.ts +132 -43
  923. package/src/resources/extensions/gsd/token-counter.ts +20 -0
  924. package/src/resources/extensions/gsd/triage-ui.ts +1 -1
  925. package/src/resources/extensions/gsd/types.ts +5 -1
  926. package/src/resources/extensions/gsd/unit-runtime.ts +16 -13
  927. package/src/resources/extensions/gsd/validate-directory.ts +164 -0
  928. package/src/resources/extensions/gsd/verification-evidence.ts +9 -4
  929. package/src/resources/extensions/gsd/verification-gate.ts +83 -7
  930. package/src/resources/extensions/gsd/visualizer-data.ts +1 -1
  931. package/src/resources/extensions/gsd/visualizer-overlay.ts +5 -2
  932. package/src/resources/extensions/gsd/visualizer-views.ts +2 -3
  933. package/src/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
  934. package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
  935. package/src/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
  936. package/src/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
  937. package/src/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
  938. package/src/resources/extensions/gsd/workflow-templates/registry.json +85 -0
  939. package/src/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
  940. package/src/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
  941. package/src/resources/extensions/gsd/workflow-templates/spike.md +69 -0
  942. package/src/resources/extensions/gsd/workflow-templates.ts +241 -0
  943. package/src/resources/extensions/gsd/worktree-command.ts +4 -51
  944. package/src/resources/extensions/gsd/worktree-manager.ts +7 -9
  945. package/src/resources/extensions/gsd/worktree.ts +41 -1
  946. package/src/resources/extensions/mcp-client/index.ts +459 -0
  947. package/src/resources/extensions/remote-questions/discord-adapter.ts +9 -20
  948. package/src/resources/extensions/remote-questions/http-client.ts +76 -0
  949. package/src/resources/extensions/remote-questions/manager.ts +6 -24
  950. package/src/resources/extensions/remote-questions/mod.ts +16 -0
  951. package/src/resources/extensions/remote-questions/notify.ts +90 -0
  952. package/src/resources/extensions/remote-questions/remote-command.ts +1 -1
  953. package/src/resources/extensions/remote-questions/slack-adapter.ts +11 -18
  954. package/src/resources/extensions/remote-questions/store.ts +5 -1
  955. package/src/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
  956. package/src/resources/extensions/remote-questions/types.ts +29 -3
  957. package/src/resources/extensions/search-the-web/native-search.ts +7 -0
  958. package/src/resources/extensions/search-the-web/provider.ts +15 -3
  959. package/src/resources/extensions/search-the-web/tool-llm-context.ts +1 -13
  960. package/src/resources/extensions/search-the-web/tool-search.ts +1 -13
  961. package/src/resources/extensions/shared/format-utils.ts +53 -0
  962. package/src/resources/extensions/shared/frontmatter.ts +117 -0
  963. package/src/resources/extensions/shared/mod.ts +33 -0
  964. package/src/resources/extensions/shared/sanitize.ts +19 -0
  965. package/src/resources/extensions/slash-commands/create-extension.ts +1 -1
  966. package/src/resources/extensions/slash-commands/create-slash-command.ts +1 -1
  967. package/src/resources/extensions/subagent/index.ts +1 -2
  968. package/src/resources/extensions/ttsr/index.ts +5 -0
  969. package/src/resources/extensions/ttsr/rule-loader.ts +4 -51
  970. package/src/resources/extensions/universal-config/discovery.ts +37 -15
  971. package/src/resources/extensions/voice/index.ts +1 -1
  972. package/src/resources/skills/accessibility/SKILL.md +522 -0
  973. package/src/resources/skills/accessibility/references/WCAG.md +162 -0
  974. package/src/resources/skills/agent-browser/SKILL.md +517 -0
  975. package/src/resources/skills/agent-browser/references/authentication.md +202 -0
  976. package/src/resources/skills/agent-browser/references/commands.md +263 -0
  977. package/src/resources/skills/agent-browser/references/profiling.md +120 -0
  978. package/src/resources/skills/agent-browser/references/proxy-support.md +194 -0
  979. package/src/resources/skills/agent-browser/references/session-management.md +193 -0
  980. package/src/resources/skills/agent-browser/references/snapshot-refs.md +194 -0
  981. package/src/resources/skills/agent-browser/references/video-recording.md +173 -0
  982. package/src/resources/skills/agent-browser/templates/authenticated-session.sh +105 -0
  983. package/src/resources/skills/agent-browser/templates/capture-workflow.sh +69 -0
  984. package/src/resources/skills/agent-browser/templates/form-automation.sh +62 -0
  985. package/src/resources/skills/best-practices/SKILL.md +583 -0
  986. package/src/resources/skills/code-optimizer/SKILL.md +160 -0
  987. package/src/resources/skills/code-optimizer/references/algorithmic-complexity.md +66 -0
  988. package/src/resources/skills/code-optimizer/references/build-compilation.md +90 -0
  989. package/src/resources/skills/code-optimizer/references/bundle-dependencies.md +82 -0
  990. package/src/resources/skills/code-optimizer/references/caching-memoization.md +76 -0
  991. package/src/resources/skills/code-optimizer/references/concurrency-async.md +80 -0
  992. package/src/resources/skills/code-optimizer/references/config-infra.md +71 -0
  993. package/src/resources/skills/code-optimizer/references/data-structures.md +80 -0
  994. package/src/resources/skills/code-optimizer/references/database-queries.md +76 -0
  995. package/src/resources/skills/code-optimizer/references/dead-code-redundancy.md +84 -0
  996. package/src/resources/skills/code-optimizer/references/error-resilience.md +80 -0
  997. package/src/resources/skills/code-optimizer/references/io-network.md +89 -0
  998. package/src/resources/skills/code-optimizer/references/logging-observability.md +64 -0
  999. package/src/resources/skills/code-optimizer/references/memory-resources.md +66 -0
  1000. package/src/resources/skills/code-optimizer/references/rendering-ui.md +90 -0
  1001. package/src/resources/skills/code-optimizer/references/security-performance.md +68 -0
  1002. package/src/resources/skills/core-web-vitals/SKILL.md +441 -0
  1003. package/src/resources/skills/core-web-vitals/references/LCP.md +208 -0
  1004. package/src/resources/skills/create-gsd-extension/SKILL.md +87 -0
  1005. package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
  1006. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
  1007. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
  1008. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
  1009. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
  1010. package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
  1011. package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
  1012. package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
  1013. package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
  1014. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
  1015. package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
  1016. package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
  1017. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
  1018. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
  1019. package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
  1020. package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
  1021. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
  1022. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
  1023. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
  1024. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
  1025. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
  1026. package/src/resources/skills/create-skill/SKILL.md +184 -0
  1027. package/src/resources/skills/create-skill/references/api-security.md +226 -0
  1028. package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
  1029. package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
  1030. package/src/resources/skills/create-skill/references/core-principles.md +437 -0
  1031. package/src/resources/skills/create-skill/references/executable-code.md +175 -0
  1032. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
  1033. package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
  1034. package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
  1035. package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
  1036. package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
  1037. package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
  1038. package/src/resources/skills/create-skill/references/using-templates.md +112 -0
  1039. package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
  1040. package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
  1041. package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
  1042. package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
  1043. package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
  1044. package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
  1045. package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
  1046. package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
  1047. package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
  1048. package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
  1049. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
  1050. package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
  1051. package/src/resources/skills/make-interfaces-feel-better/SKILL.md +122 -0
  1052. package/src/resources/skills/make-interfaces-feel-better/animations.md +379 -0
  1053. package/src/resources/skills/make-interfaces-feel-better/performance.md +88 -0
  1054. package/src/resources/skills/make-interfaces-feel-better/surfaces.md +247 -0
  1055. package/src/resources/skills/make-interfaces-feel-better/typography.md +123 -0
  1056. package/src/resources/skills/react-best-practices/README.md +123 -0
  1057. package/src/resources/skills/react-best-practices/SKILL.md +136 -0
  1058. package/src/resources/skills/react-best-practices/metadata.json +15 -0
  1059. package/src/resources/skills/react-best-practices/rules/_sections.md +46 -0
  1060. package/src/resources/skills/react-best-practices/rules/_template.md +28 -0
  1061. package/src/resources/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  1062. package/src/resources/skills/react-best-practices/rules/advanced-init-once.md +42 -0
  1063. package/src/resources/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
  1064. package/src/resources/skills/react-best-practices/rules/async-api-routes.md +38 -0
  1065. package/src/resources/skills/react-best-practices/rules/async-defer-await.md +80 -0
  1066. package/src/resources/skills/react-best-practices/rules/async-dependencies.md +51 -0
  1067. package/src/resources/skills/react-best-practices/rules/async-parallel.md +28 -0
  1068. package/src/resources/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  1069. package/src/resources/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  1070. package/src/resources/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  1071. package/src/resources/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  1072. package/src/resources/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  1073. package/src/resources/skills/react-best-practices/rules/bundle-preload.md +50 -0
  1074. package/src/resources/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  1075. package/src/resources/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
  1076. package/src/resources/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  1077. package/src/resources/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  1078. package/src/resources/skills/react-best-practices/rules/js-batch-dom-css.md +107 -0
  1079. package/src/resources/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  1080. package/src/resources/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  1081. package/src/resources/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  1082. package/src/resources/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  1083. package/src/resources/skills/react-best-practices/rules/js-early-exit.md +50 -0
  1084. package/src/resources/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  1085. package/src/resources/skills/react-best-practices/rules/js-index-maps.md +37 -0
  1086. package/src/resources/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  1087. package/src/resources/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  1088. package/src/resources/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  1089. package/src/resources/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  1090. package/src/resources/skills/react-best-practices/rules/rendering-activity.md +26 -0
  1091. package/src/resources/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  1092. package/src/resources/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  1093. package/src/resources/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  1094. package/src/resources/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  1095. package/src/resources/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  1096. package/src/resources/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  1097. package/src/resources/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  1098. package/src/resources/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  1099. package/src/resources/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  1100. package/src/resources/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  1101. package/src/resources/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  1102. package/src/resources/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  1103. package/src/resources/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  1104. package/src/resources/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  1105. package/src/resources/skills/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  1106. package/src/resources/skills/react-best-practices/rules/rerender-memo.md +44 -0
  1107. package/src/resources/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  1108. package/src/resources/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  1109. package/src/resources/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  1110. package/src/resources/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  1111. package/src/resources/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  1112. package/src/resources/skills/react-best-practices/rules/server-auth-actions.md +96 -0
  1113. package/src/resources/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  1114. package/src/resources/skills/react-best-practices/rules/server-cache-react.md +76 -0
  1115. package/src/resources/skills/react-best-practices/rules/server-dedup-props.md +65 -0
  1116. package/src/resources/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  1117. package/src/resources/skills/react-best-practices/rules/server-serialization.md +38 -0
  1118. package/src/resources/skills/userinterface-wiki/SKILL.md +253 -0
  1119. package/src/resources/skills/userinterface-wiki/rules/_sections.md +66 -0
  1120. package/src/resources/skills/userinterface-wiki/rules/_template.md +24 -0
  1121. package/src/resources/skills/userinterface-wiki/rules/a11y-reduced-motion-check.md +30 -0
  1122. package/src/resources/skills/userinterface-wiki/rules/a11y-toggle-setting.md +30 -0
  1123. package/src/resources/skills/userinterface-wiki/rules/a11y-visual-equivalent.md +36 -0
  1124. package/src/resources/skills/userinterface-wiki/rules/a11y-volume-control.md +28 -0
  1125. package/src/resources/skills/userinterface-wiki/rules/appropriate-confirmations-only.md +19 -0
  1126. package/src/resources/skills/userinterface-wiki/rules/appropriate-errors-warnings.md +18 -0
  1127. package/src/resources/skills/userinterface-wiki/rules/appropriate-no-decorative.md +21 -0
  1128. package/src/resources/skills/userinterface-wiki/rules/appropriate-no-high-frequency.md +28 -0
  1129. package/src/resources/skills/userinterface-wiki/rules/appropriate-no-punishing.md +27 -0
  1130. package/src/resources/skills/userinterface-wiki/rules/container-callback-ref.md +31 -0
  1131. package/src/resources/skills/userinterface-wiki/rules/container-guard-initial-zero.md +25 -0
  1132. package/src/resources/skills/userinterface-wiki/rules/container-no-excessive-use.md +13 -0
  1133. package/src/resources/skills/userinterface-wiki/rules/container-overflow-hidden.md +25 -0
  1134. package/src/resources/skills/userinterface-wiki/rules/container-transition-delay.md +21 -0
  1135. package/src/resources/skills/userinterface-wiki/rules/container-two-div-pattern.md +35 -0
  1136. package/src/resources/skills/userinterface-wiki/rules/container-use-resize-observer.md +48 -0
  1137. package/src/resources/skills/userinterface-wiki/rules/context-cleanup-nodes.md +25 -0
  1138. package/src/resources/skills/userinterface-wiki/rules/context-resume-suspended.md +28 -0
  1139. package/src/resources/skills/userinterface-wiki/rules/context-reuse-single.md +30 -0
  1140. package/src/resources/skills/userinterface-wiki/rules/design-filter-for-character.md +25 -0
  1141. package/src/resources/skills/userinterface-wiki/rules/design-noise-for-percussion.md +26 -0
  1142. package/src/resources/skills/userinterface-wiki/rules/design-oscillator-for-tonal.md +22 -0
  1143. package/src/resources/skills/userinterface-wiki/rules/duration-max-300ms.md +21 -0
  1144. package/src/resources/skills/userinterface-wiki/rules/duration-press-hover.md +21 -0
  1145. package/src/resources/skills/userinterface-wiki/rules/duration-shorten-before-curve.md +21 -0
  1146. package/src/resources/skills/userinterface-wiki/rules/duration-small-state.md +15 -0
  1147. package/src/resources/skills/userinterface-wiki/rules/easing-entrance-ease-out.md +21 -0
  1148. package/src/resources/skills/userinterface-wiki/rules/easing-exit-ease-in.md +21 -0
  1149. package/src/resources/skills/userinterface-wiki/rules/easing-for-state-change.md +27 -0
  1150. package/src/resources/skills/userinterface-wiki/rules/easing-linear-only-progress.md +21 -0
  1151. package/src/resources/skills/userinterface-wiki/rules/easing-natural-decay.md +22 -0
  1152. package/src/resources/skills/userinterface-wiki/rules/easing-no-linear-motion.md +22 -0
  1153. package/src/resources/skills/userinterface-wiki/rules/easing-transition-ease-in-out.md +15 -0
  1154. package/src/resources/skills/userinterface-wiki/rules/envelope-exponential-decay.md +21 -0
  1155. package/src/resources/skills/userinterface-wiki/rules/envelope-no-zero-target.md +21 -0
  1156. package/src/resources/skills/userinterface-wiki/rules/envelope-set-initial-value.md +22 -0
  1157. package/src/resources/skills/userinterface-wiki/rules/exit-key-required.md +29 -0
  1158. package/src/resources/skills/userinterface-wiki/rules/exit-matches-initial.md +29 -0
  1159. package/src/resources/skills/userinterface-wiki/rules/exit-prop-required.md +33 -0
  1160. package/src/resources/skills/userinterface-wiki/rules/exit-requires-wrapper.md +27 -0
  1161. package/src/resources/skills/userinterface-wiki/rules/impl-default-subtle.md +21 -0
  1162. package/src/resources/skills/userinterface-wiki/rules/impl-preload-audio.md +34 -0
  1163. package/src/resources/skills/userinterface-wiki/rules/impl-reset-current-time.md +26 -0
  1164. package/src/resources/skills/userinterface-wiki/rules/mode-pop-layout-for-lists.md +25 -0
  1165. package/src/resources/skills/userinterface-wiki/rules/mode-sync-layout-conflict.md +29 -0
  1166. package/src/resources/skills/userinterface-wiki/rules/mode-wait-doubles-duration.md +25 -0
  1167. package/src/resources/skills/userinterface-wiki/rules/morphing-aria-hidden.md +21 -0
  1168. package/src/resources/skills/userinterface-wiki/rules/morphing-consistent-viewbox.md +23 -0
  1169. package/src/resources/skills/userinterface-wiki/rules/morphing-group-variants.md +33 -0
  1170. package/src/resources/skills/userinterface-wiki/rules/morphing-jump-non-grouped.md +29 -0
  1171. package/src/resources/skills/userinterface-wiki/rules/morphing-reduced-motion.md +28 -0
  1172. package/src/resources/skills/userinterface-wiki/rules/morphing-spring-rotation.md +23 -0
  1173. package/src/resources/skills/userinterface-wiki/rules/morphing-strokelinecap-round.md +21 -0
  1174. package/src/resources/skills/userinterface-wiki/rules/morphing-three-lines.md +32 -0
  1175. package/src/resources/skills/userinterface-wiki/rules/morphing-use-collapsed.md +33 -0
  1176. package/src/resources/skills/userinterface-wiki/rules/native-backdrop-styling.md +27 -0
  1177. package/src/resources/skills/userinterface-wiki/rules/native-placeholder-styling.md +27 -0
  1178. package/src/resources/skills/userinterface-wiki/rules/native-selection-styling.md +18 -0
  1179. package/src/resources/skills/userinterface-wiki/rules/nested-consistent-timing.md +25 -0
  1180. package/src/resources/skills/userinterface-wiki/rules/nested-propagate-required.md +41 -0
  1181. package/src/resources/skills/userinterface-wiki/rules/none-context-menu-entrance.md +25 -0
  1182. package/src/resources/skills/userinterface-wiki/rules/none-high-frequency.md +29 -0
  1183. package/src/resources/skills/userinterface-wiki/rules/none-keyboard-navigation.md +32 -0
  1184. package/src/resources/skills/userinterface-wiki/rules/param-click-duration.md +21 -0
  1185. package/src/resources/skills/userinterface-wiki/rules/param-filter-frequency-range.md +21 -0
  1186. package/src/resources/skills/userinterface-wiki/rules/param-q-value-range.md +21 -0
  1187. package/src/resources/skills/userinterface-wiki/rules/param-reasonable-gain.md +21 -0
  1188. package/src/resources/skills/userinterface-wiki/rules/physics-active-state.md +23 -0
  1189. package/src/resources/skills/userinterface-wiki/rules/physics-no-excessive-stagger.md +22 -0
  1190. package/src/resources/skills/userinterface-wiki/rules/physics-spring-for-overshoot.md +23 -0
  1191. package/src/resources/skills/userinterface-wiki/rules/physics-subtle-deformation.md +22 -0
  1192. package/src/resources/skills/userinterface-wiki/rules/prefetch-hit-slop.md +27 -0
  1193. package/src/resources/skills/userinterface-wiki/rules/prefetch-keyboard-tab.md +19 -0
  1194. package/src/resources/skills/userinterface-wiki/rules/prefetch-not-everything.md +22 -0
  1195. package/src/resources/skills/userinterface-wiki/rules/prefetch-touch-fallback.md +34 -0
  1196. package/src/resources/skills/userinterface-wiki/rules/prefetch-trajectory-over-hover.md +32 -0
  1197. package/src/resources/skills/userinterface-wiki/rules/prefetch-use-selectively.md +13 -0
  1198. package/src/resources/skills/userinterface-wiki/rules/presence-disable-interactions.md +31 -0
  1199. package/src/resources/skills/userinterface-wiki/rules/presence-hook-in-child.md +31 -0
  1200. package/src/resources/skills/userinterface-wiki/rules/presence-safe-to-remove.md +37 -0
  1201. package/src/resources/skills/userinterface-wiki/rules/pseudo-content-required.md +28 -0
  1202. package/src/resources/skills/userinterface-wiki/rules/pseudo-first-line-styling.md +27 -0
  1203. package/src/resources/skills/userinterface-wiki/rules/pseudo-hit-target-expansion.md +31 -0
  1204. package/src/resources/skills/userinterface-wiki/rules/pseudo-marker-styling.md +28 -0
  1205. package/src/resources/skills/userinterface-wiki/rules/pseudo-over-dom-node.md +32 -0
  1206. package/src/resources/skills/userinterface-wiki/rules/pseudo-position-relative-parent.md +33 -0
  1207. package/src/resources/skills/userinterface-wiki/rules/pseudo-z-index-layering.md +37 -0
  1208. package/src/resources/skills/userinterface-wiki/rules/spring-for-gestures.md +27 -0
  1209. package/src/resources/skills/userinterface-wiki/rules/spring-for-interruptible.md +27 -0
  1210. package/src/resources/skills/userinterface-wiki/rules/spring-params-balanced.md +29 -0
  1211. package/src/resources/skills/userinterface-wiki/rules/spring-preserves-velocity.md +28 -0
  1212. package/src/resources/skills/userinterface-wiki/rules/staging-dim-background.md +22 -0
  1213. package/src/resources/skills/userinterface-wiki/rules/staging-one-focal-point.md +24 -0
  1214. package/src/resources/skills/userinterface-wiki/rules/staging-z-index-hierarchy.md +22 -0
  1215. package/src/resources/skills/userinterface-wiki/rules/timing-consistent.md +24 -0
  1216. package/src/resources/skills/userinterface-wiki/rules/timing-no-entrance-context-menu.md +22 -0
  1217. package/src/resources/skills/userinterface-wiki/rules/timing-under-300ms.md +22 -0
  1218. package/src/resources/skills/userinterface-wiki/rules/transition-name-cleanup.md +28 -0
  1219. package/src/resources/skills/userinterface-wiki/rules/transition-name-required.md +27 -0
  1220. package/src/resources/skills/userinterface-wiki/rules/transition-name-unique.md +24 -0
  1221. package/src/resources/skills/userinterface-wiki/rules/transition-over-js-library.md +32 -0
  1222. package/src/resources/skills/userinterface-wiki/rules/transition-style-pseudo-elements.md +24 -0
  1223. package/src/resources/skills/userinterface-wiki/rules/type-antialiased-on-retina.md +18 -0
  1224. package/src/resources/skills/userinterface-wiki/rules/type-disambiguation-stylistic-set.md +15 -0
  1225. package/src/resources/skills/userinterface-wiki/rules/type-font-display-swap.md +28 -0
  1226. package/src/resources/skills/userinterface-wiki/rules/type-justify-with-hyphens.md +24 -0
  1227. package/src/resources/skills/userinterface-wiki/rules/type-letter-spacing-uppercase.md +28 -0
  1228. package/src/resources/skills/userinterface-wiki/rules/type-no-font-synthesis.md +18 -0
  1229. package/src/resources/skills/userinterface-wiki/rules/type-oldstyle-nums-for-prose.md +21 -0
  1230. package/src/resources/skills/userinterface-wiki/rules/type-opentype-contextual-alternates.md +15 -0
  1231. package/src/resources/skills/userinterface-wiki/rules/type-optical-sizing-auto.md +25 -0
  1232. package/src/resources/skills/userinterface-wiki/rules/type-proper-fractions.md +15 -0
  1233. package/src/resources/skills/userinterface-wiki/rules/type-slashed-zero.md +17 -0
  1234. package/src/resources/skills/userinterface-wiki/rules/type-tabular-nums-for-data.md +21 -0
  1235. package/src/resources/skills/userinterface-wiki/rules/type-text-wrap-balance-headings.md +21 -0
  1236. package/src/resources/skills/userinterface-wiki/rules/type-text-wrap-pretty.md +16 -0
  1237. package/src/resources/skills/userinterface-wiki/rules/type-underline-offset.md +25 -0
  1238. package/src/resources/skills/userinterface-wiki/rules/type-variable-weight-continuous.md +23 -0
  1239. package/src/resources/skills/userinterface-wiki/rules/ux-aesthetic-usability.md +32 -0
  1240. package/src/resources/skills/userinterface-wiki/rules/ux-cognitive-load-reduce.md +49 -0
  1241. package/src/resources/skills/userinterface-wiki/rules/ux-common-region-boundaries.md +50 -0
  1242. package/src/resources/skills/userinterface-wiki/rules/ux-doherty-perceived-speed.md +29 -0
  1243. package/src/resources/skills/userinterface-wiki/rules/ux-doherty-under-400ms.md +30 -0
  1244. package/src/resources/skills/userinterface-wiki/rules/ux-fitts-hit-area.md +32 -0
  1245. package/src/resources/skills/userinterface-wiki/rules/ux-fitts-target-size.md +31 -0
  1246. package/src/resources/skills/userinterface-wiki/rules/ux-goal-gradient-progress.md +33 -0
  1247. package/src/resources/skills/userinterface-wiki/rules/ux-hicks-minimize-choices.md +45 -0
  1248. package/src/resources/skills/userinterface-wiki/rules/ux-jakobs-familiar-patterns.md +37 -0
  1249. package/src/resources/skills/userinterface-wiki/rules/ux-millers-chunking.md +23 -0
  1250. package/src/resources/skills/userinterface-wiki/rules/ux-pareto-prioritize-features.md +36 -0
  1251. package/src/resources/skills/userinterface-wiki/rules/ux-peak-end-finish-strong.md +35 -0
  1252. package/src/resources/skills/userinterface-wiki/rules/ux-postels-accept-messy-input.md +45 -0
  1253. package/src/resources/skills/userinterface-wiki/rules/ux-pragnanz-simplify.md +33 -0
  1254. package/src/resources/skills/userinterface-wiki/rules/ux-progressive-disclosure.md +41 -0
  1255. package/src/resources/skills/userinterface-wiki/rules/ux-proximity-grouping.md +38 -0
  1256. package/src/resources/skills/userinterface-wiki/rules/ux-serial-position.md +31 -0
  1257. package/src/resources/skills/userinterface-wiki/rules/ux-similarity-consistency.md +35 -0
  1258. package/src/resources/skills/userinterface-wiki/rules/ux-teslers-complexity.md +28 -0
  1259. package/src/resources/skills/userinterface-wiki/rules/ux-uniform-connectedness.md +43 -0
  1260. package/src/resources/skills/userinterface-wiki/rules/ux-von-restorff-emphasis.md +29 -0
  1261. package/src/resources/skills/userinterface-wiki/rules/ux-zeigarnik-show-incomplete.md +36 -0
  1262. package/src/resources/skills/userinterface-wiki/rules/visual-animate-shadow-pseudo.md +49 -0
  1263. package/src/resources/skills/userinterface-wiki/rules/visual-border-alpha-colors.md +25 -0
  1264. package/src/resources/skills/userinterface-wiki/rules/visual-button-shadow-anatomy.md +49 -0
  1265. package/src/resources/skills/userinterface-wiki/rules/visual-concentric-radius.md +40 -0
  1266. package/src/resources/skills/userinterface-wiki/rules/visual-consistent-spacing-scale.md +35 -0
  1267. package/src/resources/skills/userinterface-wiki/rules/visual-layered-shadows.md +30 -0
  1268. package/src/resources/skills/userinterface-wiki/rules/visual-no-pure-black-shadow.md +25 -0
  1269. package/src/resources/skills/userinterface-wiki/rules/visual-shadow-direction.md +25 -0
  1270. package/src/resources/skills/userinterface-wiki/rules/visual-shadow-matches-elevation.md +23 -0
  1271. package/src/resources/skills/userinterface-wiki/rules/weight-duration-matches-action.md +29 -0
  1272. package/src/resources/skills/userinterface-wiki/rules/weight-match-action.md +32 -0
  1273. package/src/resources/skills/web-design-guidelines/SKILL.md +39 -0
  1274. package/src/resources/skills/web-quality-audit/SKILL.md +170 -0
  1275. package/src/resources/skills/web-quality-audit/scripts/analyze.sh +91 -0
  1276. package/dist/resources/extensions/gsd/complexity.ts +0 -237
  1277. package/dist/resources/extensions/gsd/github-client.ts +0 -235
  1278. package/dist/resources/extensions/gsd/tests/activity-log-prune.test.ts +0 -297
  1279. package/dist/resources/extensions/gsd/tests/activity-log-save.test.ts +0 -127
  1280. package/dist/resources/extensions/gsd/tests/agent-end-provider-error.test.ts +0 -110
  1281. package/dist/resources/extensions/gsd/tests/auto-draft-pause.test.ts +0 -115
  1282. package/dist/resources/extensions/gsd/tests/complexity-routing.test.ts +0 -294
  1283. package/dist/resources/extensions/gsd/tests/metrics-io.test.ts +0 -176
  1284. package/dist/resources/extensions/gsd/tests/network-error-fallback.test.ts +0 -104
  1285. package/dist/resources/extensions/gsd/tests/preferences-git.test.ts +0 -120
  1286. package/dist/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -226
  1287. package/dist/resources/extensions/gsd/tests/preferences-mode.test.ts +0 -110
  1288. package/dist/resources/extensions/gsd/tests/preferences-models.test.ts +0 -207
  1289. package/dist/resources/extensions/gsd/tests/preferences-schema-validation.test.ts +0 -183
  1290. package/dist/resources/extensions/gsd/tests/preferences-wizard-fields.test.ts +0 -168
  1291. package/dist/resources/extensions/mcporter/index.ts +0 -512
  1292. package/dist/resources/extensions/shared/progress-widget.ts +0 -282
  1293. package/dist/resources/extensions/shared/thinking-widget.ts +0 -107
  1294. package/src/resources/extensions/gsd/complexity.ts +0 -237
  1295. package/src/resources/extensions/gsd/github-client.ts +0 -235
  1296. package/src/resources/extensions/gsd/tests/activity-log-prune.test.ts +0 -297
  1297. package/src/resources/extensions/gsd/tests/activity-log-save.test.ts +0 -127
  1298. package/src/resources/extensions/gsd/tests/agent-end-provider-error.test.ts +0 -110
  1299. package/src/resources/extensions/gsd/tests/auto-draft-pause.test.ts +0 -115
  1300. package/src/resources/extensions/gsd/tests/complexity-routing.test.ts +0 -294
  1301. package/src/resources/extensions/gsd/tests/metrics-io.test.ts +0 -176
  1302. package/src/resources/extensions/gsd/tests/network-error-fallback.test.ts +0 -104
  1303. package/src/resources/extensions/gsd/tests/preferences-git.test.ts +0 -120
  1304. package/src/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -226
  1305. package/src/resources/extensions/gsd/tests/preferences-mode.test.ts +0 -110
  1306. package/src/resources/extensions/gsd/tests/preferences-models.test.ts +0 -207
  1307. package/src/resources/extensions/gsd/tests/preferences-schema-validation.test.ts +0 -183
  1308. package/src/resources/extensions/gsd/tests/preferences-wizard-fields.test.ts +0 -168
  1309. package/src/resources/extensions/mcporter/index.ts +0 -512
  1310. package/src/resources/extensions/shared/progress-widget.ts +0 -282
  1311. package/src/resources/extensions/shared/thinking-widget.ts +0 -107
@@ -1,13 +1,83 @@
1
- import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
1
+ /**
2
+ * GSD Preferences -- loading, merging, and rendering.
3
+ *
4
+ * This module is the primary entry point for preference operations.
5
+ * Type definitions live in ./preferences-types.js, validation in
6
+ * ./preferences-validation.js, skill logic in ./preferences-skills.js,
7
+ * and model logic in ./preferences-models.js.
8
+ *
9
+ * All symbols are re-exported here so that existing `import { ... } from "./preferences.js"`
10
+ * statements continue to work without modification.
11
+ */
12
+
13
+ import { existsSync, readFileSync } from "node:fs";
2
14
  import { homedir } from "node:os";
3
- import { isAbsolute, join } from "node:path";
4
- import { getAgentDir } from "@gsd/pi-coding-agent";
15
+ import { join } from "node:path";
5
16
  import { parse as parseYaml } from "yaml";
6
- import type { GitPreferences } from "./git-service.js";
7
- import type { PostUnitHookConfig, PreDispatchHookConfig, BudgetEnforcementMode, NotificationPreferences, TokenProfile, InlineLevel, PhaseSkipPreferences } from "./types.js";
17
+ import type { PostUnitHookConfig, PreDispatchHookConfig } from "./types.js";
8
18
  import type { DynamicRoutingConfig } from "./model-router.js";
9
- import { defaultRoutingConfig } from "./model-router.js";
10
- import { VALID_BRANCH_NAME } from "./git-service.js";
19
+ import { normalizeStringArray } from "../shared/mod.js";
20
+
21
+ import {
22
+ MODE_DEFAULTS,
23
+ type WorkflowMode,
24
+ type GSDPreferences,
25
+ type LoadedGSDPreferences,
26
+ type SkillResolution,
27
+ } from "./preferences-types.js";
28
+ import { validatePreferences } from "./preferences-validation.js";
29
+ import { formatSkillRef } from "./preferences-skills.js";
30
+
31
+ // ─── Re-exports: types ──────────────────────────────────────────────────────
32
+ // Every type/interface that was previously exported from this file is
33
+ // re-exported so that downstream `import { Foo } from "./preferences.js"`
34
+ // statements keep compiling.
35
+
36
+ export type {
37
+ WorkflowMode,
38
+ GSDSkillRule,
39
+ GSDPhaseModelConfig,
40
+ GSDModelConfig,
41
+ GSDModelConfigV2,
42
+ ResolvedModelConfig,
43
+ SkillDiscoveryMode,
44
+ AutoSupervisorConfig,
45
+ RemoteQuestionsConfig,
46
+ GSDPreferences,
47
+ LoadedGSDPreferences,
48
+ SkillResolution,
49
+ SkillResolutionReport,
50
+ } from "./preferences-types.js";
51
+
52
+ // ─── Re-exports: validation ─────────────────────────────────────────────────
53
+ export { validatePreferences } from "./preferences-validation.js";
54
+
55
+ // ─── Re-exports: skills ─────────────────────────────────────────────────────
56
+ export {
57
+ resolveAllSkillReferences,
58
+ resolveSkillDiscoveryMode,
59
+ resolveSkillStalenessDays,
60
+ } from "./preferences-skills.js";
61
+
62
+ // ─── Re-exports: models ─────────────────────────────────────────────────────
63
+ export {
64
+ resolveModelForUnit,
65
+ resolveModelWithFallbacksForUnit,
66
+ getNextFallbackModel,
67
+ isTransientNetworkError,
68
+ validateModelId,
69
+ updatePreferencesModels,
70
+ resolveDynamicRoutingConfig,
71
+ resolveAutoSupervisorConfig,
72
+ resolveProfileDefaults,
73
+ resolveEffectiveProfile,
74
+ resolveInlineLevel,
75
+ resolveCompressionStrategy,
76
+ resolveContextSelection,
77
+ resolveSearchProviderFromPreferences,
78
+ } from "./preferences-models.js";
79
+
80
+ // ─── Path Constants & Getters ───────────────────────────────────────────────
11
81
 
12
82
  const GLOBAL_PREFERENCES_PATH = join(homedir(), ".gsd", "preferences.md");
13
83
  const LEGACY_GLOBAL_PREFERENCES_PATH = join(homedir(), ".pi", "agent", "gsd-preferences.md");
@@ -16,181 +86,6 @@ const PROJECT_PREFERENCES_PATH = join(process.cwd(), ".gsd", "preferences.md");
16
86
  // Check uppercase as a fallback so those files aren't silently ignored.
17
87
  const GLOBAL_PREFERENCES_PATH_UPPERCASE = join(homedir(), ".gsd", "PREFERENCES.md");
18
88
  const PROJECT_PREFERENCES_PATH_UPPERCASE = join(process.cwd(), ".gsd", "PREFERENCES.md");
19
- const SKILL_ACTIONS = new Set(["use", "prefer", "avoid"]);
20
-
21
- // ─── Workflow Modes ──────────────────────────────────────────────────────────
22
-
23
- export type WorkflowMode = "solo" | "team";
24
-
25
- /** Default preference values for each workflow mode. */
26
- const MODE_DEFAULTS: Record<WorkflowMode, Partial<GSDPreferences>> = {
27
- solo: {
28
- git: {
29
- auto_push: true,
30
- push_branches: false,
31
- pre_merge_check: false,
32
- merge_strategy: "squash",
33
- isolation: "worktree",
34
- commit_docs: true,
35
- },
36
- unique_milestone_ids: false,
37
- },
38
- team: {
39
- git: {
40
- auto_push: false,
41
- push_branches: true,
42
- pre_merge_check: true,
43
- merge_strategy: "squash",
44
- isolation: "worktree",
45
- commit_docs: true,
46
- },
47
- unique_milestone_ids: true,
48
- },
49
- };
50
-
51
- /** All recognized top-level keys in GSDPreferences. Used to detect typos / stale config. */
52
- const KNOWN_PREFERENCE_KEYS = new Set<string>([
53
- "version",
54
- "mode",
55
- "always_use_skills",
56
- "prefer_skills",
57
- "avoid_skills",
58
- "skill_rules",
59
- "custom_instructions",
60
- "models",
61
- "skill_discovery",
62
- "skill_staleness_days",
63
- "auto_supervisor",
64
- "uat_dispatch",
65
- "unique_milestone_ids",
66
- "budget_ceiling",
67
- "budget_enforcement",
68
- "context_pause_threshold",
69
- "notifications",
70
- "remote_questions",
71
- "git",
72
- "post_unit_hooks",
73
- "pre_dispatch_hooks",
74
- "dynamic_routing",
75
- "token_profile",
76
- "phases",
77
- "auto_visualize",
78
- "auto_report",
79
- "parallel",
80
- "verification_commands",
81
- "verification_auto_fix",
82
- "verification_max_retries",
83
- ]);
84
-
85
- export interface GSDSkillRule {
86
- when: string;
87
- use?: string[];
88
- prefer?: string[];
89
- avoid?: string[];
90
- }
91
-
92
- /**
93
- * Model configuration for a single phase.
94
- * Supports primary model with optional fallbacks for resilience.
95
- */
96
- export interface GSDPhaseModelConfig {
97
- /** Primary model ID (e.g., "claude-opus-4-6") */
98
- model: string;
99
- /** Provider name to disambiguate when the same model ID exists across providers (e.g., "bedrock", "anthropic") */
100
- provider?: string;
101
- /** Fallback models to try in order if primary fails (e.g., rate limits, credits exhausted) */
102
- fallbacks?: string[];
103
- }
104
-
105
- /**
106
- * Legacy model config — simple string per phase.
107
- * Kept for backward compatibility; will be migrated to GSDModelConfigV2 on load.
108
- */
109
- export interface GSDModelConfig {
110
- research?: string;
111
- planning?: string;
112
- execution?: string;
113
- execution_simple?: string;
114
- completion?: string;
115
- subagent?: string;
116
- }
117
-
118
- /**
119
- * Extended model config with per-phase fallback support.
120
- * Each phase can specify a primary model and ordered fallbacks.
121
- */
122
- export interface GSDModelConfigV2 {
123
- research?: string | GSDPhaseModelConfig;
124
- planning?: string | GSDPhaseModelConfig;
125
- execution?: string | GSDPhaseModelConfig;
126
- execution_simple?: string | GSDPhaseModelConfig;
127
- completion?: string | GSDPhaseModelConfig;
128
- subagent?: string | GSDPhaseModelConfig;
129
- }
130
-
131
- /** Normalized model selection with resolved fallbacks */
132
- export interface ResolvedModelConfig {
133
- primary: string;
134
- fallbacks: string[];
135
- }
136
-
137
- export type SkillDiscoveryMode = "auto" | "suggest" | "off";
138
-
139
- export interface AutoSupervisorConfig {
140
- model?: string;
141
- soft_timeout_minutes?: number;
142
- idle_timeout_minutes?: number;
143
- hard_timeout_minutes?: number;
144
- }
145
-
146
- export interface RemoteQuestionsConfig {
147
- channel: "slack" | "discord" | "telegram";
148
- channel_id: string | number;
149
- timeout_minutes?: number; // clamped to 1-30
150
- poll_interval_seconds?: number; // clamped to 2-30
151
- }
152
-
153
- export interface GSDPreferences {
154
- version?: number;
155
- mode?: WorkflowMode;
156
- always_use_skills?: string[];
157
- prefer_skills?: string[];
158
- avoid_skills?: string[];
159
- skill_rules?: GSDSkillRule[];
160
- custom_instructions?: string[];
161
- models?: GSDModelConfig | GSDModelConfigV2;
162
- skill_discovery?: SkillDiscoveryMode;
163
- skill_staleness_days?: number; // Skills unused for N days get deprioritized (#599). 0 = disabled. Default: 60.
164
- auto_supervisor?: AutoSupervisorConfig;
165
- uat_dispatch?: boolean;
166
- unique_milestone_ids?: boolean;
167
- budget_ceiling?: number;
168
- budget_enforcement?: BudgetEnforcementMode;
169
- context_pause_threshold?: number;
170
- notifications?: NotificationPreferences;
171
- remote_questions?: RemoteQuestionsConfig;
172
- git?: GitPreferences;
173
- post_unit_hooks?: PostUnitHookConfig[];
174
- pre_dispatch_hooks?: PreDispatchHookConfig[];
175
- dynamic_routing?: DynamicRoutingConfig;
176
- token_profile?: TokenProfile;
177
- phases?: PhaseSkipPreferences;
178
- auto_visualize?: boolean;
179
- /** Generate HTML report snapshot after each milestone completion. Default: true. Set false to disable. */
180
- auto_report?: boolean;
181
- parallel?: import("./types.js").ParallelConfig;
182
- verification_commands?: string[];
183
- verification_auto_fix?: boolean;
184
- verification_max_retries?: number;
185
- }
186
-
187
- export interface LoadedGSDPreferences {
188
- path: string;
189
- scope: "global" | "project";
190
- preferences: GSDPreferences;
191
- /** Validation warnings (unknown keys, type mismatches, deprecations). Empty when preferences are clean. */
192
- warnings?: string[];
193
- }
194
89
 
195
90
  export function getGlobalGSDPreferencesPath(): string {
196
91
  return GLOBAL_PREFERENCES_PATH;
@@ -204,6 +99,8 @@ export function getProjectGSDPreferencesPath(): string {
204
99
  return PROJECT_PREFERENCES_PATH;
205
100
  }
206
101
 
102
+ // ─── Loading ────────────────────────────────────────────────────────────────
103
+
207
104
  export function loadGlobalGSDPreferences(): LoadedGSDPreferences | null {
208
105
  return loadPreferencesFile(GLOBAL_PREFERENCES_PATH, "global")
209
106
  ?? loadPreferencesFile(GLOBAL_PREFERENCES_PATH_UPPERCASE, "global")
@@ -215,16 +112,6 @@ export function loadProjectGSDPreferences(): LoadedGSDPreferences | null {
215
112
  ?? loadPreferencesFile(PROJECT_PREFERENCES_PATH_UPPERCASE, "project");
216
113
  }
217
114
 
218
- /**
219
- * Apply mode defaults as the lowest-priority layer.
220
- * Mode defaults fill in undefined fields; any explicit user value wins.
221
- */
222
- export function applyModeDefaults(mode: WorkflowMode, prefs: GSDPreferences): GSDPreferences {
223
- const defaults = MODE_DEFAULTS[mode];
224
- if (!defaults) return prefs;
225
- return mergePreferences(defaults, prefs);
226
- }
227
-
228
115
  export function loadEffectiveGSDPreferences(): LoadedGSDPreferences | null {
229
116
  const globalPreferences = loadGlobalGSDPreferences();
230
117
  const projectPreferences = loadProjectGSDPreferences();
@@ -260,149 +147,152 @@ export function loadEffectiveGSDPreferences(): LoadedGSDPreferences | null {
260
147
  return result;
261
148
  }
262
149
 
263
- // ─── Skill Reference Resolution ───────────────────────────────────────────────
150
+ function loadPreferencesFile(path: string, scope: "global" | "project"): LoadedGSDPreferences | null {
151
+ if (!existsSync(path)) return null;
264
152
 
265
- export interface SkillResolution {
266
- /** The original reference from preferences (bare name or path). */
267
- original: string;
268
- /** The resolved absolute path to the SKILL.md file, or null if unresolved. */
269
- resolvedPath: string | null;
270
- /** How it was resolved. */
271
- method: "absolute-path" | "absolute-dir" | "user-skill" | "project-skill" | "unresolved";
272
- }
153
+ const raw = readFileSync(path, "utf-8");
154
+ const preferences = parsePreferencesMarkdown(raw);
155
+ if (!preferences) return null;
273
156
 
274
- export interface SkillResolutionReport {
275
- /** All resolution results, keyed by original reference. */
276
- resolutions: Map<string, SkillResolution>;
277
- /** References that could not be resolved. */
278
- warnings: string[];
279
- }
157
+ const validation = validatePreferences(preferences);
158
+ const allWarnings = [...validation.warnings, ...validation.errors];
280
159
 
281
- /**
282
- * Known skill directories, in priority order.
283
- * User skills (~/.gsd/agent/skills/) take precedence over project skills.
284
- */
285
- function getSkillSearchDirs(cwd: string): Array<{ dir: string; method: SkillResolution["method"] }> {
286
- return [
287
- { dir: join(getAgentDir(), "skills"), method: "user-skill" },
288
- { dir: join(cwd, ".pi", "agent", "skills"), method: "project-skill" },
289
- ];
160
+ return {
161
+ path,
162
+ scope,
163
+ preferences: validation.preferences,
164
+ ...(allWarnings.length > 0 ? { warnings: allWarnings } : {}),
165
+ };
290
166
  }
291
167
 
292
- /**
293
- * Resolve a single skill reference to an absolute path.
294
- *
295
- * Resolution order:
296
- * 1. Absolute path to a file → check existsSync
297
- * 2. Absolute path to a directory → check for SKILL.md inside
298
- * 3. Bare name → scan known skill directories for <name>/SKILL.md
299
- */
300
- function resolveSkillReference(ref: string, cwd: string): SkillResolution {
301
- const trimmed = ref.trim();
302
-
303
- // Expand tilde
304
- const expanded = trimmed.startsWith("~/")
305
- ? join(homedir(), trimmed.slice(2))
306
- : trimmed;
168
+ /** @internal Exported for testing only */
169
+ export function parsePreferencesMarkdown(content: string): GSDPreferences | null {
170
+ // Use indexOf instead of [\s\S]*? regex to avoid backtracking (#468)
171
+ const startMarker = content.startsWith('---\r\n') ? '---\r\n' : '---\n';
172
+ if (!content.startsWith(startMarker)) return null;
173
+ const searchStart = startMarker.length;
174
+ const endIdx = content.indexOf('\n---', searchStart);
175
+ if (endIdx === -1) return null;
176
+ const block = content.slice(searchStart, endIdx);
177
+ return parseFrontmatterBlock(block.replace(/\r/g, ''));
178
+ }
307
179
 
308
- // Absolute path
309
- if (isAbsolute(expanded)) {
310
- // Direct file reference
311
- if (existsSync(expanded)) {
312
- // Check if it's a directory — look for SKILL.md inside
313
- try {
314
- const stat = statSync(expanded);
315
- if (stat.isDirectory()) {
316
- const skillFile = join(expanded, "SKILL.md");
317
- if (existsSync(skillFile)) {
318
- return { original: ref, resolvedPath: skillFile, method: "absolute-dir" };
319
- }
320
- return { original: ref, resolvedPath: null, method: "unresolved" };
321
- }
322
- } catch { /* fall through */ }
323
- return { original: ref, resolvedPath: expanded, method: "absolute-path" };
324
- }
325
- // Maybe it's a directory path without SKILL.md suffix
326
- const withSkillMd = join(expanded, "SKILL.md");
327
- if (existsSync(withSkillMd)) {
328
- return { original: ref, resolvedPath: withSkillMd, method: "absolute-dir" };
180
+ function parseFrontmatterBlock(frontmatter: string): GSDPreferences {
181
+ try {
182
+ const parsed = parseYaml(frontmatter);
183
+ if (typeof parsed !== 'object' || parsed === null) {
184
+ return {} as GSDPreferences;
329
185
  }
330
- return { original: ref, resolvedPath: null, method: "unresolved" };
331
- }
332
-
333
- // Bare name — scan known skill directories
334
- for (const { dir, method } of getSkillSearchDirs(cwd)) {
335
- if (!existsSync(dir)) continue;
336
- try {
337
- const entries = readdirSync(dir, { withFileTypes: true });
338
- for (const entry of entries) {
339
- if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
340
- if (entry.name === expanded) {
341
- const skillFile = join(dir, entry.name, "SKILL.md");
342
- if (existsSync(skillFile)) {
343
- return { original: ref, resolvedPath: skillFile, method };
344
- }
345
- }
346
- }
347
- } catch { /* directory not readable — skip */ }
186
+ return parsed as GSDPreferences;
187
+ } catch (e) {
188
+ console.error("[parseFrontmatterBlock] YAML parse error:", e);
189
+ return {} as GSDPreferences;
348
190
  }
349
-
350
- return { original: ref, resolvedPath: null, method: "unresolved" };
351
191
  }
352
192
 
193
+ // ─── Merging ────────────────────────────────────────────────────────────────
194
+
353
195
  /**
354
- * Resolve all skill references in a preferences object.
355
- * Caches resolution per reference string to avoid redundant filesystem scans.
196
+ * Apply mode defaults as the lowest-priority layer.
197
+ * Mode defaults fill in undefined fields; any explicit user value wins.
356
198
  */
357
- export function resolveAllSkillReferences(preferences: GSDPreferences, cwd: string): SkillResolutionReport {
358
- const validated = validatePreferences(preferences).preferences;
359
- preferences = validated;
360
-
361
- const resolutions = new Map<string, SkillResolution>();
362
- const warnings: string[] = [];
199
+ export function applyModeDefaults(mode: WorkflowMode, prefs: GSDPreferences): GSDPreferences {
200
+ const defaults = MODE_DEFAULTS[mode];
201
+ if (!defaults) return prefs;
202
+ return mergePreferences(defaults, prefs);
203
+ }
363
204
 
364
- function resolve(ref: string): SkillResolution {
365
- const existing = resolutions.get(ref);
366
- if (existing) return existing;
367
- const result = resolveSkillReference(ref, cwd);
368
- resolutions.set(ref, result);
369
- if (result.method === "unresolved") {
370
- warnings.push(ref);
371
- }
372
- return result;
373
- }
205
+ function mergePreferences(base: GSDPreferences, override: GSDPreferences): GSDPreferences {
206
+ return {
207
+ version: override.version ?? base.version,
208
+ mode: override.mode ?? base.mode,
209
+ always_use_skills: mergeStringLists(base.always_use_skills, override.always_use_skills),
210
+ prefer_skills: mergeStringLists(base.prefer_skills, override.prefer_skills),
211
+ avoid_skills: mergeStringLists(base.avoid_skills, override.avoid_skills),
212
+ skill_rules: [...(base.skill_rules ?? []), ...(override.skill_rules ?? [])],
213
+ custom_instructions: mergeStringLists(base.custom_instructions, override.custom_instructions),
214
+ models: { ...(base.models ?? {}), ...(override.models ?? {}) },
215
+ skill_discovery: override.skill_discovery ?? base.skill_discovery,
216
+ skill_staleness_days: override.skill_staleness_days ?? base.skill_staleness_days,
217
+ auto_supervisor: { ...(base.auto_supervisor ?? {}), ...(override.auto_supervisor ?? {}) },
218
+ uat_dispatch: override.uat_dispatch ?? base.uat_dispatch,
219
+ unique_milestone_ids: override.unique_milestone_ids ?? base.unique_milestone_ids,
220
+ budget_ceiling: override.budget_ceiling ?? base.budget_ceiling,
221
+ budget_enforcement: override.budget_enforcement ?? base.budget_enforcement,
222
+ context_pause_threshold: override.context_pause_threshold ?? base.context_pause_threshold,
223
+ notifications: (base.notifications || override.notifications)
224
+ ? { ...(base.notifications ?? {}), ...(override.notifications ?? {}) }
225
+ : undefined,
226
+ remote_questions: override.remote_questions
227
+ ? { ...(base.remote_questions ?? {}), ...override.remote_questions }
228
+ : base.remote_questions,
229
+ git: (base.git || override.git)
230
+ ? { ...(base.git ?? {}), ...(override.git ?? {}) }
231
+ : undefined,
232
+ post_unit_hooks: mergePostUnitHooks(base.post_unit_hooks, override.post_unit_hooks),
233
+ pre_dispatch_hooks: mergePreDispatchHooks(base.pre_dispatch_hooks, override.pre_dispatch_hooks),
234
+ dynamic_routing: (base.dynamic_routing || override.dynamic_routing)
235
+ ? { ...(base.dynamic_routing ?? {}), ...(override.dynamic_routing ?? {}) } as DynamicRoutingConfig
236
+ : undefined,
237
+ token_profile: override.token_profile ?? base.token_profile,
238
+ phases: (base.phases || override.phases)
239
+ ? { ...(base.phases ?? {}), ...(override.phases ?? {}) }
240
+ : undefined,
241
+ parallel: (base.parallel || override.parallel)
242
+ ? { ...(base.parallel ?? {}), ...(override.parallel ?? {}) } as import("./types.js").ParallelConfig
243
+ : undefined,
244
+ verification_commands: mergeStringLists(base.verification_commands, override.verification_commands),
245
+ verification_auto_fix: override.verification_auto_fix ?? base.verification_auto_fix,
246
+ verification_max_retries: override.verification_max_retries ?? base.verification_max_retries,
247
+ search_provider: override.search_provider ?? base.search_provider,
248
+ compression_strategy: override.compression_strategy ?? base.compression_strategy,
249
+ context_selection: override.context_selection ?? base.context_selection,
250
+ };
251
+ }
374
252
 
375
- // Resolve all skill lists
376
- for (const skill of preferences.always_use_skills ?? []) resolve(skill);
377
- for (const skill of preferences.prefer_skills ?? []) resolve(skill);
378
- for (const skill of preferences.avoid_skills ?? []) resolve(skill);
253
+ function mergeStringLists(base?: unknown, override?: unknown): string[] | undefined {
254
+ const merged = [
255
+ ...normalizeStringArray(base),
256
+ ...normalizeStringArray(override),
257
+ ]
258
+ .map((item) => item.trim())
259
+ .filter(Boolean);
260
+ return merged.length > 0 ? Array.from(new Set(merged)) : undefined;
261
+ }
379
262
 
380
- // Resolve skill rules
381
- for (const rule of preferences.skill_rules ?? []) {
382
- for (const skill of rule.use ?? []) resolve(skill);
383
- for (const skill of rule.prefer ?? []) resolve(skill);
384
- for (const skill of rule.avoid ?? []) resolve(skill);
263
+ function mergePostUnitHooks(
264
+ base?: PostUnitHookConfig[],
265
+ override?: PostUnitHookConfig[],
266
+ ): PostUnitHookConfig[] | undefined {
267
+ if (!base?.length && !override?.length) return undefined;
268
+ const merged = [...(base ?? [])];
269
+ for (const hook of override ?? []) {
270
+ // Override hooks with same name replace base hooks
271
+ const idx = merged.findIndex(h => h.name === hook.name);
272
+ if (idx >= 0) {
273
+ merged[idx] = hook;
274
+ } else {
275
+ merged.push(hook);
276
+ }
385
277
  }
386
-
387
- return { resolutions, warnings };
278
+ return merged.length > 0 ? merged : undefined;
388
279
  }
389
280
 
390
- /**
391
- * Format a skill reference for the system prompt.
392
- * If resolved, shows the path so the agent knows exactly where to read.
393
- * If unresolved, marks it clearly.
394
- */
395
- function formatSkillRef(ref: string, resolutions: Map<string, SkillResolution>): string {
396
- const resolution = resolutions.get(ref);
397
- if (!resolution || resolution.method === "unresolved") {
398
- return `${ref} ( not found — check skill name or path)`;
399
- }
400
- // For absolute paths where SKILL.md is just appended, don't clutter the output
401
- if (resolution.method === "absolute-path" || resolution.method === "absolute-dir") {
402
- return ref;
281
+ function mergePreDispatchHooks(
282
+ base?: PreDispatchHookConfig[],
283
+ override?: PreDispatchHookConfig[],
284
+ ): PreDispatchHookConfig[] | undefined {
285
+ if (!base?.length && !override?.length) return undefined;
286
+ const merged = [...(base ?? [])];
287
+ for (const hook of override ?? []) {
288
+ const idx = merged.findIndex(h => h.name === hook.name);
289
+ if (idx >= 0) {
290
+ merged[idx] = hook;
291
+ } else {
292
+ merged.push(hook);
293
+ }
403
294
  }
404
- // For bare names resolved from skill directories, show the resolved path
405
- return `${ref} → \`${resolution.resolvedPath}\``;
295
+ return merged.length > 0 ? merged : undefined;
406
296
  }
407
297
 
408
298
  // ─── System Prompt Rendering ──────────────────────────────────────────────────
@@ -475,67 +365,30 @@ export function renderPreferencesForSystemPrompt(preferences: GSDPreferences, re
475
365
  return lines.join("\n");
476
366
  }
477
367
 
478
- function loadPreferencesFile(path: string, scope: "global" | "project"): LoadedGSDPreferences | null {
479
- if (!existsSync(path)) return null;
480
-
481
- const raw = readFileSync(path, "utf-8");
482
- const preferences = parsePreferencesMarkdown(raw);
483
- if (!preferences) return null;
484
-
485
- const validation = validatePreferences(preferences);
486
- const allWarnings = [...validation.warnings, ...validation.errors];
487
-
488
- return {
489
- path,
490
- scope,
491
- preferences: validation.preferences,
492
- ...(allWarnings.length > 0 ? { warnings: allWarnings } : {}),
493
- };
494
- }
495
-
496
- /** @internal Exported for testing only */
497
- export function parsePreferencesMarkdown(content: string): GSDPreferences | null {
498
- // Use indexOf instead of [\s\S]*? regex to avoid backtracking (#468)
499
- const startMarker = content.startsWith('---\r\n') ? '---\r\n' : '---\n';
500
- if (!content.startsWith(startMarker)) return null;
501
- const searchStart = startMarker.length;
502
- const endIdx = content.indexOf('\n---', searchStart);
503
- if (endIdx === -1) return null;
504
- const block = content.slice(searchStart, endIdx);
505
- return parseFrontmatterBlock(block.replace(/\r/g, ''));
506
- }
507
-
508
- function parseFrontmatterBlock(frontmatter: string): GSDPreferences {
509
- try {
510
- const parsed = parseYaml(frontmatter);
511
- if (typeof parsed !== 'object' || parsed === null) {
512
- return {} as GSDPreferences;
513
- }
514
- return parsed as GSDPreferences;
515
- } catch (e) {
516
- console.error("[parseFrontmatterBlock] YAML parse error:", e);
517
- return {} as GSDPreferences;
518
- }
519
- }
368
+ // ─── Hook Resolution ──────────────────────────────────────────────────────────
520
369
 
521
370
  /**
522
- * Resolve the skill discovery mode from effective preferences.
523
- * Defaults to "suggest" skills are identified during research but not installed automatically.
371
+ * Resolve enabled post-unit hooks from effective preferences.
372
+ * Returns an empty array when no hooks are configured.
524
373
  */
525
- export function resolveSkillDiscoveryMode(): SkillDiscoveryMode {
374
+ export function resolvePostUnitHooks(): PostUnitHookConfig[] {
526
375
  const prefs = loadEffectiveGSDPreferences();
527
- return prefs?.preferences.skill_discovery ?? "suggest";
376
+ return (prefs?.preferences.post_unit_hooks ?? [])
377
+ .filter(h => h.enabled !== false);
528
378
  }
529
379
 
530
380
  /**
531
- * Resolve the skill staleness threshold in days.
532
- * Returns 0 if disabled, default 60 if not configured.
381
+ * Resolve enabled pre-dispatch hooks from effective preferences.
382
+ * Returns an empty array when no hooks are configured.
533
383
  */
534
- export function resolveSkillStalenessDays(): number {
384
+ export function resolvePreDispatchHooks(): PreDispatchHookConfig[] {
535
385
  const prefs = loadEffectiveGSDPreferences();
536
- return prefs?.preferences.skill_staleness_days ?? 60;
386
+ return (prefs?.preferences.pre_dispatch_hooks ?? [])
387
+ .filter(h => h.enabled !== false);
537
388
  }
538
389
 
390
+ // ─── Isolation & Parallel ─────────────────────────────────────────────────────
391
+
539
392
  /**
540
393
  * Resolve the effective git isolation mode from preferences.
541
394
  * Returns "worktree" (default), "branch", or "none".
@@ -547,945 +400,6 @@ export function getIsolationMode(): "none" | "worktree" | "branch" {
547
400
  return "worktree"; // default
548
401
  }
549
402
 
550
- /**
551
- * Resolve which model ID to use for a given auto-mode unit type.
552
- * Returns undefined if no model preference is set for this unit type.
553
- */
554
- export function resolveModelForUnit(unitType: string): string | undefined {
555
- const resolved = resolveModelWithFallbacksForUnit(unitType);
556
- return resolved?.primary;
557
- }
558
-
559
- /**
560
- * Resolve model and fallbacks for a given auto-mode unit type.
561
- * Returns the primary model and ordered fallbacks, or undefined if not configured.
562
- *
563
- * Supports both legacy string format and extended object format:
564
- * - Legacy: `planning: claude-opus-4-6`
565
- * - Extended: `planning: { model: claude-opus-4-6, fallbacks: [glm-5, minimax-m2.5] }`
566
- */
567
- /**
568
- * Determines the next fallback model to try when the current model fails.
569
- * If the current model is not in the configured list, returns the primary model.
570
- * If the current model is the last in the list, returns undefined (exhausted).
571
- */
572
- export function getNextFallbackModel(
573
- currentModelId: string | undefined,
574
- modelConfig: ResolvedModelConfig,
575
- ): string | undefined {
576
- const modelsToTry = [modelConfig.primary, ...modelConfig.fallbacks];
577
-
578
- if (!currentModelId) {
579
- return modelsToTry[0];
580
- }
581
-
582
- let foundCurrent = false;
583
- for (let i = 0; i < modelsToTry.length; i++) {
584
- const mId = modelsToTry[i];
585
- // Check for exact match or provider/model suffix match
586
- if (mId === currentModelId || (mId.includes("/") && mId.endsWith(`/${currentModelId}`))) {
587
- foundCurrent = true;
588
- return modelsToTry[i + 1]; // Return the next one, or undefined if at the end
589
- }
590
- }
591
-
592
- // If the current model wasn't in our preference list, default to starting the sequence
593
- if (!foundCurrent) {
594
- return modelsToTry[0];
595
- }
596
- }
597
-
598
- /**
599
- * Detect whether an error message indicates a transient network error
600
- * (worth retrying the same model) vs a permanent provider error
601
- * (auth failure, quota exceeded, etc. — should fall back immediately).
602
- */
603
- export function isTransientNetworkError(errorMsg: string): boolean {
604
- if (!errorMsg) return false;
605
- const hasNetworkSignal = /network|ECONNRESET|ETIMEDOUT|ECONNREFUSED|socket hang up|fetch failed|connection.*reset|dns/i.test(errorMsg);
606
- const hasPermanentSignal = /auth|unauthorized|forbidden|invalid.*key|quota|billing/i.test(errorMsg);
607
- return hasNetworkSignal && !hasPermanentSignal;
608
- }
609
-
610
- export function resolveModelWithFallbacksForUnit(unitType: string): ResolvedModelConfig | undefined {
611
- const prefs = loadEffectiveGSDPreferences();
612
- if (!prefs?.preferences.models) return undefined;
613
- const m = prefs.preferences.models as GSDModelConfigV2;
614
-
615
- let phaseConfig: string | GSDPhaseModelConfig | undefined;
616
- switch (unitType) {
617
- case "research-milestone":
618
- case "research-slice":
619
- phaseConfig = m.research;
620
- break;
621
- case "plan-milestone":
622
- case "plan-slice":
623
- case "replan-slice":
624
- phaseConfig = m.planning;
625
- break;
626
- case "execute-task":
627
- phaseConfig = m.execution;
628
- break;
629
- case "execute-task-simple":
630
- phaseConfig = m.execution_simple ?? m.execution;
631
- break;
632
- case "complete-slice":
633
- case "run-uat":
634
- phaseConfig = m.completion;
635
- break;
636
- default:
637
- // Subagent unit types (e.g., "subagent", "subagent/scout")
638
- if (unitType === "subagent" || unitType.startsWith("subagent/")) {
639
- phaseConfig = m.subagent;
640
- break;
641
- }
642
- return undefined;
643
- }
644
-
645
- if (!phaseConfig) return undefined;
646
-
647
- // Normalize: string -> { model, fallbacks: [] }
648
- if (typeof phaseConfig === "string") {
649
- return { primary: phaseConfig, fallbacks: [] };
650
- }
651
-
652
- // When provider is explicitly set, prepend it to the model ID so the
653
- // resolution code in auto.ts can do an explicit provider match.
654
- const primary = phaseConfig.provider && !phaseConfig.model.includes("/")
655
- ? `${phaseConfig.provider}/${phaseConfig.model}`
656
- : phaseConfig.model;
657
-
658
- return {
659
- primary,
660
- fallbacks: phaseConfig.fallbacks ?? [],
661
- };
662
- }
663
-
664
- /**
665
- * Resolve the dynamic routing configuration from effective preferences.
666
- * Returns the merged config with defaults applied.
667
- */
668
- export function resolveDynamicRoutingConfig(): DynamicRoutingConfig {
669
- const prefs = loadEffectiveGSDPreferences();
670
- const configured = prefs?.preferences.dynamic_routing;
671
- if (!configured) return defaultRoutingConfig();
672
- return {
673
- ...defaultRoutingConfig(),
674
- ...configured,
675
- };
676
- }
677
-
678
- export function resolveAutoSupervisorConfig(): AutoSupervisorConfig {
679
- const prefs = loadEffectiveGSDPreferences();
680
- const configured = prefs?.preferences.auto_supervisor ?? {};
681
-
682
- return {
683
- soft_timeout_minutes: configured.soft_timeout_minutes ?? 20,
684
- idle_timeout_minutes: configured.idle_timeout_minutes ?? 10,
685
- hard_timeout_minutes: configured.hard_timeout_minutes ?? 30,
686
- ...(configured.model ? { model: configured.model } : {}),
687
- };
688
- }
689
-
690
- // ─── Token Profile Resolution ─────────────────────────────────────────────
691
-
692
- const VALID_TOKEN_PROFILES = new Set<TokenProfile>(["budget", "balanced", "quality"]);
693
-
694
- /**
695
- * Resolve profile defaults for a given token profile tier.
696
- * Returns a partial GSDPreferences that is used as the base layer —
697
- * explicit user preferences always override these defaults.
698
- */
699
- export function resolveProfileDefaults(profile: TokenProfile): Partial<GSDPreferences> {
700
- switch (profile) {
701
- case "budget":
702
- return {
703
- models: {
704
- planning: "claude-sonnet-4-5-20250514",
705
- execution: "claude-sonnet-4-5-20250514",
706
- execution_simple: "claude-haiku-4-5-20250414",
707
- completion: "claude-haiku-4-5-20250414",
708
- subagent: "claude-haiku-4-5-20250414",
709
- },
710
- phases: {
711
- skip_research: true,
712
- skip_reassess: true,
713
- skip_slice_research: true,
714
- skip_milestone_validation: true,
715
- },
716
- };
717
- case "balanced":
718
- return {
719
- models: {
720
- subagent: "claude-sonnet-4-5-20250514",
721
- },
722
- phases: {
723
- skip_slice_research: true,
724
- },
725
- };
726
- case "quality":
727
- return {
728
- models: {},
729
- phases: {},
730
- };
731
- }
732
- }
733
-
734
- /**
735
- * Resolve the effective token profile from preferences.
736
- * Returns "balanced" when no profile is set (D046).
737
- */
738
- export function resolveEffectiveProfile(): TokenProfile {
739
- const prefs = loadEffectiveGSDPreferences();
740
- const profile = prefs?.preferences.token_profile;
741
- if (profile && VALID_TOKEN_PROFILES.has(profile)) return profile;
742
- return "balanced";
743
- }
744
-
745
- /**
746
- * Resolve the inline level from the active token profile.
747
- * budget → minimal, balanced → standard, quality → full.
748
- */
749
- export function resolveInlineLevel(): InlineLevel {
750
- const profile = resolveEffectiveProfile();
751
- switch (profile) {
752
- case "budget": return "minimal";
753
- case "balanced": return "standard";
754
- case "quality": return "full";
755
- }
756
- }
757
-
758
- function mergePreferences(base: GSDPreferences, override: GSDPreferences): GSDPreferences {
759
- return {
760
- version: override.version ?? base.version,
761
- mode: override.mode ?? base.mode,
762
- always_use_skills: mergeStringLists(base.always_use_skills, override.always_use_skills),
763
- prefer_skills: mergeStringLists(base.prefer_skills, override.prefer_skills),
764
- avoid_skills: mergeStringLists(base.avoid_skills, override.avoid_skills),
765
- skill_rules: [...(base.skill_rules ?? []), ...(override.skill_rules ?? [])],
766
- custom_instructions: mergeStringLists(base.custom_instructions, override.custom_instructions),
767
- models: { ...(base.models ?? {}), ...(override.models ?? {}) },
768
- skill_discovery: override.skill_discovery ?? base.skill_discovery,
769
- skill_staleness_days: override.skill_staleness_days ?? base.skill_staleness_days,
770
- auto_supervisor: { ...(base.auto_supervisor ?? {}), ...(override.auto_supervisor ?? {}) },
771
- uat_dispatch: override.uat_dispatch ?? base.uat_dispatch,
772
- unique_milestone_ids: override.unique_milestone_ids ?? base.unique_milestone_ids,
773
- budget_ceiling: override.budget_ceiling ?? base.budget_ceiling,
774
- budget_enforcement: override.budget_enforcement ?? base.budget_enforcement,
775
- context_pause_threshold: override.context_pause_threshold ?? base.context_pause_threshold,
776
- notifications: (base.notifications || override.notifications)
777
- ? { ...(base.notifications ?? {}), ...(override.notifications ?? {}) }
778
- : undefined,
779
- remote_questions: override.remote_questions
780
- ? { ...(base.remote_questions ?? {}), ...override.remote_questions }
781
- : base.remote_questions,
782
- git: (base.git || override.git)
783
- ? { ...(base.git ?? {}), ...(override.git ?? {}) }
784
- : undefined,
785
- post_unit_hooks: mergePostUnitHooks(base.post_unit_hooks, override.post_unit_hooks),
786
- pre_dispatch_hooks: mergePreDispatchHooks(base.pre_dispatch_hooks, override.pre_dispatch_hooks),
787
- dynamic_routing: (base.dynamic_routing || override.dynamic_routing)
788
- ? { ...(base.dynamic_routing ?? {}), ...(override.dynamic_routing ?? {}) } as DynamicRoutingConfig
789
- : undefined,
790
- token_profile: override.token_profile ?? base.token_profile,
791
- phases: (base.phases || override.phases)
792
- ? { ...(base.phases ?? {}), ...(override.phases ?? {}) }
793
- : undefined,
794
- parallel: (base.parallel || override.parallel)
795
- ? { ...(base.parallel ?? {}), ...(override.parallel ?? {}) } as import("./types.js").ParallelConfig
796
- : undefined,
797
- verification_commands: mergeStringLists(base.verification_commands, override.verification_commands),
798
- verification_auto_fix: override.verification_auto_fix ?? base.verification_auto_fix,
799
- verification_max_retries: override.verification_max_retries ?? base.verification_max_retries,
800
- };
801
- }
802
-
803
- export function validatePreferences(preferences: GSDPreferences): {
804
- preferences: GSDPreferences;
805
- errors: string[];
806
- warnings: string[];
807
- } {
808
- const errors: string[] = [];
809
- const warnings: string[] = [];
810
- const validated: GSDPreferences = {};
811
-
812
- // ─── Unknown Key Detection ──────────────────────────────────────────
813
- for (const key of Object.keys(preferences)) {
814
- if (!KNOWN_PREFERENCE_KEYS.has(key)) {
815
- warnings.push(`unknown preference key "${key}" — ignored`);
816
- }
817
- }
818
-
819
- if (preferences.version !== undefined) {
820
- if (preferences.version === 1) {
821
- validated.version = 1;
822
- } else {
823
- errors.push(`unsupported version ${preferences.version}`);
824
- }
825
- }
826
-
827
- // ─── Workflow Mode ──────────────────────────────────────────────────
828
- if (preferences.mode !== undefined) {
829
- const validModes = new Set<string>(["solo", "team"]);
830
- if (typeof preferences.mode === "string" && validModes.has(preferences.mode)) {
831
- validated.mode = preferences.mode as WorkflowMode;
832
- } else {
833
- errors.push(`invalid mode "${preferences.mode}" — must be one of: solo, team`);
834
- }
835
- }
836
-
837
- const validDiscoveryModes = new Set(["auto", "suggest", "off"]);
838
- if (preferences.skill_discovery) {
839
- if (validDiscoveryModes.has(preferences.skill_discovery)) {
840
- validated.skill_discovery = preferences.skill_discovery;
841
- } else {
842
- errors.push(`invalid skill_discovery value: ${preferences.skill_discovery}`);
843
- }
844
- }
845
-
846
- if (preferences.skill_staleness_days !== undefined) {
847
- const days = Number(preferences.skill_staleness_days);
848
- if (Number.isFinite(days) && days >= 0) {
849
- validated.skill_staleness_days = Math.floor(days);
850
- } else {
851
- errors.push(`invalid skill_staleness_days: must be a non-negative number`);
852
- }
853
- }
854
-
855
- validated.always_use_skills = normalizeStringList(preferences.always_use_skills);
856
- validated.prefer_skills = normalizeStringList(preferences.prefer_skills);
857
- validated.avoid_skills = normalizeStringList(preferences.avoid_skills);
858
- validated.custom_instructions = normalizeStringList(preferences.custom_instructions);
859
-
860
- if (preferences.skill_rules) {
861
- const validRules: GSDSkillRule[] = [];
862
- for (const rule of preferences.skill_rules) {
863
- if (!rule || typeof rule !== "object") {
864
- errors.push("invalid skill_rules entry");
865
- continue;
866
- }
867
- const when = typeof rule.when === "string" ? rule.when.trim() : "";
868
- if (!when) {
869
- errors.push("skill_rules entry missing when");
870
- continue;
871
- }
872
- const validatedRule: GSDSkillRule = { when };
873
- for (const action of SKILL_ACTIONS) {
874
- const values = normalizeStringList((rule as unknown as Record<string, unknown>)[action]);
875
- if (values.length > 0) {
876
- validatedRule[action as keyof GSDSkillRule] = values as never;
877
- }
878
- }
879
- if (!validatedRule.use && !validatedRule.prefer && !validatedRule.avoid) {
880
- errors.push(`skill rule has no actions: ${when}`);
881
- continue;
882
- }
883
- validRules.push(validatedRule);
884
- }
885
- if (validRules.length > 0) {
886
- validated.skill_rules = validRules;
887
- }
888
- }
889
-
890
- for (const key of ["always_use_skills", "prefer_skills", "avoid_skills", "custom_instructions"] as const) {
891
- if (validated[key] && validated[key]!.length === 0) {
892
- delete validated[key];
893
- }
894
- }
895
-
896
- if (preferences.uat_dispatch !== undefined) {
897
- validated.uat_dispatch = !!preferences.uat_dispatch;
898
- }
899
-
900
- if (preferences.unique_milestone_ids !== undefined) {
901
- validated.unique_milestone_ids = !!preferences.unique_milestone_ids;
902
- }
903
-
904
- if (preferences.budget_ceiling !== undefined) {
905
- const raw = preferences.budget_ceiling;
906
- if (typeof raw === "number" && Number.isFinite(raw)) {
907
- validated.budget_ceiling = raw;
908
- } else if (typeof raw === "string" && Number.isFinite(Number(raw))) {
909
- validated.budget_ceiling = Number(raw);
910
- } else {
911
- errors.push("budget_ceiling must be a finite number");
912
- }
913
- }
914
-
915
- // ─── Budget Enforcement ──────────────────────────────────────────────
916
- if (preferences.budget_enforcement !== undefined) {
917
- const validModes = new Set(["warn", "pause", "halt"]);
918
- if (typeof preferences.budget_enforcement === "string" && validModes.has(preferences.budget_enforcement)) {
919
- validated.budget_enforcement = preferences.budget_enforcement;
920
- } else {
921
- errors.push(`budget_enforcement must be one of: warn, pause, halt`);
922
- }
923
- }
924
-
925
- // ─── Token Profile ─────────────────────────────────────────────────
926
- if (preferences.token_profile !== undefined) {
927
- if (typeof preferences.token_profile === "string" && VALID_TOKEN_PROFILES.has(preferences.token_profile as TokenProfile)) {
928
- validated.token_profile = preferences.token_profile as TokenProfile;
929
- } else {
930
- errors.push(`token_profile must be one of: budget, balanced, quality`);
931
- }
932
- }
933
-
934
- // ─── Phase Skip Preferences ─────────────────────────────────────────
935
- if (preferences.phases !== undefined) {
936
- if (typeof preferences.phases === "object" && preferences.phases !== null) {
937
- const validatedPhases: PhaseSkipPreferences = {};
938
- const p = preferences.phases as Record<string, unknown>;
939
- if (p.skip_research !== undefined) validatedPhases.skip_research = !!p.skip_research;
940
- if (p.skip_reassess !== undefined) validatedPhases.skip_reassess = !!p.skip_reassess;
941
- if (p.skip_slice_research !== undefined) validatedPhases.skip_slice_research = !!p.skip_slice_research;
942
- if (p.skip_milestone_validation !== undefined) validatedPhases.skip_milestone_validation = !!p.skip_milestone_validation;
943
- if ((p as any).require_slice_discussion !== undefined) (validatedPhases as any).require_slice_discussion = !!(p as any).require_slice_discussion;
944
- // Warn on unknown phase keys
945
- const knownPhaseKeys = new Set(["skip_research", "skip_reassess", "skip_slice_research", "skip_milestone_validation", "require_slice_discussion"]);
946
- for (const key of Object.keys(p)) {
947
- if (!knownPhaseKeys.has(key)) {
948
- warnings.push(`unknown phases key "${key}" — ignored`);
949
- }
950
- }
951
- validated.phases = validatedPhases;
952
- } else {
953
- errors.push(`phases must be an object`);
954
- }
955
- }
956
-
957
- // ─── Context Pause Threshold ────────────────────────────────────────
958
- if (preferences.context_pause_threshold !== undefined) {
959
- const raw = preferences.context_pause_threshold;
960
- if (typeof raw === "number" && Number.isFinite(raw)) {
961
- validated.context_pause_threshold = raw;
962
- } else if (typeof raw === "string" && Number.isFinite(Number(raw))) {
963
- validated.context_pause_threshold = Number(raw);
964
- } else {
965
- errors.push("context_pause_threshold must be a finite number");
966
- }
967
- }
968
-
969
- // ─── Models ─────────────────────────────────────────────────────────
970
- if (preferences.models !== undefined) {
971
- if (preferences.models && typeof preferences.models === "object") {
972
- validated.models = preferences.models;
973
- } else {
974
- errors.push("models must be an object");
975
- }
976
- }
977
-
978
- // ─── Auto Supervisor ────────────────────────────────────────────────
979
- if (preferences.auto_supervisor !== undefined) {
980
- if (preferences.auto_supervisor && typeof preferences.auto_supervisor === "object") {
981
- validated.auto_supervisor = preferences.auto_supervisor;
982
- } else {
983
- errors.push("auto_supervisor must be an object");
984
- }
985
- }
986
-
987
- // ─── Notifications ──────────────────────────────────────────────────
988
- if (preferences.notifications !== undefined) {
989
- if (preferences.notifications && typeof preferences.notifications === "object") {
990
- validated.notifications = preferences.notifications;
991
- } else {
992
- errors.push("notifications must be an object");
993
- }
994
- }
995
-
996
- // ─── Remote Questions ───────────────────────────────────────────────
997
- if (preferences.remote_questions !== undefined) {
998
- if (preferences.remote_questions && typeof preferences.remote_questions === "object") {
999
- validated.remote_questions = preferences.remote_questions;
1000
- } else {
1001
- errors.push("remote_questions must be an object");
1002
- }
1003
- }
1004
-
1005
- // ─── Post-Unit Hooks ─────────────────────────────────────────────────
1006
- if (preferences.post_unit_hooks && Array.isArray(preferences.post_unit_hooks)) {
1007
- const validHooks: PostUnitHookConfig[] = [];
1008
- const seenNames = new Set<string>();
1009
- const knownUnitTypes = new Set([
1010
- "research-milestone", "plan-milestone", "research-slice", "plan-slice",
1011
- "execute-task", "complete-slice", "replan-slice", "reassess-roadmap",
1012
- "run-uat", "complete-milestone",
1013
- ]);
1014
- for (const hook of preferences.post_unit_hooks) {
1015
- if (!hook || typeof hook !== "object") {
1016
- errors.push("post_unit_hooks entry must be an object");
1017
- continue;
1018
- }
1019
- const name = typeof hook.name === "string" ? hook.name.trim() : "";
1020
- if (!name) {
1021
- errors.push("post_unit_hooks entry missing name");
1022
- continue;
1023
- }
1024
- if (seenNames.has(name)) {
1025
- errors.push(`duplicate post_unit_hooks name: ${name}`);
1026
- continue;
1027
- }
1028
- const after = normalizeStringList(hook.after);
1029
- if (after.length === 0) {
1030
- errors.push(`post_unit_hooks "${name}" missing after`);
1031
- continue;
1032
- }
1033
- for (const ut of after) {
1034
- if (!knownUnitTypes.has(ut)) {
1035
- errors.push(`post_unit_hooks "${name}" unknown unit type in after: ${ut}`);
1036
- }
1037
- }
1038
- const prompt = typeof hook.prompt === "string" ? hook.prompt.trim() : "";
1039
- if (!prompt) {
1040
- errors.push(`post_unit_hooks "${name}" missing prompt`);
1041
- continue;
1042
- }
1043
- const validHook: PostUnitHookConfig = { name, after, prompt };
1044
- if (hook.max_cycles !== undefined) {
1045
- const mc = typeof hook.max_cycles === "number" ? hook.max_cycles : Number(hook.max_cycles);
1046
- validHook.max_cycles = Number.isFinite(mc) ? Math.max(1, Math.min(10, Math.round(mc))) : 1;
1047
- }
1048
- if (typeof hook.model === "string" && hook.model.trim()) {
1049
- validHook.model = hook.model.trim();
1050
- }
1051
- if (typeof hook.artifact === "string" && hook.artifact.trim()) {
1052
- validHook.artifact = hook.artifact.trim();
1053
- }
1054
- if (typeof hook.retry_on === "string" && hook.retry_on.trim()) {
1055
- validHook.retry_on = hook.retry_on.trim();
1056
- }
1057
- if (typeof hook.agent === "string" && hook.agent.trim()) {
1058
- validHook.agent = hook.agent.trim();
1059
- }
1060
- if (hook.enabled !== undefined) {
1061
- validHook.enabled = !!hook.enabled;
1062
- }
1063
- seenNames.add(name);
1064
- validHooks.push(validHook);
1065
- }
1066
- if (validHooks.length > 0) {
1067
- validated.post_unit_hooks = validHooks;
1068
- }
1069
- }
1070
-
1071
- // ─── Pre-Dispatch Hooks ─────────────────────────────────────────────────
1072
- if (preferences.pre_dispatch_hooks && Array.isArray(preferences.pre_dispatch_hooks)) {
1073
- const validPreHooks: PreDispatchHookConfig[] = [];
1074
- const seenPreNames = new Set<string>();
1075
- const knownUnitTypes = new Set([
1076
- "research-milestone", "plan-milestone", "research-slice", "plan-slice",
1077
- "execute-task", "complete-slice", "replan-slice", "reassess-roadmap",
1078
- "run-uat", "complete-milestone",
1079
- ]);
1080
- const validActions = new Set(["modify", "skip", "replace"]);
1081
- for (const hook of preferences.pre_dispatch_hooks) {
1082
- if (!hook || typeof hook !== "object") {
1083
- errors.push("pre_dispatch_hooks entry must be an object");
1084
- continue;
1085
- }
1086
- const name = typeof hook.name === "string" ? hook.name.trim() : "";
1087
- if (!name) {
1088
- errors.push("pre_dispatch_hooks entry missing name");
1089
- continue;
1090
- }
1091
- if (seenPreNames.has(name)) {
1092
- errors.push(`duplicate pre_dispatch_hooks name: ${name}`);
1093
- continue;
1094
- }
1095
- const before = normalizeStringList(hook.before);
1096
- if (before.length === 0) {
1097
- errors.push(`pre_dispatch_hooks "${name}" missing before`);
1098
- continue;
1099
- }
1100
- for (const ut of before) {
1101
- if (!knownUnitTypes.has(ut)) {
1102
- errors.push(`pre_dispatch_hooks "${name}" unknown unit type in before: ${ut}`);
1103
- }
1104
- }
1105
- const action = typeof hook.action === "string" ? hook.action.trim() : "";
1106
- if (!validActions.has(action)) {
1107
- errors.push(`pre_dispatch_hooks "${name}" invalid action: ${action} (must be modify, skip, or replace)`);
1108
- continue;
1109
- }
1110
- const validHook: PreDispatchHookConfig = { name, before, action: action as PreDispatchHookConfig["action"] };
1111
- if (typeof hook.prepend === "string" && hook.prepend.trim()) validHook.prepend = hook.prepend.trim();
1112
- if (typeof hook.append === "string" && hook.append.trim()) validHook.append = hook.append.trim();
1113
- if (typeof hook.prompt === "string" && hook.prompt.trim()) validHook.prompt = hook.prompt.trim();
1114
- if (typeof hook.unit_type === "string" && hook.unit_type.trim()) validHook.unit_type = hook.unit_type.trim();
1115
- if (typeof hook.skip_if === "string" && hook.skip_if.trim()) validHook.skip_if = hook.skip_if.trim();
1116
- if (typeof hook.model === "string" && hook.model.trim()) validHook.model = hook.model.trim();
1117
- if (hook.enabled !== undefined) validHook.enabled = !!hook.enabled;
1118
-
1119
- // Validation: action-specific required fields
1120
- if (action === "replace" && !validHook.prompt) {
1121
- errors.push(`pre_dispatch_hooks "${name}" action "replace" requires prompt`);
1122
- continue;
1123
- }
1124
- if (action === "modify" && !validHook.prepend && !validHook.append) {
1125
- errors.push(`pre_dispatch_hooks "${name}" action "modify" requires prepend or append`);
1126
- continue;
1127
- }
1128
-
1129
- seenPreNames.add(name);
1130
- validPreHooks.push(validHook);
1131
- }
1132
- if (validPreHooks.length > 0) {
1133
- validated.pre_dispatch_hooks = validPreHooks;
1134
- }
1135
- }
1136
-
1137
- // ─── Dynamic Routing ─────────────────────────────────────────────────
1138
- if (preferences.dynamic_routing !== undefined) {
1139
- if (typeof preferences.dynamic_routing === "object" && preferences.dynamic_routing !== null) {
1140
- const dr = preferences.dynamic_routing as unknown as Record<string, unknown>;
1141
- const validDr: Partial<DynamicRoutingConfig> = {};
1142
-
1143
- if (dr.enabled !== undefined) {
1144
- if (typeof dr.enabled === "boolean") validDr.enabled = dr.enabled;
1145
- else errors.push("dynamic_routing.enabled must be a boolean");
1146
- }
1147
- if (dr.escalate_on_failure !== undefined) {
1148
- if (typeof dr.escalate_on_failure === "boolean") validDr.escalate_on_failure = dr.escalate_on_failure;
1149
- else errors.push("dynamic_routing.escalate_on_failure must be a boolean");
1150
- }
1151
- if (dr.budget_pressure !== undefined) {
1152
- if (typeof dr.budget_pressure === "boolean") validDr.budget_pressure = dr.budget_pressure;
1153
- else errors.push("dynamic_routing.budget_pressure must be a boolean");
1154
- }
1155
- if (dr.cross_provider !== undefined) {
1156
- if (typeof dr.cross_provider === "boolean") validDr.cross_provider = dr.cross_provider;
1157
- else errors.push("dynamic_routing.cross_provider must be a boolean");
1158
- }
1159
- if (dr.hooks !== undefined) {
1160
- if (typeof dr.hooks === "boolean") validDr.hooks = dr.hooks;
1161
- else errors.push("dynamic_routing.hooks must be a boolean");
1162
- }
1163
- if (dr.tier_models !== undefined) {
1164
- if (typeof dr.tier_models === "object" && dr.tier_models !== null) {
1165
- const tm = dr.tier_models as Record<string, unknown>;
1166
- const validTm: Record<string, string> = {};
1167
- for (const tier of ["light", "standard", "heavy"]) {
1168
- if (tm[tier] !== undefined) {
1169
- if (typeof tm[tier] === "string") validTm[tier] = tm[tier] as string;
1170
- else errors.push(`dynamic_routing.tier_models.${tier} must be a string`);
1171
- }
1172
- }
1173
- if (Object.keys(validTm).length > 0) validDr.tier_models = validTm as DynamicRoutingConfig["tier_models"];
1174
- } else {
1175
- errors.push("dynamic_routing.tier_models must be an object");
1176
- }
1177
- }
1178
-
1179
- if (Object.keys(validDr).length > 0) {
1180
- validated.dynamic_routing = validDr as unknown as DynamicRoutingConfig;
1181
- }
1182
- } else {
1183
- errors.push("dynamic_routing must be an object");
1184
- }
1185
- }
1186
-
1187
- // ─── Parallel Config ────────────────────────────────────────────────────
1188
- if (preferences.parallel && typeof preferences.parallel === "object") {
1189
- const p = preferences.parallel as unknown as Record<string, unknown>;
1190
- const parallel: Record<string, unknown> = {};
1191
-
1192
- if (p.enabled !== undefined) {
1193
- if (typeof p.enabled === "boolean") parallel.enabled = p.enabled;
1194
- else errors.push("parallel.enabled must be a boolean");
1195
- }
1196
- if (p.max_workers !== undefined) {
1197
- if (typeof p.max_workers === "number" && p.max_workers >= 1 && p.max_workers <= 4) {
1198
- parallel.max_workers = Math.floor(p.max_workers);
1199
- } else {
1200
- errors.push("parallel.max_workers must be a number between 1 and 4");
1201
- }
1202
- }
1203
- if (p.budget_ceiling !== undefined) {
1204
- if (typeof p.budget_ceiling === "number" && p.budget_ceiling > 0) {
1205
- parallel.budget_ceiling = p.budget_ceiling;
1206
- } else {
1207
- errors.push("parallel.budget_ceiling must be a positive number");
1208
- }
1209
- }
1210
- if (p.merge_strategy !== undefined) {
1211
- const validStrategies = new Set(["per-slice", "per-milestone"]);
1212
- if (typeof p.merge_strategy === "string" && validStrategies.has(p.merge_strategy)) {
1213
- parallel.merge_strategy = p.merge_strategy;
1214
- } else {
1215
- errors.push("parallel.merge_strategy must be one of: per-slice, per-milestone");
1216
- }
1217
- }
1218
- if (p.auto_merge !== undefined) {
1219
- const validModes = new Set(["auto", "confirm", "manual"]);
1220
- if (typeof p.auto_merge === "string" && validModes.has(p.auto_merge)) {
1221
- parallel.auto_merge = p.auto_merge;
1222
- } else {
1223
- errors.push("parallel.auto_merge must be one of: auto, confirm, manual");
1224
- }
1225
- }
1226
-
1227
- if (Object.keys(parallel).length > 0) {
1228
- validated.parallel = parallel as unknown as import("./types.js").ParallelConfig;
1229
- }
1230
- }
1231
-
1232
- // ─── Verification Preferences ───────────────────────────────────────────
1233
- if (preferences.verification_commands !== undefined) {
1234
- if (Array.isArray(preferences.verification_commands)) {
1235
- const allStrings = preferences.verification_commands.every(
1236
- (item: unknown) => typeof item === "string",
1237
- );
1238
- if (allStrings) {
1239
- validated.verification_commands = preferences.verification_commands;
1240
- } else {
1241
- errors.push("verification_commands must be an array of strings");
1242
- }
1243
- } else {
1244
- errors.push("verification_commands must be an array of strings");
1245
- }
1246
- }
1247
-
1248
- if (preferences.verification_auto_fix !== undefined) {
1249
- if (typeof preferences.verification_auto_fix === "boolean") {
1250
- validated.verification_auto_fix = preferences.verification_auto_fix;
1251
- } else {
1252
- errors.push("verification_auto_fix must be a boolean");
1253
- }
1254
- }
1255
-
1256
- if (preferences.verification_max_retries !== undefined) {
1257
- const raw = preferences.verification_max_retries;
1258
- if (typeof raw === "number" && Number.isFinite(raw) && raw >= 0) {
1259
- validated.verification_max_retries = Math.floor(raw);
1260
- } else {
1261
- errors.push("verification_max_retries must be a non-negative number");
1262
- }
1263
- }
1264
-
1265
- // ─── Git Preferences ───────────────────────────────────────────────────
1266
- if (preferences.git && typeof preferences.git === "object") {
1267
- const git: Record<string, unknown> = {};
1268
- const g = preferences.git as Record<string, unknown>;
1269
-
1270
- if (g.auto_push !== undefined) {
1271
- if (typeof g.auto_push === "boolean") git.auto_push = g.auto_push;
1272
- else errors.push("git.auto_push must be a boolean");
1273
- }
1274
- if (g.push_branches !== undefined) {
1275
- if (typeof g.push_branches === "boolean") git.push_branches = g.push_branches;
1276
- else errors.push("git.push_branches must be a boolean");
1277
- }
1278
- if (g.remote !== undefined) {
1279
- if (typeof g.remote === "string" && g.remote.trim() !== "") git.remote = g.remote.trim();
1280
- else errors.push("git.remote must be a non-empty string");
1281
- }
1282
- if (g.snapshots !== undefined) {
1283
- if (typeof g.snapshots === "boolean") git.snapshots = g.snapshots;
1284
- else errors.push("git.snapshots must be a boolean");
1285
- }
1286
- if (g.pre_merge_check !== undefined) {
1287
- if (typeof g.pre_merge_check === "boolean") {
1288
- git.pre_merge_check = g.pre_merge_check;
1289
- } else if (typeof g.pre_merge_check === "string" && g.pre_merge_check.trim() !== "") {
1290
- git.pre_merge_check = g.pre_merge_check.trim();
1291
- } else {
1292
- errors.push("git.pre_merge_check must be a boolean or a non-empty string command");
1293
- }
1294
- }
1295
- if (g.commit_type !== undefined) {
1296
- const validCommitTypes = new Set([
1297
- "feat", "fix", "refactor", "docs", "test", "chore", "perf", "ci", "build", "style",
1298
- ]);
1299
- if (typeof g.commit_type === "string" && validCommitTypes.has(g.commit_type)) {
1300
- git.commit_type = g.commit_type;
1301
- } else {
1302
- errors.push(`git.commit_type must be one of: feat, fix, refactor, docs, test, chore, perf, ci, build, style`);
1303
- }
1304
- }
1305
- if (g.merge_strategy !== undefined) {
1306
- const validStrategies = new Set(["squash", "merge"]);
1307
- if (typeof g.merge_strategy === "string" && validStrategies.has(g.merge_strategy)) {
1308
- git.merge_strategy = g.merge_strategy as "squash" | "merge";
1309
- } else {
1310
- errors.push("git.merge_strategy must be one of: squash, merge");
1311
- }
1312
- }
1313
- if (g.main_branch !== undefined) {
1314
- if (typeof g.main_branch === "string" && g.main_branch.trim() !== "" && VALID_BRANCH_NAME.test(g.main_branch)) {
1315
- git.main_branch = g.main_branch;
1316
- } else {
1317
- errors.push("git.main_branch must be a valid branch name (alphanumeric, _, -, /, .)");
1318
- }
1319
- }
1320
- if (g.isolation !== undefined) {
1321
- const validIsolation = new Set(["worktree", "branch", "none"]);
1322
- if (typeof g.isolation === "string" && validIsolation.has(g.isolation)) {
1323
- git.isolation = g.isolation as "worktree" | "branch" | "none";
1324
- } else {
1325
- errors.push("git.isolation must be one of: worktree, branch, none");
1326
- }
1327
- }
1328
- if (g.commit_docs !== undefined) {
1329
- if (typeof g.commit_docs === "boolean") git.commit_docs = g.commit_docs;
1330
- else errors.push("git.commit_docs must be a boolean");
1331
- }
1332
- if (g.manage_gitignore !== undefined) {
1333
- if (typeof g.manage_gitignore === "boolean") git.manage_gitignore = g.manage_gitignore;
1334
- else errors.push("git.manage_gitignore must be a boolean");
1335
- }
1336
- if (g.worktree_post_create !== undefined) {
1337
- if (typeof g.worktree_post_create === "string" && g.worktree_post_create.trim()) {
1338
- git.worktree_post_create = g.worktree_post_create.trim();
1339
- } else {
1340
- errors.push("git.worktree_post_create must be a non-empty string (path to script)");
1341
- }
1342
- }
1343
- // Deprecated: merge_to_main is ignored (branchless architecture).
1344
- if (g.merge_to_main !== undefined) {
1345
- warnings.push("git.merge_to_main is deprecated — milestone-level merge is now always used. Remove this setting.");
1346
- }
1347
-
1348
- if (Object.keys(git).length > 0) {
1349
- validated.git = git as GitPreferences;
1350
- }
1351
- }
1352
-
1353
- return { preferences: validated, errors, warnings };
1354
- }
1355
-
1356
- function mergeStringLists(base?: unknown, override?: unknown): string[] | undefined {
1357
- const merged = [
1358
- ...normalizeStringList(base),
1359
- ...normalizeStringList(override),
1360
- ]
1361
- .map((item) => item.trim())
1362
- .filter(Boolean);
1363
- return merged.length > 0 ? Array.from(new Set(merged)) : undefined;
1364
- }
1365
-
1366
- function normalizeStringList(value: unknown): string[] {
1367
- if (!Array.isArray(value)) return [];
1368
- return value
1369
- .filter((item): item is string => typeof item === "string")
1370
- .map((item) => item.trim())
1371
- .filter(Boolean);
1372
- }
1373
-
1374
- function mergePostUnitHooks(
1375
- base?: PostUnitHookConfig[],
1376
- override?: PostUnitHookConfig[],
1377
- ): PostUnitHookConfig[] | undefined {
1378
- if (!base?.length && !override?.length) return undefined;
1379
- const merged = [...(base ?? [])];
1380
- for (const hook of override ?? []) {
1381
- // Override hooks with same name replace base hooks
1382
- const idx = merged.findIndex(h => h.name === hook.name);
1383
- if (idx >= 0) {
1384
- merged[idx] = hook;
1385
- } else {
1386
- merged.push(hook);
1387
- }
1388
- }
1389
- return merged.length > 0 ? merged : undefined;
1390
- }
1391
-
1392
- /**
1393
- * Resolve enabled post-unit hooks from effective preferences.
1394
- * Returns an empty array when no hooks are configured.
1395
- */
1396
- export function resolvePostUnitHooks(): PostUnitHookConfig[] {
1397
- const prefs = loadEffectiveGSDPreferences();
1398
- return (prefs?.preferences.post_unit_hooks ?? [])
1399
- .filter(h => h.enabled !== false);
1400
- }
1401
-
1402
- function mergePreDispatchHooks(
1403
- base?: PreDispatchHookConfig[],
1404
- override?: PreDispatchHookConfig[],
1405
- ): PreDispatchHookConfig[] | undefined {
1406
- if (!base?.length && !override?.length) return undefined;
1407
- const merged = [...(base ?? [])];
1408
- for (const hook of override ?? []) {
1409
- const idx = merged.findIndex(h => h.name === hook.name);
1410
- if (idx >= 0) {
1411
- merged[idx] = hook;
1412
- } else {
1413
- merged.push(hook);
1414
- }
1415
- }
1416
- return merged.length > 0 ? merged : undefined;
1417
- }
1418
-
1419
- /**
1420
- * Resolve enabled pre-dispatch hooks from effective preferences.
1421
- * Returns an empty array when no hooks are configured.
1422
- */
1423
- export function resolvePreDispatchHooks(): PreDispatchHookConfig[] {
1424
- const prefs = loadEffectiveGSDPreferences();
1425
- return (prefs?.preferences.pre_dispatch_hooks ?? [])
1426
- .filter(h => h.enabled !== false);
1427
- }
1428
-
1429
- /**
1430
- * Validate a model ID string.
1431
- * Returns true if the ID looks like a valid model identifier.
1432
- */
1433
- export function validateModelId(modelId: string): boolean {
1434
- if (!modelId || typeof modelId !== "string") return false;
1435
- const trimmed = modelId.trim();
1436
- if (trimmed.length === 0 || trimmed.length > 256) return false;
1437
- // Allow alphanumeric, hyphens, underscores, dots, slashes, colons
1438
- return /^[a-zA-Z0-9\-_./:]+$/.test(trimmed);
1439
- }
1440
-
1441
- /**
1442
- * Update the models section of the global GSD preferences file.
1443
- * Performs a safe read-modify-write: reads current content, updates the models
1444
- * YAML block, and writes back. Creates the file if it doesn't exist.
1445
- */
1446
- export function updatePreferencesModels(models: GSDModelConfigV2): void {
1447
- const prefsPath = getGlobalGSDPreferencesPath();
1448
-
1449
- let content = "";
1450
- if (existsSync(prefsPath)) {
1451
- content = readFileSync(prefsPath, "utf-8");
1452
- }
1453
-
1454
- // Build the new models block
1455
- const lines: string[] = ["models:"];
1456
- for (const [phase, value] of Object.entries(models)) {
1457
- if (typeof value === "string") {
1458
- lines.push(` ${phase}: ${value}`);
1459
- } else if (value && typeof value === "object") {
1460
- const config = value as GSDPhaseModelConfig;
1461
- lines.push(` ${phase}:`);
1462
- lines.push(` model: ${config.model}`);
1463
- if (config.provider) {
1464
- lines.push(` provider: ${config.provider}`);
1465
- }
1466
- if (config.fallbacks && config.fallbacks.length > 0) {
1467
- lines.push(` fallbacks:`);
1468
- for (const fb of config.fallbacks) {
1469
- lines.push(` - ${fb}`);
1470
- }
1471
- }
1472
- }
1473
- }
1474
- const modelsBlock = lines.join("\n");
1475
-
1476
- // Replace existing models block or append
1477
- const modelsRegex = /^models:[\s\S]*?(?=\n[a-z_]|\n*$)/m;
1478
- if (modelsRegex.test(content)) {
1479
- content = content.replace(modelsRegex, modelsBlock);
1480
- } else {
1481
- content = content.trimEnd() + "\n\n" + modelsBlock + "\n";
1482
- }
1483
-
1484
- writeFileSync(prefsPath, content, "utf-8");
1485
- }
1486
-
1487
- // ─── Parallel Config Resolver ──────────────────────────────────────────────
1488
-
1489
403
  export function resolveParallelConfig(prefs: GSDPreferences | undefined): import("./types.js").ParallelConfig {
1490
404
  return {
1491
405
  enabled: prefs?.parallel?.enabled ?? false,