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
@@ -9,19 +9,26 @@
9
9
  */
10
10
  import * as fs from "node:fs";
11
11
  import * as os from "node:os";
12
- import * as path from "node:path";
13
-
14
- import { launchDriverInTmuxOrFallback } from "../../../lib-ts/base/tmux-driver.js";
15
- import { cleanupSentinelPath } from "../../../lib-ts/base/sentinel-ipc.js";
16
- import { getProjectRoot } from "../../../lib-ts/base/constants.js";
17
- import { resolveCodexModel, codexReplSpec, buildCliInvocation, isCodexSandbox, type CodexSandbox, type CliArgSpec } from "../../../lib-ts/base/cli-args.js";
18
- import { CODEX_MODELS } from "../../../lib-ts/base/models.js";
19
- import { logDebug, logWarn } from "../../../lib-ts/base/logger.js";
20
- import { displayPath } from "../../../lib-ts/base/utils.js";
21
- import { getContextBySessionId, getContext } from "../../../lib-ts/context/context-store.js";
22
- import { buildExternalAgentContext } from "../../../lib-ts/context/context-formatter.js";
12
+ import path from "node:path";
13
+
23
14
  import { findLatestPlan } from "../../../lib-ts/context/plan-manager.js";
24
- import type { ContextState } from "../../../lib-ts/types.js";
15
+ import {
16
+ cleanupSentinel,
17
+ eprint,
18
+ findLatestPlanByMtime,
19
+ getWellKnownSummaryPath,
20
+ resolveContextForLaunch,
21
+ samePath,
22
+ sleep,
23
+ writeFileRefPromptFile,
24
+ writeInlinePromptFile,
25
+ } from "../../../lib-ts/runtime/agent-launcher.js";
26
+ import { aiwLaunch } from "../../../lib-ts/runtime/aiw-cli.js";
27
+ import { resolveCodexModel, buildCliInvocation, isCodexSandbox, type CodexSandbox, type CliArgSpec } from "../../../lib-ts/runtime/cli-args.js";
28
+ import { getProjectRoot } from "../../../lib-ts/runtime/constants.js";
29
+ import { logDebug, logWarn } from "../../../lib-ts/runtime/logger.js";
30
+ import { CODEX_MODELS } from "../../../lib-ts/runtime/models.js";
31
+ import { displayPath } from "../../../lib-ts/runtime/utils.js";
25
32
 
26
33
  /** Codex-specific model abbreviations. Checked before tier resolution. */
27
34
  const CODEX_ALIASES: Record<string, string> = {
@@ -30,22 +37,14 @@ const CODEX_ALIASES: Record<string, string> = {
30
37
  gpt: CODEX_MODELS.gpt,
31
38
  };
32
39
 
33
- const SESSION_DISCOVERY_TIMEOUT_MS = 12000;
40
+ const SESSION_DISCOVERY_TIMEOUT_MS = 12_000;
34
41
  const SESSION_DISCOVERY_POLL_MS = 250;
35
- const SESSION_MTIME_WINDOW_MS = 120000;
42
+ const SESSION_MTIME_WINDOW_MS = 120_000;
36
43
 
37
44
  // ---------------------------------------------------------------------------
38
45
  // Helpers
39
46
  // ---------------------------------------------------------------------------
40
47
 
41
- function eprint(...args: unknown[]): void {
42
- process.stderr.write(args.map(String).join(" ") + "\n");
43
- }
44
-
45
- function sleep(ms: number): Promise<void> {
46
- return new Promise((resolve) => setTimeout(resolve, ms));
47
- }
48
-
49
48
  function collectSessionJsonlFiles(rootDir: string): string[] {
50
49
  if (!fs.existsSync(rootDir)) return [];
51
50
  const stack: string[] = [rootDir];
@@ -74,26 +73,21 @@ function collectSessionJsonlFiles(rootDir: string): string[] {
74
73
  return files;
75
74
  }
76
75
 
77
- function samePath(a: string, b: string): boolean {
78
- const left = path.resolve(a);
79
- const right = path.resolve(b);
80
- if (process.platform === "win32") {
81
- return left.toLowerCase() === right.toLowerCase();
82
- }
83
- return left === right;
84
- }
85
-
86
- function readSessionMeta(sessionFile: string): { sessionId: string; cwd: string } | null {
76
+ function readSessionMeta(sessionFile: string): { sessionId: string; cwd: string; startedAtMs: number } | null {
87
77
  try {
88
- const raw = fs.readFileSync(sessionFile, "utf-8");
78
+ const raw = fs.readFileSync(sessionFile, "utf8");
89
79
  const firstLine = raw.split(/\r?\n/).find((line) => line.trim().length > 0);
90
80
  if (!firstLine) return null;
91
81
  const parsed = JSON.parse(firstLine);
92
82
  if (parsed?.type !== "session_meta") return null;
93
83
  const sessionId = parsed?.payload?.id;
94
84
  const cwd = parsed?.payload?.cwd;
85
+ const startedAt = parsed?.payload?.timestamp;
95
86
  if (typeof sessionId !== "string" || typeof cwd !== "string") return null;
96
- return { sessionId, cwd };
87
+ const startedAtMs = typeof startedAt === "string"
88
+ ? (Date.parse(startedAt) || 0)
89
+ : 0;
90
+ return { sessionId, cwd, startedAtMs };
97
91
  } catch {
98
92
  return null;
99
93
  }
@@ -102,12 +96,14 @@ function readSessionMeta(sessionFile: string): { sessionId: string; cwd: string
102
96
  function findLatestSessionCandidate(
103
97
  projectRoot: string,
104
98
  launchStartedAtMs: number,
99
+ requireProjectCwd = true,
105
100
  ): { sessionId: string; sessionFile: string } | null {
106
101
  const sessionsRoot = path.join(os.homedir(), ".codex", "sessions");
107
102
  const files = collectSessionJsonlFiles(sessionsRoot);
108
103
  if (files.length === 0) return null;
109
104
 
110
105
  const candidates: Array<{ sessionId: string; sessionFile: string; mtimeMs: number }> = [];
106
+ const currentThreadId = process.env.CODEX_THREAD_ID ?? "";
111
107
  for (const sessionFile of files) {
112
108
  let mtimeMs = 0;
113
109
  try {
@@ -119,7 +115,9 @@ function findLatestSessionCandidate(
119
115
 
120
116
  const meta = readSessionMeta(sessionFile);
121
117
  if (!meta) continue;
122
- if (!samePath(meta.cwd, projectRoot)) continue;
118
+ if (currentThreadId && meta.sessionId === currentThreadId) continue;
119
+ if (meta.startedAtMs > 0 && meta.startedAtMs < launchStartedAtMs - 1000) continue;
120
+ if (requireProjectCwd && !samePath(meta.cwd, projectRoot)) continue;
123
121
 
124
122
  candidates.push({ sessionId: meta.sessionId, sessionFile, mtimeMs });
125
123
  }
@@ -136,38 +134,12 @@ async function waitForCaptureSession(
136
134
  ): Promise<{ sessionId: string; sessionFile: string } | null> {
137
135
  const deadline = Date.now() + SESSION_DISCOVERY_TIMEOUT_MS;
138
136
  while (Date.now() < deadline) {
139
- const candidate = findLatestSessionCandidate(projectRoot, launchStartedAtMs);
137
+ const candidate = findLatestSessionCandidate(projectRoot, launchStartedAtMs, true);
140
138
  if (candidate) return candidate;
141
139
  await sleep(SESSION_DISCOVERY_POLL_MS);
142
140
  }
143
- return findLatestSessionCandidate(projectRoot, launchStartedAtMs);
144
- }
145
-
146
- /** Fallback plan discovery: scan all context plan dirs by mtime. */
147
- function findLatestPlanByMtime(projectRoot: string): string | null {
148
- const contextsDir = path.join(projectRoot, "_output", "contexts");
149
- if (!fs.existsSync(contextsDir)) return null;
150
-
151
- let best: { path: string; mtime: number } | null = null;
152
-
153
- for (const ctxEntry of fs.readdirSync(contextsDir)) {
154
- if (ctxEntry.startsWith("_")) continue;
155
- const plansDir = path.join(contextsDir, ctxEntry, "plans");
156
- if (!fs.existsSync(plansDir)) continue;
157
-
158
- for (const file of fs.readdirSync(plansDir)) {
159
- if (!file.endsWith(".md")) continue;
160
- const fullPath = path.join(plansDir, file);
161
- try {
162
- const mtime = fs.statSync(fullPath).mtimeMs;
163
- if (!best || mtime > best.mtime) {
164
- best = { path: fullPath, mtime };
165
- }
166
- } catch { /* skip unreadable */ }
167
- }
168
- }
169
-
170
- return best?.path ?? null;
141
+ // Fallback: tolerate launcher cwd drift (common on Windows pane backends).
142
+ return findLatestSessionCandidate(projectRoot, launchStartedAtMs, false);
171
143
  }
172
144
 
173
145
  // ---------------------------------------------------------------------------
@@ -186,6 +158,7 @@ let modelFlag: string | undefined;
186
158
  let sandboxFlag: CodexSandbox | undefined;
187
159
  let contextFlag: string | undefined;
188
160
  let extraPrompt: string | undefined;
161
+ let taskId: string | undefined;
189
162
  let yolo = true;
190
163
  let watch = true;
191
164
  const args: string[] = [];
@@ -204,18 +177,34 @@ for (let i = 0; i < rawArgs.length; i++) {
204
177
  contextFlag = rawArgs[++i];
205
178
  } else if (rawArgs[i] === "--prompt" && i + 1 < rawArgs.length) {
206
179
  extraPrompt = rawArgs[++i];
207
- } else if (rawArgs[i] === "--prompt") {
180
+ } else if (rawArgs[i] === "--task-id" && i + 1 < rawArgs.length) {
181
+ taskId = rawArgs[++i];
182
+ } else switch (rawArgs[i]) {
183
+ case "--no-watch": {
184
+ watch = false;
185
+
186
+ break;
187
+ }
188
+ case "--no-yolo": {
189
+ yolo = false;
190
+
191
+ break;
192
+ }
193
+ case "--prompt": {
208
194
  eprint("Error: --prompt requires a text argument.");
209
195
  process.exit(1);
210
- } else if (rawArgs[i] === "--yolo") {
196
+
197
+ break;
198
+ }
199
+ case "--yolo": {
211
200
  yolo = true;
212
- } else if (rawArgs[i] === "--no-yolo") {
213
- yolo = false;
214
- } else if (rawArgs[i] === "--no-watch") {
215
- watch = false;
216
- } else {
201
+
202
+ break;
203
+ }
204
+ default: {
217
205
  args.push(rawArgs[i]);
218
206
  }
207
+ }
219
208
  }
220
209
 
221
210
  if (args.length === 0) {
@@ -233,21 +222,9 @@ if (modelFlag) {
233
222
  }
234
223
 
235
224
  let promptPath: string | null = null;
236
- let tempFile: string | null = null;
237
225
 
238
226
  const projectRoot = getProjectRoot(process.cwd());
239
-
240
- // Context lookup — available for all modes (orientation header + plan discovery)
241
- // --context flag preferred (passed by skill caller); CLAUDE_SESSION_ID as fallback (hooks only)
242
- let ctx: ContextState | null = null;
243
- if (contextFlag) {
244
- ctx = getContext(contextFlag, projectRoot) ?? null;
245
- } else {
246
- const sessionId = process.env.CLAUDE_SESSION_ID;
247
- if (sessionId) {
248
- ctx = getContextBySessionId(sessionId, projectRoot) ?? null;
249
- }
250
- }
227
+ const ctx = resolveContextForLaunch(contextFlag, projectRoot);
251
228
 
252
229
  if (args[0] === "plan") {
253
230
  // Plan discovery: context system first, mtime fallback second
@@ -266,8 +243,15 @@ if (args[0] === "plan") {
266
243
  process.exit(1);
267
244
  }
268
245
 
269
- promptPath = planPath;
270
246
  console.log(`Found plan: ${displayPath(planPath)}`);
247
+ promptPath = writeFileRefPromptFile({
248
+ fileReferencePath: path.resolve(planPath),
249
+ label: "plan",
250
+ extraPrompt,
251
+ ctx,
252
+ projectRoot,
253
+ tempFilePrefix: "codex",
254
+ });
271
255
 
272
256
  } else if (args[0] === "--file") {
273
257
  if (!args[1]) {
@@ -279,69 +263,60 @@ if (args[0] === "plan") {
279
263
  eprint(`Error: File not found: ${filePath}`);
280
264
  process.exit(1);
281
265
  }
282
- promptPath = filePath;
266
+ promptPath = writeFileRefPromptFile({
267
+ fileReferencePath: filePath,
268
+ label: "file",
269
+ extraPrompt,
270
+ ctx,
271
+ projectRoot,
272
+ tempFilePrefix: "codex",
273
+ });
283
274
 
284
275
  } else {
285
- // Inline text: join args, write to temp file
286
- const text = args.join(" ");
287
- tempFile = path.join(os.tmpdir(), `codex-prompt-${Date.now()}.md`);
288
- fs.writeFileSync(tempFile, text, "utf-8");
289
- promptPath = tempFile;
290
- }
291
-
292
- // Prepend context orientation if available — graceful degradation on failure
293
- if (ctx && promptPath) {
294
- try {
295
- const orientation = buildExternalAgentContext(ctx, projectRoot);
296
- const original = fs.readFileSync(promptPath, "utf-8");
297
- const combined = `${orientation}\n\n---\n\n${original}`;
298
- const contextPromptPath = path.join(os.tmpdir(), `codex-ctx-prompt-${Date.now()}.md`);
299
- fs.writeFileSync(contextPromptPath, combined, "utf-8");
300
- if (tempFile) {
301
- try { fs.unlinkSync(tempFile); } catch { /* ignore */ }
302
- }
303
- promptPath = contextPromptPath;
304
- tempFile = contextPromptPath;
305
- } catch {
306
- logWarn("codex-skill", `Context orientation prepend failed for ${ctx.id}, continuing without header`);
307
- }
308
- }
309
-
310
- if (extraPrompt && promptPath) {
311
- try {
312
- const base = fs.readFileSync(promptPath, "utf-8");
313
- const combined = `${base}\n\n---\n\n## Additional Instructions\n\n${extraPrompt}`;
314
- const extraPromptPath = path.join(os.tmpdir(), `codex-extra-prompt-${Date.now()}.md`);
315
- fs.writeFileSync(extraPromptPath, combined, "utf-8");
316
- if (tempFile) {
317
- try { fs.unlinkSync(tempFile); } catch { /* ignore */ }
318
- }
319
- promptPath = extraPromptPath;
320
- tempFile = extraPromptPath;
321
- } catch {
322
- logWarn("codex-skill", "Extra prompt append failed, continuing without it");
323
- }
276
+ // Inline text: join args, write to temp file with context + extra prompt
277
+ promptPath = writeInlinePromptFile({
278
+ text: args.join(" "),
279
+ extraPrompt,
280
+ ctx,
281
+ projectRoot,
282
+ tempFilePrefix: "codex",
283
+ });
324
284
  }
325
285
 
326
286
  // ---------------------------------------------------------------------------
327
287
  // Launch Codex
328
288
  // ---------------------------------------------------------------------------
329
289
 
330
- const codexArgs = buildCliInvocation(codexReplSpec(resolvedModel, sandboxFlag, yolo)).args;
290
+ const launchCwd = process.env.AIW_CALLER_CWD?.trim() || process.cwd();
291
+
292
+ // Generate task ID if not provided by caller. Caller-provided IDs enable
293
+ // direct file lookup; auto-generated IDs still allow glob discovery.
294
+ if (!taskId) {
295
+ taskId = `${Date.now()}-${process.pid}`;
296
+ }
297
+ const wellKnownPath = getWellKnownSummaryPath("codex", taskId, projectRoot);
298
+ // Print task ID and well-known path early — even if the background task
299
+ // output is lost, the caller can note these from partial stdout capture.
300
+ console.log(`Task ID: ${taskId}`);
301
+ console.log(`Summary will be at: ${wellKnownPath}`);
302
+
331
303
  if (yolo) console.log("Mode: YOLO (bypass approvals and sandbox)");
332
304
  if (sandboxFlag) console.log(`Sandbox: ${sandboxFlag}`);
333
305
  if (resolvedModel) console.log(`Model: ${resolvedModel}${modelFlag !== resolvedModel ? ` (from "${modelFlag}")` : ""}`);
334
306
 
335
- logDebug("codex-skill", `Launching: model=${resolvedModel ?? "default"}, sandbox=${sandboxFlag ?? "default"}, yolo=${yolo}, extraPrompt=${!!extraPrompt}, source=${args[0]}, bytes=${promptPath ? fs.statSync(promptPath).size : 0}`);
307
+ logDebug("codex-skill", `Launching: model=${resolvedModel ?? "default"}, sandbox=${sandboxFlag ?? "default"}, yolo=${yolo}, taskId=${taskId}, extraPrompt=${Boolean(extraPrompt)}, source=${args[0]}, bytes=${promptPath ? fs.statSync(promptPath).size : 0}`);
336
308
 
337
309
  const launchStartedAtMs = Date.now();
338
- const result = await launchDriverInTmuxOrFallback({
339
- toolName: "codex",
340
- mode: "repl",
341
- args: codexArgs,
342
- splitFlag: "auto",
310
+
311
+ // Shell out to `aiw launch` instead of importing tmux modules directly.
312
+ // This consolidates all pane-launching logic in the CLI binary.
313
+ const result = await aiwLaunch({
314
+ codex: true,
315
+ wait: false,
316
+ json: true,
317
+ split: "auto",
343
318
  promptPath: promptPath ?? undefined,
344
- allowExecFallback: false,
319
+ cwd: launchCwd,
345
320
  });
346
321
 
347
322
  if (!result.launched) {
@@ -355,13 +330,13 @@ if (!result.launched) {
355
330
  sandbox: sandboxFlag ?? "danger-full-access",
356
331
  };
357
332
  const execInv = buildCliInvocation(execSpec);
358
- const promptContent = promptPath ? fs.readFileSync(promptPath, "utf-8") : "";
333
+ const promptContent = promptPath ? fs.readFileSync(promptPath, "utf8") : "";
359
334
 
360
- if (tempFile) {
361
- try { fs.unlinkSync(tempFile); } catch { /* ignore */ }
335
+ if (promptPath) {
336
+ try { fs.unlinkSync(promptPath); } catch { /* ignore */ }
362
337
  }
363
338
 
364
- const { execFileAsync } = await import("../../../lib-ts/base/subprocess-utils.js");
339
+ const { execFileAsync } = await import("../../../lib-ts/runtime/subprocess-utils.js");
365
340
  const execResult = await execFileAsync(execInv.cliName, execInv.args, {
366
341
  input: promptContent,
367
342
  env: { ...process.env, ...execInv.env },
@@ -379,11 +354,7 @@ if (!result.launched) {
379
354
  process.exit(0);
380
355
  }
381
356
 
382
- if (tempFile) {
383
- try { fs.unlinkSync(tempFile); } catch { /* ignore */ }
384
- }
385
-
386
- const backendLabel = result.backend === "tmux" ? "tmux pane" : (result.backend === "wt" ? "Windows Terminal pane" : "window");
357
+ const backendLabel = result.backend === "tmux" ? "tmux pane" : result.backend === "psmux" ? "psmux pane" : "window";
387
358
  if (result.paneId) {
388
359
  console.log(`Codex launched in ${backendLabel}: ${result.paneId}`);
389
360
  } else {
@@ -393,10 +364,11 @@ if (result.paneId) {
393
364
  if (watch && (result.paneId || result.sentinelPath)) {
394
365
  try {
395
366
  const {
367
+ persistSummary,
396
368
  SUMMARY_UNAVAILABLE_MESSAGE,
397
369
  summarizeFromSessionFileFallback,
398
370
  summarizeViaResume,
399
- summarizeViaSessionFileSpark,
371
+ summarizeViaSessionFile,
400
372
  waitForPaneClose,
401
373
  } = await import("../lib/codex-watcher.js");
402
374
 
@@ -409,24 +381,38 @@ if (watch && (result.paneId || result.sentinelPath)) {
409
381
 
410
382
  const sessionFile = sessionInfo?.sessionFile ?? "";
411
383
  const sessionId = sessionInfo?.sessionId ?? "";
412
- const summary = summarizeViaSessionFileSpark(sessionFile)
384
+ const summary = (await summarizeViaSessionFile(sessionFile))
413
385
  ?? (sessionId ? await summarizeViaResume(sessionId) : null)
414
386
  ?? summarizeFromSessionFileFallback(sessionFile)
415
387
  ?? SUMMARY_UNAVAILABLE_MESSAGE;
388
+ const summaryPath = persistSummary(summary, "codex", sessionId || undefined, taskId, projectRoot);
416
389
 
417
390
  console.log("\n--- Codex Session Summary ---");
418
391
  console.log(summary);
392
+ console.log(`\n[well_known_summary:${wellKnownPath}]`);
393
+ if (summaryPath) {
394
+ console.log(`[summary_file:${summaryPath}]`);
395
+ }
419
396
  } catch (error) {
420
- logWarn("codex-skill", `Watch flow failed for ${result.paneId ?? result.backend}: ${String(error)}`);
397
+ logWarn("codex-skill", `Watch flow failed: ${String(error)}`);
398
+ const fallbackMsg = "Codex session completed. Summary unavailable (watch error).";
399
+ const { persistSummary: persistFallback } = await import("../lib/codex-watcher.js");
400
+ const fallbackPath = persistFallback(fallbackMsg, "codex", undefined, taskId, projectRoot);
421
401
  console.log("\n--- Codex Session Summary ---");
422
- console.log("Codex session completed. Summary unavailable.");
402
+ console.log(fallbackMsg);
403
+ console.log(`\n[well_known_summary:${wellKnownPath}]`);
404
+ if (fallbackPath) {
405
+ console.log(`[summary_file:${fallbackPath}]`);
406
+ }
423
407
  } finally {
424
- cleanupSentinelPath(result.sentinelPath);
408
+ cleanupSentinel(result.sentinelPath);
425
409
  }
426
410
  } else {
427
- cleanupSentinelPath(result.sentinelPath);
411
+ cleanupSentinel(result.sentinelPath);
428
412
  }
429
413
 
430
414
  if (result.reason) {
431
415
  eprint(`Warning: ${result.reason}`);
432
416
  }
417
+
418
+
@@ -11,7 +11,7 @@ import {
11
11
  SUMMARY_UNAVAILABLE_MESSAGE,
12
12
  summarizeFromSessionFileFallback,
13
13
  summarizeViaResume,
14
- summarizeViaSessionFileSpark,
14
+ summarizeViaSessionFile,
15
15
  waitForPaneClose,
16
16
  } from "../lib/codex-watcher.js";
17
17
 
@@ -27,7 +27,7 @@ async function main(): Promise<void> {
27
27
  const sf = sessionFile ?? "";
28
28
  const sid = sessionId ?? "";
29
29
  const summary =
30
- summarizeViaSessionFileSpark(sf) ??
30
+ (await summarizeViaSessionFile(sf)) ??
31
31
  (sid ? await summarizeViaResume(sid) : null) ??
32
32
  summarizeFromSessionFileFallback(sf) ??
33
33
  SUMMARY_UNAVAILABLE_MESSAGE;
@@ -36,7 +36,9 @@ async function main(): Promise<void> {
36
36
  console.log(summary);
37
37
  }
38
38
 
39
- main().catch((error) => {
39
+ try {
40
+ await main();
41
+ } catch (error) {
40
42
  console.error(`watch-codex error: ${String(error)}`);
41
43
  console.log(SUMMARY_UNAVAILABLE_MESSAGE);
42
- });
44
+ }
@@ -0,0 +1,122 @@
1
+ # Devin Skill
2
+
3
+ Launch Devin CLI in a visible pane (tmux on Unix, fallback to exec mode) and pass the prompt at process start.
4
+
5
+ ## Directory Structure
6
+
7
+ ```
8
+ devin/
9
+ ├── CLAUDE.md <- This file
10
+ ├── SKILL.md <- Skill metadata (user-invocable)
11
+ ├── lib/
12
+ │ └── devin-watcher.ts <- Watch/summarize library
13
+ └── scripts/
14
+ └── launch-devin.ts <- Single entry point (launch + optional watch)
15
+ ```
16
+
17
+ ## Devin CLI Contract (verified 2026-03-08)
18
+
19
+ **Always re-verify against the real CLI before changing assumptions.**
20
+ Run `devin list --format json`, `devin --help`, and inspect `~/.local/share/devin/cli/sessions.db` to confirm.
21
+
22
+ ### `devin list --format json` output schema
23
+
24
+ ```jsonc
25
+ {
26
+ "id": "uuid", // full session UUID
27
+ "short_id": "8-char-hex",
28
+ "title": "string", // user prompt or session title
29
+ "working_directory": "/abs/path", // NOT "cwd"
30
+ "working_directory_display": "~/relative",
31
+ "last_activity_at": 1772942203, // unix timestamp SECONDS — NOT ISO string, NOT "created_at"
32
+ "last_activity_ago": "10h ago"
33
+ }
34
+ ```
35
+
36
+ Fields that do **NOT** exist: `cwd`, `created_at`, `status`, `model`, `session_id`.
37
+
38
+ ### Session data storage
39
+
40
+ - **SQLite DB:** `~/.local/share/devin/cli/sessions.db`
41
+ - `sessions` table: `id`, `working_directory`, `model`, `created_at` (integer), `last_activity_at`, `title`, `main_chain_id`, `cogs_json`
42
+ - `message_nodes` table: `session_id`, `node_id`, `chat_message` (JSON with `{role, content}`)
43
+ - Full conversation transcript (user, assistant, system, tool messages) stored in `message_nodes`
44
+ - **Summary files:** `~/.local/share/devin/cli/summaries/history_<hex>.md` — full session transcripts, NOT Devin-specific (shared with Claude Code sessions). No reliable session-to-file mapping exists.
45
+ - **NOT stored at:** `~/.config/devin/cli/` (only has `config.json`, no session data)
46
+
47
+ ### Devin CLI flags
48
+
49
+ - `--prompt-file <FILE>` — load prompt from file (NOT positional arg)
50
+ - `--model <MODEL>` — short names: `opus`, `sonnet`, `swe`, `gpt` (server-resolved)
51
+ - `--permission-mode <MODE>` — `auto` (default) or `dangerous`
52
+ - `-p, --print` — non-interactive mode
53
+ - `-r, --resume [SESSION_ID]` — resume session
54
+ - No `--sandbox` or `--yolo` flags (unlike Codex)
55
+
56
+ ## Script: launch-devin.ts
57
+
58
+ **Usage:**
59
+ ```bash
60
+ bun ~/.aiwcli/bin/resolve-run.ts .aiwcli/_core/skills/devin/scripts/launch-devin.ts [--model <tier|id>] [--prompt <text>] [--no-watch] [--context <id>] plan
61
+ bun ~/.aiwcli/bin/resolve-run.ts .aiwcli/_core/skills/devin/scripts/launch-devin.ts [--model <tier|id>] [--prompt <text>] [--no-watch] [--context <id>] --file <path>
62
+ bun ~/.aiwcli/bin/resolve-run.ts .aiwcli/_core/skills/devin/scripts/launch-devin.ts [--model <tier|id>] [--prompt <text>] [--no-watch] [--context <id>] <inline text...>
63
+ ```
64
+
65
+ **Args:**
66
+ - `plan` -- discover active plan via context system, build a bootstrap startup prompt
67
+ - `--file <path>` -- build a bootstrap startup prompt that includes the file path
68
+ - `<text...>` -- join remaining args as inline prompt
69
+ - `--model <name>` -- Models: `swe`, `gpt`, `opus`, `sonnet`. Tiers: `fast`/`standard`/`smart`. Or pass-through.
70
+ - `--prompt <text>` -- append extra instructions
71
+ - `--task-id <id>` -- Caller-provided task ID for direct summary file lookup. If omitted, auto-generated as `<timestamp>-<pid>`. Enables the caller to know the exact summary file path without reading background task stdout.
72
+ - `--no-watch` -- Disable watch/summarize mode
73
+
74
+ **Plan discovery order:**
75
+ 1. `--context` flag or `CLAUDE_SESSION_ID` env -> context -> `findLatestPlan(contextId)`
76
+ 2. Fallback: scan `_output/contexts/*/plans/*.md` by mtime
77
+
78
+ **Dependencies:**
79
+ - `runtime/aiw-cli.ts` -- shells out to `aiw launch --devin`
80
+ - `runtime/agent-launcher.ts` -- shared plan discovery, prompt construction, pane watching
81
+ - `runtime/cli-args.ts` -- Devin model resolution and invocation building
82
+ - `context/*` -- context lookup, formatting, plan discovery
83
+
84
+ **Watch behavior:**
85
+ - Watch is enabled by default
86
+ - Uses `waitForPaneClose` from shared agent-launcher
87
+ - Summary cascade: (1) `devin list` -> session ID -> SQLite `message_nodes` transcript, (2) tmux pane scrollback capture, (3) static unavailable message
88
+ - Summary persisted to temp file via `persistSummary("devin", ...)` (unique per run)
89
+ - Also writes to well-known path: `$TMPDIR/aiw-agent-output/<session-key>/devin-<taskId>.md`
90
+ - Task ID is caller-provided via `--task-id` or auto-generated as `<timestamp>-<pid>`
91
+ - Caller can compute the exact path via `getWellKnownSummaryPath("devin", taskId)` -- no discovery needed
92
+ - Multiple concurrent agents use different task IDs, so they don't clobber each other
93
+ - Session key resolution: tmux (`$TMUX`), psmux (`psmux display-message`), exec fallback (project-root hash)
94
+ - Task ID + summary path printed early (before agent runs) so even partial stdout capture is useful
95
+
96
+ **Design decisions:**
97
+ - No sandbox/YOLO flags (Devin uses `--permission-mode` instead, defaulting to `auto`)
98
+ - Devin model short names are server-resolved (we store just the short names)
99
+ - Shared helpers from `agent-launcher.ts` (plan discovery, prompt files, pane watching)
100
+
101
+ ## Library: lib/devin-watcher.ts
102
+
103
+ Session discovery and summarization:
104
+ - `summarizeDevinSession(projectRoot, launchStartedAtMs, paneId?)` -- full discovery + summary pipeline
105
+ - `collectTranscriptFromDb(sessionId)` -- extract user/assistant messages from SQLite `message_nodes` (uses `python3 -c` to avoid native module dependency)
106
+ - `findDevinSessionViaList(projectRoot, launchStartedAtMs)` -- match session via `devin list --format json` using `working_directory` + `last_activity_at`
107
+ - `capturePaneScrollback(paneId)` -- tmux pane capture fallback
108
+
109
+ Re-exports `persistSummary`, `waitForPaneClose` from agent-launcher.
110
+
111
+ ---
112
+ ## Context Maintenance
113
+
114
+ **After modifying files in this directory:** scan the entries above -- if any claim is now
115
+ false or incomplete, update this file before ending the task. Do not defer.
116
+
117
+ **Verification rule:** When changing code that depends on external CLI output formats (field names,
118
+ data types, storage paths), **always verify against the real CLI** before committing. Run the
119
+ actual command and inspect the output. Do not assume field names or paths from memory or from
120
+ other similar tools.
121
+
122
+ <!-- context-layer: generated=2026-03-06 | last-audited=2026-03-08 | version=3 -->
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: devin
3
+ description: Delegate implementation to Devin sub-agents. USE WHEN devin OR send to devin OR devin implement OR hand off to devin OR launch devin OR run devin.
4
+ user-invocable: true
5
+ ---
6
+
7
+ # /devin
8
+
9
+ ## Role
10
+
11
+ You are the orchestrator. Each Devin launch spawns an implementation sub-agent. Delegate implementation work to Devin, then review results when summaries arrive.
12
+
13
+ The script blocks until Devin exits and prints a session summary. Run with Bash `run_in_background: true` so you stay unblocked and receive the summary as a background task notification.
14
+
15
+ ## Command
16
+
17
+ ```
18
+ bun ~/.aiwcli/bin/resolve-run.ts .aiwcli/_core/skills/devin/scripts/launch-devin.ts [flags] <mode>
19
+ ```
20
+
21
+ **Modes:** `plan` | `--file <path>` | `<inline text...>`
22
+
23
+ `plan` and `--file` modes pass a filepath-first bootstrap prompt so Devin reads the file from disk instead of relying on a pasted full document.
24
+
25
+ **Flags:**
26
+ - `--context <id>` -- Project orientation for the sub-agent. Pass when implementing a plan so Devin understands the project structure.
27
+ - `--prompt <text>` -- Add extra instructions. In `plan`/`--file` mode, this is embedded into the bootstrap temp file with the target path.
28
+ - `--model <name>` -- Models: `swe`, `gpt`, `opus`, `sonnet`. Tiers: `fast`, `standard`, `smart`. Or pass-through for server-side resolution.
29
+ - `--no-watch` -- Fire-and-forget: exit immediately after launch, skip waiting for summary.
30
+
31
+ ## Retrieving Results
32
+
33
+ The script prints a summary to stdout and writes it to a temp file.
34
+
35
+ **Primary:** Check TaskOutput for the background task -- the summary and file path are inline.
36
+
37
+ **Fallback (if TaskOutput is empty):** Look for the `[summary_file:<path>]` line in the output. If found, read that file path directly.
38
+
39
+ ## Delegation Patterns
40
+
41
+ ### One-shot
42
+
43
+ For small or tightly coupled plans. One sub-agent implements the whole plan.
44
+
45
+ ```bash
46
+ bun ~/.aiwcli/bin/resolve-run.ts .aiwcli/_core/skills/devin/scripts/launch-devin.ts --context <ctx-id> plan
47
+ ```
48
+
49
+ Run with `run_in_background: true`. Wait for the summary. Review the changes.
50
+
51
+ ### Parallel
52
+
53
+ For plans with independent sections, create small section-brief files and launch one sub-agent per brief with `--file`.
54
+
55
+ ### Ad-hoc
56
+
57
+ For tasks outside a plan. Pass inline text or a file path.
58
+
59
+ ```bash
60
+ bun ~/.aiwcli/bin/resolve-run.ts .aiwcli/_core/skills/devin/scripts/launch-devin.ts \
61
+ "Fix the failing test in auth.ts"
62
+
63
+ bun ~/.aiwcli/bin/resolve-run.ts .aiwcli/_core/skills/devin/scripts/launch-devin.ts \
64
+ --file path/to/task-description.md
65
+ ```
66
+
67
+ ## Orchestrator Checklist
68
+
69
+ - **Delegate implementation.** If the work involves writing code and Devin can handle it, send it to Devin.
70
+ - **Split independent sections** into parallel sub-agents for faster execution.
71
+ - **Pass `--context`** when implementing a plan -- Devin needs project orientation to make good decisions.
72
+ - **Scope parallel agents with separate `--file` briefs** so each sub-agent has an explicit task boundary.
73
+ - **Review results** when summaries arrive. Check for merge conflicts between parallel agents, then verify with `tsc --noEmit`, tests, or manual inspection.