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,93 +0,0 @@
1
- #!/usr/bin/env bun
2
- /**
3
- * UserPromptSubmit hook: Context enforcement — ensures every prompt belongs
4
- * to a tracked context. The most complex shared hook.
5
- *
6
- * Uses emitContext() for output — context text is passed via hookSpecificOutput JSON.
7
- * Catches BlockRequest and uses emitBlock() to block the prompt.
8
- */
9
- import { getProjectRoot } from "../lib-ts/base/constants.js";
10
- import {
11
- loadHookInput, runHookAsync, logDebug, logInfo, logWarn, hookLog, emitContext, emitBlock,
12
- } from "../lib-ts/base/hook-utils.js";
13
- import { buildContextInventory } from "../lib-ts/context/context-formatter.js";
14
- import { determineContext, BlockRequest } from "../lib-ts/context/context-selector.js";
15
- import {
16
- getContextBySessionId, bindSession, maybeActivate, saveState,
17
- } from "../lib-ts/context/context-store.js";
18
-
19
- async function asyncMain(): Promise<void> {
20
- const payload = loadHookInput();
21
- if (!payload) return;
22
-
23
- const prompt = (payload as any).prompt as string | undefined;
24
- const sessionId = payload.session_id;
25
- const permissionMode = payload.permission_mode ?? "";
26
- const projectRoot = getProjectRoot(payload.cwd);
27
-
28
- if (!sessionId) {
29
- logDebug("user_prompt_submit", "No session_id");
30
- return;
31
- }
32
-
33
- const outputs: string[] = [];
34
-
35
- // Check if session is already bound to a context
36
- const existingCtx = getContextBySessionId(sessionId, projectRoot);
37
-
38
- if (existingCtx) {
39
- // Returning user — context already bound (stderr: false to avoid "hook error" display)
40
- try {
41
- maybeActivate(existingCtx.id, permissionMode, projectRoot, "user_prompt_submit");
42
- } catch (error) {
43
- hookLog("warn", "user_prompt_submit", `maybeActivate failed (non-critical): ${error}`, { stderr: false });
44
- }
45
- hookLog("debug", "user_prompt_submit", `Session bound to ${existingCtx.id}`, { stderr: false });
46
- } else if (prompt) {
47
- // First prompt — need to determine context
48
- try {
49
- const [contextId, method, outputText] = await determineContext(prompt, sessionId, projectRoot);
50
-
51
- if (contextId) {
52
- bindSession(contextId, sessionId, projectRoot);
53
- maybeActivate(contextId, permissionMode, projectRoot, "user_prompt_submit");
54
-
55
- // Clear handoff_path after binding (prevents re-injection)
56
- const state = getContextBySessionId(sessionId, projectRoot);
57
- if (state && state.handoff_path) {
58
- state.handoff_path = null;
59
- saveState(state.id, state, projectRoot);
60
- }
61
-
62
- logInfo("user_prompt_submit", `Context ${contextId} via ${method}`);
63
- }
64
-
65
- if (outputText) {
66
- outputs.push(outputText);
67
- }
68
-
69
- // Append context folder inventory
70
- try {
71
- const boundState = getContextBySessionId(sessionId, projectRoot);
72
- if (boundState) {
73
- const inventory = buildContextInventory(boundState, projectRoot);
74
- if (inventory) outputs.push(inventory);
75
- }
76
- } catch (error) {
77
- logWarn("user_prompt_submit", `Inventory failed (non-critical): ${error}`);
78
- }
79
- } catch (error) {
80
- if (error instanceof BlockRequest) {
81
- emitBlock((error as Error).message);
82
- return;
83
- }
84
- throw error; // Re-throw unexpected errors
85
- }
86
- }
87
-
88
- if (outputs.length > 0) {
89
- emitContext(outputs.join("\n\n"));
90
- }
91
- }
92
-
93
- runHookAsync(asyncMain, "user_prompt_submit");
@@ -1,33 +0,0 @@
1
- /**
2
- * Headless execution backend — wraps execFileAsync() for subprocess execution.
3
- * Default backend for all CLI agents. If outputFilePath is specified and exists
4
- * after execution, reads output from file instead of stdout (Codex pattern).
5
- */
6
-
7
- import * as fs from "node:fs";
8
-
9
- import { execFileAsync } from "../../base/subprocess-utils.js";
10
- import type { ExecutionBackend, ExecutionRequest, ExecutionResult } from "../execution-backend.js";
11
-
12
- export class HeadlessBackend implements ExecutionBackend {
13
- async execute(request: ExecutionRequest): Promise<ExecutionResult> {
14
- const result = await execFileAsync(request.cliPath, request.args, {
15
- input: request.input,
16
- timeout: request.timeoutMs,
17
- env: request.env,
18
- maxBuffer: request.maxBuffer ?? 10 * 1024 * 1024,
19
- shell: request.shell ?? (process.platform === "win32"),
20
- });
21
-
22
- // If outputFilePath specified and exists, read from file instead of stdout
23
- if (request.outputFilePath && fs.existsSync(request.outputFilePath)) {
24
- const fileContent = fs.readFileSync(request.outputFilePath, "utf-8");
25
- return {
26
- ...result,
27
- stdout: fileContent,
28
- };
29
- }
30
-
31
- return result;
32
- }
33
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * Barrel re-export for execution backends.
3
- */
4
-
5
- export { HeadlessBackend } from "./headless.js";
6
- export { TmuxBackend, type TmuxBackendOptions } from "./tmux.js";
@@ -1,119 +0,0 @@
1
- /**
2
- * Tmux execution backend — runs CLI agents in visible tmux panes
3
- * with sentinel-file-based output capture.
4
- *
5
- * Delegates pane management to tmux-driver.ts primitives. Does NOT use
6
- * launchDriverInTmuxOrFallback() because fallback is the caller's concern,
7
- * not the backend's.
8
- */
9
-
10
- import * as fs from "node:fs";
11
- import * as path from "node:path";
12
-
13
- import { execFileAsync } from "../../base/subprocess-utils.js";
14
- import {
15
- buildShellCaptureScript,
16
- cleanupSentinelIpc,
17
- createSentinelIpcPaths,
18
- readSentinelExitCode,
19
- readTextIfExists,
20
- waitForSentinelFile,
21
- } from "../../base/sentinel-ipc.js";
22
- import { getTmuxAvailability, quoteForSh, normalizeSplitFlag } from "../../base/tmux-driver.js";
23
- import type { ExecutionBackend, ExecutionRequest, ExecutionResult } from "../execution-backend.js";
24
-
25
- export interface TmuxBackendOptions {
26
- splitFlag?: string;
27
- splitTarget?: string;
28
- }
29
-
30
- export class TmuxBackend implements ExecutionBackend {
31
- private options: TmuxBackendOptions;
32
-
33
- constructor(options?: TmuxBackendOptions) {
34
- this.options = options ?? {};
35
- }
36
-
37
- async execute(request: ExecutionRequest): Promise<ExecutionResult> {
38
- const tmux = getTmuxAvailability({ requireSessionEnv: true });
39
- if (!tmux.available || !tmux.tmuxPath) {
40
- return {
41
- stdout: "",
42
- stderr: `tmux pane launch failed: ${tmux.reason ?? "tmux unavailable"}`,
43
- exitCode: 1,
44
- killed: false,
45
- signal: null,
46
- };
47
- }
48
-
49
- const agentName = path.basename(request.cliPath).replace(/\.[^.]+$/, "");
50
- const ipc = createSentinelIpcPaths(`aiwcli-agent-${agentName}`);
51
-
52
- try {
53
- fs.writeFileSync(ipc.inputPath, request.input, "utf-8");
54
-
55
- const envEntries = Object.entries(request.env).filter(
56
- ([, value]) => value !== undefined,
57
- ) as Array<[string, string]>;
58
- const envPrefix = envEntries
59
- .map(([key, value]) => `${key}=${quoteForSh(value)}`)
60
- .join(" ");
61
-
62
- const quotedArgs = request.args.map((arg) => quoteForSh(arg)).join(" ");
63
- const command = `${envPrefix} ${quoteForSh(request.cliPath)} ${quotedArgs}`.trim();
64
- const script = buildShellCaptureScript(command, ipc, quoteForSh);
65
-
66
- const splitFlag = normalizeSplitFlag(this.options.splitFlag);
67
- const tmuxArgs = ["split-window", splitFlag, "-P", "-F", "#{pane_id}"];
68
- if (this.options.splitTarget) {
69
- tmuxArgs.push("-t", this.options.splitTarget);
70
- }
71
- tmuxArgs.push(`bash -lc ${quoteForSh(script)}`);
72
-
73
- const split = await execFileAsync(tmux.tmuxPath, tmuxArgs, { timeout: 5000 });
74
- if (split.exitCode !== 0) {
75
- return {
76
- stdout: "",
77
- stderr: `tmux pane launch failed: ${split.stderr.trim()}`,
78
- exitCode: 1,
79
- killed: false,
80
- signal: null,
81
- };
82
- }
83
-
84
- const paneId = split.stdout.trim().split(/\r?\n/).pop() ?? "";
85
- const finished = await waitForSentinelFile(ipc.sentinelPath, request.timeoutMs);
86
-
87
- if (!finished) {
88
- if (paneId) {
89
- await execFileAsync(tmux.tmuxPath, ["kill-pane", "-t", paneId], { timeout: 3000 });
90
- }
91
- return {
92
- stdout: "",
93
- stderr: "",
94
- exitCode: -1,
95
- killed: true,
96
- signal: "SIGTERM",
97
- };
98
- }
99
-
100
- const exitCode = readSentinelExitCode(ipc.sentinelPath, 1);
101
- const stdout = readTextIfExists(ipc.stdoutPath);
102
- const stderr = readTextIfExists(ipc.stderrPath);
103
-
104
- if (request.outputFilePath && fs.existsSync(request.outputFilePath)) {
105
- return {
106
- stdout: fs.readFileSync(request.outputFilePath, "utf-8"),
107
- stderr,
108
- exitCode,
109
- killed: false,
110
- signal: null,
111
- };
112
- }
113
-
114
- return { stdout, stderr, exitCode, killed: false, signal: null };
115
- } finally {
116
- cleanupSentinelIpc(ipc);
117
- }
118
- }
119
- }
@@ -1,50 +0,0 @@
1
- /**
2
- * Execution backend interfaces for CLI agent subprocess invocations.
3
- * Decouples agent logic (prompt building, output parsing) from execution
4
- * strategy (headless subprocess vs tmux pane).
5
- */
6
-
7
- // ---------------------------------------------------------------------------
8
- // Execution Request / Result
9
- // ---------------------------------------------------------------------------
10
-
11
- /** Request to execute a CLI subprocess. */
12
- export interface ExecutionRequest {
13
- cliPath: string;
14
- args: string[];
15
- input: string;
16
- env: Record<string, string | undefined>;
17
- timeoutMs: number;
18
- /** If set, read output from this file instead of stdout (Codex pattern). */
19
- outputFilePath?: string;
20
- maxBuffer?: number;
21
- shell?: boolean;
22
- }
23
-
24
- /** Result from a CLI subprocess execution. */
25
- export interface ExecutionResult {
26
- stdout: string;
27
- stderr: string;
28
- exitCode: number;
29
- killed: boolean;
30
- signal: string | null;
31
- }
32
-
33
- // ---------------------------------------------------------------------------
34
- // Execution Backend
35
- // ---------------------------------------------------------------------------
36
-
37
- /** Strategy interface for running CLI agent subprocesses. */
38
- export interface ExecutionBackend {
39
- execute(request: ExecutionRequest): Promise<ExecutionResult>;
40
- }
41
-
42
- // ---------------------------------------------------------------------------
43
- // Debug Logger
44
- // ---------------------------------------------------------------------------
45
-
46
- /** Injectable debug logger for agents running in _shared context. */
47
- export interface AgentDebugLogger {
48
- log(contextPath: string, sessionName: string, component: string, message: string, data?: unknown): void;
49
- raw(contextPath: string, sessionName: string, component: string, label: string, raw: string): void;
50
- }
@@ -1,6 +0,0 @@
1
- export { BaseCliAgent, type AgentExecutionConfig } from "./base-agent.js";
2
- export type { ExecutionBackend, ExecutionRequest, ExecutionResult, AgentDebugLogger } from "./execution-backend.js";
3
- export { HeadlessBackend } from "./backends/headless.js";
4
- export { TmuxBackend } from "./backends/tmux.js";
5
- export { parseJsonObjectMaybe, parseStructuredOutput } from "./structured-output.js";
6
- export type { StructuredOutputParseOptions } from "./structured-output.js";
@@ -1,166 +0,0 @@
1
- /**
2
- * Shared structured output parsing utilities for CLI-based agents.
3
- * Supports Claude/Codex-style envelopes and heuristic JSON extraction.
4
- */
5
-
6
- import { logDebug, logError, logWarn } from "../base/logger.js";
7
-
8
- export interface StructuredOutputParseOptions {
9
- requireFields?: string[];
10
- loggerTag?: string;
11
- }
12
-
13
- const DEFAULT_LOG_TAG = "structured_output";
14
-
15
- function getTag(options?: StructuredOutputParseOptions): string {
16
- return options?.loggerTag ?? DEFAULT_LOG_TAG;
17
- }
18
-
19
- function validateRequiredFields(
20
- obj: Record<string, unknown>,
21
- parseMethod: "strict" | "heuristic",
22
- options?: StructuredOutputParseOptions,
23
- ): Record<string, unknown> | null {
24
- const required = options?.requireFields;
25
- if (!required || required.length === 0) return obj;
26
-
27
- const missing = required.filter((field) => !(field in obj) || obj[field] === undefined || obj[field] === null);
28
- if (missing.length === 0) return obj;
29
-
30
- const tag = getTag(options);
31
- logWarn(tag, `Parsed JSON (${parseMethod}) missing required fields: ${JSON.stringify(missing)}`);
32
- logDebug(tag, `Parsed keys: ${JSON.stringify(Object.keys(obj))}`);
33
-
34
- // Heuristic extraction often grabs the wrong JSON blob. Reject in that case.
35
- if (parseMethod === "heuristic") {
36
- return null;
37
- }
38
- return obj;
39
- }
40
-
41
- /**
42
- * Parse a JSON object from text using strict parse first, then heuristic
43
- * extraction of the first object-like block.
44
- */
45
- export function parseJsonObjectMaybe(
46
- text: string,
47
- options?: StructuredOutputParseOptions,
48
- ): Record<string, unknown> | null {
49
- const tag = getTag(options);
50
- const trimmed = text.trim();
51
- if (!trimmed) return null;
52
-
53
- // Strict parse first.
54
- try {
55
- const parsed: unknown = JSON.parse(trimmed);
56
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
57
- return validateRequiredFields(parsed as Record<string, unknown>, "strict", options);
58
- }
59
- } catch {
60
- // Fall through to heuristic extraction.
61
- }
62
-
63
- // Heuristic parse: extract the first object-like block.
64
- const start = trimmed.indexOf("{");
65
- const end = trimmed.lastIndexOf("}");
66
- if (start === -1 || end === -1 || end <= start) return null;
67
-
68
- const candidate = trimmed.slice(start, end + 1);
69
- try {
70
- const parsed: unknown = JSON.parse(candidate);
71
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
72
- logDebug(tag, `Used heuristic JSON extraction (chars ${start}-${end})`);
73
- return validateRequiredFields(parsed as Record<string, unknown>, "heuristic", options);
74
- }
75
- } catch {
76
- logDebug(tag, `Heuristic JSON extraction failed (chars ${start}-${end})`);
77
- }
78
-
79
- return null;
80
- }
81
-
82
- function parseAssistantEnvelope(
83
- envelope: Record<string, unknown>,
84
- options?: StructuredOutputParseOptions,
85
- ): Record<string, unknown> | null {
86
- const tag = getTag(options);
87
- const message = envelope.message;
88
- if (!message || typeof message !== "object") return null;
89
-
90
- const content = (message as Record<string, unknown>).content;
91
- if (!Array.isArray(content)) return null;
92
-
93
- for (const item of content) {
94
- if (!item || typeof item !== "object") continue;
95
- const toolUse = item as Record<string, unknown>;
96
- if (toolUse.name !== "StructuredOutput") continue;
97
- if (toolUse.input && typeof toolUse.input === "object" && !Array.isArray(toolUse.input)) {
98
- logDebug(tag, "Found StructuredOutput in assistant envelope");
99
- return toolUse.input as Record<string, unknown>;
100
- }
101
- }
102
- return null;
103
- }
104
-
105
- /**
106
- * Parse structured output across known CLI envelope formats.
107
- * Falls back to generic JSON extraction when no recognized envelope exists.
108
- */
109
- export function parseStructuredOutput(
110
- raw: string,
111
- options?: StructuredOutputParseOptions,
112
- ): Record<string, unknown> | null {
113
- const tag = getTag(options);
114
-
115
- try {
116
- const parsed: unknown = JSON.parse(raw);
117
-
118
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
119
- const obj = parsed as Record<string, unknown>;
120
-
121
- if (obj.structured_output && typeof obj.structured_output === "object" && !Array.isArray(obj.structured_output)) {
122
- logDebug(tag, "Found structured_output in root object");
123
- return validateRequiredFields(obj.structured_output as Record<string, unknown>, "strict", options);
124
- }
125
-
126
- const assistantResult = parseAssistantEnvelope(obj, options);
127
- if (assistantResult) return assistantResult;
128
-
129
- // Session result envelope (no structured output tool call).
130
- if (obj.type === "result" || ("duration_ms" in obj && "session_id" in obj)) {
131
- if (obj.is_error === true || (Array.isArray(obj.errors) && obj.errors.length > 0)) {
132
- logWarn(tag, `CLI returned error envelope: ${JSON.stringify(obj.errors ?? "is_error=true")}`);
133
- return null;
134
- }
135
-
136
- if (typeof obj.result === "string" && obj.result.trim().length > 0) {
137
- logDebug(tag, "Found text result in session envelope, attempting JSON extraction");
138
- const extracted = parseJsonObjectMaybe(obj.result, options);
139
- if (extracted) return extracted;
140
- logWarn(tag, "Session envelope result contained no extractable JSON object");
141
- }
142
- return null;
143
- }
144
- } else if (Array.isArray(parsed)) {
145
- for (let i = 0; i < parsed.length; i++) {
146
- const event = parsed[i];
147
- if (!event || typeof event !== "object") continue;
148
- const eventObj = event as Record<string, unknown>;
149
- const assistantResult = parseAssistantEnvelope(eventObj, options);
150
- if (assistantResult) {
151
- logDebug(tag, `Found StructuredOutput in event[${i}]`);
152
- return assistantResult;
153
- }
154
- }
155
- }
156
- } catch (error: unknown) {
157
- if (error instanceof SyntaxError) {
158
- logWarn(tag, `JSON decode error: ${error.message}`);
159
- } else {
160
- logError(tag, `Unexpected parse error: ${error}`);
161
- }
162
- }
163
-
164
- logDebug(tag, "No structured envelope found, falling back to generic JSON extraction");
165
- return parseJsonObjectMaybe(raw, options);
166
- }
@@ -1,173 +0,0 @@
1
- import { execFileAsync, findExecutable } from "../subprocess-utils.js";
2
- import { findBestSplit, listPanes } from "../tmux-pane-placement.js";
3
- import type { PaneLaunchOptions, PaneLaunchResult, PaneLauncher } from "../pane-launcher.js";
4
-
5
- export type TmuxSplitFlag = "-h" | "-v";
6
-
7
- export interface TmuxAvailability {
8
- available: boolean;
9
- tmuxPath?: string;
10
- reason?: string;
11
- }
12
-
13
- export interface TmuxLauncherOptions {
14
- requireSessionEnv?: boolean;
15
- }
16
-
17
- export function quoteForSh(input: string): string {
18
- return `'${input.replaceAll("'", "'\"'\"'")}'`;
19
- }
20
-
21
- export function normalizeSplitFlag(value: string | undefined): TmuxSplitFlag {
22
- return value?.trim() === "-v" ? "-v" : "-h";
23
- }
24
-
25
- export function getTmuxAvailability(options?: TmuxLauncherOptions): TmuxAvailability {
26
- const requireSessionEnv = options?.requireSessionEnv ?? true;
27
- if (requireSessionEnv && !process.env.TMUX) {
28
- return { available: false, reason: "TMUX is not set" };
29
- }
30
-
31
- const tmuxPath = findExecutable("tmux");
32
- if (!tmuxPath) {
33
- return { available: false, reason: "tmux not found on PATH" };
34
- }
35
-
36
- return { available: true, tmuxPath };
37
- }
38
-
39
- function splitFlagFromDimensions(width: number, height: number): TmuxSplitFlag {
40
- // Terminal cells are ~2x taller than wide. Correct for aspect ratio so BSP
41
- // splits the visually longer axis, not just the higher character count.
42
- const CELL_ASPECT_RATIO = 2.0;
43
- return width >= height * CELL_ASPECT_RATIO ? "-h" : "-v";
44
- }
45
-
46
- function getLastLine(text: string): string {
47
- const lines = text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
48
- return lines.at(-1) ?? "";
49
- }
50
-
51
- async function resolveSplitFlagForTargetPane(
52
- tmuxPath: string,
53
- splitTarget: string,
54
- ): Promise<TmuxSplitFlag | null> {
55
- const size = await execFileAsync(
56
- tmuxPath,
57
- ["display-message", "-p", "-t", splitTarget, "#{pane_width} #{pane_height}"],
58
- { timeout: 3000 },
59
- );
60
- if (size.exitCode !== 0) return null;
61
-
62
- const parts = size.stdout.trim().split(/\s+/);
63
- if (parts.length < 2) return null;
64
-
65
- const width = Number.parseInt(parts[0] ?? "", 10);
66
- const height = Number.parseInt(parts[1] ?? "", 10);
67
- if (!Number.isFinite(width) || !Number.isFinite(height)) return null;
68
-
69
- return splitFlagFromDimensions(width, height);
70
- }
71
-
72
- async function resolveAutoSplit(
73
- tmuxPath: string,
74
- splitTarget?: string,
75
- ): Promise<{ splitFlag: TmuxSplitFlag; splitTarget?: string }> {
76
- const explicitTarget = splitTarget?.trim();
77
- if (explicitTarget) {
78
- const splitFlag = await resolveSplitFlagForTargetPane(tmuxPath, explicitTarget);
79
- return {
80
- splitFlag: splitFlag ?? "-h",
81
- splitTarget: explicitTarget,
82
- };
83
- }
84
-
85
- const panes = await listPanes(tmuxPath);
86
- const placement = findBestSplit(panes);
87
- if (!placement) return { splitFlag: "-h" };
88
-
89
- return {
90
- splitFlag: placement.splitFlag,
91
- splitTarget: placement.targetPane,
92
- };
93
- }
94
-
95
- export class TmuxLauncher implements PaneLauncher {
96
- readonly backend = "tmux" as const;
97
- private options: TmuxLauncherOptions;
98
-
99
- constructor(options?: TmuxLauncherOptions) {
100
- this.options = options ?? {};
101
- }
102
-
103
- async available(): Promise<boolean> {
104
- return getTmuxAvailability(this.options).available;
105
- }
106
-
107
- async launch(options: PaneLaunchOptions): Promise<PaneLaunchResult> {
108
- const tmux = getTmuxAvailability(this.options);
109
- if (!tmux.available || !tmux.tmuxPath) {
110
- return {
111
- launched: false,
112
- backend: this.backend,
113
- reason: tmux.reason ?? "tmux unavailable",
114
- };
115
- }
116
-
117
- const splitDirection = options.splitDirection ?? "h";
118
- const explicitTarget = options.splitTarget?.trim();
119
-
120
- let splitFlag: TmuxSplitFlag;
121
- let splitTarget: string | undefined;
122
-
123
- if (splitDirection === "auto") {
124
- try {
125
- const resolved = await resolveAutoSplit(tmux.tmuxPath, explicitTarget);
126
- splitFlag = resolved.splitFlag;
127
- splitTarget = resolved.splitTarget;
128
- } catch {
129
- splitFlag = "-h";
130
- splitTarget = explicitTarget;
131
- }
132
- } else {
133
- splitFlag = splitDirection === "v" ? "-v" : "-h";
134
- splitTarget = explicitTarget;
135
- }
136
-
137
- const body = options.cwd?.trim()
138
- ? `cd ${quoteForSh(options.cwd.trim())} && ${options.command}`
139
- : options.command;
140
-
141
- const tmuxArgs = ["split-window", splitFlag, "-P", "-F", "#{pane_id}"];
142
- if (splitTarget) tmuxArgs.push("-t", splitTarget);
143
- tmuxArgs.push(`bash -lc ${quoteForSh(body)}`);
144
-
145
- const split = await execFileAsync(tmux.tmuxPath, tmuxArgs, { timeout: 5000 });
146
- if (split.exitCode !== 0) {
147
- return {
148
- launched: false,
149
- backend: this.backend,
150
- reason: "tmux split-window failed",
151
- stderr: split.stderr.trim() || undefined,
152
- };
153
- }
154
-
155
- const paneId = getLastLine(split.stdout) || undefined;
156
- return {
157
- launched: true,
158
- backend: this.backend,
159
- paneId,
160
- };
161
- }
162
-
163
- async kill(paneId: string): Promise<void> {
164
- if (!paneId) return;
165
-
166
- const tmux = getTmuxAvailability(this.options);
167
- if (!tmux.available || !tmux.tmuxPath) return;
168
-
169
- await execFileAsync(tmux.tmuxPath, ["kill-pane", "-t", paneId], {
170
- timeout: 3000,
171
- });
172
- }
173
- }