aiwcli 0.15.5 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (435) hide show
  1. package/README.md +108 -1124
  2. package/bin/run.js +0 -4
  3. package/dist/capabilities/branch/adapters.d.ts +2 -0
  4. package/dist/capabilities/branch/adapters.js +21 -0
  5. package/dist/capabilities/branch/contracts.d.ts +57 -0
  6. package/dist/capabilities/branch/contracts.js +1 -0
  7. package/dist/capabilities/branch/control-plane.d.ts +2 -0
  8. package/dist/capabilities/branch/control-plane.js +343 -0
  9. package/dist/capabilities/branch/runtime-core.d.ts +5 -0
  10. package/dist/capabilities/branch/runtime-core.js +36 -0
  11. package/dist/capabilities/installation/control-plane/clean-command.d.ts +41 -0
  12. package/dist/capabilities/installation/control-plane/clean-command.js +196 -0
  13. package/dist/capabilities/installation/control-plane/clear-command.d.ts +162 -0
  14. package/dist/capabilities/installation/control-plane/clear-command.js +1249 -0
  15. package/dist/capabilities/installation/control-plane/init-command.d.ts +81 -0
  16. package/dist/capabilities/installation/control-plane/init-command.js +449 -0
  17. package/dist/capabilities/launch/contracts.d.ts +86 -0
  18. package/dist/capabilities/launch/contracts.js +1 -0
  19. package/dist/capabilities/launch/control-plane/execute-launch.d.ts +2 -0
  20. package/dist/capabilities/launch/control-plane/execute-launch.js +261 -0
  21. package/dist/capabilities/launch/runtime-core/launch-decisions.d.ts +82 -0
  22. package/dist/capabilities/launch/runtime-core/launch-decisions.js +202 -0
  23. package/dist/capabilities/launch/runtime-core/launch-options.d.ts +14 -0
  24. package/dist/capabilities/launch/runtime-core/launch-options.js +69 -0
  25. package/dist/cli/base-command.d.ts +18 -0
  26. package/dist/cli/base-command.js +55 -0
  27. package/dist/commands/branch.d.ts +1 -21
  28. package/dist/commands/branch.js +25 -417
  29. package/dist/commands/clean.d.ts +1 -41
  30. package/dist/commands/clean.js +1 -196
  31. package/dist/commands/clear.d.ts +1 -161
  32. package/dist/commands/clear.js +1 -1121
  33. package/dist/commands/init/index.d.ts +1 -98
  34. package/dist/commands/init/index.js +4 -478
  35. package/dist/commands/launch.d.ts +32 -12
  36. package/dist/commands/launch.js +107 -166
  37. package/dist/lib/claude-settings-types.d.ts +31 -19
  38. package/dist/lib/config.js +1 -2
  39. package/dist/lib/context/context-formatter.d.ts +74 -0
  40. package/dist/lib/context/context-formatter.js +493 -0
  41. package/dist/lib/context/context-selector.d.ts +42 -0
  42. package/dist/lib/context/context-selector.js +451 -0
  43. package/dist/lib/context/context-store.d.ts +100 -0
  44. package/dist/lib/context/context-store.js +644 -0
  45. package/dist/lib/context/plan-manager.d.ts +54 -0
  46. package/dist/lib/context/plan-manager.js +282 -0
  47. package/dist/lib/context/task-tracker.d.ts +44 -0
  48. package/dist/lib/context/task-tracker.js +146 -0
  49. package/dist/lib/core-ide-base.d.ts +4 -0
  50. package/dist/lib/core-ide-base.js +77 -0
  51. package/dist/lib/core-installer.d.ts +5 -0
  52. package/dist/lib/core-installer.js +33 -0
  53. package/dist/lib/debug.d.ts +0 -10
  54. package/dist/lib/debug.js +0 -10
  55. package/dist/lib/env-sanitizer.d.ts +25 -0
  56. package/dist/lib/env-sanitizer.js +46 -0
  57. package/dist/lib/errors.d.ts +0 -13
  58. package/dist/lib/errors.js +0 -15
  59. package/dist/lib/git-exclude-manager.d.ts +2 -2
  60. package/dist/lib/git-exclude-manager.js +3 -3
  61. package/dist/lib/hooks/context-monitor-logic.d.ts +6 -0
  62. package/dist/lib/hooks/context-monitor-logic.js +25 -0
  63. package/dist/lib/hooks/hook-utils.d.ts +143 -0
  64. package/dist/lib/hooks/hook-utils.js +620 -0
  65. package/dist/lib/hooks/prompt-binding-logic.d.ts +7 -0
  66. package/dist/lib/hooks/prompt-binding-logic.js +50 -0
  67. package/dist/lib/hooks/session-end-logic.d.ts +5 -0
  68. package/dist/lib/hooks/session-end-logic.js +51 -0
  69. package/dist/lib/hooks-merger.js +25 -19
  70. package/dist/lib/ide-path-resolver.d.ts +19 -7
  71. package/dist/lib/ide-path-resolver.js +25 -9
  72. package/dist/lib/install-state.d.ts +34 -0
  73. package/dist/lib/install-state.js +154 -0
  74. package/dist/lib/json-io.d.ts +12 -0
  75. package/dist/lib/json-io.js +30 -0
  76. package/dist/lib/lsp-patch.d.ts +12 -0
  77. package/dist/lib/lsp-patch.js +156 -0
  78. package/dist/lib/multiplexer.d.ts +65 -0
  79. package/dist/lib/multiplexer.js +38 -0
  80. package/dist/lib/multiplexers/psmux.d.ts +55 -0
  81. package/dist/lib/multiplexers/psmux.js +324 -0
  82. package/dist/lib/multiplexers/tmux.d.ts +36 -0
  83. package/dist/lib/multiplexers/tmux.js +221 -0
  84. package/dist/lib/multiplexers/wezterm.d.ts +38 -0
  85. package/dist/lib/multiplexers/wezterm.js +225 -0
  86. package/dist/lib/mux-utils.d.ts +6 -0
  87. package/dist/lib/mux-utils.js +36 -0
  88. package/dist/lib/paths.d.ts +2 -2
  89. package/dist/lib/paths.js +2 -2
  90. package/dist/lib/platform-commands.d.ts +27 -0
  91. package/dist/lib/platform-commands.js +49 -0
  92. package/dist/lib/prompt-file-manager.d.ts +23 -0
  93. package/dist/lib/prompt-file-manager.js +41 -0
  94. package/dist/lib/runtime/agent-launcher.d.ts +67 -0
  95. package/dist/lib/runtime/agent-launcher.js +262 -0
  96. package/dist/lib/runtime/aiw-cli.d.ts +39 -0
  97. package/dist/lib/runtime/aiw-cli.js +76 -0
  98. package/dist/lib/runtime/atomic-write.d.ts +19 -0
  99. package/dist/lib/runtime/atomic-write.js +121 -0
  100. package/dist/lib/runtime/cli-args.d.ts +58 -0
  101. package/dist/lib/runtime/cli-args.js +200 -0
  102. package/dist/lib/runtime/constants.d.ts +56 -0
  103. package/dist/lib/runtime/constants.js +230 -0
  104. package/dist/lib/runtime/executable-policy.d.ts +16 -0
  105. package/dist/lib/runtime/executable-policy.js +57 -0
  106. package/dist/lib/runtime/git-state.d.ts +9 -0
  107. package/dist/lib/runtime/git-state.js +59 -0
  108. package/dist/lib/runtime/inference.d.ts +37 -0
  109. package/dist/lib/runtime/inference.js +251 -0
  110. package/dist/lib/runtime/lint-dispatch.d.ts +40 -0
  111. package/dist/lib/runtime/lint-dispatch.js +285 -0
  112. package/dist/lib/runtime/logger.d.ts +66 -0
  113. package/dist/lib/runtime/logger.js +201 -0
  114. package/dist/lib/runtime/models.d.ts +20 -0
  115. package/dist/lib/runtime/models.js +20 -0
  116. package/dist/lib/runtime/platform-adapter.d.ts +7 -0
  117. package/dist/lib/runtime/platform-adapter.js +21 -0
  118. package/dist/lib/runtime/preflight.d.ts +24 -0
  119. package/dist/lib/runtime/preflight.js +65 -0
  120. package/dist/lib/runtime/sentinel-ipc.d.ts +14 -0
  121. package/dist/lib/runtime/sentinel-ipc.js +67 -0
  122. package/dist/lib/runtime/state-io.d.ts +31 -0
  123. package/dist/lib/runtime/state-io.js +179 -0
  124. package/dist/lib/runtime/stop-words.d.ts +20 -0
  125. package/dist/lib/runtime/stop-words.js +150 -0
  126. package/dist/lib/runtime/subprocess-utils.d.ts +29 -0
  127. package/dist/lib/runtime/subprocess-utils.js +96 -0
  128. package/dist/lib/runtime/tmux-preflight.d.ts +13 -0
  129. package/dist/lib/runtime/tmux-preflight.js +78 -0
  130. package/dist/lib/runtime/utils.d.ts +62 -0
  131. package/dist/lib/runtime/utils.js +192 -0
  132. package/dist/lib/schemas.d.ts +250 -0
  133. package/dist/lib/schemas.js +216 -0
  134. package/dist/lib/sentinel-manager.d.ts +32 -0
  135. package/dist/lib/sentinel-manager.js +62 -0
  136. package/dist/lib/sentinel-wrapper.d.ts +10 -0
  137. package/dist/lib/sentinel-wrapper.js +29 -0
  138. package/dist/lib/settings-hierarchy.js +3 -20
  139. package/dist/lib/shell-adapters/bash-adapter.d.ts +18 -0
  140. package/dist/lib/shell-adapters/bash-adapter.js +69 -0
  141. package/dist/lib/shell-adapters/index.d.ts +5 -0
  142. package/dist/lib/shell-adapters/index.js +7 -0
  143. package/dist/lib/shell-adapters/powershell-adapter.d.ts +18 -0
  144. package/dist/lib/shell-adapters/powershell-adapter.js +62 -0
  145. package/dist/lib/shell-adapters/shell-adapter.d.ts +45 -0
  146. package/dist/lib/shell-adapters/shell-adapter.js +5 -0
  147. package/dist/lib/shell-quoting.d.ts +5 -0
  148. package/dist/lib/shell-quoting.js +17 -0
  149. package/dist/lib/spawn-errors.d.ts +9 -0
  150. package/dist/lib/spawn-errors.js +29 -0
  151. package/dist/lib/spawn.js +5 -11
  152. package/dist/lib/spinner.d.ts +0 -5
  153. package/dist/lib/spinner.js +0 -16
  154. package/dist/lib/template-installer.d.ts +14 -5
  155. package/dist/lib/template-installer.js +40 -38
  156. package/dist/lib/template-resolver.d.ts +6 -7
  157. package/dist/lib/template-resolver.js +26 -21
  158. package/dist/lib/template-settings-reconstructor.d.ts +7 -2
  159. package/dist/lib/template-settings-reconstructor.js +76 -45
  160. package/dist/lib/terminal-strategy.d.ts +12 -0
  161. package/dist/lib/terminal-strategy.js +55 -0
  162. package/dist/lib/terminal.d.ts +34 -4
  163. package/dist/lib/terminal.js +192 -119
  164. package/dist/lib/tmux-pane-placement.d.ts +17 -0
  165. package/dist/lib/tmux-pane-placement.js +58 -0
  166. package/dist/lib/tmux-primitives.d.ts +3 -0
  167. package/dist/lib/tmux-primitives.js +11 -0
  168. package/dist/lib/tmux-session.d.ts +32 -0
  169. package/dist/lib/tmux-session.js +87 -0
  170. package/dist/lib/tty-detection.js +1 -1
  171. package/dist/lib/types.d.ts +168 -0
  172. package/dist/lib/types.js +6 -0
  173. package/dist/lib/version.d.ts +1 -1
  174. package/dist/lib/version.js +1 -1
  175. package/dist/lib/windsurf-hooks-hierarchy.js +6 -23
  176. package/dist/platform/launch.d.ts +11 -0
  177. package/dist/platform/launch.js +11 -0
  178. package/dist/templates/CLAUDE.md +30 -40
  179. package/dist/templates/cc-native/.claude/settings.json +26 -36
  180. package/dist/templates/cc-native/CC-NATIVE-README.md +1 -1
  181. package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +20 -12
  182. package/dist/templates/cc-native/_cc-native/cc-native.config.json +2 -6
  183. package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +39 -59
  184. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +9 -11
  185. package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_subagent.ts +2 -2
  186. package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_write.ts +4 -5
  187. package/dist/templates/cc-native/_cc-native/hooks/mark_questions_asked.ts +4 -4
  188. package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +2 -27
  189. package/dist/templates/cc-native/_cc-native/hooks/validate_task_prompt.ts +7 -7
  190. package/dist/templates/cc-native/_cc-native/lib-ts/.mocharc.json +9 -0
  191. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/aggregate-agents.test.ts +118 -0
  192. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/artifacts.test.ts +234 -0
  193. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/cc-native-state.test.ts +170 -0
  194. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/cli-output-parser.test.ts +73 -0
  195. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/config.test.ts +64 -0
  196. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/constants.test.ts +40 -0
  197. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/debug.test.ts +42 -0
  198. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/exports.test.ts +58 -0
  199. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/helpers.ts +107 -0
  200. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/hooks/add-plan-context.hook.test.ts +97 -0
  201. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/hooks/plan-questions.hook.test.ts +81 -0
  202. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/hooks/plan-review.hook.test.ts +71 -0
  203. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/json-parser.test.ts +99 -0
  204. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/orchestrator-agent.test.ts +288 -0
  205. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/orchestrator.test.ts +48 -0
  206. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/reviewers.test.ts +32 -0
  207. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/state.test.ts +124 -0
  208. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/verdict.test.ts +93 -0
  209. package/dist/templates/cc-native/_cc-native/lib-ts/agent-selection.ts +163 -0
  210. package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +6 -14
  211. package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/format.ts +597 -599
  212. package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/index.ts +26 -26
  213. package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/tracker.ts +106 -107
  214. package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/write.ts +118 -119
  215. package/dist/templates/cc-native/_cc-native/lib-ts/artifacts.ts +21 -0
  216. package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +17 -16
  217. package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +132 -10
  218. package/dist/templates/cc-native/_cc-native/lib-ts/config.ts +1 -1
  219. package/dist/templates/cc-native/_cc-native/lib-ts/constants.ts +6 -6
  220. package/dist/templates/cc-native/_cc-native/lib-ts/corroboration.ts +119 -0
  221. package/dist/templates/cc-native/_cc-native/lib-ts/debug.ts +2 -3
  222. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/graduation.ts +132 -132
  223. package/dist/templates/cc-native/_cc-native/lib-ts/index.ts +88 -86
  224. package/dist/templates/cc-native/_cc-native/lib-ts/json-parser.ts +5 -6
  225. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/orchestrator.ts +70 -70
  226. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/output-builder.ts +130 -121
  227. package/dist/templates/cc-native/_cc-native/lib-ts/package-lock.json +1679 -0
  228. package/dist/templates/cc-native/_cc-native/lib-ts/package.json +24 -0
  229. package/dist/templates/cc-native/_cc-native/lib-ts/plan-discovery.ts +5 -5
  230. package/dist/templates/cc-native/_cc-native/lib-ts/plan-enhancement.ts +1 -6
  231. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/plan-questions.ts +101 -101
  232. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/review-pipeline.ts +511 -543
  233. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/__tests__/agent-providers.test.ts +262 -0
  234. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/agent.ts +71 -85
  235. package/dist/templates/{_shared/lib-ts/agent-exec → cc-native/_cc-native/lib-ts/reviewers/base}/base-agent.ts +138 -150
  236. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/index.ts +12 -12
  237. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/claude-agent.ts +66 -57
  238. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/codex-agent.ts +185 -200
  239. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/gemini-agent.ts +39 -40
  240. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/orchestrator-claude-agent.ts +196 -225
  241. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/schemas.ts +201 -201
  242. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/types.ts +21 -23
  243. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/__tests__/hyde.test.ts +365 -0
  244. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/__tests__/ollama-client.test.ts +223 -0
  245. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/embedding-indexer.ts +12 -16
  246. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/hyde.ts +3 -2
  247. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/index.ts +31 -31
  248. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/logger.ts +7 -8
  249. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/ollama-client.ts +7 -9
  250. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/retrieval-pipeline.ts +16 -19
  251. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-indexer.ts +37 -41
  252. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-loader.ts +33 -43
  253. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-searcher.ts +20 -20
  254. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/types.ts +9 -10
  255. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/vector-store.ts +3 -4
  256. package/dist/templates/cc-native/_cc-native/lib-ts/settings.ts +50 -126
  257. package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +20 -22
  258. package/dist/templates/cc-native/_cc-native/lib-ts/tsconfig.json +2 -2
  259. package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +14 -89
  260. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/verdict.ts +72 -72
  261. package/dist/templates/cc-native/_cc-native/plan-review/CLAUDE.md +38 -1
  262. package/dist/templates/cc-native/_cc-native/plan-review/lib/__tests__/agent-selection.test.ts +345 -0
  263. package/dist/templates/cc-native/_cc-native/plan-review/lib/__tests__/preflight.test.ts +344 -0
  264. package/dist/templates/cc-native/_cc-native/plan-review/lib/agent-selection.ts +38 -16
  265. package/dist/templates/cc-native/_cc-native/plan-review/lib/preflight.ts +56 -26
  266. package/dist/templates/cc-native/_cc-native/scripts/council_debate.ts +242 -0
  267. package/dist/templates/cc-native/_cc-native/scripts/council_debate_simple.ts +294 -0
  268. package/dist/templates/cc-native/_cc-native/{plan-review/workflows → workflows}/specdev.md +9 -9
  269. package/dist/templates/core/.claude/skills/codex/SKILL.md +25 -0
  270. package/dist/templates/core/.claude/skills/devin/SKILL.md +25 -0
  271. package/dist/templates/core/.claude/skills/handoff/SKILL.md +11 -0
  272. package/dist/templates/core/.claude/skills/handoff-resume/SKILL.md +11 -0
  273. package/dist/templates/core/.claude/skills/meta-plan/SKILL.md +13 -0
  274. package/dist/templates/core/.codex/skills/codex/SKILL.md +13 -0
  275. package/dist/templates/core/.codex/skills/devin/SKILL.md +19 -0
  276. package/dist/templates/core/.codex/skills/handoff/SKILL.md +11 -0
  277. package/dist/templates/core/.codex/skills/handoff-resume/SKILL.md +11 -0
  278. package/dist/templates/core/.codex/skills/meta-plan/SKILL.md +13 -0
  279. package/dist/templates/core/.devin/AGENTS.md +5 -0
  280. package/dist/templates/core/.devin/config.json +12 -0
  281. package/dist/templates/core/.devin/skills/codex/SKILL.md +19 -0
  282. package/dist/templates/core/.devin/skills/devin/SKILL.md +13 -0
  283. package/dist/templates/core/.devin/skills/handoff/SKILL.md +11 -0
  284. package/dist/templates/core/.devin/skills/handoff-resume/SKILL.md +11 -0
  285. package/dist/templates/core/.devin/skills/meta-plan/SKILL.md +13 -0
  286. package/dist/templates/core/.windsurf/workflows/handoff-resume.md +9 -0
  287. package/dist/templates/{_shared → core}/.windsurf/workflows/handoff.md +1 -1
  288. package/dist/templates/{_shared → core}/.windsurf/workflows/meta-plan.md +1 -1
  289. package/dist/templates/core/hooks-ts/_utils/git-state.ts +2 -0
  290. package/dist/templates/{_shared → core}/hooks-ts/archive_plan.ts +15 -44
  291. package/dist/templates/core/hooks-ts/codex_explorer.ts +160 -0
  292. package/dist/templates/{_shared → core}/hooks-ts/context_monitor.ts +23 -55
  293. package/dist/templates/{_shared → core}/hooks-ts/file-suggestion.ts +5 -22
  294. package/dist/templates/{_shared → core}/hooks-ts/lint_after_edit.ts +7 -9
  295. package/dist/templates/core/hooks-ts/pre_compact.ts +36 -0
  296. package/dist/templates/{_shared → core}/hooks-ts/session_end.ts +38 -78
  297. package/dist/templates/{_shared → core}/hooks-ts/session_start.ts +5 -5
  298. package/dist/templates/core/hooks-ts/task_create_capture.ts +32 -0
  299. package/dist/templates/{_shared → core}/hooks-ts/task_update_capture.ts +9 -24
  300. package/dist/templates/core/hooks-ts/user_prompt_submit.ts +46 -0
  301. package/dist/templates/{_shared → core}/lib-ts/CLAUDE.md +27 -16
  302. package/dist/templates/{_shared → core}/lib-ts/context/CLAUDE.md +9 -6
  303. package/dist/templates/{_shared → core}/lib-ts/context/context-formatter.ts +16 -21
  304. package/dist/templates/{_shared → core}/lib-ts/context/context-selector.ts +8 -6
  305. package/dist/templates/{_shared → core}/lib-ts/context/context-store.ts +59 -20
  306. package/dist/templates/{_shared → core}/lib-ts/context/plan-manager.ts +19 -15
  307. package/dist/templates/{_shared → core}/lib-ts/context/task-tracker.ts +3 -3
  308. package/dist/templates/core/lib-ts/hooks/context-monitor-logic.ts +32 -0
  309. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/hooks}/hook-utils.ts +179 -41
  310. package/dist/templates/core/lib-ts/hooks/prompt-binding-logic.ts +80 -0
  311. package/dist/templates/core/lib-ts/hooks/session-end-logic.ts +82 -0
  312. package/dist/templates/core/lib-ts/package.json +19 -0
  313. package/dist/templates/core/lib-ts/runtime/agent-launcher.ts +369 -0
  314. package/dist/templates/core/lib-ts/runtime/aiw-cli.ts +108 -0
  315. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/atomic-write.ts +12 -7
  316. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/cli-args.ts +24 -8
  317. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/constants.ts +326 -324
  318. package/dist/templates/core/lib-ts/runtime/executable-policy.ts +89 -0
  319. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/git-state.ts +6 -4
  320. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/inference.ts +60 -23
  321. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/lint-dispatch.ts +25 -23
  322. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/logger.ts +32 -29
  323. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/models.ts +9 -2
  324. package/dist/templates/core/lib-ts/runtime/platform-adapter.ts +33 -0
  325. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/preflight.ts +4 -3
  326. package/dist/templates/core/lib-ts/runtime/sentinel-ipc.ts +91 -0
  327. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/state-io.ts +20 -11
  328. package/dist/templates/core/lib-ts/runtime/stop-words.ts +185 -0
  329. package/dist/templates/core/lib-ts/runtime/subprocess-utils.ts +147 -0
  330. package/dist/templates/core/lib-ts/runtime/tmux-preflight.ts +93 -0
  331. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/utils.ts +34 -4
  332. package/dist/templates/core/lib-ts/schemas.ts +233 -0
  333. package/dist/templates/{_shared → core}/lib-ts/templates/formatters.ts +7 -5
  334. package/dist/templates/{_shared → core}/lib-ts/templates/plan-context.ts +2 -1
  335. package/dist/templates/{_shared → core}/lib-ts/tsconfig.json +3 -1
  336. package/dist/templates/{_shared → core}/lib-ts/types.ts +78 -77
  337. package/dist/templates/core/scripts/resolve-run.ts +93 -0
  338. package/dist/templates/{_shared → core}/scripts/resolve_context.ts +3 -3
  339. package/dist/templates/{_shared → core}/scripts/status_line.ts +26 -21
  340. package/dist/templates/core/skills/codex/CLAUDE.md +83 -0
  341. package/dist/templates/{_shared → core}/skills/codex/SKILL.md +27 -18
  342. package/dist/templates/{_shared → core}/skills/codex/lib/codex-watcher.ts +79 -113
  343. package/dist/templates/{_shared → core}/skills/codex/scripts/launch-codex.ts +134 -148
  344. package/dist/templates/{_shared → core}/skills/codex/scripts/watch-codex.ts +6 -4
  345. package/dist/templates/core/skills/devin/CLAUDE.md +122 -0
  346. package/dist/templates/core/skills/devin/SKILL.md +73 -0
  347. package/dist/templates/core/skills/devin/lib/devin-watcher.ts +300 -0
  348. package/dist/templates/core/skills/devin/scripts/launch-devin.ts +258 -0
  349. package/dist/templates/{_shared → core}/skills/handoff-system/CLAUDE.md +436 -433
  350. package/dist/templates/{_shared → core}/skills/handoff-system/lib/document-generator.ts +9 -7
  351. package/dist/templates/{_shared → core}/skills/handoff-system/lib/handoff-reader.ts +6 -4
  352. package/dist/templates/{_shared → core}/skills/handoff-system/scripts/resume_handoff.ts +10 -8
  353. package/dist/templates/{_shared → core}/skills/handoff-system/scripts/save_handoff.ts +12 -10
  354. package/dist/templates/{_shared → core}/skills/handoff-system/workflows/handoff-resume.md +2 -2
  355. package/dist/templates/{_shared → core}/skills/handoff-system/workflows/handoff.md +6 -5
  356. package/dist/templates/{_shared → core}/skills/meta-plan/CLAUDE.md +2 -1
  357. package/dist/templates/{_shared → core}/skills/meta-plan/workflows/meta-plan.md +8 -7
  358. package/oclif.manifest.json +89 -13
  359. package/package.json +13 -12
  360. package/dist/lib/base-command.d.ts +0 -114
  361. package/dist/lib/base-command.js +0 -153
  362. package/dist/lib/env-compat.d.ts +0 -18
  363. package/dist/lib/env-compat.js +0 -23
  364. package/dist/lib/stdin.d.ts +0 -48
  365. package/dist/lib/stdin.js +0 -60
  366. package/dist/templates/_shared/.claude/settings.json +0 -120
  367. package/dist/templates/_shared/.claude/skills/codex/SKILL.md +0 -35
  368. package/dist/templates/_shared/.claude/skills/handoff/SKILL.md +0 -13
  369. package/dist/templates/_shared/.claude/skills/handoff-resume/SKILL.md +0 -13
  370. package/dist/templates/_shared/.claude/skills/meta-plan/SKILL.md +0 -43
  371. package/dist/templates/_shared/.codex/workflows/codex.md +0 -11
  372. package/dist/templates/_shared/.codex/workflows/handoff.md +0 -226
  373. package/dist/templates/_shared/.codex/workflows/meta-plan.md +0 -347
  374. package/dist/templates/_shared/hooks-ts/_utils/git-state.ts +0 -2
  375. package/dist/templates/_shared/hooks-ts/pre_compact.ts +0 -49
  376. package/dist/templates/_shared/hooks-ts/task_create_capture.ts +0 -48
  377. package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +0 -93
  378. package/dist/templates/_shared/lib-ts/agent-exec/backends/headless.ts +0 -33
  379. package/dist/templates/_shared/lib-ts/agent-exec/backends/index.ts +0 -6
  380. package/dist/templates/_shared/lib-ts/agent-exec/backends/tmux.ts +0 -119
  381. package/dist/templates/_shared/lib-ts/agent-exec/execution-backend.ts +0 -50
  382. package/dist/templates/_shared/lib-ts/agent-exec/index.ts +0 -6
  383. package/dist/templates/_shared/lib-ts/agent-exec/structured-output.ts +0 -166
  384. package/dist/templates/_shared/lib-ts/base/launchers/tmux-launcher.ts +0 -173
  385. package/dist/templates/_shared/lib-ts/base/launchers/window-launcher.ts +0 -93
  386. package/dist/templates/_shared/lib-ts/base/launchers/wt-launcher.ts +0 -64
  387. package/dist/templates/_shared/lib-ts/base/pane-launcher.ts +0 -55
  388. package/dist/templates/_shared/lib-ts/base/sentinel-ipc.ts +0 -87
  389. package/dist/templates/_shared/lib-ts/base/stop-words.ts +0 -184
  390. package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +0 -249
  391. package/dist/templates/_shared/lib-ts/base/tmux-driver.ts +0 -341
  392. package/dist/templates/_shared/lib-ts/base/tmux-pane-placement.ts +0 -78
  393. package/dist/templates/_shared/lib-ts/package.json +0 -20
  394. package/dist/templates/_shared/scripts/resolve-run.ts +0 -62
  395. package/dist/templates/_shared/skills/codex/CLAUDE.md +0 -70
  396. package/dist/templates/cc-native/_cc-native/CLAUDE.md +0 -73
  397. package/dist/templates/cc-native/_cc-native/artifacts/CLAUDE.md +0 -64
  398. package/dist/templates/cc-native/_cc-native/lib-ts/CLAUDE.md +0 -70
  399. package/dist/templates/cc-native/_cc-native/plan-review/CODING-STANDARDS-CHECKLIST.md +0 -75
  400. package/dist/templates/cc-native/_cc-native/plan-review/agents/CLAUDE.md +0 -143
  401. package/dist/templates/cc-native/_cc-native/plan-review/agents/PLAN-ORCHESTRATOR.md +0 -213
  402. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-questions/PLAN-QUESTIONER.md +0 -70
  403. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-EVOLUTION.md +0 -62
  404. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-PATTERNS.md +0 -61
  405. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-STRUCTURE.md +0 -62
  406. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ASSUMPTION-TRACER.md +0 -56
  407. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/CLARITY-AUDITOR.md +0 -53
  408. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-FEASIBILITY.md +0 -66
  409. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-GAPS.md +0 -70
  410. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-ORDERING.md +0 -62
  411. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/CONSTRAINT-VALIDATOR.md +0 -72
  412. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DESIGN-ADR-VALIDATOR.md +0 -61
  413. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DESIGN-SCALE-MATCHER.md +0 -64
  414. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DEVILS-ADVOCATE.md +0 -56
  415. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DOCUMENTATION-PHILOSOPHY.md +0 -86
  416. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/HANDOFF-READINESS.md +0 -59
  417. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/HIDDEN-COMPLEXITY.md +0 -58
  418. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/INCREMENTAL-DELIVERY.md +0 -66
  419. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-DEPENDENCY.md +0 -62
  420. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-FMEA.md +0 -66
  421. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-PREMORTEM.md +0 -71
  422. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-REVERSIBILITY.md +0 -74
  423. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SCOPE-BOUNDARY.md +0 -77
  424. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SIMPLICITY-GUARDIAN.md +0 -62
  425. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SKEPTIC.md +0 -68
  426. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-BEHAVIOR-AUDITOR.md +0 -61
  427. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-CHARACTERIZATION.md +0 -71
  428. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-FIRST-VALIDATOR.md +0 -61
  429. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-PYRAMID-ANALYZER.md +0 -61
  430. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TRADEOFF-COSTS.md +0 -67
  431. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TRADEOFF-STAKEHOLDERS.md +0 -65
  432. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/VERIFY-COVERAGE.md +0 -74
  433. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/VERIFY-STRENGTH.md +0 -69
  434. package/dist/templates/cc-native/_cc-native/plan-review/lib/corroboration.ts +0 -172
  435. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/base/base-agent.ts +0 -7
@@ -1,72 +1,72 @@
1
- /**
2
- * Pure verdict aggregation logic.
3
- * See cc-native-plan-review-spec.md §4.2
4
- */
5
-
6
- import type { ReviewDecisionResult, Verdict } from "../../lib-ts/types.js";
7
-
8
- /**
9
- * Return the worst verdict from a list.
10
- * Order: pass < warn < fail. skip→pass, error→warn.
11
- */
12
- export function worstVerdict(verdicts: Verdict[]): Verdict {
13
- const order: Record<Verdict, number> = {
14
- pass: 0,
15
- warn: 1,
16
- fail: 2,
17
- skip: 0,
18
- error: 1,
19
- };
20
-
21
- let worst: Verdict = "pass";
22
- for (const v of verdicts) {
23
- if ((order[v] ?? 1) > (order[worst] ?? 0)) {
24
- worst = v;
25
- }
26
- }
27
-
28
- // Normalize error → warn
29
- if (worst === "error") return "warn";
30
- return worst;
31
- }
32
-
33
- /**
34
- * Verdict aggregation: fail veto triggers a block.
35
- *
36
- * Priority order:
37
- * 1. Fail Veto: Any fail → deny (ISO 61508 zero-tolerance)
38
- * 2. Acceptable: warns are informational only
39
- *
40
- * Error exclusion: Detectors that produce no signal (error/skip) are excluded
41
- * from the denominator.
42
- *
43
- * @param allVerdicts - List of verdict strings from all reviewers
44
- * @returns ReviewDecisionResult with should_deny, reason, and score
45
- */
46
- export function computeReviewDecision(
47
- allVerdicts: Verdict[],
48
- ): ReviewDecisionResult {
49
- // Exclude non-signal verdicts
50
- const signalVerdicts = allVerdicts.filter(
51
- (v) => v === "pass" || v === "warn" || v === "fail",
52
- );
53
-
54
- if (signalVerdicts.length === 0) {
55
- return { should_deny: false, reason: "no_signal", score: 0 };
56
- }
57
-
58
- // Fail blocks unconditionally
59
- const failCount = signalVerdicts.filter((v) => v === "fail").length;
60
- if (failCount > 0) {
61
- return { should_deny: true, reason: "fail_veto", score: 1 };
62
- }
63
-
64
- // Warn also blocks — reviewers flagged concerns worth addressing
65
- const warnCount = signalVerdicts.filter((v) => v === "warn").length;
66
- const warnRatio = warnCount / signalVerdicts.length;
67
- if (warnCount > 0) {
68
- return { should_deny: true, reason: "warn_block", score: warnRatio };
69
- }
70
-
71
- return { should_deny: false, reason: "acceptable", score: 0 };
72
- }
1
+ /**
2
+ * Pure verdict aggregation logic.
3
+ * See cc-native-plan-review-spec.md §4.2
4
+ */
5
+
6
+ import type { ReviewDecisionResult, Verdict } from "./types.js";
7
+
8
+ /**
9
+ * Return the worst verdict from a list.
10
+ * Order: pass < warn < fail. skip→pass, error→warn.
11
+ */
12
+ export function worstVerdict(verdicts: Verdict[]): Verdict {
13
+ const order: Record<Verdict, number> = {
14
+ pass: 0,
15
+ warn: 1,
16
+ fail: 2,
17
+ skip: 0,
18
+ error: 1,
19
+ };
20
+
21
+ let worst: Verdict = "pass";
22
+ for (const v of verdicts) {
23
+ if ((order[v] ?? 1) > (order[worst] ?? 0)) {
24
+ worst = v;
25
+ }
26
+ }
27
+
28
+ // Normalize error → warn
29
+ if (worst === "error") return "warn";
30
+ return worst;
31
+ }
32
+
33
+ /**
34
+ * Verdict aggregation: fail veto triggers a block.
35
+ *
36
+ * Priority order:
37
+ * 1. Fail Veto: Any fail → deny (ISO 61508 zero-tolerance)
38
+ * 2. Acceptable: warns are informational only
39
+ *
40
+ * Error exclusion: Detectors that produce no signal (error/skip) are excluded
41
+ * from the denominator.
42
+ *
43
+ * @param allVerdicts - List of verdict strings from all reviewers
44
+ * @returns ReviewDecisionResult with should_deny, reason, and score
45
+ */
46
+ export function computeReviewDecision(
47
+ allVerdicts: Verdict[],
48
+ ): ReviewDecisionResult {
49
+ // Exclude non-signal verdicts
50
+ const signalVerdicts = allVerdicts.filter(
51
+ (v) => v === "pass" || v === "warn" || v === "fail",
52
+ );
53
+
54
+ if (signalVerdicts.length === 0) {
55
+ return { should_deny: false, reason: "no_signal", score: 0.0 };
56
+ }
57
+
58
+ // Fail blocks unconditionally
59
+ const failCount = signalVerdicts.filter((v) => v === "fail").length;
60
+ if (failCount > 0) {
61
+ return { should_deny: true, reason: "fail_veto", score: 1.0 };
62
+ }
63
+
64
+ // Warn also blocks — reviewers flagged concerns worth addressing
65
+ const warnCount = signalVerdicts.filter((v) => v === "warn").length;
66
+ const warnRatio = warnCount / signalVerdicts.length;
67
+ if (warnCount > 0) {
68
+ return { should_deny: true, reason: "warn_block", score: warnRatio };
69
+ }
70
+
71
+ return { should_deny: false, reason: "acceptable", score: 0.0 };
72
+ }
@@ -67,8 +67,9 @@ Hooks that invoke this system (all in `../_cc-native/hooks/`):
67
67
  | Module | Key Exports |
68
68
  |--------|-------------|
69
69
  | `review-pipeline.ts` | `runReviewPipeline(input)` — main entry point |
70
- | `agent-selection.ts` | `resolveMandatoryAgents()`, `selectAgents()`, `assignModelsToAgents()` |
70
+ | `agent-selection.ts` | `resolveMandatoryAgents()`, `selectAgents()`, `assignModelsToAgents(agents, config, available?, options?)`, `resolveEnabledProviders()` (@internal). `assignModelsToAgents` accepts optional `{ isCliAvailable, randomFn }` for DI. |
71
71
  | `corroboration.ts` | `computeCorroboratedDecision()` |
72
+ | `preflight.ts` | `runPreflight()`, `collectPreflightChecks()` (@internal), `buildPreflightReport()` (@internal), `KNOWN_PROVIDERS` |
72
73
  | `graduation.ts` | `computePassEligible()`, `extractTopIssuesForTracker()`, `advanceIterationState()` |
73
74
  | `orchestrator.ts` | `runOrchestrator()`, `buildOrchestratorSchema()` (re-exported) |
74
75
  | `output-builder.ts` | `buildReviewOutput()`, `truncateAgentIssues()`, `overrideVerdictsByThreshold()` |
@@ -79,6 +80,7 @@ Hooks that invoke this system (all in `../_cc-native/hooks/`):
79
80
  ## Dependencies
80
81
 
81
82
  **Reads from shared lib-ts (stays in lib-ts, not part of plan-review):**
83
+ - `_core/lib-ts/runtime/cli-args.ts` — centralized CLI arg construction (`buildCliInvocation`, `reviewSpec`, `preflightCommandConfig`). All provider agents and preflight delegate flag construction here.
82
84
  - `../../lib-ts/types.ts` — all shared types (AgentConfig, ReviewerResult, etc.)
83
85
  - `../../lib-ts/settings.ts` — config loading
84
86
  - `../../lib-ts/plan-discovery.ts` — plan file discovery
@@ -142,9 +144,44 @@ weight: 1.0
142
144
 
143
145
  `mandatory: true` agents always run. `mandatory: false` agents are selected by the orchestrator based on plan complexity.
144
146
 
147
+ ## Model & Provider Configuration
148
+
149
+ Model assignment flows through a multi-layer pipeline:
150
+
151
+ 1. **Config source:** `cc-native.config.json` → `models.providers` section
152
+ 2. **Defaults:** `lib-ts/settings.ts` → `DEFAULT_MODELS_CONFIG`
153
+ 3. **Loading:** `loadModelsConfig()` parses config into `ModelsConfig` (including `reasoning_effort`)
154
+ 4. **Assignment:** `assignModelsToAgents()` assigns provider, model, and `reasoning_effort` from the selected `ProviderConfig` to each `AgentConfig`
155
+ 5. **Invocation:** Provider agents (e.g. `CodexAgent.buildCliArgs()`) emit CLI flags
156
+
157
+ **Current defaults:**
158
+ - Codex: model `gpt-5.4`, `reasoning_effort: "low"` → `codex exec --model gpt-5.4 -c model_reasoning_effort="low"`
159
+ - Claude: model `sonnet` → `claude --model sonnet`
160
+
161
+ **Provider priority:** `["codex", "claude"]` — Codex is preferred (cheaper/faster), Claude is fallback.
162
+
163
+ **`reasoning_effort` field:** Configured per-provider in `ProviderConfig`. Passed through `assignModelsToAgents()` to `AgentConfig.reasoning_effort`. `CodexAgent` emits it as `-c model_reasoning_effort="<value>"`. When absent, the flag is omitted and the CLI default applies.
164
+
165
+ ### Verifying model/config changes
166
+
167
+ **Always test model or config changes against the real CLI.** Use `codex exec` directly to confirm the model name and flags are accepted before committing:
168
+
169
+ ```bash
170
+ # Verify model + reasoning_effort works
171
+ codex exec --model gpt-5.4 -c 'model_reasoning_effort="low"' --sandbox read-only --ephemeral \
172
+ -o /tmp/test-out.txt "Say hello" 2>&1 | head -20
173
+
174
+ # Check the output header for: model, reasoning effort, provider
175
+ # A 400 error like "model is not supported" means the model name is wrong
176
+ ```
177
+
178
+ Invalid model names fail at runtime with no compile-time safety net. The CLI header prints the resolved `model:` and `reasoning effort:` — always verify these match expectations.
179
+
145
180
  ## Design Decisions
146
181
 
147
182
  - **Thin hook, fat pipeline:** The hook is ~70 lines and delegates everything to `review-pipeline.ts`. This enables testing the pipeline without hook machinery.
148
183
  - **Parallel reviews:** All selected agents run simultaneously via `Promise.all()`. Review time is bounded by the slowest agent, not total agents.
149
184
  - **Questions gate first:** Questions must be asked before review. `wasQuestionsAsked()` prevents skipping the gate via repeated ExitPlanMode attempts.
150
185
  - **Co-location:** Moved from scattered `lib-ts/`, `agents/`, and `workflows/` to `plan-review/` to follow the handoff system pattern. See root CLAUDE.md "System Co-location Pattern".
186
+
187
+ <!-- context-layer: last-audited=2026-03-07 | version=2 -->
@@ -0,0 +1,345 @@
1
+ /**
2
+ * Tests for agent-selection module.
3
+ * Tests resolveEnabledProviders directly with simple predicates — zero mocks.
4
+ * Tests assignModelsToAgents with DI options (randomFn, isCliAvailable) — zero mocks.
5
+ * Logger mock is for noise suppression only.
6
+ */
7
+
8
+ import { describe, it, expect, mock } from "bun:test";
9
+
10
+ import type { AgentConfig, ModelsConfig } from "../../../lib-ts/types.js";
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // Mock logger for noise suppression only (no assertions on logger calls)
14
+ // ---------------------------------------------------------------------------
15
+
16
+ mock.module("../../../../_core/lib-ts/runtime/logger.js", () => ({
17
+ logDebug() {},
18
+ logInfo() {},
19
+ logWarn() {},
20
+ logError() {},
21
+ }));
22
+
23
+ // Mock subprocess-utils so module load doesn't fail (not used by tests via DI)
24
+ mock.module("../../../../_core/lib-ts/runtime/subprocess-utils.js", () => ({
25
+ findExecutable: () => null,
26
+ }));
27
+
28
+ const { assignModelsToAgents, resolveEnabledProviders } = await import("../agent-selection.js");
29
+
30
+ // ---------------------------------------------------------------------------
31
+ // Helpers
32
+ // ---------------------------------------------------------------------------
33
+
34
+ function makeAgent(name: string): AgentConfig {
35
+ return {
36
+ name,
37
+ model: "default-model",
38
+ provider: "",
39
+ focus: "test",
40
+ categories: [],
41
+ description: `Test agent ${name}`,
42
+ system_prompt: "",
43
+ };
44
+ }
45
+
46
+ function makeModelsConfig(providers: Record<string, { enabled: boolean; models: string[] }>): ModelsConfig {
47
+ return { providers };
48
+ }
49
+
50
+ /** CLI always available */
51
+ const allAvailable = () => true;
52
+
53
+ /** CLI never available */
54
+ const noneAvailable = () => false;
55
+
56
+ /** Only specific CLIs available */
57
+ const onlyAvailable = (...names: string[]) => (name: string) => names.includes(name);
58
+
59
+ // ---------------------------------------------------------------------------
60
+ // resolveEnabledProviders — pure, zero mocks
61
+ // ---------------------------------------------------------------------------
62
+
63
+ describe("agent-selection", () => {
64
+ describe("resolveEnabledProviders", () => {
65
+ it("returns enabled providers sorted by priority (codex first)", () => {
66
+ const config = makeModelsConfig({
67
+ claude: { enabled: true, models: ["sonnet"] },
68
+ codex: { enabled: true, models: ["codex-mini-latest"] },
69
+ });
70
+
71
+ const result = resolveEnabledProviders(config, allAvailable);
72
+
73
+ expect(result.length).toBe(2);
74
+ expect(result[0]![0]).toBe("codex");
75
+ expect(result[1]![0]).toBe("claude");
76
+ });
77
+
78
+ it("excludes providers whose CLI is not available", () => {
79
+ const config = makeModelsConfig({
80
+ claude: { enabled: true, models: ["sonnet"] },
81
+ codex: { enabled: true, models: ["codex-mini-latest"] },
82
+ });
83
+
84
+ const result = resolveEnabledProviders(config, onlyAvailable("claude"));
85
+
86
+ expect(result.length).toBe(1);
87
+ expect(result[0]![0]).toBe("claude");
88
+ });
89
+
90
+ it("excludes disabled providers", () => {
91
+ const config = makeModelsConfig({
92
+ claude: { enabled: false, models: ["sonnet"] },
93
+ codex: { enabled: true, models: ["codex-mini-latest"] },
94
+ });
95
+
96
+ const result = resolveEnabledProviders(config, allAvailable);
97
+
98
+ expect(result.length).toBe(1);
99
+ expect(result[0]![0]).toBe("codex");
100
+ });
101
+
102
+ it("excludes providers with empty model lists", () => {
103
+ const config = makeModelsConfig({
104
+ claude: { enabled: true, models: [] },
105
+ codex: { enabled: true, models: ["codex-mini-latest"] },
106
+ });
107
+
108
+ const result = resolveEnabledProviders(config, allAvailable);
109
+
110
+ expect(result.length).toBe(1);
111
+ expect(result[0]![0]).toBe("codex");
112
+ });
113
+
114
+ it("filters models by preflight results", () => {
115
+ const config = makeModelsConfig({
116
+ claude: { enabled: true, models: ["sonnet", "opus"] },
117
+ });
118
+
119
+ const preflightAvailable = new Map([
120
+ ["claude", new Set(["sonnet"])],
121
+ ]);
122
+
123
+ const result = resolveEnabledProviders(config, allAvailable, preflightAvailable);
124
+
125
+ expect(result.length).toBe(1);
126
+ expect(result[0]![1].models).toEqual(["sonnet"]);
127
+ });
128
+
129
+ it("skips provider when no models passed preflight", () => {
130
+ const config = makeModelsConfig({
131
+ claude: { enabled: true, models: ["sonnet"] },
132
+ codex: { enabled: true, models: ["codex-mini-latest"] },
133
+ });
134
+
135
+ // Only claude passed preflight
136
+ const preflightAvailable = new Map([
137
+ ["claude", new Set(["sonnet"])],
138
+ ]);
139
+
140
+ const result = resolveEnabledProviders(config, allAvailable, preflightAvailable);
141
+
142
+ expect(result.length).toBe(1);
143
+ expect(result[0]![0]).toBe("claude");
144
+ });
145
+
146
+ it("returns empty when no providers are available", () => {
147
+ const config = makeModelsConfig({
148
+ codex: { enabled: true, models: ["codex-mini-latest"] },
149
+ });
150
+
151
+ const result = resolveEnabledProviders(config, noneAvailable);
152
+
153
+ expect(result).toEqual([]);
154
+ });
155
+
156
+ it("puts unknown providers after known ones in priority", () => {
157
+ const config = makeModelsConfig({
158
+ gemini: { enabled: true, models: ["gemini-pro"] },
159
+ codex: { enabled: true, models: ["codex-mini"] },
160
+ });
161
+
162
+ const result = resolveEnabledProviders(config, allAvailable);
163
+
164
+ expect(result[0]![0]).toBe("codex");
165
+ expect(result[1]![0]).toBe("gemini");
166
+ });
167
+ });
168
+
169
+ // ---------------------------------------------------------------------------
170
+ // assignModelsToAgents — uses DI, zero subprocess mocks
171
+ // ---------------------------------------------------------------------------
172
+
173
+ describe("assignModelsToAgents", () => {
174
+ it("assigns provider and model to agents", () => {
175
+ const agents = [makeAgent("a1"), makeAgent("a2")];
176
+ const config = makeModelsConfig({
177
+ claude: { enabled: true, models: ["sonnet"] },
178
+ });
179
+
180
+ const result = assignModelsToAgents(agents, config, undefined, {
181
+ isCliAvailable: allAvailable,
182
+ randomFn: () => 0,
183
+ });
184
+
185
+ expect(result.length).toBe(2);
186
+ expect(result[0]!.provider).toBe("claude");
187
+ expect(result[0]!.model).toBe("sonnet");
188
+ expect(result[1]!.provider).toBe("claude");
189
+ });
190
+
191
+ it("prefers codex over claude when both available", () => {
192
+ const agents = [makeAgent("a1"), makeAgent("a2"), makeAgent("a3")];
193
+ const config = makeModelsConfig({
194
+ claude: { enabled: true, models: ["sonnet"] },
195
+ codex: { enabled: true, models: ["codex-mini-latest"] },
196
+ });
197
+
198
+ const result = assignModelsToAgents(agents, config, undefined, {
199
+ isCliAvailable: allAvailable,
200
+ randomFn: () => 0,
201
+ });
202
+
203
+ expect(result.every(a => a.provider === "codex")).toBe(true);
204
+ expect(result.every(a => a.model === "codex-mini-latest")).toBe(true);
205
+ });
206
+
207
+ it("falls back to claude when codex CLI not found", () => {
208
+ const agents = [makeAgent("a1")];
209
+ const config = makeModelsConfig({
210
+ claude: { enabled: true, models: ["sonnet"] },
211
+ codex: { enabled: true, models: ["codex-mini-latest"] },
212
+ });
213
+
214
+ const result = assignModelsToAgents(agents, config, undefined, {
215
+ isCliAvailable: onlyAvailable("claude"),
216
+ randomFn: () => 0,
217
+ });
218
+
219
+ expect(result[0]!.provider).toBe("claude");
220
+ expect(result[0]!.model).toBe("sonnet");
221
+ });
222
+
223
+ it("filters models by preflight results", () => {
224
+ const agents = [makeAgent("a1")];
225
+ const config = makeModelsConfig({
226
+ claude: { enabled: true, models: ["sonnet", "opus"] },
227
+ });
228
+
229
+ const preflightAvailable = new Map([
230
+ ["claude", new Set(["sonnet"])],
231
+ ]);
232
+
233
+ const result = assignModelsToAgents(agents, config, preflightAvailable, {
234
+ isCliAvailable: allAvailable,
235
+ randomFn: () => 0,
236
+ });
237
+
238
+ expect(result[0]!.provider).toBe("claude");
239
+ expect(result[0]!.model).toBe("sonnet");
240
+ });
241
+
242
+ it("skips provider entirely when no models passed preflight", () => {
243
+ const agents = [makeAgent("a1")];
244
+ const config = makeModelsConfig({
245
+ claude: { enabled: true, models: ["sonnet"] },
246
+ codex: { enabled: true, models: ["codex-mini-latest"] },
247
+ });
248
+
249
+ const preflightAvailable = new Map([
250
+ ["claude", new Set(["sonnet"])],
251
+ ]);
252
+
253
+ const result = assignModelsToAgents(agents, config, preflightAvailable, {
254
+ isCliAvailable: allAvailable,
255
+ randomFn: () => 0,
256
+ });
257
+
258
+ expect(result[0]!.provider).toBe("claude");
259
+ });
260
+
261
+ it("falls back to claude defaults when all providers fail CLI check", () => {
262
+ const agents = [makeAgent("a1")];
263
+ const config = makeModelsConfig({
264
+ codex: { enabled: true, models: ["codex-mini-latest"] },
265
+ });
266
+
267
+ const result = assignModelsToAgents(agents, config, undefined, {
268
+ isCliAvailable: noneAvailable,
269
+ randomFn: () => 0,
270
+ });
271
+
272
+ expect(result[0]!.provider).toBe("claude");
273
+ });
274
+
275
+ it("skips disabled providers", () => {
276
+ const agents = [makeAgent("a1")];
277
+ const config = makeModelsConfig({
278
+ claude: { enabled: false, models: ["sonnet"] },
279
+ codex: { enabled: true, models: ["codex-mini-latest"] },
280
+ });
281
+
282
+ const result = assignModelsToAgents(agents, config, undefined, {
283
+ isCliAvailable: allAvailable,
284
+ randomFn: () => 0,
285
+ });
286
+
287
+ expect(result[0]!.provider).toBe("codex");
288
+ });
289
+
290
+ it("skips providers with empty model lists", () => {
291
+ const agents = [makeAgent("a1")];
292
+ const config = makeModelsConfig({
293
+ claude: { enabled: true, models: [] },
294
+ codex: { enabled: true, models: ["codex-mini-latest"] },
295
+ });
296
+
297
+ const result = assignModelsToAgents(agents, config, undefined, {
298
+ isCliAvailable: allAvailable,
299
+ randomFn: () => 0,
300
+ });
301
+
302
+ expect(result[0]!.provider).toBe("codex");
303
+ });
304
+
305
+ it("selects deterministic model with randomFn", () => {
306
+ const agents = [makeAgent("a1")];
307
+ const config = makeModelsConfig({
308
+ codex: { enabled: true, models: ["model-a", "model-b"] },
309
+ });
310
+
311
+ // randomFn=0 picks index 0 (model-a)
312
+ const result0 = assignModelsToAgents(agents, config, undefined, {
313
+ isCliAvailable: allAvailable,
314
+ randomFn: () => 0,
315
+ });
316
+ expect(result0[0]!.model).toBe("model-a");
317
+
318
+ // randomFn=0.5 picks index 1 (model-b)
319
+ const result1 = assignModelsToAgents(agents, config, undefined, {
320
+ isCliAvailable: allAvailable,
321
+ randomFn: () => 0.5,
322
+ });
323
+ expect(result1[0]!.model).toBe("model-b");
324
+ });
325
+
326
+ it("preserves agent fields other than provider and model", () => {
327
+ const agent = makeAgent("test-agent");
328
+ agent.focus = "security";
329
+ agent.system_prompt = "Be thorough";
330
+
331
+ const config = makeModelsConfig({
332
+ claude: { enabled: true, models: ["sonnet"] },
333
+ });
334
+
335
+ const result = assignModelsToAgents([agent], config, undefined, {
336
+ isCliAvailable: allAvailable,
337
+ randomFn: () => 0,
338
+ });
339
+
340
+ expect(result[0]!.name).toBe("test-agent");
341
+ expect(result[0]!.focus).toBe("security");
342
+ expect(result[0]!.system_prompt).toBe("Be thorough");
343
+ });
344
+ });
345
+ });