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
@@ -0,0 +1,344 @@
1
+ /**
2
+ * Tests for preflight health checks.
3
+ * Tests pure functions (collectPreflightChecks, buildPreflightReport) directly.
4
+ * Tests classifyError from shared preflight module directly.
5
+ * Slim integration tests for runPreflight mock only checkProviderModel (network boundary).
6
+ */
7
+
8
+ import { describe, it, expect, mock, beforeEach } from "bun:test";
9
+
10
+ import type { ModelsConfig, PreflightCheckResult, PreflightReport } 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
+ hookLog() {},
18
+ logDebug() {},
19
+ logInfo() {},
20
+ logWarn() {},
21
+ logError() {},
22
+ logBlocking() {},
23
+ logDiagnostic() {},
24
+ logHookError() {},
25
+ setSessionId() {},
26
+ setContextPath() {},
27
+ getContextPath: () => null,
28
+ }));
29
+
30
+ // ---------------------------------------------------------------------------
31
+ // Import pure functions under test (no mocks needed)
32
+ // ---------------------------------------------------------------------------
33
+
34
+ const { collectPreflightChecks, buildPreflightReport } = await import("../preflight.js");
35
+ const { classifyError } = await import("../../../../_core/lib-ts/runtime/preflight.js");
36
+
37
+ // ---------------------------------------------------------------------------
38
+ // Helpers
39
+ // ---------------------------------------------------------------------------
40
+
41
+ function makeModelsConfig(providers: Record<string, { enabled: boolean; models: string[] }>): ModelsConfig {
42
+ return { providers };
43
+ }
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // collectPreflightChecks — pure, zero mocks
47
+ // ---------------------------------------------------------------------------
48
+
49
+ describe("preflight", () => {
50
+ describe("collectPreflightChecks", () => {
51
+ const knownProviders = new Set(["claude", "codex"]);
52
+
53
+ it("collects enabled providers with known names", () => {
54
+ const config = makeModelsConfig({
55
+ claude: { enabled: true, models: ["sonnet"] },
56
+ codex: { enabled: true, models: ["codex-mini-latest"] },
57
+ });
58
+
59
+ const { checks, skippedProviders } = collectPreflightChecks(config, knownProviders);
60
+
61
+ expect(checks).toEqual([
62
+ { provider: "claude", model: "sonnet" },
63
+ { provider: "codex", model: "codex-mini-latest" },
64
+ ]);
65
+ expect(skippedProviders).toEqual([]);
66
+ });
67
+
68
+ it("skips disabled providers", () => {
69
+ const config = makeModelsConfig({
70
+ claude: { enabled: false, models: ["sonnet"] },
71
+ codex: { enabled: true, models: ["codex-mini-latest"] },
72
+ });
73
+
74
+ const { checks } = collectPreflightChecks(config, knownProviders);
75
+
76
+ expect(checks).toEqual([{ provider: "codex", model: "codex-mini-latest" }]);
77
+ });
78
+
79
+ it("skips providers with empty model lists", () => {
80
+ const config = makeModelsConfig({
81
+ claude: { enabled: true, models: [] },
82
+ });
83
+
84
+ const { checks } = collectPreflightChecks(config, knownProviders);
85
+
86
+ expect(checks).toEqual([]);
87
+ });
88
+
89
+ it("reports unknown providers in skippedProviders", () => {
90
+ const config = makeModelsConfig({
91
+ unknown_provider: { enabled: true, models: ["some-model"] },
92
+ });
93
+
94
+ const { checks, skippedProviders } = collectPreflightChecks(config, knownProviders);
95
+
96
+ expect(checks).toEqual([]);
97
+ expect(skippedProviders).toEqual(["unknown_provider"]);
98
+ });
99
+
100
+ it("deduplicates same provider:model combo", () => {
101
+ const config = makeModelsConfig({
102
+ claude: { enabled: true, models: ["sonnet", "sonnet"] },
103
+ });
104
+
105
+ const { checks } = collectPreflightChecks(config, knownProviders);
106
+
107
+ expect(checks).toEqual([{ provider: "claude", model: "sonnet" }]);
108
+ });
109
+
110
+ it("collects multiple models per provider", () => {
111
+ const config = makeModelsConfig({
112
+ claude: { enabled: true, models: ["sonnet", "opus"] },
113
+ });
114
+
115
+ const { checks } = collectPreflightChecks(config, knownProviders);
116
+
117
+ expect(checks).toEqual([
118
+ { provider: "claude", model: "sonnet" },
119
+ { provider: "claude", model: "opus" },
120
+ ]);
121
+ });
122
+
123
+ it("returns empty checks when no providers are enabled", () => {
124
+ const config = makeModelsConfig({
125
+ claude: { enabled: false, models: ["sonnet"] },
126
+ });
127
+
128
+ const { checks, skippedProviders } = collectPreflightChecks(config, knownProviders);
129
+
130
+ expect(checks).toEqual([]);
131
+ expect(skippedProviders).toEqual([]);
132
+ });
133
+ });
134
+
135
+ // ---------------------------------------------------------------------------
136
+ // buildPreflightReport — pure, zero mocks
137
+ // ---------------------------------------------------------------------------
138
+
139
+ describe("buildPreflightReport", () => {
140
+ it("builds available map from passing results", () => {
141
+ const results = [
142
+ { provider: "claude", model: "sonnet", available: true, latencyMs: 50 },
143
+ { provider: "codex", model: "codex-mini-latest", available: true, latencyMs: 30 },
144
+ ];
145
+
146
+ const report = buildPreflightReport(results, 100);
147
+
148
+ expect(report.allFailed).toBe(false);
149
+ expect(report.available.size).toBe(2);
150
+ expect(report.available.get("claude")?.has("sonnet")).toBe(true);
151
+ expect(report.available.get("codex")?.has("codex-mini-latest")).toBe(true);
152
+ expect(report.totalMs).toBe(100);
153
+ });
154
+
155
+ it("reports allFailed when all results fail", () => {
156
+ const results = [
157
+ { provider: "claude", model: "sonnet", available: false, error: "Auth failed", latencyMs: 10 },
158
+ { provider: "codex", model: "codex-mini", available: false, error: "Timeout", latencyMs: 15_000 },
159
+ ];
160
+
161
+ const report = buildPreflightReport(results, 15_000);
162
+
163
+ expect(report.allFailed).toBe(true);
164
+ expect(report.available.size).toBe(0);
165
+ });
166
+
167
+ it("reports allFailed=true for empty results", () => {
168
+ const report = buildPreflightReport([], 5);
169
+
170
+ expect(report.allFailed).toBe(true);
171
+ expect(report.available.size).toBe(0);
172
+ expect(report.checks).toEqual([]);
173
+ });
174
+
175
+ it("groups multiple models under same provider", () => {
176
+ const results = [
177
+ { provider: "claude", model: "sonnet", available: true, latencyMs: 50 },
178
+ { provider: "claude", model: "opus", available: true, latencyMs: 80 },
179
+ ];
180
+
181
+ const report = buildPreflightReport(results, 80);
182
+
183
+ expect(report.available.get("claude")?.size).toBe(2);
184
+ expect(report.available.get("claude")?.has("sonnet")).toBe(true);
185
+ expect(report.available.get("claude")?.has("opus")).toBe(true);
186
+ });
187
+
188
+ it("excludes failed models from available map", () => {
189
+ const results = [
190
+ { provider: "claude", model: "sonnet", available: true, latencyMs: 50 },
191
+ { provider: "claude", model: "opus", available: false, error: "Rate limited", latencyMs: 10 },
192
+ ];
193
+
194
+ const report = buildPreflightReport(results, 50);
195
+
196
+ expect(report.allFailed).toBe(false);
197
+ expect(report.available.get("claude")?.has("sonnet")).toBe(true);
198
+ expect(report.available.get("claude")?.has("opus")).toBe(false);
199
+ });
200
+
201
+ it("preserves check results in output", () => {
202
+ const results = [
203
+ { provider: "claude", model: "sonnet", available: true, latencyMs: 42 },
204
+ ];
205
+
206
+ const report = buildPreflightReport(results, 42);
207
+
208
+ expect(report.checks.length).toBe(1);
209
+ expect(report.checks[0]!.provider).toBe("claude");
210
+ expect(report.checks[0]!.model).toBe("sonnet");
211
+ expect(report.checks[0]!.available).toBe(true);
212
+ expect(report.checks[0]!.latencyMs).toBe(42);
213
+ });
214
+ });
215
+
216
+ // ---------------------------------------------------------------------------
217
+ // classifyError — pure, zero mocks (from shared _core/lib-ts/runtime/preflight.ts)
218
+ // ---------------------------------------------------------------------------
219
+
220
+ describe("classifyError", () => {
221
+ it("classifies timeout (killed + SIGTERM)", () => {
222
+ expect(classifyError("", null, true, "SIGTERM")).toBe("Preflight timed out");
223
+ });
224
+
225
+ it("classifies timeout (killed without signal)", () => {
226
+ expect(classifyError("", null, true, null)).toBe("Preflight timed out");
227
+ });
228
+
229
+ it("classifies model not found", () => {
230
+ expect(classifyError("model not found", 1, false, null)).toBe("Model not available for this account");
231
+ });
232
+
233
+ it("classifies not available", () => {
234
+ expect(classifyError("not available for your plan", 1, false, null)).toBe("Model not available for this account");
235
+ });
236
+
237
+ it("classifies rate limit by text", () => {
238
+ expect(classifyError("rate limit exceeded", 1, false, null)).toBe("Rate limited");
239
+ });
240
+
241
+ it("classifies rate limit by 429", () => {
242
+ expect(classifyError("error 429", 1, false, null)).toBe("Rate limited");
243
+ });
244
+
245
+ it("classifies auth errors", () => {
246
+ expect(classifyError("invalid api key", 1, false, null)).toBe("Authentication failed");
247
+ });
248
+
249
+ it("classifies 401 as auth", () => {
250
+ expect(classifyError("HTTP 401 Unauthorized", 1, false, null)).toBe("Authentication failed");
251
+ });
252
+
253
+ it("classifies quota errors", () => {
254
+ expect(classifyError("billing quota exceeded", 1, false, null)).toBe("Quota/billing issue");
255
+ });
256
+
257
+ it("falls back to exit code for unknown errors", () => {
258
+ expect(classifyError("something unexpected", 42, false, null)).toBe("Exit code 42");
259
+ });
260
+ });
261
+
262
+ // ---------------------------------------------------------------------------
263
+ // runPreflight — slim integration (mock only checkProviderModel)
264
+ // ---------------------------------------------------------------------------
265
+
266
+ describe("runPreflight", () => {
267
+ // Mock the network boundary: checkProviderModel and subprocess-utils
268
+ const mockCheckProviderModel = mock(
269
+ async (provider: string, model: string) =>
270
+ ({ provider, model, available: true, latencyMs: 10 }) as PreflightCheckResult,
271
+ );
272
+
273
+ const mockFindExecutable = mock(() => "/usr/bin/mock-cli" as string | null);
274
+
275
+ // Re-mock the modules to inject our mock for integration tests
276
+ mock.module("../../../../_core/lib-ts/runtime/preflight.js", () => ({
277
+ checkProviderModel: mockCheckProviderModel,
278
+ classifyError,
279
+ }));
280
+
281
+ mock.module("../../../../_core/lib-ts/runtime/subprocess-utils.js", () => ({
282
+ findExecutable: mockFindExecutable,
283
+ execFileAsync: mock(() => Promise.resolve({ stdout: "ok", stderr: "", exitCode: 0, killed: false, signal: null })),
284
+ isInternalCall: () => false,
285
+ getInternalSubprocessEnv: () => ({}),
286
+ normalizePathForCli: (p: string) => p,
287
+ shellQuoteWin: (arg: string) => arg,
288
+ isExecSyncError: () => false,
289
+ }));
290
+
291
+ // Re-import to pick up the mocked checkProviderModel
292
+ let runPreflight: (config: ModelsConfig, timeoutMs?: number) => Promise<PreflightReport>;
293
+
294
+ beforeEach(async () => {
295
+ mockCheckProviderModel.mockReset();
296
+ mockCheckProviderModel.mockImplementation(
297
+ async (provider: string, model: string) =>
298
+ ({ provider, model, available: true, latencyMs: 10 }) as PreflightCheckResult,
299
+ );
300
+ // Force fresh import to pick up mocks
301
+ const mod = await import("../preflight.js");
302
+ runPreflight = mod.runPreflight;
303
+ });
304
+
305
+ it("returns available report when checks pass", async () => {
306
+ const config = makeModelsConfig({
307
+ claude: { enabled: true, models: ["sonnet"] },
308
+ codex: { enabled: true, models: ["codex-mini-latest"] },
309
+ });
310
+
311
+ const report = await runPreflight(config);
312
+
313
+ expect(report.allFailed).toBe(false);
314
+ expect(report.available.size).toBe(2);
315
+ });
316
+
317
+ it("reports allFailed when all checks fail", async () => {
318
+ mockCheckProviderModel.mockImplementation(
319
+ async (provider: string, model: string) =>
320
+ ({ provider, model, available: false, latencyMs: 10, error: "Auth failed" }) as PreflightCheckResult,
321
+ );
322
+
323
+ const config = makeModelsConfig({
324
+ claude: { enabled: true, models: ["sonnet"] },
325
+ });
326
+
327
+ const report = await runPreflight(config);
328
+
329
+ expect(report.allFailed).toBe(true);
330
+ expect(report.available.size).toBe(0);
331
+ });
332
+
333
+ it("returns empty checks when no providers enabled", async () => {
334
+ const config = makeModelsConfig({
335
+ claude: { enabled: false, models: ["sonnet"] },
336
+ });
337
+
338
+ const report = await runPreflight(config);
339
+
340
+ expect(report.allFailed).toBe(true);
341
+ expect(report.checks.length).toBe(0);
342
+ });
343
+ });
344
+ });
@@ -3,8 +3,8 @@
3
3
  * Extracted from cc-native-plan-review.ts.
4
4
  */
5
5
 
6
- import { logDebug, logInfo, logWarn } from "../../../_shared/lib-ts/base/logger.js";
7
- import { findExecutable } from "../../../_shared/lib-ts/base/subprocess-utils.js";
6
+ import { logDebug, logInfo, logWarn } from "../../../_core/lib-ts/runtime/logger.js";
7
+ import { findExecutable } from "../../../_core/lib-ts/runtime/subprocess-utils.js";
8
8
  import type {
9
9
  AgentConfig,
10
10
  AgentReviewSettings,
@@ -51,22 +51,21 @@ export function resolveMandatoryAgents(
51
51
  /** Provider priority order: codex first (cheaper/faster), claude as fallback */
52
52
  const PROVIDER_PRIORITY = ["codex", "claude"];
53
53
 
54
- /**
55
- * Assign providers and models to agents.
56
- * When preflightAvailable is provided, filters to only models that passed preflight.
57
- * Providers are ordered by PROVIDER_PRIORITY (codex first, claude fallback).
58
- * All agents get the first available provider; random model within that provider.
59
- */
60
- export function assignModelsToAgents(
61
- agents: AgentConfig[],
54
+ // ---------------------------------------------------------------------------
55
+ // Pure Provider Resolution (extracted for direct testing)
56
+ // ---------------------------------------------------------------------------
57
+
58
+ /** @internal */
59
+ export function resolveEnabledProviders(
62
60
  modelsConfig: ModelsConfig,
61
+ isCliAvailable: (cliName: string) => boolean,
63
62
  preflightAvailable?: Map<string, Set<string>>,
64
- ): AgentConfig[] {
65
- let enabledProviders = Object.entries(modelsConfig.providers)
63
+ ): Array<[string, { enabled: boolean; models: string[] }]> {
64
+ const result = Object.entries(modelsConfig.providers)
66
65
  .filter(([name, config]) => {
67
66
  if (!config.enabled || config.models.length === 0) return false;
68
67
  const cliName = name === "claude" ? "claude" : name;
69
- const found = findExecutable(cliName);
68
+ const found = isCliAvailable(cliName);
70
69
  if (!found) {
71
70
  logWarn(HOOK, `Provider '${name}' enabled but CLI '${cliName}' not found on PATH — skipping`);
72
71
  return false;
@@ -93,12 +92,35 @@ export function assignModelsToAgents(
93
92
  .filter((entry): entry is [string, { enabled: boolean; models: string[] }] => entry !== null);
94
93
 
95
94
  // Sort by provider priority (codex first)
96
- enabledProviders.sort((a, b) => {
95
+ result.sort((a, b) => {
97
96
  const aIdx = PROVIDER_PRIORITY.indexOf(a[0]);
98
97
  const bIdx = PROVIDER_PRIORITY.indexOf(b[0]);
99
98
  return (aIdx === -1 ? 999 : aIdx) - (bIdx === -1 ? 999 : bIdx);
100
99
  });
101
100
 
101
+ return result;
102
+ }
103
+
104
+ /**
105
+ * Assign providers and models to agents.
106
+ * When preflightAvailable is provided, filters to only models that passed preflight.
107
+ * Providers are ordered by PROVIDER_PRIORITY (codex first, claude fallback).
108
+ * All agents get the first available provider; random model within that provider.
109
+ */
110
+ export function assignModelsToAgents(
111
+ agents: AgentConfig[],
112
+ modelsConfig: ModelsConfig,
113
+ preflightAvailable?: Map<string, Set<string>>,
114
+ options?: {
115
+ isCliAvailable?: (name: string) => boolean;
116
+ randomFn?: () => number;
117
+ },
118
+ ): AgentConfig[] {
119
+ const isCliAvailable = options?.isCliAvailable ?? ((name: string) => Boolean(findExecutable(name)));
120
+ const randomFn = options?.randomFn ?? Math.random;
121
+
122
+ const enabledProviders = resolveEnabledProviders(modelsConfig, isCliAvailable, preflightAvailable);
123
+
102
124
  if (enabledProviders.length === 0) {
103
125
  logWarn(HOOK, "No providers with available CLI found, falling back to Claude with agent defaults");
104
126
  return agents.map(a => ({ ...a, provider: "claude" }));
@@ -109,9 +131,9 @@ export function assignModelsToAgents(
109
131
  logInfo(HOOK, `Using provider: ${providerName} (models: ${providerConfig.models.join(", ")})`);
110
132
 
111
133
  return agents.map(agent => {
112
- const modelIdx = Math.floor(Math.random() * providerConfig.models.length);
134
+ const modelIdx = Math.floor(randomFn() * providerConfig.models.length);
113
135
  const model = providerConfig.models[modelIdx] ?? providerConfig.models[0] ?? agent.model;
114
- return { ...agent, provider: providerName, model };
136
+ return { ...agent, provider: providerName, model, reasoning_effort: providerConfig.reasoning_effort };
115
137
  });
116
138
  }
117
139
 
@@ -3,18 +3,18 @@
3
3
  * Validates provider+model combos work before committing agents to them.
4
4
  * Runs minimal "ping" requests in parallel per unique provider:model combo.
5
5
  *
6
- * Uses shared checkProviderModel() from _shared/lib-ts/base/preflight.ts.
6
+ * Uses shared checkProviderModel() from _core/lib-ts/runtime/preflight.ts.
7
7
  * This module provides the batch orchestrator and provider registry specific
8
8
  * to the plan review pipeline.
9
9
  */
10
10
 
11
- import { preflightCommandConfig } from "../../../_shared/lib-ts/base/cli-args.js";
12
- import { logInfo, logWarn } from "../../../_shared/lib-ts/base/logger.js";
13
- import { checkProviderModel, type PreflightCommandConfig } from "../../../_shared/lib-ts/base/preflight.js";
11
+ import { preflightCommandConfig } from "../../../_core/lib-ts/runtime/cli-args.js";
12
+ import { logInfo, logWarn } from "../../../_core/lib-ts/runtime/logger.js";
13
+ import { checkProviderModel, type PreflightCommandConfig } from "../../../_core/lib-ts/runtime/preflight.js";
14
14
  import type { ModelsConfig, PreflightCheckResult, PreflightReport } from "../../lib-ts/types.js";
15
15
 
16
16
  const HOOK = "preflight";
17
- const DEFAULT_TIMEOUT_MS = 15000;
17
+ const DEFAULT_TIMEOUT_MS = 15_000;
18
18
 
19
19
  // ---------------------------------------------------------------------------
20
20
  // Provider Registry (built from centralized cli-args)
@@ -25,25 +25,25 @@ const PREFLIGHT_COMMANDS: Record<string, PreflightCommandConfig> = {
25
25
  codex: preflightCommandConfig("codex"),
26
26
  };
27
27
 
28
+ export const KNOWN_PROVIDERS = new Set(Object.keys(PREFLIGHT_COMMANDS));
29
+
28
30
  // ---------------------------------------------------------------------------
29
- // Run All Checks
31
+ // Pure Functions (extracted for direct testing)
30
32
  // ---------------------------------------------------------------------------
31
33
 
32
- export async function runPreflight(
34
+ /** @internal */
35
+ export function collectPreflightChecks(
33
36
  modelsConfig: ModelsConfig,
34
- timeoutMs?: number,
35
- ): Promise<PreflightReport> {
36
- const effectiveTimeout = timeoutMs ?? DEFAULT_TIMEOUT_MS;
37
- const start = Date.now();
38
-
39
- // Collect unique provider:model combos from enabled providers
37
+ knownProviders: Set<string>,
38
+ ): { checks: Array<{ provider: string; model: string }>; skippedProviders: string[] } {
40
39
  const checks: Array<{ provider: string; model: string }> = [];
41
40
  const seen = new Set<string>();
41
+ const skippedProviders: string[] = [];
42
42
 
43
43
  for (const [provider, config] of Object.entries(modelsConfig.providers)) {
44
44
  if (!config.enabled || config.models.length === 0) continue;
45
- if (!PREFLIGHT_COMMANDS[provider]) {
46
- logWarn(HOOK, `No preflight command for provider '${provider}', skipping`);
45
+ if (!knownProviders.has(provider)) {
46
+ skippedProviders.push(provider);
47
47
  continue;
48
48
  }
49
49
  for (const model of config.models) {
@@ -55,6 +55,45 @@ export async function runPreflight(
55
55
  }
56
56
  }
57
57
 
58
+ return { checks, skippedProviders };
59
+ }
60
+
61
+ /** @internal */
62
+ export function buildPreflightReport(
63
+ results: Array<{ provider: string; model: string; available: boolean; error?: string; latencyMs?: number }>,
64
+ totalMs: number,
65
+ ): PreflightReport {
66
+ const available = new Map<string, Set<string>>();
67
+ for (const r of results) {
68
+ if (r.available) {
69
+ if (!available.has(r.provider)) available.set(r.provider, new Set());
70
+ available.get(r.provider)!.add(r.model);
71
+ }
72
+ }
73
+
74
+ const allFailed = available.size === 0;
75
+
76
+ return { checks: results as PreflightCheckResult[], available, allFailed, totalMs };
77
+ }
78
+
79
+ // ---------------------------------------------------------------------------
80
+ // Run All Checks
81
+ // ---------------------------------------------------------------------------
82
+
83
+ export async function runPreflight(
84
+ modelsConfig: ModelsConfig,
85
+ timeoutMs?: number,
86
+ ): Promise<PreflightReport> {
87
+ const effectiveTimeout = timeoutMs ?? DEFAULT_TIMEOUT_MS;
88
+ const start = Date.now();
89
+
90
+ // Collect unique provider:model combos from enabled providers
91
+ const { checks, skippedProviders } = collectPreflightChecks(modelsConfig, KNOWN_PROVIDERS);
92
+
93
+ for (const provider of skippedProviders) {
94
+ logWarn(HOOK, `No preflight command for provider '${provider}', skipping`);
95
+ }
96
+
58
97
  if (checks.length === 0) {
59
98
  logWarn(HOOK, "No provider:model combos to check");
60
99
  return { checks: [], available: new Map(), allFailed: true, totalMs: Date.now() - start };
@@ -69,17 +108,8 @@ export async function runPreflight(
69
108
  ),
70
109
  );
71
110
 
72
- // Build available map
73
- const available = new Map<string, Set<string>>();
74
- for (const r of results) {
75
- if (r.available) {
76
- if (!available.has(r.provider)) available.set(r.provider, new Set());
77
- available.get(r.provider)!.add(r.model);
78
- }
79
- }
80
-
81
- const allFailed = available.size === 0;
82
111
  const totalMs = Date.now() - start;
112
+ const report = buildPreflightReport(results, totalMs);
83
113
 
84
114
  // Log summary
85
115
  const passed = results.filter(r => r.available).length;
@@ -92,5 +122,5 @@ export async function runPreflight(
92
122
  }
93
123
  }
94
124
 
95
- return { checks: results, available, allFailed, totalMs };
125
+ return report;
96
126
  }