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,31 +1,35 @@
1
1
  import { execFileSync } from "child_process";
2
- import { existsSync, readFileSync } from "fs";
2
+ import { closeSync, existsSync, openSync, readFileSync, readSync } from "fs";
3
3
  import { mkdir, readFile, readdir, writeFile } from "fs/promises";
4
- import { join, resolve } from "path";
4
+ import { join, relative, resolve } from "path";
5
5
  import { pathToFileURL } from "url";
6
6
  import { readModeState, readModeStateForSession, updateModeState } from "../modes/base.js";
7
7
  import { listActiveSkills, readVisibleSkillActiveState, } from "../state/skill-active.js";
8
- import { readSubagentSessionSummary } from "../subagents/tracker.js";
9
- import { resolveCanonicalTeamStateRoot } from "../team/state-root.js";
10
- import { isSessionStateUsable, readSessionState, readUsableSessionState, reconcileNativeSessionStart, } from "../hooks/session.js";
8
+ import { readSubagentSessionSummary, recordSubagentTurnForSession, } from "../subagents/tracker.js";
9
+ import { resolveCanonicalTeamStateRoot, resolveWorkerNotifyTeamStateRootPath } from "../team/state-root.js";
10
+ import { appendToLog, isSessionStateUsable, readSessionState, readUsableSessionState, reconcileNativeSessionStart, } from "../hooks/session.js";
11
11
  import { appendTeamEvent, readTeamLeaderAttention, readTeamManifestV2, readTeamPhase, writeTeamLeaderAttention, writeTeamPhase, } from "../team/state.js";
12
12
  import { omxNotepadPath, omxProjectMemoryPath } from "../utils/paths.js";
13
+ import { findGitLayout } from "../utils/git-layout.js";
13
14
  import { getStateFilePath, getStatePath } from "../mcp/state-paths.js";
14
15
  import { detectKeywords, detectPrimaryKeyword, recordSkillActivation, } from "../hooks/keyword-detector.js";
15
16
  import { detectNativeStopStallPattern, loadAutoNudgeConfig, normalizeAutoNudgeSignatureText, resolveEffectiveAutoNudgeResponse, } from "./notify-hook/auto-nudge.js";
16
17
  import { buildNativePostToolUseOutput, buildNativePreToolUseOutput, detectMcpTransportFailure, } from "./codex-native-pre-post.js";
18
+ import { handleTeamWorkerPostToolUseSuccess } from "./notify-hook/team-worker-posttooluse.js";
19
+ import { resolveCodexExecutionSurface, } from "./codex-execution-surface.js";
17
20
  import { buildNativeHookEvent, } from "../hooks/extensibility/events.js";
18
21
  import { dispatchHookEvent } from "../hooks/extensibility/dispatcher.js";
19
22
  import { reconcileHudForPromptSubmit } from "../hud/reconcile.js";
20
- import { shellEscapeSingle } from "../hud/tmux.js";
21
23
  import { onSessionStart as buildWikiSessionStartContext } from "../wiki/lifecycle.js";
22
24
  import { readAutoresearchCompletionStatus, readAutoresearchModeState } from "../autoresearch/skill-validation.js";
23
- import { shouldContinueRun } from "../runtime/run-loop.js";
25
+ import { readRunState } from "../runtime/run-state.js";
26
+ import { getRunContinuationSnapshot, shouldContinueRun } from "../runtime/run-loop.js";
24
27
  import { triagePrompt } from "../hooks/triage-heuristic.js";
25
28
  import { readTriageConfig } from "../hooks/triage-config.js";
26
29
  import { readTriageState, writeTriageState, shouldSuppressFollowup, promptSignature, } from "../hooks/triage-state.js";
27
30
  import { isPendingDeepInterviewQuestionEnforcement, reconcileDeepInterviewQuestionEnforcementFromAnsweredRecords, } from "../question/deep-interview.js";
28
- import { resolveOmxCliEntryPath } from "../utils/paths.js";
31
+ import { buildDocumentRefreshAdvisoryOutput, evaluateFinalHandoffDocumentRefresh, isFinalHandoffDocumentRefreshCandidate, } from "../document-refresh/enforcer.js";
32
+ import { buildExecFollowupStopOutput } from "../exec/followup.js";
29
33
  const TERMINAL_MODE_PHASES = new Set(["complete", "failed", "cancelled"]);
30
34
  const SKILL_STOP_BLOCKERS = new Set(["ralplan"]);
31
35
  const TEAM_TERMINAL_TASK_STATUSES = new Set(["completed", "failed"]);
@@ -49,12 +53,125 @@ const SHORT_FOLLOWUP_PRIORITY_PATTERNS = [
49
53
  /(?:按照|按|基于)(?:这个|上述|当前)?(?:plan|计划|方案)/u,
50
54
  /\b(?:follow up|latest request|this turn|current turn|newest request)\b/i,
51
55
  ];
56
+ const MAX_SESSION_META_LINE_BYTES = 256 * 1024;
52
57
  function safeString(value) {
53
58
  return typeof value === "string" ? value : "";
54
59
  }
55
60
  function safeObject(value) {
56
61
  return value && typeof value === "object" ? value : {};
57
62
  }
63
+ function readBoundedFirstLineSync(path) {
64
+ const fd = openSync(path, "r");
65
+ try {
66
+ const chunks = [];
67
+ const buffer = Buffer.alloc(Math.min(8192, MAX_SESSION_META_LINE_BYTES));
68
+ let totalBytesRead = 0;
69
+ while (totalBytesRead < MAX_SESSION_META_LINE_BYTES) {
70
+ const bytesToRead = Math.min(buffer.length, MAX_SESSION_META_LINE_BYTES - totalBytesRead);
71
+ const bytesRead = readSync(fd, buffer, 0, bytesToRead, totalBytesRead);
72
+ if (bytesRead <= 0)
73
+ break;
74
+ totalBytesRead += bytesRead;
75
+ const chunk = buffer.subarray(0, bytesRead);
76
+ const newlineOffset = chunk.indexOf(0x0a);
77
+ if (newlineOffset >= 0) {
78
+ chunks.push(Buffer.from(chunk.subarray(0, newlineOffset)));
79
+ break;
80
+ }
81
+ chunks.push(Buffer.from(chunk));
82
+ }
83
+ return Buffer.concat(chunks).toString("utf-8").replace(/\r$/, "");
84
+ }
85
+ finally {
86
+ closeSync(fd);
87
+ }
88
+ }
89
+ function readNativeSubagentSessionStartMetadata(transcriptPath) {
90
+ const normalizedPath = transcriptPath.trim();
91
+ if (!normalizedPath)
92
+ return null;
93
+ try {
94
+ const firstLine = readBoundedFirstLineSync(normalizedPath).trim();
95
+ if (!firstLine)
96
+ return null;
97
+ const firstRecord = safeObject(JSON.parse(firstLine));
98
+ if (safeString(firstRecord.type) !== "session_meta")
99
+ return null;
100
+ const payload = safeObject(firstRecord.payload);
101
+ const source = safeObject(payload.source);
102
+ const subagent = safeObject(source.subagent);
103
+ const threadSpawn = safeObject(subagent.thread_spawn);
104
+ const parentThreadId = safeString(threadSpawn.parent_thread_id).trim();
105
+ if (!parentThreadId)
106
+ return null;
107
+ const agentNickname = safeString(threadSpawn.agent_nickname ?? payload.agent_nickname).trim();
108
+ const agentRole = safeString(threadSpawn.agent_role ?? payload.agent_role).trim();
109
+ return {
110
+ parentThreadId,
111
+ ...(agentNickname ? { agentNickname } : {}),
112
+ ...(agentRole ? { agentRole } : {}),
113
+ };
114
+ }
115
+ catch {
116
+ return null;
117
+ }
118
+ }
119
+ async function recordNativeSubagentSessionStart(cwd, canonicalSessionId, childSessionId, metadata, transcriptPath) {
120
+ const trackingSessionIds = [...new Set([
121
+ canonicalSessionId.trim(),
122
+ metadata.parentThreadId.trim(),
123
+ ].filter(Boolean))];
124
+ for (const sessionId of trackingSessionIds) {
125
+ await recordSubagentTurnForSession(cwd, {
126
+ sessionId,
127
+ threadId: metadata.parentThreadId,
128
+ }).catch(() => { });
129
+ await recordSubagentTurnForSession(cwd, {
130
+ sessionId,
131
+ threadId: childSessionId,
132
+ mode: metadata.agentRole,
133
+ }).catch(() => { });
134
+ }
135
+ await appendToLog(cwd, {
136
+ event: "subagent_session_start",
137
+ session_id: canonicalSessionId,
138
+ native_owner_session_id: metadata.parentThreadId,
139
+ native_session_id: childSessionId,
140
+ parent_thread_id: metadata.parentThreadId,
141
+ ...(metadata.agentNickname ? { agent_nickname: metadata.agentNickname } : {}),
142
+ ...(metadata.agentRole ? { agent_role: metadata.agentRole } : {}),
143
+ ...(transcriptPath ? { transcript_path: transcriptPath } : {}),
144
+ timestamp: new Date().toISOString(),
145
+ }).catch(() => { });
146
+ }
147
+ async function nativeSubagentSessionStartBelongsToCanonicalSession(cwd, canonicalSessionId, currentSessionState, metadata) {
148
+ const parentThreadId = metadata.parentThreadId.trim();
149
+ if (!parentThreadId)
150
+ return false;
151
+ const currentNativeSessionId = safeString(currentSessionState?.native_session_id).trim();
152
+ if (currentNativeSessionId && currentNativeSessionId === parentThreadId) {
153
+ return true;
154
+ }
155
+ const summary = await readSubagentSessionSummary(cwd, canonicalSessionId).catch(() => null);
156
+ if (!summary)
157
+ return false;
158
+ if (summary.leaderThreadId === parentThreadId)
159
+ return true;
160
+ return summary.allThreadIds.includes(parentThreadId);
161
+ }
162
+ async function recordIgnoredNativeSubagentSessionStart(cwd, canonicalSessionId, childSessionId, metadata, transcriptPath) {
163
+ await appendToLog(cwd, {
164
+ event: "subagent_session_start_ignored",
165
+ reason: "parent_not_in_canonical_session",
166
+ session_id: canonicalSessionId,
167
+ native_session_id: childSessionId,
168
+ parent_thread_id: metadata.parentThreadId,
169
+ ...(metadata.agentNickname ? { agent_nickname: metadata.agentNickname } : {}),
170
+ ...(metadata.agentRole ? { agent_role: metadata.agentRole } : {}),
171
+ ...(transcriptPath ? { transcript_path: transcriptPath } : {}),
172
+ timestamp: new Date().toISOString(),
173
+ }).catch(() => { });
174
+ }
58
175
  function safePositiveInteger(value) {
59
176
  if (typeof value === "number" && Number.isInteger(value) && value > 0)
60
177
  return value;
@@ -192,6 +309,31 @@ async function readActiveAutoresearchState(cwd, sessionId) {
192
309
  return null;
193
310
  return state;
194
311
  }
312
+ function isRalphStartingPhase(state) {
313
+ return safeString(state.current_phase ?? state.currentPhase).trim().toLowerCase() === "starting";
314
+ }
315
+ function shouldHonorCanonicalTerminalRunState(runState, mode) {
316
+ if (!runState)
317
+ return false;
318
+ const runMode = safeString(runState.mode).trim();
319
+ if (runMode && runMode !== mode)
320
+ return false;
321
+ return getRunContinuationSnapshot(runState)?.terminal === true;
322
+ }
323
+ async function readCanonicalTerminalRunStateForStop(cwd, sessionId, mode) {
324
+ if (!safeString(sessionId).trim())
325
+ return null;
326
+ const runState = await readRunState(cwd, sessionId).catch(() => null);
327
+ const runRecord = runState;
328
+ return shouldHonorCanonicalTerminalRunState(runRecord, mode) ? runRecord : null;
329
+ }
330
+ async function isVisibleRalphActiveForSession(cwd, sessionId) {
331
+ const canonicalState = await readVisibleSkillActiveState(cwd, sessionId);
332
+ if (!canonicalState)
333
+ return false;
334
+ return listActiveSkills(canonicalState).some((entry) => (entry.skill === "ralph"
335
+ && matchesSkillStopContext(entry, canonicalState, sessionId, "")));
336
+ }
195
337
  async function readActiveRalphState(stateDir, preferredSessionId) {
196
338
  const cwd = resolve(stateDir, "..", "..");
197
339
  const [rawSessionInfo, usableSessionInfo] = await Promise.all([
@@ -213,16 +355,26 @@ async function readActiveRalphState(stateDir, preferredSessionId) {
213
355
  if (staleCurrentSessionId && sessionId === staleCurrentSessionId) {
214
356
  continue;
215
357
  }
216
- const sessionScoped = await readStopSessionPinnedState("ralph-state.json", cwd, sessionId);
358
+ if (await readCanonicalTerminalRunStateForStop(cwd, sessionId, "ralph")) {
359
+ continue;
360
+ }
361
+ const sessionScopedPath = getStateFilePath("ralph-state.json", cwd, sessionId);
362
+ const sessionScoped = await readJsonIfExists(sessionScopedPath);
363
+ if (sessionScoped?.active === true
364
+ && isRalphStartingPhase(sessionScoped)
365
+ && !(await isVisibleRalphActiveForSession(cwd, sessionId))) {
366
+ continue;
367
+ }
217
368
  if (sessionScoped?.active === true && shouldContinueRun(sessionScoped)) {
218
- return sessionScoped;
369
+ return { state: sessionScoped, path: sessionScopedPath };
219
370
  }
220
371
  }
221
372
  if (sessionCandidates.length > 0)
222
373
  return null;
223
- const direct = await readJsonIfExists(join(stateDir, "ralph-state.json"));
374
+ const directPath = join(stateDir, "ralph-state.json");
375
+ const direct = await readJsonIfExists(directPath);
224
376
  if (direct?.active === true && shouldContinueRun(direct)) {
225
- return direct;
377
+ return { state: direct, path: directPath };
226
378
  }
227
379
  return null;
228
380
  }
@@ -328,6 +480,22 @@ function tryReadGitValue(cwd, args) {
328
480
  return null;
329
481
  }
330
482
  }
483
+ function localExcludeAlreadyIgnoresOmx(cwd) {
484
+ const layout = findGitLayout(cwd);
485
+ if (!layout)
486
+ return false;
487
+ const excludePath = join(layout.gitDir, "info", "exclude");
488
+ try {
489
+ const lines = readFileSync(excludePath, "utf-8")
490
+ .split(/\r?\n/)
491
+ .map((line) => line.trim())
492
+ .filter((line) => line && !line.startsWith("#"));
493
+ return lines.includes(".omx/") || lines.includes(".omx");
494
+ }
495
+ catch {
496
+ return false;
497
+ }
498
+ }
331
499
  function isPathIgnoredByGit(cwd, path) {
332
500
  try {
333
501
  execFileSync("git", ["check-ignore", "-q", path], {
@@ -345,7 +513,7 @@ async function ensureOmxLocalIgnoreEntry(cwd) {
345
513
  const repoRoot = tryReadGitValue(cwd, ["rev-parse", "--show-toplevel"]);
346
514
  if (!repoRoot)
347
515
  return { changed: false };
348
- if (isPathIgnoredByGit(repoRoot, ".omx/")) {
516
+ if (localExcludeAlreadyIgnoresOmx(repoRoot) || isPathIgnoredByGit(repoRoot, ".omx/")) {
349
517
  return { changed: false };
350
518
  }
351
519
  const excludePathValue = tryReadGitValue(repoRoot, ["rev-parse", "--git-path", "info/exclude"]);
@@ -363,8 +531,14 @@ async function ensureOmxLocalIgnoreEntry(cwd) {
363
531
  await writeFile(excludePath, next);
364
532
  return { changed: true, excludePath };
365
533
  }
366
- async function buildSessionStartContext(cwd, sessionId) {
534
+ async function buildSessionStartContext(cwd, sessionId, options = {}) {
367
535
  const sections = [];
536
+ sections.push(buildExecutionEnvironmentSection(cwd, {
537
+ hookEventName: options.hookEventName,
538
+ payload: options.payload,
539
+ canonicalSessionId: options.canonicalSessionId,
540
+ nativeSessionId: options.nativeSessionId,
541
+ }));
368
542
  const localIgnoreResult = await ensureOmxLocalIgnoreEntry(cwd);
369
543
  if (localIgnoreResult.changed) {
370
544
  sections.push(`Added .omx/ to ${localIgnoreResult.excludePath} to keep local OMX state out of source control without mutating tracked repo ignores.`);
@@ -453,6 +627,79 @@ async function buildSessionStartContext(cwd, sessionId) {
453
627
  }
454
628
  return sections.length > 0 ? sections.join("\n\n") : null;
455
629
  }
630
+ function resolveExecutionEnvironment(cwd, options = {}) {
631
+ const executionSurface = resolveCodexExecutionSurface(cwd, options);
632
+ const leaderPaneHint = resolveQuestionLeaderPaneHint(cwd, options.payload);
633
+ const questionBridgeHint = leaderPaneHint
634
+ ? `tmux return bridge recorded at ${leaderPaneHint}, but this process is not attached to tmux; prefer native/user-input fallback unless running from an attached tmux pane`
635
+ : "not available from this outside-tmux surface; use native structured input when available or ask one concise plain-text question";
636
+ if (executionSurface.transport === "attached-tmux") {
637
+ return {
638
+ kind: "attached-tmux-runtime",
639
+ launcher: executionSurface.launcher,
640
+ transport: executionSurface.transport,
641
+ surface: "attached tmux runtime - tmux",
642
+ tmuxWorkflowGuidance: "omx team, omx hud, and omx question are directly usable in this session",
643
+ questionGuidance: "visible renderer available from the current pane",
644
+ teamRuntimeInstruction: "Use the durable OMX team runtime via `omx team ...` for coordinated execution; do not replace it with in-process fanout.",
645
+ teamHelpInstruction: "If you need runtime syntax, run `omx team --help` yourself.",
646
+ deepInterviewInstruction: "Deep-interview must ask each interview round via `omx question`; do not fall back to `request_user_input` or plain-text questioning. This session is already attached to tmux, so `omx question` can open its visible renderer directly. After starting `omx question` in a background terminal, wait for that terminal to finish and read the JSON answer before continuing the interview. Stop remains blocked while a deep-interview question obligation is pending.",
647
+ leaderPaneHint,
648
+ };
649
+ }
650
+ if (leaderPaneHint) {
651
+ const isNativeOutsideTmux = executionSurface.launcher === "native";
652
+ return {
653
+ kind: "outside-tmux-with-bridge",
654
+ launcher: executionSurface.launcher,
655
+ transport: executionSurface.transport,
656
+ surface: isNativeOutsideTmux
657
+ ? "native-hook / Codex App outside tmux with tmux return bridge"
658
+ : "direct CLI outside tmux with tmux return bridge",
659
+ tmuxWorkflowGuidance: "omx team and omx hud need an attached tmux OMX CLI shell from this surface; omx question can use the detected bridge",
660
+ questionGuidance: questionBridgeHint,
661
+ teamRuntimeInstruction: isNativeOutsideTmux
662
+ ? "This session is native-hook / Codex App outside tmux; `omx team` is a CLI/tmux runtime surface, not directly available here. Launch OMX CLI from an attached tmux shell first; do not replace it with in-process fanout."
663
+ : "This session is direct CLI outside tmux with a tmux return bridge for `omx question`; prompt-side `$team` does not auto-start the durable tmux team runtime here. If you intentionally want the runtime, run `omx team ...` yourself from shell instead of replacing it with in-process fanout.",
664
+ teamHelpInstruction: isNativeOutsideTmux
665
+ ? "If you need runtime syntax, run `omx team --help` from an attached tmux OMX CLI shell."
666
+ : "If you need runtime syntax, run `omx team --help` yourself from shell.",
667
+ deepInterviewInstruction: `Deep-interview is active, but this session is not attached to tmux. Do not invoke \`omx question\`, \`omx hud\`, or \`omx team\` from this surface. Ask each interview round through the native structured question tool when available; otherwise ask exactly one concise plain-text question and wait for the answer. A tmux return bridge (${leaderPaneHint}) is recorded for explicit attached-tmux recovery only, not for default Codex App/native fallback.`,
668
+ leaderPaneHint,
669
+ };
670
+ }
671
+ const isNativeOutsideTmux = executionSurface.launcher === "native" && executionSurface.transport === "outside-tmux";
672
+ const surface = isNativeOutsideTmux
673
+ ? "native-hook / Codex App outside tmux"
674
+ : "direct CLI outside tmux";
675
+ const teamRuntimeInstruction = isNativeOutsideTmux
676
+ ? "This session is native-hook / Codex App outside tmux; `omx team` is a CLI/tmux runtime surface, not directly available here. Launch OMX CLI from an attached tmux shell first; do not replace it with in-process fanout."
677
+ : "This session is direct CLI outside tmux; prompt-side `$team` does not auto-start the durable tmux team runtime here. If you intentionally want the runtime, run `omx team ...` yourself from shell instead of replacing it with in-process fanout.";
678
+ const teamHelpInstruction = isNativeOutsideTmux
679
+ ? "If you need runtime syntax, run `omx team --help` from an attached tmux OMX CLI shell rather than from Codex App/native outside-tmux context."
680
+ : "If you need runtime syntax, run `omx team --help` yourself from shell.";
681
+ return {
682
+ kind: isNativeOutsideTmux ? "native-outside-tmux" : "direct-cli-outside-tmux",
683
+ launcher: executionSurface.launcher,
684
+ transport: executionSurface.transport,
685
+ surface,
686
+ tmuxWorkflowGuidance: "omx team, omx hud, and omx question need an attached tmux OMX CLI shell or preserved question bridge from this surface",
687
+ questionGuidance: questionBridgeHint,
688
+ teamRuntimeInstruction,
689
+ teamHelpInstruction,
690
+ deepInterviewInstruction: "Deep-interview is active, but this session is not attached to tmux. Do not invoke `omx question`, `omx hud`, or `omx team` from this surface. Ask each interview round through the native structured question tool when available; otherwise ask exactly one concise plain-text question and wait for the answer. Stop gating still applies to the interview, but no tmux question obligation should be created outside tmux.",
691
+ leaderPaneHint: "",
692
+ };
693
+ }
694
+ function buildExecutionEnvironmentSection(cwd, options = {}) {
695
+ const environment = resolveExecutionEnvironment(cwd, options);
696
+ return [
697
+ "[Execution environment]",
698
+ `- surface: ${environment.surface}`,
699
+ `- omx runtime surfaces: ${environment.tmuxWorkflowGuidance}`,
700
+ `- omx question: ${environment.questionGuidance}`,
701
+ ].join("\n");
702
+ }
456
703
  function resolveQuestionLeaderPaneHint(cwd, payload) {
457
704
  const payloadSessionId = safeString(payload?.session_id).trim();
458
705
  const envSessionId = safeString(process.env.OMX_SESSION_ID || process.env.CODEX_SESSION_ID || process.env.SESSION_ID).trim();
@@ -480,15 +727,54 @@ function resolveQuestionLeaderPaneHint(cwd, payload) {
480
727
  return /^%\d+$/.test(envPane) ? envPane : '';
481
728
  }
482
729
  function buildDeepInterviewQuestionBridgeInstruction(cwd, payload) {
483
- const omxBin = resolveOmxCliEntryPath({ cwd }) || process.argv[1] || "omx";
484
- const leaderPaneHint = resolveQuestionLeaderPaneHint(cwd, payload);
485
- const bridgeCommand = leaderPaneHint
486
- ? `OMX_QUESTION_RETURN_PANE=${shellEscapeSingle(leaderPaneHint)} ${shellEscapeSingle(process.execPath)} ${shellEscapeSingle(omxBin)} question`
487
- : `${shellEscapeSingle(process.execPath)} ${shellEscapeSingle(omxBin)} question`;
488
- const enforcementNote = leaderPaneHint
489
- ? ` When using Bash/background-terminal tool paths, preserve the leader pane by exporting \`OMX_QUESTION_RETURN_PANE=${leaderPaneHint}\` (or equivalent) before invoking \`omx question\`.`
490
- : '';
491
- return `Deep-interview must ask each interview round via \`omx question\`; do not fall back to \`request_user_input\` or plain-text questioning. After starting \`omx question\` in a background terminal, wait for that terminal to finish and read the JSON answer before continuing the interview. If bare \`omx question\` is unavailable in this reused session, use the current-session CLI bridge command: \`${bridgeCommand}\`.${enforcementNote} Stop remains blocked while a deep-interview question obligation is pending.`;
730
+ return resolveExecutionEnvironment(cwd, {
731
+ hookEventName: "UserPromptSubmit",
732
+ payload,
733
+ nativeSessionId: safeString(payload?.session_id ?? payload?.sessionId).trim(),
734
+ }).deepInterviewInstruction;
735
+ }
736
+ function buildTeamRuntimeInstruction(cwd, payload) {
737
+ return resolveExecutionEnvironment(cwd, {
738
+ hookEventName: "UserPromptSubmit",
739
+ payload,
740
+ nativeSessionId: safeString(payload?.session_id ?? payload?.sessionId).trim(),
741
+ }).teamRuntimeInstruction;
742
+ }
743
+ function buildTeamHelpInstruction(cwd, payload) {
744
+ return resolveExecutionEnvironment(cwd, {
745
+ hookEventName: "UserPromptSubmit",
746
+ payload,
747
+ nativeSessionId: safeString(payload?.session_id ?? payload?.sessionId).trim(),
748
+ }).teamHelpInstruction;
749
+ }
750
+ function buildNativeOutsideTmuxTeamPromptBlockState(prompt, cwd, payload, sessionId, threadId, turnId) {
751
+ const match = detectPrimaryKeyword(prompt);
752
+ if (match?.skill !== "team")
753
+ return null;
754
+ const environment = resolveExecutionEnvironment(cwd, {
755
+ hookEventName: "UserPromptSubmit",
756
+ payload,
757
+ canonicalSessionId: sessionId ?? "",
758
+ nativeSessionId: safeString(payload.session_id ?? payload.sessionId).trim(),
759
+ });
760
+ if (!(environment.launcher === "native" && environment.transport === "outside-tmux"))
761
+ return null;
762
+ const nowIso = new Date().toISOString();
763
+ return {
764
+ version: 1,
765
+ active: false,
766
+ skill: "team",
767
+ keyword: match.keyword,
768
+ phase: "planning",
769
+ activated_at: nowIso,
770
+ updated_at: nowIso,
771
+ source: "keyword-detector",
772
+ session_id: sessionId,
773
+ thread_id: threadId,
774
+ turn_id: turnId,
775
+ active_skills: [],
776
+ transition_error: "Codex App/native outside-tmux sessions cannot activate the tmux-only `team` workflow directly. Launch OMX CLI from an attached tmux shell first, then run `omx team ...` there.",
777
+ };
492
778
  }
493
779
  function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(), payload) {
494
780
  if (!prompt)
@@ -548,9 +834,9 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
548
834
  ? `skill: ${skillState.initialized_mode} activated and initial state initialized at ${skillState.initialized_state_path}; write subsequent updates via omx_state MCP.`
549
835
  : null,
550
836
  teamDetected
551
- ? "Use the durable OMX team runtime via `omx team ...` for coordinated execution; do not replace it with in-process fanout."
837
+ ? buildTeamRuntimeInstruction(cwd, payload)
552
838
  : null,
553
- teamDetected ? "If you need runtime syntax, run `omx team --help` yourself." : null,
839
+ teamDetected ? buildTeamHelpInstruction(cwd, payload) : null,
554
840
  'Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.',
555
841
  ].filter(Boolean).join(' ');
556
842
  }
@@ -568,8 +854,8 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
568
854
  initializedStateMessage,
569
855
  deepInterviewPromptActivationNote,
570
856
  ultraworkPromptActivationNote,
571
- "Use the durable OMX team runtime via `omx team ...` for coordinated execution; do not replace it with in-process fanout.",
572
- "If you need runtime syntax, run `omx team --help` yourself.",
857
+ buildTeamRuntimeInstruction(cwd, payload),
858
+ buildTeamHelpInstruction(cwd, payload),
573
859
  "Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.",
574
860
  ].filter(Boolean).join(" ");
575
861
  }
@@ -599,43 +885,16 @@ function parseTeamWorkerEnv(rawValue) {
599
885
  workerName: match[2] || "",
600
886
  };
601
887
  }
602
- async function readTeamStateRootFromJson(path) {
603
- const parsed = await readJsonIfExists(path);
604
- const value = safeString(parsed?.team_state_root).trim();
605
- return value || null;
606
- }
607
888
  async function resolveTeamStateDirForWorkerContext(cwd, workerContext) {
608
- const explicitStateRoot = safeString(process.env.OMX_TEAM_STATE_ROOT).trim();
609
- if (explicitStateRoot) {
610
- return resolve(cwd, explicitStateRoot);
611
- }
612
- const leaderCwd = safeString(process.env.OMX_TEAM_LEADER_CWD).trim();
613
- const candidateStateDirs = [
614
- ...(leaderCwd ? [join(resolve(leaderCwd), ".omx", "state")] : []),
615
- join(cwd, ".omx", "state"),
616
- ];
617
- for (const candidateStateDir of candidateStateDirs) {
618
- const teamRoot = join(candidateStateDir, "team", workerContext.teamName);
619
- if (!existsSync(teamRoot))
620
- continue;
621
- const identityRoot = await readTeamStateRootFromJson(join(teamRoot, "workers", workerContext.workerName, "identity.json"));
622
- if (identityRoot)
623
- return resolve(cwd, identityRoot);
624
- const manifestRoot = await readTeamStateRootFromJson(join(teamRoot, "manifest.v2.json"));
625
- if (manifestRoot)
626
- return resolve(cwd, manifestRoot);
627
- const configRoot = await readTeamStateRootFromJson(join(teamRoot, "config.json"));
628
- if (configRoot)
629
- return resolve(cwd, configRoot);
630
- return candidateStateDir;
631
- }
632
- return join(cwd, ".omx", "state");
889
+ return resolveWorkerNotifyTeamStateRootPath(cwd, workerContext, process.env);
633
890
  }
634
891
  async function buildTeamWorkerStopOutput(cwd) {
635
892
  const workerContext = parseTeamWorkerEnv(safeString(process.env.OMX_TEAM_WORKER));
636
893
  if (!workerContext)
637
894
  return null;
638
895
  const stateDir = await resolveTeamStateDirForWorkerContext(cwd, workerContext);
896
+ if (!stateDir)
897
+ return null;
639
898
  const workerRoot = join(stateDir, "team", workerContext.teamName, "workers", workerContext.workerName);
640
899
  const [identity, status] = await Promise.all([
641
900
  readJsonIfExists(join(workerRoot, "identity.json")),
@@ -716,6 +975,9 @@ async function readTeamModeStateForStop(cwd, sessionId) {
716
975
  return rootState;
717
976
  }
718
977
  async function buildTeamStopOutput(cwd, sessionId) {
978
+ if (await readCanonicalTerminalRunStateForStop(cwd, sessionId, "team")) {
979
+ return null;
980
+ }
719
981
  const teamState = await readTeamModeStateForStop(cwd, sessionId);
720
982
  if (teamState?.active !== true)
721
983
  return null;
@@ -943,6 +1205,12 @@ function buildRepeatableStopSignature(payload, kind, detail = "", canonicalSessi
943
1205
  normalizedDetail || "no-detail",
944
1206
  ].join("|");
945
1207
  }
1208
+ function formatStopStatePath(cwd, statePath) {
1209
+ const relativePath = relative(cwd, statePath);
1210
+ if (!relativePath || relativePath.startsWith(".."))
1211
+ return statePath;
1212
+ return relativePath.replace(/\\/g, "/");
1213
+ }
946
1214
  function readNativeStopSessionKey(payload, canonicalSessionId) {
947
1215
  return resolveRepeatableStopSessionId(payload, canonicalSessionId) || readPayloadThreadId(payload) || "global";
948
1216
  }
@@ -1153,6 +1421,9 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
1153
1421
  const sessionId = readPayloadSessionId(payload);
1154
1422
  const canonicalSessionId = await resolveInternalSessionIdForPayload(cwd, sessionId);
1155
1423
  const threadId = readPayloadThreadId(payload);
1424
+ const execFollowupOutput = await buildExecFollowupStopOutput(cwd, canonicalSessionId);
1425
+ if (execFollowupOutput)
1426
+ return execFollowupOutput;
1156
1427
  const ralphState = await readActiveRalphState(stateDir, canonicalSessionId);
1157
1428
  if (!ralphState) {
1158
1429
  const autoresearchState = await readActiveAutoresearchState(cwd, canonicalSessionId);
@@ -1170,8 +1441,9 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
1170
1441
  }
1171
1442
  }
1172
1443
  const teamWorkerOutput = await buildTeamWorkerStopOutput(cwd);
1173
- if (hasTeamWorkerContext() && teamWorkerOutput)
1174
- return teamWorkerOutput;
1444
+ if (hasTeamWorkerContext() && teamWorkerOutput) {
1445
+ return await returnPersistentStopBlock(payload, stateDir, "team-worker-stop", safeString(teamWorkerOutput.stopReason), teamWorkerOutput, canonicalSessionId, { allowRepeatDuringStopHook: false });
1446
+ }
1175
1447
  const autopilotOutput = await buildModeBasedStopOutput("autopilot", cwd, canonicalSessionId);
1176
1448
  if (autopilotOutput) {
1177
1449
  return await returnPersistentStopBlock(payload, stateDir, "autopilot-stop", safeString(autopilotOutput.stopReason), autopilotOutput, canonicalSessionId, { allowRepeatDuringStopHook: false });
@@ -1196,7 +1468,9 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
1196
1468
  if (deepInterviewQuestionOutput) {
1197
1469
  return await returnPersistentStopBlock(payload, stateDir, "deep-interview-question-stop", deepInterviewQuestionOutput.obligationId, deepInterviewQuestionOutput.output, canonicalSessionId);
1198
1470
  }
1199
- const canonicalTeam = await findCanonicalActiveTeamForSession(cwd, canonicalSessionId);
1471
+ const canonicalTeam = await readCanonicalTerminalRunStateForStop(cwd, canonicalSessionId, "team")
1472
+ ? null
1473
+ : await findCanonicalActiveTeamForSession(cwd, canonicalSessionId);
1200
1474
  if (canonicalTeam) {
1201
1475
  const canonicalTeamOutput = buildTeamStopOutputForPhase(canonicalTeam.teamName, canonicalTeam.phase);
1202
1476
  const repeatedCanonicalTeamOutput = await returnPersistentStopBlock(payload, stateDir, "team-stop", `${canonicalTeam.teamName}|${canonicalTeam.phase}`, canonicalTeamOutput, canonicalSessionId);
@@ -1221,11 +1495,18 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
1221
1495
  systemMessage: "OMX native Stop detected a stall/permission-style handoff and continued the turn automatically.",
1222
1496
  }, canonicalSessionId);
1223
1497
  }
1498
+ if (isFinalHandoffDocumentRefreshCandidate(lastAssistantMessage)) {
1499
+ const documentRefreshWarning = evaluateFinalHandoffDocumentRefresh(cwd, lastAssistantMessage);
1500
+ if (documentRefreshWarning) {
1501
+ return await maybeReturnRepeatableStopOutput(payload, stateDir, buildRepeatableStopSignature(payload, "document-refresh-stop", documentRefreshWarning.triggeringPaths.join("|"), canonicalSessionId), buildDocumentRefreshAdvisoryOutput(documentRefreshWarning, "Stop"), canonicalSessionId, { allowRepeatDuringStopHook: false });
1502
+ }
1503
+ }
1224
1504
  return null;
1225
1505
  }
1226
- const currentPhase = safeString(ralphState?.current_phase).trim() || "executing";
1506
+ const currentPhase = safeString(ralphState.state.current_phase).trim() || "executing";
1507
+ const blockingPath = formatStopStatePath(cwd, ralphState.path);
1227
1508
  const stopReason = `ralph_${currentPhase}`;
1228
- const systemMessage = `OMX Ralph is still active (phase: ${currentPhase}); continue the task and gather fresh verification evidence before stopping.`;
1509
+ const systemMessage = `OMX Ralph is still active (phase: ${currentPhase}; state: ${blockingPath}); continue the task and gather fresh verification evidence before stopping.`;
1229
1510
  return await returnPersistentStopBlock(payload, stateDir, "ralph-stop", currentPhase, {
1230
1511
  decision: "block",
1231
1512
  reason: systemMessage,
@@ -1247,12 +1528,30 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
1247
1528
  const currentSessionState = await readUsableSessionState(cwd);
1248
1529
  let canonicalSessionId = safeString(currentSessionState?.session_id).trim();
1249
1530
  let resolvedNativeSessionId = nativeSessionId;
1531
+ let skipCanonicalSessionStartContext = false;
1250
1532
  if (hookEventName === "SessionStart" && nativeSessionId) {
1251
- const sessionState = await reconcileNativeSessionStart(cwd, nativeSessionId, {
1252
- pid: options.sessionOwnerPid ?? resolveSessionOwnerPid(payload),
1253
- });
1254
- canonicalSessionId = safeString(sessionState.session_id).trim();
1255
- resolvedNativeSessionId = safeString(sessionState.native_session_id).trim() || nativeSessionId;
1533
+ const transcriptPath = safeString(payload.transcript_path ?? payload.transcriptPath).trim();
1534
+ const subagentSessionStart = readNativeSubagentSessionStartMetadata(transcriptPath);
1535
+ if (subagentSessionStart && canonicalSessionId) {
1536
+ const belongsToCanonicalSession = await nativeSubagentSessionStartBelongsToCanonicalSession(cwd, canonicalSessionId, currentSessionState, subagentSessionStart);
1537
+ if (belongsToCanonicalSession) {
1538
+ resolvedNativeSessionId = nativeSessionId;
1539
+ await recordNativeSubagentSessionStart(cwd, canonicalSessionId, nativeSessionId, subagentSessionStart, transcriptPath);
1540
+ }
1541
+ else {
1542
+ skipCanonicalSessionStartContext = true;
1543
+ resolvedNativeSessionId =
1544
+ safeString(currentSessionState?.native_session_id).trim() || nativeSessionId;
1545
+ await recordIgnoredNativeSubagentSessionStart(cwd, canonicalSessionId, nativeSessionId, subagentSessionStart, transcriptPath);
1546
+ }
1547
+ }
1548
+ else {
1549
+ const sessionState = await reconcileNativeSessionStart(cwd, nativeSessionId, {
1550
+ pid: options.sessionOwnerPid ?? resolveSessionOwnerPid(payload),
1551
+ });
1552
+ canonicalSessionId = safeString(sessionState.session_id).trim();
1553
+ resolvedNativeSessionId = safeString(sessionState.native_session_id).trim() || nativeSessionId;
1554
+ }
1256
1555
  }
1257
1556
  else if (!canonicalSessionId) {
1258
1557
  canonicalSessionId = safeString(currentSessionState?.session_id).trim();
@@ -1273,7 +1572,7 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
1273
1572
  if (hookEventName === "UserPromptSubmit") {
1274
1573
  const prompt = readPromptText(payload);
1275
1574
  if (prompt) {
1276
- skillState = await recordSkillActivation({
1575
+ skillState = buildNativeOutsideTmuxTeamPromptBlockState(prompt, cwd, payload, sessionIdForState, threadId || undefined, turnId || undefined) ?? await recordSkillActivation({
1277
1576
  stateDir,
1278
1577
  text: prompt,
1279
1578
  sessionId: sessionIdForState,
@@ -1326,6 +1625,10 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
1326
1625
  triageAdditionalContext =
1327
1626
  "OMX native UserPromptSubmit triage detected a visual/style request with no workflow keyword. This is advisory prompt-routing context only. Prefer the designer role surface.";
1328
1627
  }
1628
+ else if (decision.destination === "researcher") {
1629
+ triageAdditionalContext =
1630
+ "OMX native UserPromptSubmit triage detected an external documentation/reference research request with no workflow keyword. This is advisory prompt-routing context only. Prefer the researcher role surface rather than repo-local explore or autopilot.";
1631
+ }
1329
1632
  if (triageAdditionalContext !== null) {
1330
1633
  const dest = decision.destination;
1331
1634
  const newState = {
@@ -1355,7 +1658,7 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
1355
1658
  const reconcileHudForPromptSubmitFn = options.reconcileHudForPromptSubmitFn ?? reconcileHudForPromptSubmit;
1356
1659
  await reconcileHudForPromptSubmitFn(cwd, { sessionId: canonicalSessionId || sessionIdForState || undefined }).catch(() => { });
1357
1660
  }
1358
- if (omxEventName) {
1661
+ if (omxEventName && !skipCanonicalSessionStartContext) {
1359
1662
  const baseContext = buildBaseContext(cwd, payload, hookEventName, canonicalSessionId);
1360
1663
  if (resolvedNativeSessionId) {
1361
1664
  baseContext.native_session_id = resolvedNativeSessionId;
@@ -1372,9 +1675,14 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
1372
1675
  });
1373
1676
  await dispatchHookEvent(event, { cwd });
1374
1677
  }
1375
- if (hookEventName === "SessionStart" || hookEventName === "UserPromptSubmit") {
1678
+ if ((hookEventName === "SessionStart" && !skipCanonicalSessionStartContext) || hookEventName === "UserPromptSubmit") {
1376
1679
  const additionalContext = hookEventName === "SessionStart"
1377
- ? await buildSessionStartContext(cwd, canonicalSessionId || nativeSessionId)
1680
+ ? await buildSessionStartContext(cwd, canonicalSessionId || nativeSessionId, {
1681
+ hookEventName,
1682
+ payload,
1683
+ canonicalSessionId,
1684
+ nativeSessionId: resolvedNativeSessionId || nativeSessionId,
1685
+ })
1378
1686
  : (buildAdditionalContextMessage(readPromptText(payload), skillState, cwd, payload) ?? triageAdditionalContext);
1379
1687
  if (additionalContext) {
1380
1688
  outputJson = {
@@ -1393,6 +1701,7 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
1393
1701
  await markTeamTransportFailure(cwd, payload);
1394
1702
  }
1395
1703
  outputJson = buildNativePostToolUseOutput(payload);
1704
+ await handleTeamWorkerPostToolUseSuccess(payload, cwd);
1396
1705
  }
1397
1706
  else if (hookEventName === "Stop") {
1398
1707
  outputJson = await buildStopHookOutput(payload, cwd, stateDir);
@@ -1431,22 +1740,55 @@ async function readStdinJson() {
1431
1740
  };
1432
1741
  }
1433
1742
  }
1743
+ function writeNativeHookJsonStdout(output) {
1744
+ process.stdout.write(`${JSON.stringify(output)}\n`);
1745
+ }
1746
+ function isStopDispatchFailureTestTrigger(payload) {
1747
+ return process.env.NODE_ENV === "test"
1748
+ && process.env.OMX_NATIVE_HOOK_TEST_THROW_STOP_DISPATCH === "1"
1749
+ && readHookEventName(payload) === "Stop";
1750
+ }
1751
+ function buildStopDispatchFailureOutput(error) {
1752
+ const detail = error instanceof Error ? error.message : String(error);
1753
+ const reason = "OMX native Stop hook failed before normal continuation handling. Continue once more, preserve runtime state, inspect the hook logs, and retry with a valid Stop JSON response.";
1754
+ return {
1755
+ decision: "block",
1756
+ reason,
1757
+ stopReason: "native_stop_dispatch_failure",
1758
+ systemMessage: `${reason} Failure: ${detail}`,
1759
+ };
1760
+ }
1434
1761
  export async function runCodexNativeHookCli() {
1435
1762
  const { payload, parseError } = await readStdinJson();
1436
1763
  if (parseError) {
1437
- process.stdout.write(`${JSON.stringify({
1764
+ writeNativeHookJsonStdout({
1438
1765
  decision: "block",
1439
1766
  reason: "OMX native hook received malformed JSON input. Preserve runtime state, inspect the emitting hook payload yourself, and retry with valid JSON.",
1440
1767
  hookSpecificOutput: {
1441
1768
  hookEventName: "Unknown",
1442
1769
  additionalContext: `stdin JSON parsing failed inside codex-native-hook: ${parseError.message}. Emit valid JSON from the native hook caller before retrying.`,
1443
1770
  },
1444
- })}\n`);
1771
+ });
1445
1772
  return;
1446
1773
  }
1447
- const result = await dispatchCodexNativeHook(payload);
1448
- if (result.outputJson) {
1449
- process.stdout.write(`${JSON.stringify(result.outputJson)}\n`);
1774
+ try {
1775
+ if (isStopDispatchFailureTestTrigger(payload)) {
1776
+ throw new Error("test-induced Stop dispatch failure");
1777
+ }
1778
+ const result = await dispatchCodexNativeHook(payload);
1779
+ if (result.outputJson) {
1780
+ writeNativeHookJsonStdout(result.outputJson);
1781
+ }
1782
+ else if (result.hookEventName === "Stop") {
1783
+ writeNativeHookJsonStdout({});
1784
+ }
1785
+ }
1786
+ catch (error) {
1787
+ if (readHookEventName(payload) !== "Stop") {
1788
+ throw error;
1789
+ }
1790
+ process.stderr.write(`[omx] codex-native Stop hook dispatch failed: ${error instanceof Error ? error.message : String(error)}\n`);
1791
+ writeNativeHookJsonStdout(buildStopDispatchFailureOutput(error));
1450
1792
  }
1451
1793
  }
1452
1794
  if (isCodexNativeHookMainModule(import.meta.url, process.argv[1])) {