oh-my-codex 0.14.4 → 0.15.1

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 (614) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/Cargo.lock +6 -6
  3. package/Cargo.toml +2 -1
  4. package/README.md +40 -7
  5. package/crates/omx-explore/Cargo.toml +1 -0
  6. package/crates/omx-explore/src/main.rs +246 -24
  7. package/crates/omx-mux/Cargo.toml +1 -0
  8. package/crates/omx-runtime/Cargo.toml +1 -0
  9. package/crates/omx-runtime-core/Cargo.toml +1 -0
  10. package/crates/omx-runtime-core/src/dispatch.rs +2 -1
  11. package/crates/omx-runtime-core/src/engine.rs +2 -2
  12. package/crates/omx-runtime-core/src/mailbox.rs +2 -1
  13. package/crates/omx-sparkshell/Cargo.toml +1 -0
  14. package/crates/omx-sparkshell/src/codex_bridge.rs +1 -0
  15. package/crates/omx-sparkshell/src/prompt.rs +1 -0
  16. package/crates/omx-sparkshell/src/threshold.rs +1 -0
  17. package/dist/agents/__tests__/native-config.test.js +98 -4
  18. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  19. package/dist/agents/native-config.d.ts +4 -0
  20. package/dist/agents/native-config.d.ts.map +1 -1
  21. package/dist/agents/native-config.js +19 -3
  22. package/dist/agents/native-config.js.map +1 -1
  23. package/dist/agents/policy.d.ts +10 -0
  24. package/dist/agents/policy.d.ts.map +1 -0
  25. package/dist/agents/policy.js +61 -0
  26. package/dist/agents/policy.js.map +1 -0
  27. package/dist/catalog/__tests__/generator.test.js +2 -0
  28. package/dist/catalog/__tests__/generator.test.js.map +1 -1
  29. package/dist/catalog/__tests__/plugin-bundle-ssot.test.d.ts +2 -0
  30. package/dist/catalog/__tests__/plugin-bundle-ssot.test.d.ts.map +1 -0
  31. package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +72 -0
  32. package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -0
  33. package/dist/catalog/installable.d.ts +5 -0
  34. package/dist/catalog/installable.d.ts.map +1 -0
  35. package/dist/catalog/installable.js +13 -0
  36. package/dist/catalog/installable.js.map +1 -0
  37. package/dist/catalog/skill-mirror.d.ts +20 -0
  38. package/dist/catalog/skill-mirror.d.ts.map +1 -0
  39. package/dist/catalog/skill-mirror.js +104 -0
  40. package/dist/catalog/skill-mirror.js.map +1 -0
  41. package/dist/cli/__tests__/ask.test.js +4 -1
  42. package/dist/cli/__tests__/ask.test.js.map +1 -1
  43. package/dist/cli/__tests__/codex-plugin-layout.test.d.ts +2 -0
  44. package/dist/cli/__tests__/codex-plugin-layout.test.d.ts.map +1 -0
  45. package/dist/cli/__tests__/codex-plugin-layout.test.js +210 -0
  46. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -0
  47. package/dist/cli/__tests__/doctor-team.test.js +46 -1
  48. package/dist/cli/__tests__/doctor-team.test.js.map +1 -1
  49. package/dist/cli/__tests__/doctor-warning-copy.test.js +225 -111
  50. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  51. package/dist/cli/__tests__/exec.test.js +96 -1
  52. package/dist/cli/__tests__/exec.test.js.map +1 -1
  53. package/dist/cli/__tests__/explore.test.js +26 -9
  54. package/dist/cli/__tests__/explore.test.js.map +1 -1
  55. package/dist/cli/__tests__/index.test.js +301 -7
  56. package/dist/cli/__tests__/index.test.js.map +1 -1
  57. package/dist/cli/__tests__/launch-fallback.test.js +358 -4
  58. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  59. package/dist/cli/__tests__/list.test.d.ts +2 -0
  60. package/dist/cli/__tests__/list.test.d.ts.map +1 -0
  61. package/dist/cli/__tests__/list.test.js +38 -0
  62. package/dist/cli/__tests__/list.test.js.map +1 -0
  63. package/dist/cli/__tests__/mcp-parity.test.js +86 -0
  64. package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
  65. package/dist/cli/__tests__/mcp-serve.test.d.ts +2 -0
  66. package/dist/cli/__tests__/mcp-serve.test.d.ts.map +1 -0
  67. package/dist/cli/__tests__/mcp-serve.test.js +38 -0
  68. package/dist/cli/__tests__/mcp-serve.test.js.map +1 -0
  69. package/dist/cli/__tests__/nested-help-routing.test.js +1 -0
  70. package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
  71. package/dist/cli/__tests__/package-bin-contract.test.js +58 -3
  72. package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
  73. package/dist/cli/__tests__/question.test.js +209 -5
  74. package/dist/cli/__tests__/question.test.js.map +1 -1
  75. package/dist/cli/__tests__/setup-agents-overwrite.test.js +146 -3
  76. package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
  77. package/dist/cli/__tests__/setup-install-mode.test.d.ts +2 -0
  78. package/dist/cli/__tests__/setup-install-mode.test.d.ts.map +1 -0
  79. package/dist/cli/__tests__/setup-install-mode.test.js +873 -0
  80. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -0
  81. package/dist/cli/__tests__/setup-prompts-overwrite.test.js +83 -22
  82. package/dist/cli/__tests__/setup-prompts-overwrite.test.js.map +1 -1
  83. package/dist/cli/__tests__/setup-refresh.test.js +120 -2
  84. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  85. package/dist/cli/__tests__/setup-skills-overwrite.test.js +32 -13
  86. package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
  87. package/dist/cli/__tests__/sidecar.test.d.ts +2 -0
  88. package/dist/cli/__tests__/sidecar.test.d.ts.map +1 -0
  89. package/dist/cli/__tests__/sidecar.test.js +24 -0
  90. package/dist/cli/__tests__/sidecar.test.js.map +1 -0
  91. package/dist/cli/__tests__/team.test.js +90 -42
  92. package/dist/cli/__tests__/team.test.js.map +1 -1
  93. package/dist/cli/__tests__/version-sync-contract.test.js +11 -0
  94. package/dist/cli/__tests__/version-sync-contract.test.js.map +1 -1
  95. package/dist/cli/codex-home.d.ts +4 -5
  96. package/dist/cli/codex-home.d.ts.map +1 -1
  97. package/dist/cli/codex-home.js +9 -37
  98. package/dist/cli/codex-home.js.map +1 -1
  99. package/dist/cli/doctor.d.ts +1 -1
  100. package/dist/cli/doctor.d.ts.map +1 -1
  101. package/dist/cli/doctor.js +509 -278
  102. package/dist/cli/doctor.js.map +1 -1
  103. package/dist/cli/index.d.ts +13 -5
  104. package/dist/cli/index.d.ts.map +1 -1
  105. package/dist/cli/index.js +351 -60
  106. package/dist/cli/index.js.map +1 -1
  107. package/dist/cli/list.d.ts +2 -0
  108. package/dist/cli/list.d.ts.map +1 -0
  109. package/dist/cli/list.js +40 -0
  110. package/dist/cli/list.js.map +1 -0
  111. package/dist/cli/mcp-serve.d.ts +12 -0
  112. package/dist/cli/mcp-serve.d.ts.map +1 -0
  113. package/dist/cli/mcp-serve.js +63 -0
  114. package/dist/cli/mcp-serve.js.map +1 -0
  115. package/dist/cli/plugin-marketplace.d.ts +13 -0
  116. package/dist/cli/plugin-marketplace.d.ts.map +1 -0
  117. package/dist/cli/plugin-marketplace.js +77 -0
  118. package/dist/cli/plugin-marketplace.js.map +1 -0
  119. package/dist/cli/question.d.ts.map +1 -1
  120. package/dist/cli/question.js +27 -2
  121. package/dist/cli/question.js.map +1 -1
  122. package/dist/cli/setup-preferences.d.ts +20 -0
  123. package/dist/cli/setup-preferences.d.ts.map +1 -0
  124. package/dist/cli/setup-preferences.js +71 -0
  125. package/dist/cli/setup-preferences.js.map +1 -0
  126. package/dist/cli/setup.d.ts +12 -3
  127. package/dist/cli/setup.d.ts.map +1 -1
  128. package/dist/cli/setup.js +1080 -254
  129. package/dist/cli/setup.js.map +1 -1
  130. package/dist/cli/team.d.ts +1 -0
  131. package/dist/cli/team.d.ts.map +1 -1
  132. package/dist/cli/team.js +22 -3
  133. package/dist/cli/team.js.map +1 -1
  134. package/dist/cli/uninstall.d.ts.map +1 -1
  135. package/dist/cli/uninstall.js +2 -8
  136. package/dist/cli/uninstall.js.map +1 -1
  137. package/dist/config/__tests__/generator-idempotent.test.js +100 -3
  138. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  139. package/dist/config/__tests__/generator-notify.test.js +6 -5
  140. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  141. package/dist/config/__tests__/generator-status-line-presets.test.d.ts +2 -0
  142. package/dist/config/__tests__/generator-status-line-presets.test.d.ts.map +1 -0
  143. package/dist/config/__tests__/generator-status-line-presets.test.js +203 -0
  144. package/dist/config/__tests__/generator-status-line-presets.test.js.map +1 -0
  145. package/dist/config/__tests__/models.test.js +35 -2
  146. package/dist/config/__tests__/models.test.js.map +1 -1
  147. package/dist/config/codex-hooks.d.ts.map +1 -1
  148. package/dist/config/codex-hooks.js +2 -7
  149. package/dist/config/codex-hooks.js.map +1 -1
  150. package/dist/config/generator.d.ts +10 -0
  151. package/dist/config/generator.d.ts.map +1 -1
  152. package/dist/config/generator.js +259 -76
  153. package/dist/config/generator.js.map +1 -1
  154. package/dist/config/models.d.ts +13 -3
  155. package/dist/config/models.d.ts.map +1 -1
  156. package/dist/config/models.js +25 -5
  157. package/dist/config/models.js.map +1 -1
  158. package/dist/config/omx-first-party-mcp.d.ts +18 -0
  159. package/dist/config/omx-first-party-mcp.d.ts.map +1 -0
  160. package/dist/config/omx-first-party-mcp.js +76 -0
  161. package/dist/config/omx-first-party-mcp.js.map +1 -0
  162. package/dist/document-refresh/__tests__/enforcer.test.d.ts +2 -0
  163. package/dist/document-refresh/__tests__/enforcer.test.d.ts.map +1 -0
  164. package/dist/document-refresh/__tests__/enforcer.test.js +128 -0
  165. package/dist/document-refresh/__tests__/enforcer.test.js.map +1 -0
  166. package/dist/document-refresh/config.d.ts +9 -0
  167. package/dist/document-refresh/config.d.ts.map +1 -0
  168. package/dist/document-refresh/config.js +70 -0
  169. package/dist/document-refresh/config.js.map +1 -0
  170. package/dist/document-refresh/enforcer.d.ts +43 -0
  171. package/dist/document-refresh/enforcer.d.ts.map +1 -0
  172. package/dist/document-refresh/enforcer.js +329 -0
  173. package/dist/document-refresh/enforcer.js.map +1 -0
  174. package/dist/exec/followup.d.ts +44 -0
  175. package/dist/exec/followup.d.ts.map +1 -0
  176. package/dist/exec/followup.js +349 -0
  177. package/dist/exec/followup.js.map +1 -0
  178. package/dist/hooks/__tests__/codebase-map.test.js +63 -1
  179. package/dist/hooks/__tests__/codebase-map.test.js.map +1 -1
  180. package/dist/hooks/__tests__/deep-interview-contract.test.js +10 -7
  181. package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
  182. package/dist/hooks/__tests__/keyword-detector.test.js +89 -0
  183. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  184. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +84 -1
  185. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  186. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +23 -2
  187. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  188. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +43 -0
  189. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  190. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +17 -0
  191. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
  192. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +53 -0
  193. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
  194. package/dist/hooks/__tests__/notify-hook-regression-205.test.js +4 -4
  195. package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
  196. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +103 -0
  197. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  198. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +27 -13
  199. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  200. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.d.ts +2 -0
  201. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.d.ts.map +1 -0
  202. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js +35 -0
  203. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js.map +1 -0
  204. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +70 -3
  205. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  206. package/dist/hooks/__tests__/pre-context-gate-skills.test.js +5 -0
  207. package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -1
  208. package/dist/hooks/__tests__/prompt-guidance-fragments.test.js +3 -2
  209. package/dist/hooks/__tests__/prompt-guidance-fragments.test.js.map +1 -1
  210. package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts +2 -0
  211. package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts.map +1 -0
  212. package/dist/hooks/__tests__/prompt-refactor-contract.test.js +22 -0
  213. package/dist/hooks/__tests__/prompt-refactor-contract.test.js.map +1 -0
  214. package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.d.ts +2 -0
  215. package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.d.ts.map +1 -0
  216. package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js +28 -0
  217. package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js.map +1 -0
  218. package/dist/hooks/__tests__/triage-heuristic.test.js +59 -4
  219. package/dist/hooks/__tests__/triage-heuristic.test.js.map +1 -1
  220. package/dist/hooks/__tests__/visual-ralph-skill.test.d.ts +2 -0
  221. package/dist/hooks/__tests__/visual-ralph-skill.test.d.ts.map +1 -0
  222. package/dist/hooks/__tests__/visual-ralph-skill.test.js +44 -0
  223. package/dist/hooks/__tests__/visual-ralph-skill.test.js.map +1 -0
  224. package/dist/hooks/codebase-map.d.ts.map +1 -1
  225. package/dist/hooks/codebase-map.js +83 -6
  226. package/dist/hooks/codebase-map.js.map +1 -1
  227. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  228. package/dist/hooks/keyword-detector.js +19 -14
  229. package/dist/hooks/keyword-detector.js.map +1 -1
  230. package/dist/hooks/prompt-guidance-contract.d.ts +6 -0
  231. package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
  232. package/dist/hooks/prompt-guidance-contract.js +89 -0
  233. package/dist/hooks/prompt-guidance-contract.js.map +1 -1
  234. package/dist/hooks/session.d.ts +2 -0
  235. package/dist/hooks/session.d.ts.map +1 -1
  236. package/dist/hooks/session.js +6 -0
  237. package/dist/hooks/session.js.map +1 -1
  238. package/dist/hooks/triage-heuristic.d.ts +2 -2
  239. package/dist/hooks/triage-heuristic.d.ts.map +1 -1
  240. package/dist/hooks/triage-heuristic.js +97 -20
  241. package/dist/hooks/triage-heuristic.js.map +1 -1
  242. package/dist/hooks/triage-state.d.ts +1 -1
  243. package/dist/hooks/triage-state.d.ts.map +1 -1
  244. package/dist/hooks/triage-state.js +2 -1
  245. package/dist/hooks/triage-state.js.map +1 -1
  246. package/dist/hud/__tests__/index.test.js +4 -4
  247. package/dist/hud/__tests__/index.test.js.map +1 -1
  248. package/dist/hud/__tests__/state.test.js +4 -0
  249. package/dist/hud/__tests__/state.test.js.map +1 -1
  250. package/dist/hud/__tests__/types.test.js +27 -0
  251. package/dist/hud/__tests__/types.test.js.map +1 -1
  252. package/dist/hud/state.d.ts.map +1 -1
  253. package/dist/hud/state.js +8 -0
  254. package/dist/hud/state.js.map +1 -1
  255. package/dist/hud/types.d.ts +9 -0
  256. package/dist/hud/types.d.ts.map +1 -1
  257. package/dist/hud/types.js +3 -0
  258. package/dist/hud/types.js.map +1 -1
  259. package/dist/mcp/__tests__/bootstrap.test.js +45 -5
  260. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  261. package/dist/mcp/__tests__/server-lifecycle.test.js +50 -7
  262. package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
  263. package/dist/mcp/__tests__/state-server.test.js +67 -9
  264. package/dist/mcp/__tests__/state-server.test.js.map +1 -1
  265. package/dist/mcp/bootstrap.d.ts +12 -1
  266. package/dist/mcp/bootstrap.d.ts.map +1 -1
  267. package/dist/mcp/bootstrap.js +87 -29
  268. package/dist/mcp/bootstrap.js.map +1 -1
  269. package/dist/mcp/state-server.d.ts +5 -11
  270. package/dist/mcp/state-server.d.ts.map +1 -1
  271. package/dist/mcp/state-server.js +16 -432
  272. package/dist/mcp/state-server.js.map +1 -1
  273. package/dist/planning/__tests__/artifacts.test.js +152 -1
  274. package/dist/planning/__tests__/artifacts.test.js.map +1 -1
  275. package/dist/planning/artifacts.d.ts +9 -0
  276. package/dist/planning/artifacts.d.ts.map +1 -1
  277. package/dist/planning/artifacts.js +60 -1
  278. package/dist/planning/artifacts.js.map +1 -1
  279. package/dist/question/__tests__/deep-interview.test.js +1 -1
  280. package/dist/question/__tests__/deep-interview.test.js.map +1 -1
  281. package/dist/question/__tests__/renderer.test.js +70 -0
  282. package/dist/question/__tests__/renderer.test.js.map +1 -1
  283. package/dist/question/__tests__/ui.test.js +49 -0
  284. package/dist/question/__tests__/ui.test.js.map +1 -1
  285. package/dist/question/renderer.d.ts +14 -1
  286. package/dist/question/renderer.d.ts.map +1 -1
  287. package/dist/question/renderer.js +109 -10
  288. package/dist/question/renderer.js.map +1 -1
  289. package/dist/question/state.d.ts +2 -0
  290. package/dist/question/state.d.ts.map +1 -1
  291. package/dist/question/state.js +4 -0
  292. package/dist/question/state.js.map +1 -1
  293. package/dist/question/types.d.ts +2 -1
  294. package/dist/question/types.d.ts.map +1 -1
  295. package/dist/question/types.js.map +1 -1
  296. package/dist/question/ui.d.ts.map +1 -1
  297. package/dist/question/ui.js +28 -8
  298. package/dist/question/ui.js.map +1 -1
  299. package/dist/runtime/__tests__/bridge.test.js +143 -1
  300. package/dist/runtime/__tests__/bridge.test.js.map +1 -1
  301. package/dist/runtime/bridge.d.ts +21 -0
  302. package/dist/runtime/bridge.d.ts.map +1 -1
  303. package/dist/runtime/bridge.js +54 -4
  304. package/dist/runtime/bridge.js.map +1 -1
  305. package/dist/scripts/__tests__/codex-native-hook.test.js +1904 -230
  306. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  307. package/dist/scripts/__tests__/generate-release-body.test.js +90 -1
  308. package/dist/scripts/__tests__/generate-release-body.test.js.map +1 -1
  309. package/dist/scripts/__tests__/hook-derived-watcher.test.js +110 -2
  310. package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +1 -1
  311. package/dist/scripts/__tests__/postinstall.test.js +7 -93
  312. package/dist/scripts/__tests__/postinstall.test.js.map +1 -1
  313. package/dist/scripts/__tests__/prompt-inventory.test.d.ts +2 -0
  314. package/dist/scripts/__tests__/prompt-inventory.test.d.ts.map +1 -0
  315. package/dist/scripts/__tests__/prompt-inventory.test.js +56 -0
  316. package/dist/scripts/__tests__/prompt-inventory.test.js.map +1 -0
  317. package/dist/scripts/__tests__/run-test-files.test.d.ts +2 -0
  318. package/dist/scripts/__tests__/run-test-files.test.d.ts.map +1 -0
  319. package/dist/scripts/__tests__/run-test-files.test.js +62 -0
  320. package/dist/scripts/__tests__/run-test-files.test.js.map +1 -0
  321. package/dist/scripts/__tests__/smoke-packed-install.test.js +13 -1
  322. package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
  323. package/dist/scripts/__tests__/verify-native-agents.test.d.ts +2 -0
  324. package/dist/scripts/__tests__/verify-native-agents.test.d.ts.map +1 -0
  325. package/dist/scripts/__tests__/verify-native-agents.test.js +166 -0
  326. package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -0
  327. package/dist/scripts/codex-execution-surface.d.ts +16 -0
  328. package/dist/scripts/codex-execution-surface.d.ts.map +1 -0
  329. package/dist/scripts/codex-execution-surface.js +42 -0
  330. package/dist/scripts/codex-execution-surface.js.map +1 -0
  331. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  332. package/dist/scripts/codex-native-hook.js +418 -76
  333. package/dist/scripts/codex-native-hook.js.map +1 -1
  334. package/dist/scripts/codex-native-pre-post.d.ts +8 -0
  335. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
  336. package/dist/scripts/codex-native-pre-post.js +133 -19
  337. package/dist/scripts/codex-native-pre-post.js.map +1 -1
  338. package/dist/scripts/generate-release-body.d.ts +1 -0
  339. package/dist/scripts/generate-release-body.d.ts.map +1 -1
  340. package/dist/scripts/generate-release-body.js +32 -3
  341. package/dist/scripts/generate-release-body.js.map +1 -1
  342. package/dist/scripts/hook-derived-watcher.js +46 -7
  343. package/dist/scripts/hook-derived-watcher.js.map +1 -1
  344. package/dist/scripts/notify-fallback-watcher.js +59 -9
  345. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  346. package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts +2 -0
  347. package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts.map +1 -0
  348. package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js +153 -0
  349. package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js.map +1 -0
  350. package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
  351. package/dist/scripts/notify-hook/managed-tmux.js +18 -1
  352. package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
  353. package/dist/scripts/notify-hook/process-runner.d.ts.map +1 -1
  354. package/dist/scripts/notify-hook/process-runner.js +7 -3
  355. package/dist/scripts/notify-hook/process-runner.js.map +1 -1
  356. package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
  357. package/dist/scripts/notify-hook/team-dispatch.js +96 -11
  358. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  359. package/dist/scripts/notify-hook/team-tmux-guard.js +3 -3
  360. package/dist/scripts/notify-hook/team-worker-posttooluse.d.ts +34 -0
  361. package/dist/scripts/notify-hook/team-worker-posttooluse.d.ts.map +1 -0
  362. package/dist/scripts/notify-hook/team-worker-posttooluse.js +434 -0
  363. package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -0
  364. package/dist/scripts/notify-hook/team-worker.d.ts +1 -1
  365. package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
  366. package/dist/scripts/notify-hook/team-worker.js +3 -43
  367. package/dist/scripts/notify-hook/team-worker.js.map +1 -1
  368. package/dist/scripts/notify-hook.js +36 -5
  369. package/dist/scripts/notify-hook.js.map +1 -1
  370. package/dist/scripts/postinstall.d.ts +1 -5
  371. package/dist/scripts/postinstall.d.ts.map +1 -1
  372. package/dist/scripts/postinstall.js +3 -42
  373. package/dist/scripts/postinstall.js.map +1 -1
  374. package/dist/scripts/prompt-inventory.d.ts +29 -0
  375. package/dist/scripts/prompt-inventory.d.ts.map +1 -0
  376. package/dist/scripts/prompt-inventory.js +178 -0
  377. package/dist/scripts/prompt-inventory.js.map +1 -0
  378. package/dist/scripts/run-test-files.js +32 -2
  379. package/dist/scripts/run-test-files.js.map +1 -1
  380. package/dist/scripts/smoke-packed-install.d.ts +3 -0
  381. package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
  382. package/dist/scripts/smoke-packed-install.js +9 -1
  383. package/dist/scripts/smoke-packed-install.js.map +1 -1
  384. package/dist/scripts/sync-plugin-mirror.d.ts +13 -0
  385. package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -0
  386. package/dist/scripts/sync-plugin-mirror.js +242 -0
  387. package/dist/scripts/sync-plugin-mirror.js.map +1 -0
  388. package/dist/scripts/verify-native-agents.d.ts +16 -0
  389. package/dist/scripts/verify-native-agents.d.ts.map +1 -0
  390. package/dist/scripts/verify-native-agents.js +188 -0
  391. package/dist/scripts/verify-native-agents.js.map +1 -0
  392. package/dist/session-history/search.d.ts.map +1 -1
  393. package/dist/session-history/search.js +7 -2
  394. package/dist/session-history/search.js.map +1 -1
  395. package/dist/sidecar/__tests__/boundary.test.d.ts +2 -0
  396. package/dist/sidecar/__tests__/boundary.test.d.ts.map +1 -0
  397. package/dist/sidecar/__tests__/boundary.test.js +48 -0
  398. package/dist/sidecar/__tests__/boundary.test.js.map +1 -0
  399. package/dist/sidecar/__tests__/collector.test.d.ts +2 -0
  400. package/dist/sidecar/__tests__/collector.test.d.ts.map +1 -0
  401. package/dist/sidecar/__tests__/collector.test.js +162 -0
  402. package/dist/sidecar/__tests__/collector.test.js.map +1 -0
  403. package/dist/sidecar/__tests__/render.test.d.ts +2 -0
  404. package/dist/sidecar/__tests__/render.test.d.ts.map +1 -0
  405. package/dist/sidecar/__tests__/render.test.js +67 -0
  406. package/dist/sidecar/__tests__/render.test.js.map +1 -0
  407. package/dist/sidecar/__tests__/tmux.test.d.ts +2 -0
  408. package/dist/sidecar/__tests__/tmux.test.d.ts.map +1 -0
  409. package/dist/sidecar/__tests__/tmux.test.js +30 -0
  410. package/dist/sidecar/__tests__/tmux.test.js.map +1 -0
  411. package/dist/sidecar/__tests__/watch.test.d.ts +2 -0
  412. package/dist/sidecar/__tests__/watch.test.d.ts.map +1 -0
  413. package/dist/sidecar/__tests__/watch.test.js +42 -0
  414. package/dist/sidecar/__tests__/watch.test.js.map +1 -0
  415. package/dist/sidecar/collector.d.ts +4 -0
  416. package/dist/sidecar/collector.d.ts.map +1 -0
  417. package/dist/sidecar/collector.js +377 -0
  418. package/dist/sidecar/collector.js.map +1 -0
  419. package/dist/sidecar/index.d.ts +25 -0
  420. package/dist/sidecar/index.d.ts.map +1 -0
  421. package/dist/sidecar/index.js +165 -0
  422. package/dist/sidecar/index.js.map +1 -0
  423. package/dist/sidecar/render.d.ts +3 -0
  424. package/dist/sidecar/render.d.ts.map +1 -0
  425. package/dist/sidecar/render.js +72 -0
  426. package/dist/sidecar/render.js.map +1 -0
  427. package/dist/sidecar/tmux.d.ts +13 -0
  428. package/dist/sidecar/tmux.d.ts.map +1 -0
  429. package/dist/sidecar/tmux.js +44 -0
  430. package/dist/sidecar/tmux.js.map +1 -0
  431. package/dist/sidecar/types.d.ts +125 -0
  432. package/dist/sidecar/types.d.ts.map +1 -0
  433. package/dist/sidecar/types.js +2 -0
  434. package/dist/sidecar/types.js.map +1 -0
  435. package/dist/state/__tests__/operations.test.js +50 -22
  436. package/dist/state/__tests__/operations.test.js.map +1 -1
  437. package/dist/state/operations.d.ts +1 -1
  438. package/dist/state/operations.d.ts.map +1 -1
  439. package/dist/state/operations.js +19 -7
  440. package/dist/state/operations.js.map +1 -1
  441. package/dist/team/__tests__/commit-hygiene.test.d.ts +2 -0
  442. package/dist/team/__tests__/commit-hygiene.test.d.ts.map +1 -0
  443. package/dist/team/__tests__/commit-hygiene.test.js +93 -0
  444. package/dist/team/__tests__/commit-hygiene.test.js.map +1 -0
  445. package/dist/team/__tests__/delegation-policy.test.d.ts +2 -0
  446. package/dist/team/__tests__/delegation-policy.test.d.ts.map +1 -0
  447. package/dist/team/__tests__/delegation-policy.test.js +69 -0
  448. package/dist/team/__tests__/delegation-policy.test.js.map +1 -0
  449. package/dist/team/__tests__/events.test.js +54 -4
  450. package/dist/team/__tests__/events.test.js.map +1 -1
  451. package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts +2 -0
  452. package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts.map +1 -0
  453. package/dist/team/__tests__/hook-primary-e2e-contract.test.js +78 -0
  454. package/dist/team/__tests__/hook-primary-e2e-contract.test.js.map +1 -0
  455. package/dist/team/__tests__/model-contract.test.js +18 -2
  456. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  457. package/dist/team/__tests__/repo-aware-decomposition.test.d.ts +2 -0
  458. package/dist/team/__tests__/repo-aware-decomposition.test.d.ts.map +1 -0
  459. package/dist/team/__tests__/repo-aware-decomposition.test.js +95 -0
  460. package/dist/team/__tests__/repo-aware-decomposition.test.js.map +1 -0
  461. package/dist/team/__tests__/runtime.test.js +677 -17
  462. package/dist/team/__tests__/runtime.test.js.map +1 -1
  463. package/dist/team/__tests__/state-root.test.js +177 -1
  464. package/dist/team/__tests__/state-root.test.js.map +1 -1
  465. package/dist/team/__tests__/state.test.js +110 -0
  466. package/dist/team/__tests__/state.test.js.map +1 -1
  467. package/dist/team/__tests__/tmux-session.test.js +301 -2
  468. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  469. package/dist/team/__tests__/worker-bootstrap.test.js +94 -0
  470. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  471. package/dist/team/commit-hygiene.d.ts +22 -3
  472. package/dist/team/commit-hygiene.d.ts.map +1 -1
  473. package/dist/team/commit-hygiene.js +134 -2
  474. package/dist/team/commit-hygiene.js.map +1 -1
  475. package/dist/team/contracts.d.ts +1 -1
  476. package/dist/team/contracts.d.ts.map +1 -1
  477. package/dist/team/contracts.js +2 -0
  478. package/dist/team/contracts.js.map +1 -1
  479. package/dist/team/dag-schema.d.ts +38 -0
  480. package/dist/team/dag-schema.d.ts.map +1 -0
  481. package/dist/team/dag-schema.js +221 -0
  482. package/dist/team/dag-schema.js.map +1 -0
  483. package/dist/team/delegation-policy.d.ts +3 -0
  484. package/dist/team/delegation-policy.d.ts.map +1 -0
  485. package/dist/team/delegation-policy.js +82 -0
  486. package/dist/team/delegation-policy.js.map +1 -0
  487. package/dist/team/model-contract.d.ts +3 -1
  488. package/dist/team/model-contract.d.ts.map +1 -1
  489. package/dist/team/model-contract.js +44 -5
  490. package/dist/team/model-contract.js.map +1 -1
  491. package/dist/team/repo-aware-decomposition.d.ts +60 -0
  492. package/dist/team/repo-aware-decomposition.d.ts.map +1 -0
  493. package/dist/team/repo-aware-decomposition.js +229 -0
  494. package/dist/team/repo-aware-decomposition.js.map +1 -0
  495. package/dist/team/runtime.d.ts +34 -0
  496. package/dist/team/runtime.d.ts.map +1 -1
  497. package/dist/team/runtime.js +191 -50
  498. package/dist/team/runtime.js.map +1 -1
  499. package/dist/team/state/tasks.d.ts.map +1 -1
  500. package/dist/team/state/tasks.js +33 -0
  501. package/dist/team/state/tasks.js.map +1 -1
  502. package/dist/team/state/types.d.ts +23 -1
  503. package/dist/team/state/types.d.ts.map +1 -1
  504. package/dist/team/state/types.js.map +1 -1
  505. package/dist/team/state-root.d.ts +35 -0
  506. package/dist/team/state-root.d.ts.map +1 -1
  507. package/dist/team/state-root.js +281 -1
  508. package/dist/team/state-root.js.map +1 -1
  509. package/dist/team/state.d.ts +27 -1
  510. package/dist/team/state.d.ts.map +1 -1
  511. package/dist/team/state.js +6 -0
  512. package/dist/team/state.js.map +1 -1
  513. package/dist/team/tmux-session.d.ts +1 -0
  514. package/dist/team/tmux-session.d.ts.map +1 -1
  515. package/dist/team/tmux-session.js +83 -6
  516. package/dist/team/tmux-session.js.map +1 -1
  517. package/dist/team/worker-bootstrap.d.ts +3 -0
  518. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  519. package/dist/team/worker-bootstrap.js +77 -4
  520. package/dist/team/worker-bootstrap.js.map +1 -1
  521. package/dist/utils/__tests__/agents-model-table.test.js +8 -0
  522. package/dist/utils/__tests__/agents-model-table.test.js.map +1 -1
  523. package/dist/utils/__tests__/paths.test.js +42 -9
  524. package/dist/utils/__tests__/paths.test.js.map +1 -1
  525. package/dist/utils/agents-md.d.ts +3 -0
  526. package/dist/utils/agents-md.d.ts.map +1 -1
  527. package/dist/utils/agents-md.js +25 -0
  528. package/dist/utils/agents-md.js.map +1 -1
  529. package/dist/utils/agents-model-table.d.ts.map +1 -1
  530. package/dist/utils/agents-model-table.js +2 -3
  531. package/dist/utils/agents-model-table.js.map +1 -1
  532. package/package.json +14 -7
  533. package/plugins/oh-my-codex/.app.json +3 -0
  534. package/plugins/oh-my-codex/.codex-plugin/plugin.json +30 -0
  535. package/plugins/oh-my-codex/.mcp.json +44 -0
  536. package/plugins/oh-my-codex/skills/ai-slop-cleaner/SKILL.md +114 -0
  537. package/plugins/oh-my-codex/skills/analyze/SKILL.md +148 -0
  538. package/plugins/oh-my-codex/skills/ask-claude/SKILL.md +61 -0
  539. package/plugins/oh-my-codex/skills/ask-gemini/SKILL.md +61 -0
  540. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +231 -0
  541. package/plugins/oh-my-codex/skills/autoresearch/SKILL.md +68 -0
  542. package/plugins/oh-my-codex/skills/cancel/SKILL.md +399 -0
  543. package/plugins/oh-my-codex/skills/code-review/SKILL.md +290 -0
  544. package/plugins/oh-my-codex/skills/configure-notifications/SKILL.md +287 -0
  545. package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +464 -0
  546. package/plugins/oh-my-codex/skills/doctor/SKILL.md +239 -0
  547. package/plugins/oh-my-codex/skills/help/SKILL.md +202 -0
  548. package/plugins/oh-my-codex/skills/hud/SKILL.md +98 -0
  549. package/plugins/oh-my-codex/skills/note/SKILL.md +62 -0
  550. package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +135 -0
  551. package/plugins/oh-my-codex/skills/pipeline/SKILL.md +86 -0
  552. package/plugins/oh-my-codex/skills/plan/SKILL.md +276 -0
  553. package/plugins/oh-my-codex/skills/ralph/SKILL.md +269 -0
  554. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +162 -0
  555. package/plugins/oh-my-codex/skills/security-review/SKILL.md +300 -0
  556. package/plugins/oh-my-codex/skills/skill/SKILL.md +835 -0
  557. package/plugins/oh-my-codex/skills/team/SKILL.md +510 -0
  558. package/plugins/oh-my-codex/skills/trace/SKILL.md +33 -0
  559. package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +143 -0
  560. package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +175 -0
  561. package/plugins/oh-my-codex/skills/visual-ralph/SKILL.md +153 -0
  562. package/plugins/oh-my-codex/skills/visual-verdict/SKILL.md +76 -0
  563. package/plugins/oh-my-codex/skills/wiki/SKILL.md +57 -0
  564. package/plugins/oh-my-codex/skills/worker/SKILL.md +106 -0
  565. package/prompts/critic.md +35 -83
  566. package/prompts/executor.md +32 -109
  567. package/prompts/explore-harness.md +1 -1
  568. package/prompts/explore.md +37 -90
  569. package/prompts/planner.md +28 -58
  570. package/prompts/researcher.md +46 -78
  571. package/prompts/verifier.md +23 -31
  572. package/skills/autopilot/SKILL.md +1 -4
  573. package/skills/deep-interview/SKILL.md +8 -5
  574. package/skills/doctor/SKILL.md +45 -17
  575. package/skills/help/SKILL.md +2 -2
  576. package/skills/omx-setup/SKILL.md +52 -9
  577. package/skills/plan/SKILL.md +1 -4
  578. package/skills/ralph/SKILL.md +3 -5
  579. package/skills/ralplan/SKILL.md +2 -6
  580. package/skills/team/SKILL.md +2 -5
  581. package/skills/ultraqa/SKILL.md +1 -4
  582. package/skills/ultrawork/SKILL.md +2 -3
  583. package/skills/visual-ralph/SKILL.md +153 -0
  584. package/skills/web-clone/SKILL.md +12 -354
  585. package/src/scripts/__tests__/codex-native-hook.test.ts +2306 -224
  586. package/src/scripts/__tests__/generate-release-body.test.ts +109 -0
  587. package/src/scripts/__tests__/hook-derived-watcher.test.ts +132 -2
  588. package/src/scripts/__tests__/postinstall.test.ts +7 -104
  589. package/src/scripts/__tests__/prompt-inventory.test.ts +64 -0
  590. package/src/scripts/__tests__/run-test-files.test.ts +72 -0
  591. package/src/scripts/__tests__/smoke-packed-install.test.ts +15 -0
  592. package/src/scripts/__tests__/verify-native-agents.test.ts +204 -0
  593. package/src/scripts/codex-execution-surface.ts +73 -0
  594. package/src/scripts/codex-native-hook.ts +579 -82
  595. package/src/scripts/codex-native-pre-post.ts +157 -19
  596. package/src/scripts/generate-release-body.ts +34 -2
  597. package/src/scripts/hook-derived-watcher.ts +51 -8
  598. package/src/scripts/notify-fallback-watcher.ts +65 -9
  599. package/src/scripts/notify-hook/__tests__/team-worker-posttooluse.test.ts +180 -0
  600. package/src/scripts/notify-hook/managed-tmux.ts +22 -4
  601. package/src/scripts/notify-hook/process-runner.ts +7 -3
  602. package/src/scripts/notify-hook/team-dispatch.ts +103 -11
  603. package/src/scripts/notify-hook/team-tmux-guard.ts +3 -3
  604. package/src/scripts/notify-hook/team-worker-posttooluse.ts +536 -0
  605. package/src/scripts/notify-hook/team-worker.ts +4 -48
  606. package/src/scripts/notify-hook.ts +36 -5
  607. package/src/scripts/postinstall.ts +4 -58
  608. package/src/scripts/prompt-inventory.ts +218 -0
  609. package/src/scripts/run-test-files.ts +41 -2
  610. package/src/scripts/smoke-packed-install.ts +10 -1
  611. package/src/scripts/sync-plugin-mirror.ts +360 -0
  612. package/src/scripts/verify-native-agents.ts +245 -0
  613. package/templates/AGENTS.md +26 -91
  614. package/templates/catalog-manifest.json +16 -1
@@ -1,5 +1,13 @@
1
+ import {
2
+ buildDocumentRefreshAdvisoryOutput,
3
+ evaluateStagedDocumentRefresh,
4
+ } from "../document-refresh/enforcer.js";
5
+ import { resolveCodexExecutionSurface } from "./codex-execution-surface.js";
6
+
1
7
  type CodexHookPayload = Record<string, unknown>;
2
8
 
9
+ type GitRepositorySelection = "current-cwd" | "explicit-target";
10
+
3
11
  export interface NormalizedPreToolUsePayload {
4
12
  toolName: string;
5
13
  toolUseId: string;
@@ -45,6 +53,16 @@ function safeObject(value: unknown): Record<string, unknown> | null {
45
53
  : null;
46
54
  }
47
55
 
56
+ function isNativeOutsideTmuxSurface(payload: CodexHookPayload): boolean {
57
+ const cwd = safeString(payload.cwd).trim() || process.cwd();
58
+ const surface = resolveCodexExecutionSurface(cwd, {
59
+ hookEventName: "PreToolUse",
60
+ payload,
61
+ nativeSessionId: safeString(payload.session_id ?? payload.sessionId).trim(),
62
+ });
63
+ return surface.launcher === "native" && surface.transport === "outside-tmux";
64
+ }
65
+
48
66
  function tryParseJsonString(value: unknown): Record<string, unknown> | null {
49
67
  const text = safeString(value).trim();
50
68
  if (!text) return null;
@@ -134,6 +152,7 @@ export function detectMcpTransportFailure(
134
152
  payload: CodexHookPayload,
135
153
  ): McpTransportFailureSignal | null {
136
154
  const normalized = normalizePostToolUsePayload(payload);
155
+ if (normalized.isBash) return null;
137
156
  const combined = [
138
157
  normalized.stderrText,
139
158
  normalized.stdoutText,
@@ -268,6 +287,7 @@ function tokenizeShellCommand(commandText: string): string[] | null {
268
287
  interface GitCommitCommandParseResult {
269
288
  isGitCommit: boolean;
270
289
  inlineMessage: string | null;
290
+ repositorySelection: GitRepositorySelection;
271
291
  requiresExternalMessageSource: boolean;
272
292
  }
273
293
 
@@ -348,6 +368,14 @@ function gitOptionConsumesNextValue(token: string): boolean {
348
368
  || token === "--attr-source";
349
369
  }
350
370
 
371
+ function gitOptionSelectsRepository(token: string): boolean {
372
+ return token === "-C"
373
+ || token === "--git-dir"
374
+ || token === "--work-tree"
375
+ || token.startsWith("--git-dir=")
376
+ || token.startsWith("--work-tree=");
377
+ }
378
+
351
379
  function gitOptionStopsBeforeSubcommand(token: string): boolean {
352
380
  return token === "-h"
353
381
  || token === "--help"
@@ -382,12 +410,22 @@ function findGitSubcommandIndex(tokens: string[], gitTokenIndex: number): number
382
410
  return index < tokens.length ? index : -1;
383
411
  }
384
412
 
385
- function parseGitCommitCommand(commandText: string): GitCommitCommandParseResult {
413
+ function readGitRepositorySelection(tokens: string[], gitTokenIndex: number, subcommandIndex: number): GitRepositorySelection {
414
+ for (let index = gitTokenIndex + 1; index < subcommandIndex; index += 1) {
415
+ const token = tokens[index] ?? "";
416
+ if (gitOptionSelectsRepository(token)) return "explicit-target";
417
+ if (gitOptionConsumesNextValue(token)) index += 1;
418
+ }
419
+ return "current-cwd";
420
+ }
421
+
422
+ export function parseGitCommitCommand(commandText: string): GitCommitCommandParseResult {
386
423
  const tokens = tokenizeShellCommand(commandText);
387
424
  if (!tokens) {
388
425
  return {
389
426
  isGitCommit: false,
390
427
  inlineMessage: null,
428
+ repositorySelection: "current-cwd",
391
429
  requiresExternalMessageSource: false,
392
430
  };
393
431
  }
@@ -397,6 +435,7 @@ function parseGitCommitCommand(commandText: string): GitCommitCommandParseResult
397
435
  return {
398
436
  isGitCommit: false,
399
437
  inlineMessage: null,
438
+ repositorySelection: "current-cwd",
400
439
  requiresExternalMessageSource: false,
401
440
  };
402
441
  }
@@ -406,10 +445,12 @@ function parseGitCommitCommand(commandText: string): GitCommitCommandParseResult
406
445
  return {
407
446
  isGitCommit: false,
408
447
  inlineMessage: null,
448
+ repositorySelection: "current-cwd",
409
449
  requiresExternalMessageSource: false,
410
450
  };
411
451
  }
412
452
 
453
+ const repositorySelection = readGitRepositorySelection(tokens, gitTokenIndex, subcommandIndex);
413
454
  const messageParts: string[] = [];
414
455
  let requiresExternalMessageSource = false;
415
456
  const args = tokens.slice(subcommandIndex + 1);
@@ -452,6 +493,7 @@ function parseGitCommitCommand(commandText: string): GitCommitCommandParseResult
452
493
  return {
453
494
  isGitCommit: true,
454
495
  inlineMessage: messageParts.length > 0 ? messageParts.join("\n\n").trim() : null,
496
+ repositorySelection,
455
497
  requiresExternalMessageSource,
456
498
  };
457
499
  }
@@ -550,10 +592,6 @@ function buildGitCommitEnforcementOutput(commandText: string): Record<string, un
550
592
  "git commit is blocked until the inline commit message satisfies the Lore format and includes the required OmX co-author trailer.",
551
593
  hookSpecificOutput: {
552
594
  hookEventName: "PreToolUse",
553
- additionalContext: [
554
- "Lore-format git commit enforcement triggered.",
555
- ...errors.map((error) => `- ${error}`),
556
- ].join("\n"),
557
595
  },
558
596
  systemMessage: [
559
597
  "git commit is blocked until the inline commit message follows the Lore protocol and includes `Co-authored-by: OmX <omx@oh-my-codex.dev>`.",
@@ -562,6 +600,22 @@ function buildGitCommitEnforcementOutput(commandText: string): Record<string, un
562
600
  };
563
601
  }
564
602
 
603
+
604
+ function buildDocumentRefreshPreToolUseOutput(
605
+ commandText: string,
606
+ cwd: string,
607
+ ): Record<string, unknown> | null {
608
+ const parsed = parseGitCommitCommand(commandText);
609
+ if (!parsed.isGitCommit) return null;
610
+
611
+ if (parsed.repositorySelection !== "current-cwd") return null;
612
+
613
+ const warning = evaluateStagedDocumentRefresh(cwd, parsed.inlineMessage);
614
+ if (!warning) return null;
615
+
616
+ return buildDocumentRefreshAdvisoryOutput(warning, "PreToolUse");
617
+ }
618
+
565
619
  function commandInvokesOmxQuestion(command: string): boolean {
566
620
  const tokens = tokenizeShellCommand(command)?.map((token) => token.toLowerCase()) ?? [];
567
621
  for (let index = 0; index < tokens.length; index += 1) {
@@ -582,26 +636,95 @@ function isQuestionReturnPaneAssignment(token: string): boolean {
582
636
  return /^%\d+$/.test(value) || /^\$\{?TMUX_PANE\}?$/.test(value);
583
637
  }
584
638
 
639
+ function hasInheritedQuestionReturnPaneBridge(): boolean {
640
+ // Intentionally trust only the explicit bridge envs that question renderer
641
+ // already accepts outside tmux; TMUX_PANE alone is not stable across all
642
+ // Bash/background-terminal tool paths that this enforcement protects.
643
+ const explicitPane = safeString(
644
+ process.env.OMX_QUESTION_RETURN_PANE || process.env.OMX_LEADER_PANE_ID,
645
+ ).trim();
646
+ return /^%\d+$/.test(explicitPane);
647
+ }
648
+
649
+ function commandHasPowerShellQuestionReturnPane(command: string): boolean {
650
+ return /\$env:(?:OMX_QUESTION_RETURN_PANE|OMX_LEADER_PANE_ID)\s*=\s*(?:['"]?%\d+['"]?|\$env:TMUX_PANE)\b/i.test(command)
651
+ || /\$env:TMUX_PANE\s*=\s*['"]?%\d+['"]?/i.test(command);
652
+ }
653
+
585
654
  function commandHasQuestionReturnPane(command: string): boolean {
655
+ if (hasInheritedQuestionReturnPaneBridge()) return true;
656
+ if (commandHasPowerShellQuestionReturnPane(command)) return true;
586
657
  return (tokenizeShellCommand(command) ?? []).some(isQuestionReturnPaneAssignment);
587
658
  }
588
659
 
589
- function buildOmxQuestionPreToolUseEnforcementOutput(command: string): Record<string, unknown> | null {
660
+ function commandInvokesOmxTeam(command: string): boolean {
661
+ const tokens = tokenizeShellCommand(command)?.map((token) => token.toLowerCase()) ?? [];
662
+ for (let index = 0; index < tokens.length; index += 1) {
663
+ const rawToken = tokens[index] || '';
664
+ const token = rawToken.replace(/\\/g, '/').split('/').pop() || '';
665
+ if ((token === 'omx' || token === 'omx.js') && tokens[index + 1] === 'team') return true;
666
+ if ((token === 'node' || token === 'node.exe') && /(?:^|\/)omx\.js$/.test(tokens[index + 1] || '') && tokens[index + 2] === 'team') return true;
667
+ }
668
+ return /\bomx\s+team\b/i.test(command) || /\bomx\.js['"]?\s+team\b/i.test(command);
669
+ }
670
+
671
+ function commandInvokesOmxHud(command: string): boolean {
672
+ const tokens = tokenizeShellCommand(command)?.map((token) => token.toLowerCase()) ?? [];
673
+ for (let index = 0; index < tokens.length; index += 1) {
674
+ const rawToken = tokens[index] || '';
675
+ const token = rawToken.replace(/\\/g, '/').split('/').pop() || '';
676
+ if ((token === 'omx' || token === 'omx.js') && tokens[index + 1] === 'hud') return true;
677
+ if ((token === 'node' || token === 'node.exe') && /(?:^|\/)omx\.js$/.test(tokens[index + 1] || '') && tokens[index + 2] === 'hud') return true;
678
+ }
679
+ return /\bomx\s+hud\b/i.test(command) || /\bomx\.js['"]?\s+hud\b/i.test(command);
680
+ }
681
+
682
+ function buildNativeOmxHudPreToolUseEnforcementOutput(
683
+ command: string,
684
+ payload: CodexHookPayload,
685
+ ): Record<string, unknown> | null {
686
+ if (!isNativeOutsideTmuxSurface(payload) || !commandInvokesOmxHud(command)) return null;
687
+
688
+ return {
689
+ decision: "block",
690
+ reason: "omx hud cannot be launched directly from Codex App/native outside-tmux Bash sessions.",
691
+ systemMessage: "omx hud is blocked from Bash in Codex App/native outside-tmux sessions; use SessionStart/HUD context instead, or launch OMX CLI from an attached tmux shell first for the tmux HUD runtime.",
692
+ };
693
+ }
694
+
695
+ function buildNativeOmxTeamPreToolUseEnforcementOutput(
696
+ command: string,
697
+ payload: CodexHookPayload,
698
+ ): Record<string, unknown> | null {
699
+ if (!isNativeOutsideTmuxSurface(payload) || !commandInvokesOmxTeam(command)) return null;
700
+
701
+ return {
702
+ decision: "block",
703
+ reason: "omx team cannot be launched directly from Codex App/native outside-tmux Bash sessions.",
704
+ systemMessage: `omx team is blocked from Bash in Codex App/native outside-tmux sessions; launch OMX CLI from an attached tmux shell first. Original command: ${command}`,
705
+ };
706
+ }
707
+
708
+ function buildOmxQuestionPreToolUseEnforcementOutput(
709
+ command: string,
710
+ payload: CodexHookPayload,
711
+ ): Record<string, unknown> | null {
590
712
  if (!commandInvokesOmxQuestion(command)) return null;
713
+
714
+ if (isNativeOutsideTmuxSurface(payload)) {
715
+ return {
716
+ decision: "block",
717
+ reason: "omx question cannot be launched directly from Codex App/native outside-tmux Bash sessions.",
718
+ systemMessage: `omx question is blocked from Codex App/native outside-tmux Bash because no attached tmux pane is available. Use the native structured question tool when available, or ask exactly one concise plain-text question. Original command: ${command}`,
719
+ };
720
+ }
721
+
591
722
  if (commandHasQuestionReturnPane(command)) return null;
592
723
 
593
724
  return {
594
725
  decision: "block",
595
726
  reason: "omx question Bash invocations must preserve the leader pane return target.",
596
- hookSpecificOutput: {
597
- hookEventName: "PreToolUse",
598
- additionalContext: [
599
- "omx question leader-pane enforcement triggered.",
600
- "Prefix the Bash command with `OMX_QUESTION_RETURN_PANE=$TMUX_PANE` (or a concrete `%pane` value) so `[omx question answered]` returns to the leader pane even when the tool path drops/stales TMUX_PANE.",
601
- `Original command: ${command}`,
602
- ].join("\n"),
603
- },
604
- systemMessage: "omx question is blocked from Bash until the command preserves the leader pane with `OMX_QUESTION_RETURN_PANE=$TMUX_PANE` or an explicit `%pane` value.",
727
+ systemMessage: `omx question is blocked from Bash until the command preserves the leader pane with \`OMX_QUESTION_RETURN_PANE=$TMUX_PANE\` or an explicit \`%pane\` value. Original command: ${command}`,
605
728
  };
606
729
  }
607
730
 
@@ -612,8 +735,17 @@ export function buildNativePreToolUseOutput(
612
735
  if (!normalized.isBash) return null;
613
736
  const gitCommitEnforcement = buildGitCommitEnforcementOutput(normalized.normalizedCommand);
614
737
  if (gitCommitEnforcement) return gitCommitEnforcement;
615
- const questionEnforcement = buildOmxQuestionPreToolUseEnforcementOutput(normalized.normalizedCommand);
738
+ const hudEnforcement = buildNativeOmxHudPreToolUseEnforcementOutput(normalized.normalizedCommand, payload);
739
+ if (hudEnforcement) return hudEnforcement;
740
+ const teamEnforcement = buildNativeOmxTeamPreToolUseEnforcementOutput(normalized.normalizedCommand, payload);
741
+ if (teamEnforcement) return teamEnforcement;
742
+ const questionEnforcement = buildOmxQuestionPreToolUseEnforcementOutput(normalized.normalizedCommand, payload);
616
743
  if (questionEnforcement) return questionEnforcement;
744
+ const documentRefreshWarning = buildDocumentRefreshPreToolUseOutput(
745
+ normalized.normalizedCommand,
746
+ safeString(payload.cwd).trim() || process.cwd(),
747
+ );
748
+ if (documentRefreshWarning) return documentRefreshWarning;
617
749
  if (!matchesDestructiveFixture(normalized.normalizedCommand)) return null;
618
750
 
619
751
  return {
@@ -629,10 +761,17 @@ function containsHardFailure(text: string): boolean {
629
761
  return /command not found|permission denied|no such file or directory/i.test(text);
630
762
  }
631
763
 
764
+ function hasActionableBashHardFailure(normalized: NormalizedPostToolUsePayload): boolean {
765
+ if (containsHardFailure(normalized.stderrText)) return true;
766
+ if (normalized.exitCode === null || normalized.exitCode === 0) return false;
767
+ return containsHardFailure(`${normalized.stderrText}\n${normalized.stdoutText}`);
768
+ }
769
+
632
770
  export function buildNativePostToolUseOutput(
633
771
  payload: CodexHookPayload,
634
772
  ): Record<string, unknown> | null {
635
- const mcpTransportFailure = detectMcpTransportFailure(payload);
773
+ const normalized = normalizePostToolUsePayload(payload);
774
+ const mcpTransportFailure = normalized.isBash ? null : detectMcpTransportFailure(payload);
636
775
  if (mcpTransportFailure) {
637
776
  const fallbackCommand = buildOmxParityFallbackCommand(payload, mcpTransportFailure.toolName);
638
777
  const fallbackText = fallbackCommand
@@ -649,11 +788,10 @@ export function buildNativePostToolUseOutput(
649
788
  };
650
789
  }
651
790
 
652
- const normalized = normalizePostToolUsePayload(payload);
653
791
  if (!normalized.isBash) return null;
654
792
 
655
793
  const combined = `${normalized.stderrText}\n${normalized.stdoutText}`.trim();
656
- if (containsHardFailure(combined)) {
794
+ if (hasActionableBashHardFailure(normalized)) {
657
795
  return {
658
796
  decision: "block",
659
797
  reason: "The Bash output indicates a command/setup failure that should be fixed before retrying.",
@@ -75,6 +75,15 @@ export function resolveCurrentTag(cwd: string, explicit?: string): string {
75
75
  throw new Error('unable to determine current release tag; pass --current-tag or set GITHUB_REF_NAME');
76
76
  }
77
77
 
78
+ function isAncestorTag(cwd: string, possibleAncestor: string, currentTag: string): boolean {
79
+ const result = spawnSync('git', ['merge-base', '--is-ancestor', possibleAncestor, currentTag], {
80
+ cwd,
81
+ encoding: 'utf-8',
82
+ stdio: 'pipe',
83
+ });
84
+ return result.status === 0;
85
+ }
86
+
78
87
  export function resolvePreviousTag(cwd: string, currentTag: string, explicit?: string): string | undefined {
79
88
  if (explicit) return explicit;
80
89
  const tags = runGit(['tag', '--list', 'v*', '--sort=-v:refname'], cwd, true)
@@ -83,8 +92,30 @@ export function resolvePreviousTag(cwd: string, currentTag: string, explicit?: s
83
92
  .filter(Boolean);
84
93
  if (tags.length === 0) return undefined;
85
94
  const currentIndex = tags.indexOf(currentTag);
86
- if (currentIndex >= 0) return tags.slice(currentIndex + 1).find(Boolean);
87
- return tags.find((tag) => tag !== currentTag);
95
+ const candidates = currentIndex >= 0
96
+ ? tags.slice(currentIndex + 1)
97
+ : tags.filter((tag) => tag !== currentTag);
98
+ return candidates.find((tag) => isAncestorTag(cwd, tag, currentTag));
99
+ }
100
+
101
+ function verifyGitCommitRef(cwd: string, ref: string, label: string): void {
102
+ if (!runGit(['rev-parse', '--verify', '--quiet', `${ref}^{commit}`], cwd, true)) {
103
+ throw new Error(`unable to verify ${label} ref for release compare: ${ref}`);
104
+ }
105
+ }
106
+
107
+ export function verifyCompareRange(cwd: string, currentTag: string, previousTag?: string): void {
108
+ if (!previousTag) return;
109
+ verifyGitCommitRef(cwd, previousTag, 'previous tag');
110
+ verifyGitCommitRef(cwd, currentTag, 'current tag');
111
+ const mergeBase = spawnSync('git', ['merge-base', '--is-ancestor', previousTag, currentTag], {
112
+ cwd,
113
+ encoding: 'utf-8',
114
+ stdio: 'pipe',
115
+ });
116
+ if (mergeBase.status !== 0) {
117
+ throw new Error(`invalid release compare range: ${previousTag} is not an ancestor of ${currentTag}`);
118
+ }
88
119
  }
89
120
 
90
121
  function normalizeContributors(contributors: Contributor[]): Contributor[] {
@@ -256,6 +287,7 @@ export async function generateReleaseBody(options: GenerateReleaseBodyOptions):
256
287
  const outPath = resolve(cwd, options.outPath);
257
288
  const currentTag = resolveCurrentTag(cwd, options.currentTag);
258
289
  const previousTag = resolvePreviousTag(cwd, currentTag, options.previousTag);
290
+ verifyCompareRange(cwd, currentTag, previousTag);
259
291
  const repo = options.repo || process.env.GITHUB_REPOSITORY || resolveRepositoryFromRemote(cwd);
260
292
  const contributors = await resolveContributors({
261
293
  cwd,
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { existsSync } from 'fs';
4
- import { appendFile, mkdir, readFile, readdir, stat, writeFile } from 'fs/promises';
4
+ import { appendFile, mkdir, open, readFile, readdir, stat, writeFile } from 'fs/promises';
5
5
  import { dirname, join, resolve } from 'path';
6
6
  import { homedir } from 'os';
7
+ import { StringDecoder } from 'string_decoder';
7
8
  import {
8
9
  buildOperationalContext,
9
10
  classifyExecCommand,
@@ -40,6 +41,7 @@ interface FileMeta {
40
41
  partial: string;
41
42
  dispatched: number;
42
43
  currentTurnId: string;
44
+ decoder: StringDecoder;
43
45
  }
44
46
 
45
47
  interface PendingCall {
@@ -415,7 +417,9 @@ async function ensureTrackedFiles(): Promise<void> {
415
417
  const firstLine = await readFirstLine(path).catch(() => '');
416
418
  const meta = shouldTrackSessionMeta(firstLine);
417
419
  if (!meta) continue;
418
- const size = (await stat(path).catch(() => ({ size: 0 }))).size || 0;
420
+ const fileStat = await stat(path).catch(() => null);
421
+ if (!fileStat) continue;
422
+ const size = fileStat.size || 0;
419
423
  const offset = runOnce ? 0 : size;
420
424
  fileState.set(path, {
421
425
  ...meta,
@@ -423,6 +427,7 @@ async function ensureTrackedFiles(): Promise<void> {
423
427
  partial: '',
424
428
  dispatched: 0,
425
429
  currentTurnId: '',
430
+ decoder: new StringDecoder('utf8'),
426
431
  });
427
432
  }
428
433
  }
@@ -504,16 +509,54 @@ async function processLine(meta: FileMeta, line: string): Promise<void> {
504
509
  meta.dispatched += 1;
505
510
  }
506
511
 
512
+ async function readFileDelta(
513
+ path: string,
514
+ offset: number,
515
+ currentSize: number,
516
+ ): Promise<{ bytes: Buffer; nextOffset: number }> {
517
+ const length = currentSize - offset;
518
+ if (length <= 0) return { bytes: Buffer.alloc(0), nextOffset: offset };
519
+ const handle = await open(path, 'r');
520
+ try {
521
+ const buffer = Buffer.allocUnsafe(length);
522
+ let totalBytesRead = 0;
523
+ while (totalBytesRead < length) {
524
+ const { bytesRead } = await handle.read(
525
+ buffer,
526
+ totalBytesRead,
527
+ length - totalBytesRead,
528
+ offset + totalBytesRead,
529
+ );
530
+ if (bytesRead === 0) break;
531
+ totalBytesRead += bytesRead;
532
+ }
533
+ return {
534
+ bytes: buffer.subarray(0, totalBytesRead),
535
+ nextOffset: offset + totalBytesRead,
536
+ };
537
+ } finally {
538
+ await handle.close().catch(() => {});
539
+ }
540
+ }
541
+
507
542
  async function pollFiles(): Promise<void> {
508
543
  for (const [path, meta] of fileState.entries()) {
509
- const currentSize = (await stat(path).catch(() => ({ size: 0 }))).size || 0;
544
+ const fileStat = await stat(path).catch(() => null);
545
+ if (!fileStat) continue;
546
+ const currentSize = fileStat.size || 0;
547
+ if (currentSize < meta.offset) {
548
+ meta.offset = 0;
549
+ meta.partial = '';
550
+ meta.decoder = new StringDecoder('utf8');
551
+ }
510
552
  if (currentSize <= meta.offset) continue;
511
553
 
512
- const content = await readFile(path, 'utf-8').catch(() => '');
513
- if (!content) continue;
514
-
515
- const delta = content.slice(meta.offset);
516
- meta.offset = currentSize;
554
+ const read = await readFileDelta(path, meta.offset, currentSize).catch(() => null);
555
+ if (!read || read.bytes.length === 0) continue;
556
+ const { bytes, nextOffset } = read;
557
+ meta.offset = nextOffset;
558
+ const delta = meta.decoder.write(bytes);
559
+ if (!delta) continue;
517
560
  const merged = meta.partial + delta;
518
561
  const lines = merged.split('\n');
519
562
  meta.partial = lines.pop() || '';
@@ -5,6 +5,7 @@ import { appendFile, mkdir, open, readFile, readdir, rename, rm, stat, unlink, w
5
5
  import { spawnSync } from 'child_process';
6
6
  import { dirname, join, resolve } from 'path';
7
7
  import { homedir } from 'os';
8
+ import { StringDecoder } from 'string_decoder';
8
9
  import { spawnPlatformCommandSync } from '../utils/platform-command.js';
9
10
  import { drainPendingTeamDispatch } from './notify-hook/team-dispatch.js';
10
11
  import {
@@ -93,6 +94,19 @@ function sleep(ms: number): Promise<void> {
93
94
  return new Promise((resolve) => setTimeout(resolve, ms));
94
95
  }
95
96
 
97
+ let atomicJsonWriteCounter = 0;
98
+
99
+ async function writeJsonObjectAtomically(path: string, value: unknown): Promise<void> {
100
+ const tempPath = `${path}.${process.pid}.${Date.now()}.${++atomicJsonWriteCounter}.tmp`;
101
+ try {
102
+ await writeFile(tempPath, JSON.stringify(value, null, 2));
103
+ await rename(tempPath, path);
104
+ } catch (error) {
105
+ await rm(tempPath, { force: true }).catch(() => {});
106
+ throw error;
107
+ }
108
+ }
109
+
96
110
  async function waitForPidExit(pid: number, timeoutMs = 3000, stepMs = 50): Promise<boolean> {
97
111
  const deadline = Date.now() + timeoutMs;
98
112
  while (Date.now() < deadline) {
@@ -156,6 +170,7 @@ interface WatcherFileMeta {
156
170
  offset: number;
157
171
  size: number;
158
172
  partial: string;
173
+ decoder: StringDecoder;
159
174
  }
160
175
 
161
176
  interface RalphContinueSteerState {
@@ -1334,7 +1349,7 @@ async function writeState(extra: Record<string, unknown> = {}): Promise<void> {
1334
1349
  },
1335
1350
  ...extra,
1336
1351
  };
1337
- await writeFile(statePath, JSON.stringify(state, null, 2)).catch(() => {});
1352
+ await writeJsonObjectAtomically(statePath, state).catch(() => {});
1338
1353
  }
1339
1354
 
1340
1355
  async function writeAuthorityBackoffState(): Promise<void> {
@@ -1343,7 +1358,7 @@ async function writeAuthorityBackoffState(): Promise<void> {
1343
1358
  const state = existing && typeof existing === 'object'
1344
1359
  ? { ...existing, authority_backoff: lastAuthorityBackoff }
1345
1360
  : { authority_backoff: lastAuthorityBackoff };
1346
- await writeFile(statePath, JSON.stringify(state, null, 2)).catch(() => {});
1361
+ await writeJsonObjectAtomically(statePath, state).catch(() => {});
1347
1362
  }
1348
1363
 
1349
1364
  async function readJsonObject(path: string): Promise<Record<string, unknown> | null> {
@@ -1683,9 +1698,11 @@ async function ensureTrackedFiles(): Promise<void> {
1683
1698
  const line = await readFirstLine(path).catch(() => '');
1684
1699
  const threadId = shouldTrackSessionMeta(line);
1685
1700
  if (!threadId) continue;
1686
- const size = (await stat(path).catch(() => ({ size: 0 }))).size || 0;
1701
+ const fileStat = await stat(path).catch(() => null);
1702
+ if (!fileStat) continue;
1703
+ const size = fileStat.size || 0;
1687
1704
  const offset = runOnce ? 0 : size;
1688
- fileState.set(path, { threadId, offset, size, partial: '' });
1705
+ fileState.set(path, { threadId, offset, size, partial: '', decoder: new StringDecoder('utf8') });
1689
1706
  }
1690
1707
  }
1691
1708
 
@@ -1698,15 +1715,54 @@ function splitBufferedLines(partial: string, delta: string): { lines: string[];
1698
1715
  };
1699
1716
  }
1700
1717
 
1718
+ async function readFileDelta(
1719
+ path: string,
1720
+ offset: number,
1721
+ currentSize: number,
1722
+ ): Promise<{ bytes: Buffer; nextOffset: number }> {
1723
+ const length = currentSize - offset;
1724
+ if (length <= 0) return { bytes: Buffer.alloc(0), nextOffset: offset };
1725
+ const handle = await open(path, 'r');
1726
+ try {
1727
+ const buffer = Buffer.allocUnsafe(length);
1728
+ let totalBytesRead = 0;
1729
+ while (totalBytesRead < length) {
1730
+ const { bytesRead } = await handle.read(
1731
+ buffer,
1732
+ totalBytesRead,
1733
+ length - totalBytesRead,
1734
+ offset + totalBytesRead,
1735
+ );
1736
+ if (bytesRead === 0) break;
1737
+ totalBytesRead += bytesRead;
1738
+ }
1739
+ return {
1740
+ bytes: buffer.subarray(0, totalBytesRead),
1741
+ nextOffset: offset + totalBytesRead,
1742
+ };
1743
+ } finally {
1744
+ await handle.close().catch(() => {});
1745
+ }
1746
+ }
1747
+
1701
1748
  async function pollFiles(): Promise<number> {
1702
1749
  let processedCount = 0;
1703
1750
  for (const [path, meta] of fileState.entries()) {
1704
- const currentSize = (await stat(path).catch(() => ({ size: 0 }))).size || 0;
1751
+ const fileStat = await stat(path).catch(() => null);
1752
+ if (!fileStat) continue;
1753
+ const currentSize = fileStat.size || 0;
1754
+ if (currentSize < meta.offset) {
1755
+ meta.offset = 0;
1756
+ meta.partial = '';
1757
+ meta.decoder = new StringDecoder('utf8');
1758
+ }
1705
1759
  if (currentSize <= meta.offset) continue;
1706
- const content = await readFile(path, 'utf-8').catch(() => '');
1707
- if (!content) continue;
1708
- const delta = content.slice(meta.offset);
1709
- meta.offset = currentSize;
1760
+ const read = await readFileDelta(path, meta.offset, currentSize).catch(() => null);
1761
+ if (!read || read.bytes.length === 0) continue;
1762
+ const { bytes, nextOffset } = read;
1763
+ meta.offset = nextOffset;
1764
+ const delta = meta.decoder.write(bytes);
1765
+ if (!delta) continue;
1710
1766
  const buffered = splitBufferedLines(meta.partial, delta);
1711
1767
  const lines = buffered.lines;
1712
1768
  meta.partial = buffered.partial;