gsd-pi 2.26.1-next.1 → 2.28.0-dev.346ee62

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