aiwcli 0.15.5 → 0.15.7

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 (299) hide show
  1. package/README.md +6 -3
  2. package/dist/capabilities/branch/adapters.d.ts +2 -0
  3. package/dist/capabilities/branch/adapters.js +21 -0
  4. package/dist/capabilities/branch/contracts.d.ts +57 -0
  5. package/dist/capabilities/branch/contracts.js +1 -0
  6. package/dist/capabilities/branch/control-plane.d.ts +2 -0
  7. package/dist/capabilities/branch/control-plane.js +343 -0
  8. package/dist/capabilities/branch/runtime-core.d.ts +5 -0
  9. package/dist/capabilities/branch/runtime-core.js +36 -0
  10. package/dist/capabilities/installation/control-plane/clean-command.d.ts +41 -0
  11. package/dist/capabilities/installation/control-plane/clean-command.js +196 -0
  12. package/dist/capabilities/installation/control-plane/clear-command.d.ts +160 -0
  13. package/dist/capabilities/installation/control-plane/clear-command.js +1220 -0
  14. package/dist/capabilities/installation/control-plane/init-command.d.ts +81 -0
  15. package/dist/capabilities/installation/control-plane/init-command.js +449 -0
  16. package/dist/capabilities/launch/contracts.d.ts +51 -0
  17. package/dist/capabilities/launch/contracts.js +1 -0
  18. package/dist/capabilities/launch/control-plane/execute-launch.d.ts +2 -0
  19. package/dist/capabilities/launch/control-plane/execute-launch.js +222 -0
  20. package/dist/capabilities/launch/runtime-core/launch-options.d.ts +14 -0
  21. package/dist/capabilities/launch/runtime-core/launch-options.js +69 -0
  22. package/dist/cli/base-command.d.ts +18 -0
  23. package/dist/cli/base-command.js +55 -0
  24. package/dist/commands/branch.d.ts +0 -20
  25. package/dist/commands/branch.js +24 -416
  26. package/dist/commands/clean.d.ts +1 -41
  27. package/dist/commands/clean.js +1 -196
  28. package/dist/commands/clear.d.ts +1 -161
  29. package/dist/commands/clear.js +1 -1121
  30. package/dist/commands/init/index.d.ts +1 -98
  31. package/dist/commands/init/index.js +4 -478
  32. package/dist/commands/launch.d.ts +36 -11
  33. package/dist/commands/launch.js +135 -159
  34. package/dist/lib/base-command.d.ts +1 -114
  35. package/dist/lib/base-command.js +1 -153
  36. package/dist/lib/claude-settings-types.d.ts +31 -19
  37. package/dist/lib/context/context-formatter.d.ts +74 -0
  38. package/dist/lib/context/context-formatter.js +493 -0
  39. package/dist/lib/context/context-selector.d.ts +42 -0
  40. package/dist/lib/context/context-selector.js +451 -0
  41. package/dist/lib/context/context-store.d.ts +100 -0
  42. package/dist/lib/context/context-store.js +618 -0
  43. package/dist/lib/context/plan-manager.d.ts +54 -0
  44. package/dist/lib/context/plan-manager.js +282 -0
  45. package/dist/lib/context/task-tracker.d.ts +44 -0
  46. package/dist/lib/context/task-tracker.js +146 -0
  47. package/dist/lib/core-ide-base.d.ts +4 -0
  48. package/dist/lib/core-ide-base.js +77 -0
  49. package/dist/lib/core-installer.d.ts +5 -0
  50. package/dist/lib/core-installer.js +54 -0
  51. package/dist/lib/git-exclude-manager.d.ts +2 -2
  52. package/dist/lib/git-exclude-manager.js +3 -3
  53. package/dist/lib/hooks/hook-utils.d.ts +143 -0
  54. package/dist/lib/hooks/hook-utils.js +609 -0
  55. package/dist/lib/hooks/session-end-logic.d.ts +5 -0
  56. package/dist/lib/hooks/session-end-logic.js +63 -0
  57. package/dist/lib/hooks-merger.js +25 -19
  58. package/dist/lib/ide-path-resolver.d.ts +19 -7
  59. package/dist/lib/ide-path-resolver.js +25 -9
  60. package/dist/lib/install-state.d.ts +34 -0
  61. package/dist/lib/install-state.js +161 -0
  62. package/dist/lib/launch-options.d.ts +1 -0
  63. package/dist/lib/launch-options.js +1 -0
  64. package/dist/lib/lsp-patch.d.ts +12 -0
  65. package/dist/lib/lsp-patch.js +156 -0
  66. package/dist/lib/multiplexer.d.ts +57 -0
  67. package/dist/lib/multiplexer.js +19 -0
  68. package/dist/lib/multiplexers/psmux.d.ts +75 -0
  69. package/dist/lib/multiplexers/psmux.js +384 -0
  70. package/dist/lib/multiplexers/tmux.d.ts +44 -0
  71. package/dist/lib/multiplexers/tmux.js +262 -0
  72. package/dist/lib/mux-utils.d.ts +5 -0
  73. package/dist/lib/mux-utils.js +42 -0
  74. package/dist/lib/paths.d.ts +2 -2
  75. package/dist/lib/paths.js +2 -2
  76. package/dist/lib/platform-commands.d.ts +27 -0
  77. package/dist/lib/platform-commands.js +49 -0
  78. package/dist/lib/runtime/aiw-cli.d.ts +37 -0
  79. package/dist/lib/runtime/aiw-cli.js +74 -0
  80. package/dist/lib/runtime/atomic-write.d.ts +19 -0
  81. package/dist/lib/runtime/atomic-write.js +121 -0
  82. package/dist/lib/runtime/cli-args.d.ts +55 -0
  83. package/dist/lib/runtime/cli-args.js +185 -0
  84. package/dist/lib/runtime/constants.d.ts +56 -0
  85. package/dist/lib/runtime/constants.js +230 -0
  86. package/dist/lib/runtime/executable-policy.d.ts +16 -0
  87. package/dist/lib/runtime/executable-policy.js +57 -0
  88. package/dist/lib/runtime/git-state.d.ts +9 -0
  89. package/dist/lib/runtime/git-state.js +59 -0
  90. package/dist/lib/runtime/inference.d.ts +37 -0
  91. package/dist/lib/runtime/inference.js +262 -0
  92. package/dist/lib/runtime/lint-dispatch.d.ts +40 -0
  93. package/dist/lib/runtime/lint-dispatch.js +285 -0
  94. package/dist/lib/runtime/logger.d.ts +66 -0
  95. package/dist/lib/runtime/logger.js +201 -0
  96. package/dist/lib/runtime/models.d.ts +14 -0
  97. package/dist/lib/runtime/models.js +14 -0
  98. package/dist/lib/runtime/platform-adapter.d.ts +7 -0
  99. package/dist/lib/runtime/platform-adapter.js +21 -0
  100. package/dist/lib/runtime/preflight.d.ts +24 -0
  101. package/dist/lib/runtime/preflight.js +65 -0
  102. package/dist/lib/runtime/sentinel-ipc.d.ts +14 -0
  103. package/dist/lib/runtime/sentinel-ipc.js +67 -0
  104. package/dist/lib/runtime/state-io.d.ts +30 -0
  105. package/dist/lib/runtime/state-io.js +174 -0
  106. package/dist/lib/runtime/stop-words.d.ts +20 -0
  107. package/dist/lib/runtime/stop-words.js +150 -0
  108. package/dist/lib/runtime/subprocess-utils.d.ts +29 -0
  109. package/dist/lib/runtime/subprocess-utils.js +96 -0
  110. package/dist/lib/runtime/tmux-preflight.d.ts +13 -0
  111. package/dist/lib/runtime/tmux-preflight.js +78 -0
  112. package/dist/lib/runtime/utils.d.ts +54 -0
  113. package/dist/lib/runtime/utils.js +162 -0
  114. package/dist/lib/sentinel-wrapper.d.ts +9 -0
  115. package/dist/lib/sentinel-wrapper.js +20 -0
  116. package/dist/lib/shell-quoting.d.ts +5 -0
  117. package/dist/lib/shell-quoting.js +17 -0
  118. package/dist/lib/spawn-errors.d.ts +6 -0
  119. package/dist/lib/spawn-errors.js +15 -0
  120. package/dist/lib/spawn.js +5 -11
  121. package/dist/lib/template-installer.d.ts +4 -5
  122. package/dist/lib/template-installer.js +36 -34
  123. package/dist/lib/template-resolver.d.ts +6 -7
  124. package/dist/lib/template-resolver.js +26 -21
  125. package/dist/lib/template-settings-reconstructor.d.ts +7 -2
  126. package/dist/lib/template-settings-reconstructor.js +76 -45
  127. package/dist/lib/terminal-strategy.d.ts +11 -0
  128. package/dist/lib/terminal-strategy.js +49 -0
  129. package/dist/lib/terminal.d.ts +28 -0
  130. package/dist/lib/terminal.js +162 -112
  131. package/dist/lib/tmux-pane-placement.d.ts +17 -0
  132. package/dist/lib/tmux-pane-placement.js +58 -0
  133. package/dist/lib/tmux-primitives.d.ts +5 -0
  134. package/dist/lib/tmux-primitives.js +15 -0
  135. package/dist/lib/tmux-session.d.ts +32 -0
  136. package/dist/lib/tmux-session.js +86 -0
  137. package/dist/lib/tty-detection.js +1 -1
  138. package/dist/lib/types.d.ts +168 -0
  139. package/dist/lib/types.js +6 -0
  140. package/dist/lib/version.d.ts +1 -1
  141. package/dist/lib/version.js +1 -1
  142. package/dist/platform/launch.d.ts +10 -0
  143. package/dist/platform/launch.js +10 -0
  144. package/dist/templates/CLAUDE.md +31 -40
  145. package/dist/templates/cc-native/.claude/settings.json +27 -27
  146. package/dist/templates/cc-native/CC-NATIVE-README.md +1 -1
  147. package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +10 -9
  148. package/dist/templates/cc-native/_cc-native/CLAUDE.md +18 -18
  149. package/dist/templates/cc-native/_cc-native/artifacts/CLAUDE.md +3 -3
  150. package/dist/templates/cc-native/_cc-native/artifacts/lib/format.ts +14 -14
  151. package/dist/templates/cc-native/_cc-native/artifacts/lib/tracker.ts +1 -1
  152. package/dist/templates/cc-native/_cc-native/artifacts/lib/write.ts +3 -3
  153. package/dist/templates/cc-native/_cc-native/cc-native.config.json +3 -3
  154. package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +16 -15
  155. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +3 -3
  156. package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_subagent.ts +2 -2
  157. package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_write.ts +2 -2
  158. package/dist/templates/cc-native/_cc-native/hooks/mark_questions_asked.ts +3 -3
  159. package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +2 -2
  160. package/dist/templates/cc-native/_cc-native/hooks/validate_task_prompt.ts +3 -3
  161. package/dist/templates/cc-native/_cc-native/lib-ts/CLAUDE.md +8 -8
  162. package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +1 -1
  163. package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +4 -4
  164. package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +1 -1
  165. package/dist/templates/cc-native/_cc-native/lib-ts/config.ts +1 -1
  166. package/dist/templates/cc-native/_cc-native/lib-ts/debug.ts +1 -1
  167. package/dist/templates/cc-native/_cc-native/lib-ts/json-parser.ts +1 -1
  168. package/dist/templates/cc-native/_cc-native/lib-ts/plan-discovery.ts +2 -2
  169. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/logger.ts +1 -1
  170. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/retrieval-pipeline.ts +2 -2
  171. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/types.ts +1 -1
  172. package/dist/templates/cc-native/_cc-native/lib-ts/settings.ts +8 -8
  173. package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +3 -3
  174. package/dist/templates/cc-native/_cc-native/lib-ts/tsconfig.json +2 -2
  175. package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +3 -3
  176. package/dist/templates/cc-native/_cc-native/plan-review/CLAUDE.md +3 -1
  177. package/dist/templates/cc-native/_cc-native/plan-review/lib/__tests__/agent-selection.test.ts +345 -0
  178. package/dist/templates/cc-native/_cc-native/plan-review/lib/__tests__/preflight.test.ts +344 -0
  179. package/dist/templates/cc-native/_cc-native/plan-review/lib/agent-selection.ts +37 -15
  180. package/dist/templates/cc-native/_cc-native/plan-review/lib/corroboration.ts +16 -69
  181. package/dist/templates/cc-native/_cc-native/plan-review/lib/orchestrator.ts +1 -1
  182. package/dist/templates/cc-native/_cc-native/plan-review/lib/output-builder.ts +1 -1
  183. package/dist/templates/cc-native/_cc-native/plan-review/lib/plan-questions.ts +2 -2
  184. package/dist/templates/cc-native/_cc-native/plan-review/lib/preflight.ts +56 -26
  185. package/dist/templates/cc-native/_cc-native/plan-review/lib/review-pipeline.ts +7 -7
  186. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/agent.ts +4 -4
  187. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/base/base-agent.ts +3 -3
  188. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/index.ts +1 -1
  189. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/claude-agent.ts +2 -2
  190. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/codex-agent.ts +4 -4
  191. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/gemini-agent.ts +1 -1
  192. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/orchestrator-claude-agent.ts +5 -6
  193. package/dist/templates/core/.codex/workflows/codex.md +17 -0
  194. package/dist/templates/core/.codex/workflows/handoff.md +5 -0
  195. package/dist/templates/core/.codex/workflows/meta-plan.md +7 -0
  196. package/dist/templates/core/.cognition/AGENTS.md +5 -0
  197. package/dist/templates/core/.cognition/config.json +12 -0
  198. package/dist/templates/{_shared → core}/.windsurf/workflows/handoff.md +1 -1
  199. package/dist/templates/{_shared → core}/.windsurf/workflows/meta-plan.md +1 -1
  200. package/dist/templates/core/hooks-ts/_utils/git-state.ts +2 -0
  201. package/dist/templates/{_shared → core}/hooks-ts/archive_plan.ts +14 -23
  202. package/dist/templates/core/hooks-ts/codex_explorer.ts +160 -0
  203. package/dist/templates/{_shared → core}/hooks-ts/context_monitor.ts +23 -55
  204. package/dist/templates/{_shared → core}/hooks-ts/file-suggestion.ts +4 -3
  205. package/dist/templates/{_shared → core}/hooks-ts/lint_after_edit.ts +7 -9
  206. package/dist/templates/{_shared → core}/hooks-ts/pre_compact.ts +5 -5
  207. package/dist/templates/{_shared → core}/hooks-ts/session_end.ts +38 -78
  208. package/dist/templates/{_shared → core}/hooks-ts/session_start.ts +5 -5
  209. package/dist/templates/core/hooks-ts/task_create_capture.ts +32 -0
  210. package/dist/templates/{_shared → core}/hooks-ts/task_update_capture.ts +9 -24
  211. package/dist/templates/core/hooks-ts/user_prompt_submit.ts +46 -0
  212. package/dist/templates/{_shared → core}/lib-ts/CLAUDE.md +27 -16
  213. package/dist/templates/{_shared → core}/lib-ts/agent-exec/backends/headless.ts +3 -2
  214. package/dist/templates/{_shared → core}/lib-ts/agent-exec/backends/tmux.ts +44 -15
  215. package/dist/templates/{_shared → core}/lib-ts/agent-exec/base-agent.ts +6 -4
  216. package/dist/templates/{_shared → core}/lib-ts/agent-exec/execution-backend.ts +1 -1
  217. package/dist/templates/{_shared → core}/lib-ts/agent-exec/index.ts +2 -2
  218. package/dist/templates/{_shared → core}/lib-ts/agent-exec/structured-output.ts +4 -5
  219. package/dist/templates/{_shared → core}/lib-ts/context/CLAUDE.md +9 -6
  220. package/dist/templates/{_shared → core}/lib-ts/context/context-formatter.ts +16 -21
  221. package/dist/templates/{_shared → core}/lib-ts/context/context-selector.ts +8 -6
  222. package/dist/templates/{_shared → core}/lib-ts/context/context-store.ts +32 -20
  223. package/dist/templates/{_shared → core}/lib-ts/context/plan-manager.ts +19 -15
  224. package/dist/templates/{_shared → core}/lib-ts/context/task-tracker.ts +3 -3
  225. package/dist/templates/core/lib-ts/hooks/context-monitor-logic.ts +32 -0
  226. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/hooks}/hook-utils.ts +168 -41
  227. package/dist/templates/core/lib-ts/hooks/prompt-binding-logic.ts +80 -0
  228. package/dist/templates/core/lib-ts/hooks/session-end-logic.ts +93 -0
  229. package/dist/templates/core/lib-ts/package.json +19 -0
  230. package/dist/templates/core/lib-ts/runtime/agent-launcher.ts +295 -0
  231. package/dist/templates/core/lib-ts/runtime/aiw-cli.ts +106 -0
  232. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/atomic-write.ts +12 -7
  233. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/cli-args.ts +8 -6
  234. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/constants.ts +326 -324
  235. package/dist/templates/core/lib-ts/runtime/executable-policy.ts +89 -0
  236. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/git-state.ts +6 -4
  237. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/inference.ts +59 -10
  238. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/lint-dispatch.ts +25 -23
  239. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/logger.ts +32 -29
  240. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/models.ts +2 -2
  241. package/dist/templates/core/lib-ts/runtime/platform-adapter.ts +33 -0
  242. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/preflight.ts +4 -3
  243. package/dist/templates/core/lib-ts/runtime/sentinel-ipc.ts +91 -0
  244. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/state-io.ts +11 -7
  245. package/dist/templates/core/lib-ts/runtime/stop-words.ts +185 -0
  246. package/dist/templates/core/lib-ts/runtime/subprocess-utils.ts +147 -0
  247. package/dist/templates/core/lib-ts/runtime/tmux-preflight.ts +93 -0
  248. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/utils.ts +4 -3
  249. package/dist/templates/{_shared → core}/lib-ts/templates/formatters.ts +7 -5
  250. package/dist/templates/{_shared → core}/lib-ts/templates/plan-context.ts +2 -1
  251. package/dist/templates/{_shared → core}/lib-ts/tsconfig.json +3 -1
  252. package/dist/templates/{_shared → core}/lib-ts/types.ts +78 -77
  253. package/dist/templates/core/scripts/resolve-run.ts +61 -0
  254. package/dist/templates/{_shared → core}/scripts/resolve_context.ts +3 -3
  255. package/dist/templates/{_shared → core}/scripts/status_line.ts +25 -20
  256. package/dist/templates/core/skills/codex/CLAUDE.md +78 -0
  257. package/dist/templates/{_shared → core}/skills/codex/SKILL.md +21 -18
  258. package/dist/templates/{_shared → core}/skills/codex/lib/codex-watcher.ts +76 -103
  259. package/dist/templates/{_shared → core}/skills/codex/scripts/launch-codex.ts +119 -133
  260. package/dist/templates/{_shared → core}/skills/codex/scripts/watch-codex.ts +6 -4
  261. package/dist/templates/core/skills/devin/CLAUDE.md +65 -0
  262. package/dist/templates/core/skills/devin/SKILL.md +73 -0
  263. package/dist/templates/core/skills/devin/lib/devin-watcher.ts +280 -0
  264. package/dist/templates/core/skills/devin/scripts/launch-devin.ts +257 -0
  265. package/dist/templates/{_shared → core}/skills/handoff-system/CLAUDE.md +436 -433
  266. package/dist/templates/{_shared → core}/skills/handoff-system/lib/document-generator.ts +9 -7
  267. package/dist/templates/{_shared → core}/skills/handoff-system/lib/handoff-reader.ts +6 -4
  268. package/dist/templates/{_shared → core}/skills/handoff-system/scripts/resume_handoff.ts +10 -8
  269. package/dist/templates/{_shared → core}/skills/handoff-system/scripts/save_handoff.ts +12 -10
  270. package/dist/templates/{_shared → core}/skills/handoff-system/workflows/handoff-resume.md +2 -2
  271. package/dist/templates/{_shared → core}/skills/handoff-system/workflows/handoff.md +6 -5
  272. package/dist/templates/{_shared → core}/skills/meta-plan/CLAUDE.md +2 -1
  273. package/dist/templates/{_shared → core}/skills/meta-plan/workflows/meta-plan.md +8 -7
  274. package/oclif.manifest.json +89 -13
  275. package/package.json +13 -12
  276. package/dist/templates/_shared/.claude/settings.json +0 -120
  277. package/dist/templates/_shared/.claude/skills/codex/SKILL.md +0 -35
  278. package/dist/templates/_shared/.claude/skills/handoff/SKILL.md +0 -13
  279. package/dist/templates/_shared/.claude/skills/handoff-resume/SKILL.md +0 -13
  280. package/dist/templates/_shared/.claude/skills/meta-plan/SKILL.md +0 -43
  281. package/dist/templates/_shared/.codex/workflows/codex.md +0 -11
  282. package/dist/templates/_shared/.codex/workflows/handoff.md +0 -226
  283. package/dist/templates/_shared/.codex/workflows/meta-plan.md +0 -347
  284. package/dist/templates/_shared/hooks-ts/_utils/git-state.ts +0 -2
  285. package/dist/templates/_shared/hooks-ts/task_create_capture.ts +0 -48
  286. package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +0 -93
  287. package/dist/templates/_shared/lib-ts/base/launchers/tmux-launcher.ts +0 -173
  288. package/dist/templates/_shared/lib-ts/base/launchers/window-launcher.ts +0 -93
  289. package/dist/templates/_shared/lib-ts/base/launchers/wt-launcher.ts +0 -64
  290. package/dist/templates/_shared/lib-ts/base/pane-launcher.ts +0 -55
  291. package/dist/templates/_shared/lib-ts/base/sentinel-ipc.ts +0 -87
  292. package/dist/templates/_shared/lib-ts/base/stop-words.ts +0 -184
  293. package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +0 -249
  294. package/dist/templates/_shared/lib-ts/base/tmux-driver.ts +0 -341
  295. package/dist/templates/_shared/lib-ts/base/tmux-pane-placement.ts +0 -78
  296. package/dist/templates/_shared/lib-ts/package.json +0 -20
  297. package/dist/templates/_shared/scripts/resolve-run.ts +0 -62
  298. package/dist/templates/_shared/skills/codex/CLAUDE.md +0 -70
  299. /package/dist/templates/{_shared → core}/lib-ts/agent-exec/backends/index.ts +0 -0
@@ -0,0 +1,80 @@
1
+ import { safeMaybeActivate, logInfo, logWarn } from "./hook-utils.js";
2
+ import { buildContextInventory } from "../context/context-formatter.js";
3
+ import { BlockRequest, determineContext } from "../context/context-selector.js";
4
+ import {
5
+ bindSession,
6
+ getContextBySessionId,
7
+ saveState,
8
+ } from "../context/context-store.js";
9
+ import type { ContextState } from "../types.js";
10
+
11
+ export interface PromptBindingResult {
12
+ outputs: string[];
13
+ blockedReason?: string;
14
+ }
15
+
16
+ export function shouldClearHandoff(state: ContextState): boolean {
17
+ return Boolean(state.handoff_path);
18
+ }
19
+
20
+ export async function executePromptBinding(
21
+ prompt: string | undefined,
22
+ sessionId: string,
23
+ permissionMode: string,
24
+ projectRoot: string,
25
+ ): Promise<PromptBindingResult> {
26
+ const outputs: string[] = [];
27
+ const existingCtx = getContextBySessionId(sessionId, projectRoot);
28
+
29
+ if (existingCtx) {
30
+ safeMaybeActivate(
31
+ existingCtx.id,
32
+ permissionMode,
33
+ projectRoot,
34
+ "user_prompt_submit",
35
+ );
36
+ return { outputs };
37
+ }
38
+
39
+ if (!prompt) return { outputs };
40
+
41
+ try {
42
+ const [contextId, method, outputText] = await determineContext(
43
+ prompt,
44
+ sessionId,
45
+ projectRoot,
46
+ );
47
+
48
+ if (contextId) {
49
+ bindSession(contextId, sessionId, projectRoot);
50
+ safeMaybeActivate(contextId, permissionMode, projectRoot, "user_prompt_submit");
51
+
52
+ const state = getContextBySessionId(sessionId, projectRoot);
53
+ if (state && shouldClearHandoff(state)) {
54
+ state.handoff_path = null;
55
+ saveState(state.id, state, projectRoot);
56
+ }
57
+
58
+ logInfo("user_prompt_submit", `Context ${contextId} via ${method}`);
59
+ }
60
+
61
+ if (outputText) outputs.push(outputText);
62
+
63
+ try {
64
+ const boundState = getContextBySessionId(sessionId, projectRoot);
65
+ if (boundState) {
66
+ const inventory = buildContextInventory(boundState, projectRoot);
67
+ if (inventory) outputs.push(inventory);
68
+ }
69
+ } catch (error) {
70
+ logWarn("user_prompt_submit", `Inventory failed (non-critical): ${error}`);
71
+ }
72
+ } catch (error) {
73
+ if (error instanceof BlockRequest) {
74
+ return { outputs, blockedReason: (error as Error).message };
75
+ }
76
+ throw error;
77
+ }
78
+
79
+ return { outputs };
80
+ }
@@ -0,0 +1,93 @@
1
+ import * as crypto from "node:crypto";
2
+
3
+ import {
4
+ extractPlanAnchors,
5
+ generatePlanId,
6
+ normalizePlanContent,
7
+ } from "../context/plan-manager.js";
8
+ import { nowIso } from "../runtime/utils.js";
9
+ import type { ContextState, GitState, LastSession } from "../types.js";
10
+
11
+ function formatArchiveTimestamp(date: Date): string {
12
+ return (
13
+ `${date.getFullYear()}-` +
14
+ `${String(date.getMonth() + 1).padStart(2, "0")}-` +
15
+ `${String(date.getDate()).padStart(2, "0")}-` +
16
+ `${String(date.getHours()).padStart(2, "0")}` +
17
+ `${String(date.getMinutes()).padStart(2, "0")}`
18
+ );
19
+ }
20
+
21
+ function resolveArtifactType(state: ContextState): "plan" | "handoff" | null {
22
+ if (state.next_artifact_type) return state.next_artifact_type;
23
+
24
+ const hasPlan = Boolean(state.plan_path && state.plan_hash);
25
+ const hasHandoff = Boolean(state.handoff_path);
26
+
27
+ if (hasPlan && hasHandoff) return "plan";
28
+ if (hasPlan) return "plan";
29
+ if (hasHandoff) return "handoff";
30
+ return null;
31
+ }
32
+
33
+ export function computePlanFallback(
34
+ state: ContextState,
35
+ planContent: string,
36
+ ): Partial<ContextState> {
37
+ const normalized = normalizePlanContent(planContent);
38
+ const planHash = crypto
39
+ .createHash("sha256")
40
+ .update(normalized, "utf8")
41
+ .digest("hex")
42
+ .slice(0, 12);
43
+
44
+ return {
45
+ plan_hash: planHash,
46
+ plan_signature: planContent.slice(0, 200),
47
+ plan_id: generatePlanId(),
48
+ plan_anchors: extractPlanAnchors(planContent),
49
+ work_consumed: state.work_consumed ?? false,
50
+ };
51
+ }
52
+
53
+ export function shouldStage(
54
+ state: ContextState,
55
+ permissionMode: string,
56
+ ): boolean {
57
+ const artifactType = resolveArtifactType(state);
58
+ const canStage = state.mode === "active" || permissionMode === "plan";
59
+ return Boolean(artifactType && canStage && !state.work_consumed);
60
+ }
61
+
62
+ export function buildSessionMetadata(
63
+ sessionId: string,
64
+ source: string,
65
+ transcriptPath: string | undefined,
66
+ gitState?: GitState,
67
+ ): LastSession {
68
+ return {
69
+ session_id: sessionId,
70
+ save_reason: source,
71
+ saved_at: nowIso(),
72
+ ...(transcriptPath ? { transcript_path: transcriptPath } : {}),
73
+ git_state: gitState ?? {},
74
+ };
75
+ }
76
+
77
+ export function generateArchiveFilename(
78
+ sessionId: string,
79
+ date: Date,
80
+ existingNames: Iterable<string>,
81
+ ): string {
82
+ const existing = new Set(existingNames);
83
+ const timestamp = formatArchiveTimestamp(date);
84
+
85
+ let archiveName = `${timestamp}-${sessionId}.jsonl`;
86
+ let counter = 2;
87
+ while (existing.has(archiveName)) {
88
+ archiveName = `${timestamp}-${sessionId}-${counter}.jsonl`;
89
+ counter += 1;
90
+ }
91
+
92
+ return archiveName;
93
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "lib-ts-tests",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "test": "vitest run",
7
+ "test:unit": "vitest run '__tests__/runtime/**/*.test.ts' '__tests__/templates/**/*.test.ts'",
8
+ "test:contract": "vitest run '__tests__/context/**/*.test.ts' '__tests__/handoff/**/*.test.ts'",
9
+ "test:integration": "vitest run '__tests__/integration/**/*.test.ts'",
10
+ "test:parity": "vitest run '__tests__/integration/python-parity.test.ts'"
11
+ },
12
+ "devDependencies": {
13
+ "chai": "^5.0.0",
14
+ "@types/sinon": "^17.0.0",
15
+ "sinon": "^17.0.0",
16
+ "typescript": "^5.0.0",
17
+ "vitest": "^3.2.4"
18
+ }
19
+ }
@@ -0,0 +1,295 @@
1
+ /**
2
+ * Shared agent-launcher utilities used by Codex, Devin, and future agent skills.
3
+ * Extracted from codex skill to avoid duplication across agent launch scripts.
4
+ */
5
+
6
+ import * as fs from "node:fs";
7
+ import * as os from "node:os";
8
+ import path from "node:path";
9
+
10
+ import { logDebug, logWarn } from "./logger.js";
11
+ import { execFileAsync, findExecutable } from "./subprocess-utils.js";
12
+ import { buildExternalAgentContext } from "../context/context-formatter.js";
13
+ import { getContextBySessionId, getContext } from "../context/context-store.js";
14
+ import type { ContextState } from "../types.js";
15
+
16
+ // ---------------------------------------------------------------------------
17
+ // Constants
18
+ // ---------------------------------------------------------------------------
19
+
20
+ export const POLL_INTERVAL_MS = 2000;
21
+ export const POLL_TIMEOUT_MS = 3000;
22
+ export const WAIT_TIMEOUT_MS_DEFAULT = 14_400_000;
23
+
24
+ // ---------------------------------------------------------------------------
25
+ // Types
26
+ // ---------------------------------------------------------------------------
27
+
28
+ type PaneBackend = "tmux" | "window" | "exec";
29
+
30
+ export interface PaneWatchTarget {
31
+ backend?: PaneBackend;
32
+ paneId?: string;
33
+ sentinelPath?: string;
34
+ }
35
+
36
+ // ---------------------------------------------------------------------------
37
+ // Generic Helpers
38
+ // ---------------------------------------------------------------------------
39
+
40
+ export function sleep(ms: number): Promise<void> {
41
+ return new Promise((resolve) => {
42
+ setTimeout(resolve, ms);
43
+ });
44
+ }
45
+
46
+ export function persistSummary(
47
+ summary: string,
48
+ prefix: string,
49
+ sessionId?: string,
50
+ ): string | null {
51
+ try {
52
+ const suffix = sessionId
53
+ ? sessionId.replaceAll(/[^a-zA-Z0-9_-]/g, "").slice(0, 8)
54
+ : String(process.pid);
55
+ const filePath = path.join(
56
+ os.tmpdir(),
57
+ `${prefix}-summary-${Date.now()}-${suffix}.md`,
58
+ );
59
+ fs.writeFileSync(filePath, summary, "utf8");
60
+ return filePath.replaceAll("\\", "/");
61
+ } catch (error) {
62
+ logWarn("agent-launcher", `Failed to persist summary: ${String(error)}`);
63
+ return null;
64
+ }
65
+ }
66
+
67
+ // ---------------------------------------------------------------------------
68
+ // Plan Discovery
69
+ // ---------------------------------------------------------------------------
70
+
71
+ /** Fallback plan discovery: scan all context plan dirs by mtime. */
72
+ export function findLatestPlanByMtime(projectRoot: string): string | null {
73
+ const contextsDir = path.join(projectRoot, "_output", "contexts");
74
+ if (!fs.existsSync(contextsDir)) return null;
75
+
76
+ let best: { path: string; mtime: number } | null = null;
77
+
78
+ for (const ctxEntry of fs.readdirSync(contextsDir)) {
79
+ if (ctxEntry.startsWith("_")) continue;
80
+ const plansDir = path.join(contextsDir, ctxEntry, "plans");
81
+ if (!fs.existsSync(plansDir)) continue;
82
+
83
+ for (const file of fs.readdirSync(plansDir)) {
84
+ if (!file.endsWith(".md")) continue;
85
+ const fullPath = path.join(plansDir, file);
86
+ try {
87
+ const mtime = fs.statSync(fullPath).mtimeMs;
88
+ if (!best || mtime > best.mtime) {
89
+ best = { path: fullPath, mtime };
90
+ }
91
+ } catch { /* skip unreadable */ }
92
+ }
93
+ }
94
+
95
+ return best?.path ?? null;
96
+ }
97
+
98
+ // ---------------------------------------------------------------------------
99
+ // Bootstrap Prompt Construction
100
+ // ---------------------------------------------------------------------------
101
+
102
+ export function buildFileModeBootstrapPrompt(
103
+ targetPath: string,
104
+ sourceLabel: "plan" | "file",
105
+ extraPrompt?: string,
106
+ orientation?: string,
107
+ ): string {
108
+ const absolutePath = path.resolve(targetPath);
109
+ const sourceTitle = sourceLabel === "plan" ? "Plan Source" : "File Source";
110
+ const sections: string[] = ["## Startup Brief", ""];
111
+
112
+ if (orientation?.trim()) {
113
+ sections.push(orientation.trim(), "", "---", "");
114
+ }
115
+
116
+ sections.push(
117
+ `## ${sourceTitle}`,
118
+ "",
119
+ `Primary input path: ${absolutePath}`,
120
+ "",
121
+ "Read this file directly from disk before taking action.",
122
+ "Treat its contents as the source of truth.",
123
+ "Do not ask for the file contents to be pasted inline.",
124
+ );
125
+
126
+ if (extraPrompt?.trim()) {
127
+ sections.push("", "## Additional Instructions", "", extraPrompt.trim());
128
+ }
129
+
130
+ return sections.join("\n");
131
+ }
132
+
133
+ // ---------------------------------------------------------------------------
134
+ // Context Resolution
135
+ // ---------------------------------------------------------------------------
136
+
137
+ export function resolveContextForLaunch(
138
+ contextFlag: string | undefined,
139
+ projectRoot: string,
140
+ ): ContextState | null {
141
+ if (contextFlag) {
142
+ return getContext(contextFlag, projectRoot) ?? null;
143
+ }
144
+ const sessionId = process.env.CLAUDE_SESSION_ID;
145
+ if (sessionId) {
146
+ return getContextBySessionId(sessionId, projectRoot) ?? null;
147
+ }
148
+ return null;
149
+ }
150
+
151
+ // ---------------------------------------------------------------------------
152
+ // Prompt File Writers
153
+ // ---------------------------------------------------------------------------
154
+
155
+ export interface WritePromptFileOpts {
156
+ ctx?: ContextState | null;
157
+ extraPrompt?: string;
158
+ projectRoot: string;
159
+ tempFilePrefix: string;
160
+ }
161
+
162
+ export interface WriteFileRefPromptFileOpts extends WritePromptFileOpts {
163
+ fileReferencePath: string;
164
+ label: "plan" | "file";
165
+ }
166
+
167
+ export interface WriteInlinePromptFileOpts extends WritePromptFileOpts {
168
+ text: string;
169
+ }
170
+
171
+ /**
172
+ * Build a file-reference bootstrap prompt and write it to a temp file.
173
+ * Returns the temp file path.
174
+ */
175
+ export function writeFileRefPromptFile(opts: WriteFileRefPromptFileOpts): string {
176
+ let orientation = "";
177
+ if (opts.ctx) {
178
+ try {
179
+ orientation = buildExternalAgentContext(opts.ctx, opts.projectRoot);
180
+ } catch {
181
+ logWarn("agent-launcher", `Context orientation build failed for ${opts.ctx.id}`);
182
+ }
183
+ }
184
+
185
+ const bootstrap = buildFileModeBootstrapPrompt(
186
+ opts.fileReferencePath,
187
+ opts.label,
188
+ opts.extraPrompt,
189
+ orientation,
190
+ );
191
+ const tempFile = path.join(os.tmpdir(), `${opts.tempFilePrefix}-file-ref-${Date.now()}.md`);
192
+ fs.writeFileSync(tempFile, bootstrap, "utf8");
193
+ return tempFile;
194
+ }
195
+
196
+ /**
197
+ * Write inline text to a temp file, prepend context orientation, append extra prompt.
198
+ * Returns the temp file path.
199
+ */
200
+ export function writeInlinePromptFile(opts: WriteInlinePromptFileOpts): string {
201
+ let content = opts.text;
202
+
203
+ if (opts.ctx) {
204
+ try {
205
+ const orientation = buildExternalAgentContext(opts.ctx, opts.projectRoot);
206
+ content = `${orientation}\n\n---\n\n${content}`;
207
+ } catch {
208
+ logWarn("agent-launcher", `Context orientation prepend failed for ${opts.ctx.id}`);
209
+ }
210
+ }
211
+
212
+ if (opts.extraPrompt?.trim()) {
213
+ content = `${content}\n\n---\n\n## Additional Instructions\n\n${opts.extraPrompt}`;
214
+ }
215
+
216
+ const tempFile = path.join(os.tmpdir(), `${opts.tempFilePrefix}-prompt-${Date.now()}.md`);
217
+ fs.writeFileSync(tempFile, content, "utf8");
218
+ return tempFile;
219
+ }
220
+
221
+ // ---------------------------------------------------------------------------
222
+ // Pane Watching
223
+ // ---------------------------------------------------------------------------
224
+
225
+ async function waitForSentinelClose(sentinelPath: string, timeoutMs: number): Promise<void> {
226
+ const deadline = Date.now() + timeoutMs;
227
+ while (true) {
228
+ if (fs.existsSync(sentinelPath)) return;
229
+ if (Date.now() >= deadline) {
230
+ logDebug("agent-launcher", `watch timeout reached waiting for sentinel ${sentinelPath}`);
231
+ return;
232
+ }
233
+
234
+ const remainingMs = deadline - Date.now();
235
+ await sleep(Math.max(0, Math.min(POLL_INTERVAL_MS, remainingMs)));
236
+ }
237
+ }
238
+
239
+ function normalizeWatchTarget(target: string | PaneWatchTarget): PaneWatchTarget {
240
+ if (typeof target === "string") {
241
+ return { backend: "tmux", paneId: target };
242
+ }
243
+ return target;
244
+ }
245
+
246
+ export async function waitForPaneClose(
247
+ target: string | PaneWatchTarget,
248
+ timeoutMs = WAIT_TIMEOUT_MS_DEFAULT,
249
+ ): Promise<void> {
250
+ const watch = normalizeWatchTarget(target);
251
+
252
+ if (watch.sentinelPath) {
253
+ await waitForSentinelClose(watch.sentinelPath, timeoutMs);
254
+ return;
255
+ }
256
+
257
+ const backend = watch.backend ?? "tmux";
258
+ const paneId = watch.paneId ?? "";
259
+
260
+ if (backend !== "tmux") {
261
+ logDebug("agent-launcher", `No pane watcher for backend=${backend}; continuing without wait`);
262
+ return;
263
+ }
264
+
265
+ if (!paneId) return;
266
+
267
+ const tmuxPath = findExecutable("tmux");
268
+ if (!tmuxPath) {
269
+ logWarn("agent-launcher", `tmux unavailable while watching pane ${paneId}`);
270
+ return;
271
+ }
272
+
273
+ const deadline = Date.now() + timeoutMs;
274
+ while (true) {
275
+ if (Date.now() >= deadline) {
276
+ logDebug("agent-launcher", `watch timeout reached for pane ${paneId} after ${timeoutMs}ms`);
277
+ return;
278
+ }
279
+
280
+ const result = await execFileAsync(tmuxPath, ["list-panes", "-a", "-F", "#{pane_id}"], {
281
+ timeout: POLL_TIMEOUT_MS,
282
+ });
283
+
284
+ if (result.exitCode !== 0) {
285
+ logDebug("agent-launcher", `list-panes failed; assuming pane closed (${result.stderr.trim() || "no stderr"})`);
286
+ return;
287
+ }
288
+
289
+ const activePaneIds = result.stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
290
+ if (!activePaneIds.includes(paneId)) return;
291
+
292
+ const remainingMs = deadline - Date.now();
293
+ await sleep(Math.max(0, Math.min(POLL_INTERVAL_MS, remainingMs)));
294
+ }
295
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Helper to discover and invoke the `aiw` CLI binary from template scripts.
3
+ *
4
+ * Reads the resolved binary path from `.aiwcli/.aiw-bin-path` (written by `aiw init`).
5
+ * Falls back to `aiw` on PATH if the file is missing.
6
+ */
7
+
8
+ import * as fs from "node:fs";
9
+ import path from "node:path";
10
+
11
+ import { getProjectRoot } from "./constants.js";
12
+ import { execFileAsync, type ExecResult } from "./subprocess-utils.js";
13
+
14
+ function resolveAiwBin(cwd?: string): string {
15
+ const projectRoot = getProjectRoot(cwd ?? process.cwd());
16
+ const binPathFile = path.join(projectRoot, ".aiwcli", ".aiw-bin-path");
17
+ try {
18
+ const binPath = fs.readFileSync(binPathFile, "utf8").trim();
19
+ if (binPath && fs.existsSync(binPath)) return binPath;
20
+ } catch {
21
+ // Fall through to PATH lookup
22
+ }
23
+
24
+ return "aiw";
25
+ }
26
+
27
+ export interface AiwLaunchOptions {
28
+ /** Launch codex instead of claude. */
29
+ codex?: boolean;
30
+ /** Working directory. */
31
+ cwd?: string;
32
+ /** Extra env vars to inject. */
33
+ env?: Record<string, string>;
34
+ /** Return JSON output. */
35
+ json?: boolean;
36
+ /** Path to prompt file. */
37
+ promptPath?: string;
38
+ /** Split direction: auto, h, or v. */
39
+ split?: "auto" | "h" | "v";
40
+ /** Timeout in ms (only relevant with --wait). */
41
+ timeoutMs?: number;
42
+ /** Block until pane exits. */
43
+ wait?: boolean;
44
+ }
45
+
46
+ export interface AiwLaunchResult {
47
+ backend: string;
48
+ exitCode: null | number;
49
+ launched: boolean;
50
+ paneId: null | string;
51
+ reason: null | string;
52
+ sentinelPath: null | string;
53
+ }
54
+
55
+ /**
56
+ * Shell out to `aiw launch` with structured options.
57
+ * Returns parsed JSON result when --json is used.
58
+ */
59
+ export async function aiwLaunch(options: AiwLaunchOptions): Promise<AiwLaunchResult> {
60
+ const bin = resolveAiwBin(options.cwd);
61
+ const args = ["launch"];
62
+
63
+ if (options.codex) args.push("--codex");
64
+ if (options.wait) args.push("--wait");
65
+ args.push("--json");
66
+ if (options.split) args.push("--split", options.split);
67
+ if (options.env && Object.keys(options.env).length > 0) {
68
+ args.push("--env", JSON.stringify(options.env));
69
+ }
70
+
71
+ if (options.promptPath) args.push("--prompt-path", options.promptPath);
72
+
73
+ const result = await execFileAsync(bin, args, {
74
+ timeout: options.timeoutMs ?? 14_400_000,
75
+ env: process.env as Record<string, string>,
76
+ shell: process.platform === "win32",
77
+ });
78
+
79
+ return parseJsonResult(result);
80
+ }
81
+
82
+ function parseJsonResult(result: ExecResult): AiwLaunchResult {
83
+ try {
84
+ const lines = result.stdout.trim().split(/\r?\n/);
85
+ const lastLine = lines.at(-1) ?? "";
86
+ const parsed = JSON.parse(lastLine);
87
+ return {
88
+ launched: Boolean(parsed.launched),
89
+ backend: String(parsed.backend ?? "exec"),
90
+ paneId: parsed.paneId ?? null,
91
+ sentinelPath: parsed.sentinelPath ?? null,
92
+ exitCode: typeof parsed.exitCode === "number" ? parsed.exitCode : null,
93
+ reason: parsed.reason ?? null,
94
+ };
95
+ } catch {
96
+ return {
97
+ launched: false,
98
+ backend: "exec",
99
+ paneId: null,
100
+ sentinelPath: null,
101
+ exitCode: result.exitCode,
102
+ reason: `Failed to parse aiw launch output: ${result.stderr || result.stdout}`,
103
+ };
104
+ }
105
+ }
106
+
@@ -8,7 +8,7 @@
8
8
  import * as crypto from "node:crypto";
9
9
  import * as fs from "node:fs";
10
10
  import * as _os from "node:os";
11
- import * as path from "node:path";
11
+ import path from "node:path";
12
12
 
13
13
  /**
14
14
  * Write file atomically with retry logic.
@@ -21,6 +21,7 @@ export function atomicWrite(
21
21
  content: string,
22
22
  maxAttempts = 2,
23
23
  backoffMs: number[] = [500, 1000],
24
+ fsync = true,
24
25
  ): [boolean, null | string] {
25
26
  // Ensure parent directory exists
26
27
  const dir = path.dirname(filePath);
@@ -36,8 +37,8 @@ export function atomicWrite(
36
37
  // Write to temp file
37
38
  const fd = fs.openSync(tmpPath, "w");
38
39
  try {
39
- fs.writeSync(fd, content, undefined, "utf-8");
40
- fs.fsyncSync(fd);
40
+ fs.writeSync(fd, content, undefined, "utf8");
41
+ if (fsync) fs.fsyncSync(fd);
41
42
  } finally {
42
43
  fs.closeSync(fd);
43
44
  }
@@ -53,7 +54,7 @@ export function atomicWrite(
53
54
  fs.renameSync(tmpPath, filePath);
54
55
 
55
56
  return [true, null];
56
- } catch (error: any) {
57
+ } catch (error: unknown) {
57
58
  // Clean up temp file
58
59
  try {
59
60
  fs.unlinkSync(tmpPath);
@@ -85,6 +86,7 @@ export function atomicAppend(
85
86
  content: string,
86
87
  maxAttempts = 2,
87
88
  backoffMs: number[] = [500, 1000],
89
+ fsync = true,
88
90
  ): [boolean, null | string] {
89
91
  // Ensure parent directory exists
90
92
  const dir = path.dirname(filePath);
@@ -96,8 +98,8 @@ export function atomicAppend(
96
98
  try {
97
99
  const fd = fs.openSync(filePath, "a");
98
100
  try {
99
- fs.writeSync(fd, content, undefined, "utf-8");
100
- fs.fsyncSync(fd);
101
+ fs.writeSync(fd, content, undefined, "utf8");
102
+ if (fsync) fs.fsyncSync(fd);
101
103
  } finally {
102
104
  fs.closeSync(fd);
103
105
  }
@@ -112,7 +114,7 @@ export function atomicAppend(
112
114
  }
113
115
 
114
116
  return [true, null];
115
- } catch (error: any) {
117
+ } catch (error: unknown) {
116
118
  if (attempt < maxAttempts - 1) {
117
119
  const waitMs = backoffMs[Math.min(attempt, backoffMs.length - 1)] ?? backoffMs.at(-1) ?? 500;
118
120
  sleepSync(waitMs);
@@ -136,3 +138,6 @@ function sleepSync(ms: number): void {
136
138
  const i32 = new Int32Array(sab);
137
139
  Atomics.wait(i32, 0, 0, ms);
138
140
  }
141
+
142
+
143
+
@@ -4,11 +4,11 @@
4
4
  * platform quoting, model tier resolution, and env setup.
5
5
  */
6
6
 
7
+ import { CLAUDE_MODELS, CODEX_MODELS } from "./models.js";
7
8
  import type { PreflightCommandConfig } from "./preflight.js";
8
9
  import { getInternalSubprocessEnv, shellQuoteWin } from "./subprocess-utils.js";
9
- import { CLAUDE_MODELS, CODEX_MODELS } from "./models.js";
10
10
 
11
- export { CLAUDE_MODELS, CODEX_MODELS };
11
+
12
12
 
13
13
  // ---------------------------------------------------------------------------
14
14
  // Types
@@ -258,7 +258,7 @@ export function reviewSpec(
258
258
  model,
259
259
  mode: "structured",
260
260
  jsonSchema: schema,
261
- systemPrompt,
261
+ ...(systemPrompt ? {systemPrompt} : {}),
262
262
  };
263
263
  }
264
264
 
@@ -270,9 +270,9 @@ export function codexReplSpec(
270
270
  return {
271
271
  provider: "codex",
272
272
  mode: "repl",
273
- model,
274
- sandbox,
275
- yolo,
273
+ ...(model ? {model} : {}),
274
+ ...(sandbox ? {sandbox} : {}),
275
+ ...(yolo !== undefined ? {yolo} : {}),
276
276
  };
277
277
  }
278
278
 
@@ -285,3 +285,5 @@ export function preflightCommandConfig(provider: CliProvider): PreflightCommandC
285
285
  input,
286
286
  };
287
287
  }
288
+
289
+ export {CLAUDE_MODELS, CODEX_MODELS} from "./models.js";