oh-my-codex 0.18.0 → 0.18.2

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 (410) hide show
  1. package/Cargo.lock +6 -6
  2. package/Cargo.toml +1 -1
  3. package/README.md +45 -19
  4. package/crates/omx-api/src/lib.rs +66 -9
  5. package/crates/omx-sparkshell/src/exec.rs +125 -3
  6. package/crates/omx-sparkshell/src/main.rs +126 -36
  7. package/crates/omx-sparkshell/tests/execution.rs +225 -1
  8. package/dist/agents/__tests__/definitions.test.js +14 -0
  9. package/dist/agents/__tests__/definitions.test.js.map +1 -1
  10. package/dist/agents/__tests__/native-config.test.js +19 -0
  11. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  12. package/dist/agents/definitions.d.ts.map +1 -1
  13. package/dist/agents/definitions.js +30 -0
  14. package/dist/agents/definitions.js.map +1 -1
  15. package/dist/agents/native-config.d.ts +1 -0
  16. package/dist/agents/native-config.d.ts.map +1 -1
  17. package/dist/agents/native-config.js +4 -0
  18. package/dist/agents/native-config.js.map +1 -1
  19. package/dist/catalog/__tests__/generator.test.js +4 -0
  20. package/dist/catalog/__tests__/generator.test.js.map +1 -1
  21. package/dist/cli/__tests__/codex-plugin-layout.test.js +15 -7
  22. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  23. package/dist/cli/__tests__/doctor-warning-copy.test.js +137 -8
  24. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  25. package/dist/cli/__tests__/index.test.js +203 -15
  26. package/dist/cli/__tests__/index.test.js.map +1 -1
  27. package/dist/cli/__tests__/install-docs-contract.test.d.ts +2 -0
  28. package/dist/cli/__tests__/install-docs-contract.test.d.ts.map +1 -0
  29. package/dist/cli/__tests__/install-docs-contract.test.js +55 -0
  30. package/dist/cli/__tests__/install-docs-contract.test.js.map +1 -0
  31. package/dist/cli/__tests__/launch-fallback.test.js +163 -0
  32. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  33. package/dist/cli/__tests__/question.test.js +29 -43
  34. package/dist/cli/__tests__/question.test.js.map +1 -1
  35. package/dist/cli/__tests__/setup-install-mode.test.js +94 -35
  36. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  37. package/dist/cli/__tests__/sparkshell-cli.test.js +20 -1
  38. package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -1
  39. package/dist/cli/__tests__/sparkshell-packaging.test.js +1 -0
  40. package/dist/cli/__tests__/sparkshell-packaging.test.js.map +1 -1
  41. package/dist/cli/__tests__/ultragoal.test.js +227 -4
  42. package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
  43. package/dist/cli/__tests__/update.test.js +72 -1
  44. package/dist/cli/__tests__/update.test.js.map +1 -1
  45. package/dist/cli/codex-feature-probe.d.ts +5 -0
  46. package/dist/cli/codex-feature-probe.d.ts.map +1 -1
  47. package/dist/cli/codex-feature-probe.js +13 -7
  48. package/dist/cli/codex-feature-probe.js.map +1 -1
  49. package/dist/cli/doctor.d.ts +7 -0
  50. package/dist/cli/doctor.d.ts.map +1 -1
  51. package/dist/cli/doctor.js +297 -17
  52. package/dist/cli/doctor.js.map +1 -1
  53. package/dist/cli/index.d.ts +9 -1
  54. package/dist/cli/index.d.ts.map +1 -1
  55. package/dist/cli/index.js +465 -110
  56. package/dist/cli/index.js.map +1 -1
  57. package/dist/cli/plugin-marketplace.d.ts +2 -0
  58. package/dist/cli/plugin-marketplace.d.ts.map +1 -1
  59. package/dist/cli/plugin-marketplace.js +15 -1
  60. package/dist/cli/plugin-marketplace.js.map +1 -1
  61. package/dist/cli/setup.d.ts.map +1 -1
  62. package/dist/cli/setup.js +71 -11
  63. package/dist/cli/setup.js.map +1 -1
  64. package/dist/cli/sparkshell.d.ts +7 -1
  65. package/dist/cli/sparkshell.d.ts.map +1 -1
  66. package/dist/cli/sparkshell.js +13 -3
  67. package/dist/cli/sparkshell.js.map +1 -1
  68. package/dist/cli/ultragoal.d.ts +1 -1
  69. package/dist/cli/ultragoal.d.ts.map +1 -1
  70. package/dist/cli/ultragoal.js +184 -10
  71. package/dist/cli/ultragoal.js.map +1 -1
  72. package/dist/cli/update.d.ts +2 -0
  73. package/dist/cli/update.d.ts.map +1 -1
  74. package/dist/cli/update.js +14 -3
  75. package/dist/cli/update.js.map +1 -1
  76. package/dist/compat/__tests__/doctor-contract.test.js +3 -0
  77. package/dist/compat/__tests__/doctor-contract.test.js.map +1 -1
  78. package/dist/config/__tests__/codex-feature-flags.test.js +11 -1
  79. package/dist/config/__tests__/codex-feature-flags.test.js.map +1 -1
  80. package/dist/config/__tests__/codex-hooks.test.js +22 -11
  81. package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
  82. package/dist/config/__tests__/commit-lore-guard.test.d.ts +2 -0
  83. package/dist/config/__tests__/commit-lore-guard.test.d.ts.map +1 -0
  84. package/dist/config/__tests__/commit-lore-guard.test.js +20 -0
  85. package/dist/config/__tests__/commit-lore-guard.test.js.map +1 -0
  86. package/dist/config/codex-feature-flags.d.ts +4 -0
  87. package/dist/config/codex-feature-flags.d.ts.map +1 -1
  88. package/dist/config/codex-feature-flags.js +4 -0
  89. package/dist/config/codex-feature-flags.js.map +1 -1
  90. package/dist/config/codex-hooks.d.ts +1 -0
  91. package/dist/config/codex-hooks.d.ts.map +1 -1
  92. package/dist/config/codex-hooks.js +8 -10
  93. package/dist/config/codex-hooks.js.map +1 -1
  94. package/dist/config/commit-lore-guard.d.ts +1 -0
  95. package/dist/config/commit-lore-guard.d.ts.map +1 -1
  96. package/dist/config/commit-lore-guard.js +29 -3
  97. package/dist/config/commit-lore-guard.js.map +1 -1
  98. package/dist/config/generator.d.ts +17 -1
  99. package/dist/config/generator.d.ts.map +1 -1
  100. package/dist/config/generator.js +124 -11
  101. package/dist/config/generator.js.map +1 -1
  102. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js +21 -0
  103. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js.map +1 -1
  104. package/dist/goal-workflows/codex-goal-snapshot.d.ts +4 -0
  105. package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -1
  106. package/dist/goal-workflows/codex-goal-snapshot.js +50 -3
  107. package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -1
  108. package/dist/hooks/__tests__/autopilot-skill-contract.test.js +27 -6
  109. package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
  110. package/dist/hooks/__tests__/consensus-execution-handoff.test.d.ts +1 -1
  111. package/dist/hooks/__tests__/consensus-execution-handoff.test.js +13 -11
  112. package/dist/hooks/__tests__/consensus-execution-handoff.test.js.map +1 -1
  113. package/dist/hooks/__tests__/deep-interview-contract.test.js +4 -3
  114. package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
  115. package/dist/hooks/__tests__/keyword-detector.test.js +173 -17
  116. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  117. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +33 -0
  118. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  119. package/dist/hooks/__tests__/prometheus-strict-contract.test.d.ts +2 -0
  120. package/dist/hooks/__tests__/prometheus-strict-contract.test.d.ts.map +1 -0
  121. package/dist/hooks/__tests__/prometheus-strict-contract.test.js +320 -0
  122. package/dist/hooks/__tests__/prometheus-strict-contract.test.js.map +1 -0
  123. package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +12 -0
  124. package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +1 -1
  125. package/dist/hooks/__tests__/research-workflow-boundaries.test.d.ts +2 -0
  126. package/dist/hooks/__tests__/research-workflow-boundaries.test.d.ts.map +1 -0
  127. package/dist/hooks/__tests__/research-workflow-boundaries.test.js +35 -0
  128. package/dist/hooks/__tests__/research-workflow-boundaries.test.js.map +1 -0
  129. package/dist/hooks/extensibility/__tests__/dispatcher.test.js +26 -3
  130. package/dist/hooks/extensibility/__tests__/dispatcher.test.js.map +1 -1
  131. package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -1
  132. package/dist/hooks/extensibility/dispatcher.js +29 -14
  133. package/dist/hooks/extensibility/dispatcher.js.map +1 -1
  134. package/dist/hooks/keyword-detector.d.ts +1 -1
  135. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  136. package/dist/hooks/keyword-detector.js +36 -9
  137. package/dist/hooks/keyword-detector.js.map +1 -1
  138. package/dist/hooks/keyword-registry.d.ts.map +1 -1
  139. package/dist/hooks/keyword-registry.js +1 -0
  140. package/dist/hooks/keyword-registry.js.map +1 -1
  141. package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
  142. package/dist/hooks/prompt-guidance-contract.js +14 -2
  143. package/dist/hooks/prompt-guidance-contract.js.map +1 -1
  144. package/dist/hud/__tests__/hud-tmux-injection.test.js +36 -8
  145. package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
  146. package/dist/hud/__tests__/reconcile.test.js +122 -11
  147. package/dist/hud/__tests__/reconcile.test.js.map +1 -1
  148. package/dist/hud/__tests__/render.test.js +84 -0
  149. package/dist/hud/__tests__/render.test.js.map +1 -1
  150. package/dist/hud/__tests__/resource-leak-watch.test.d.ts +2 -0
  151. package/dist/hud/__tests__/resource-leak-watch.test.d.ts.map +1 -0
  152. package/dist/hud/__tests__/resource-leak-watch.test.js +28 -0
  153. package/dist/hud/__tests__/resource-leak-watch.test.js.map +1 -0
  154. package/dist/hud/__tests__/state.test.js +51 -1
  155. package/dist/hud/__tests__/state.test.js.map +1 -1
  156. package/dist/hud/__tests__/tmux.test.js +69 -23
  157. package/dist/hud/__tests__/tmux.test.js.map +1 -1
  158. package/dist/hud/index.d.ts +2 -2
  159. package/dist/hud/index.d.ts.map +1 -1
  160. package/dist/hud/index.js +17 -6
  161. package/dist/hud/index.js.map +1 -1
  162. package/dist/hud/reconcile.d.ts.map +1 -1
  163. package/dist/hud/reconcile.js +6 -3
  164. package/dist/hud/reconcile.js.map +1 -1
  165. package/dist/hud/render.d.ts.map +1 -1
  166. package/dist/hud/render.js +26 -0
  167. package/dist/hud/render.js.map +1 -1
  168. package/dist/hud/state.d.ts +2 -1
  169. package/dist/hud/state.d.ts.map +1 -1
  170. package/dist/hud/state.js +62 -1
  171. package/dist/hud/state.js.map +1 -1
  172. package/dist/hud/tmux.d.ts +10 -3
  173. package/dist/hud/tmux.d.ts.map +1 -1
  174. package/dist/hud/tmux.js +60 -11
  175. package/dist/hud/tmux.js.map +1 -1
  176. package/dist/hud/types.d.ts +22 -0
  177. package/dist/hud/types.d.ts.map +1 -1
  178. package/dist/hud/types.js.map +1 -1
  179. package/dist/notifications/__tests__/http-client-resource.test.d.ts +2 -0
  180. package/dist/notifications/__tests__/http-client-resource.test.d.ts.map +1 -0
  181. package/dist/notifications/__tests__/http-client-resource.test.js +41 -0
  182. package/dist/notifications/__tests__/http-client-resource.test.js.map +1 -0
  183. package/dist/notifications/__tests__/verbosity.test.js +20 -0
  184. package/dist/notifications/__tests__/verbosity.test.js.map +1 -1
  185. package/dist/notifications/config.d.ts.map +1 -1
  186. package/dist/notifications/config.js +6 -3
  187. package/dist/notifications/config.js.map +1 -1
  188. package/dist/notifications/http-client.d.ts.map +1 -1
  189. package/dist/notifications/http-client.js +78 -27
  190. package/dist/notifications/http-client.js.map +1 -1
  191. package/dist/notifications/types.d.ts +2 -0
  192. package/dist/notifications/types.d.ts.map +1 -1
  193. package/dist/openclaw/__tests__/dispatcher.test.js +49 -1
  194. package/dist/openclaw/__tests__/dispatcher.test.js.map +1 -1
  195. package/dist/openclaw/dispatcher.d.ts +7 -4
  196. package/dist/openclaw/dispatcher.d.ts.map +1 -1
  197. package/dist/openclaw/dispatcher.js +32 -69
  198. package/dist/openclaw/dispatcher.js.map +1 -1
  199. package/dist/pipeline/__tests__/orchestrator.test.js +128 -4
  200. package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
  201. package/dist/pipeline/__tests__/stages.test.js +460 -9
  202. package/dist/pipeline/__tests__/stages.test.js.map +1 -1
  203. package/dist/pipeline/index.d.ts +8 -2
  204. package/dist/pipeline/index.d.ts.map +1 -1
  205. package/dist/pipeline/index.js +5 -2
  206. package/dist/pipeline/index.js.map +1 -1
  207. package/dist/pipeline/orchestrator.d.ts +5 -4
  208. package/dist/pipeline/orchestrator.d.ts.map +1 -1
  209. package/dist/pipeline/orchestrator.js +85 -17
  210. package/dist/pipeline/orchestrator.js.map +1 -1
  211. package/dist/pipeline/stages/code-review.d.ts +2 -2
  212. package/dist/pipeline/stages/code-review.d.ts.map +1 -1
  213. package/dist/pipeline/stages/code-review.js +5 -3
  214. package/dist/pipeline/stages/code-review.js.map +1 -1
  215. package/dist/pipeline/stages/deep-interview.d.ts +15 -0
  216. package/dist/pipeline/stages/deep-interview.d.ts.map +1 -0
  217. package/dist/pipeline/stages/deep-interview.js +32 -0
  218. package/dist/pipeline/stages/deep-interview.js.map +1 -0
  219. package/dist/pipeline/stages/ralph-verify.d.ts +5 -5
  220. package/dist/pipeline/stages/ralph-verify.d.ts.map +1 -1
  221. package/dist/pipeline/stages/ralph-verify.js +2 -2
  222. package/dist/pipeline/stages/ralph-verify.js.map +1 -1
  223. package/dist/pipeline/stages/ralplan.d.ts.map +1 -1
  224. package/dist/pipeline/stages/ralplan.js +41 -6
  225. package/dist/pipeline/stages/ralplan.js.map +1 -1
  226. package/dist/pipeline/stages/ultragoal.d.ts +19 -0
  227. package/dist/pipeline/stages/ultragoal.d.ts.map +1 -0
  228. package/dist/pipeline/stages/ultragoal.js +38 -0
  229. package/dist/pipeline/stages/ultragoal.js.map +1 -0
  230. package/dist/pipeline/stages/ultraqa.d.ts +30 -0
  231. package/dist/pipeline/stages/ultraqa.d.ts.map +1 -0
  232. package/dist/pipeline/stages/ultraqa.js +46 -0
  233. package/dist/pipeline/stages/ultraqa.js.map +1 -0
  234. package/dist/pipeline/types.d.ts +8 -6
  235. package/dist/pipeline/types.d.ts.map +1 -1
  236. package/dist/pipeline/types.js +2 -2
  237. package/dist/question/__tests__/ui.test.js +43 -10
  238. package/dist/question/__tests__/ui.test.js.map +1 -1
  239. package/dist/question/ui.d.ts +12 -0
  240. package/dist/question/ui.d.ts.map +1 -1
  241. package/dist/question/ui.js +83 -46
  242. package/dist/question/ui.js.map +1 -1
  243. package/dist/ralplan/__tests__/runtime.test.js +200 -10
  244. package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
  245. package/dist/ralplan/consensus-gate.d.ts +23 -0
  246. package/dist/ralplan/consensus-gate.d.ts.map +1 -0
  247. package/dist/ralplan/consensus-gate.js +212 -0
  248. package/dist/ralplan/consensus-gate.js.map +1 -0
  249. package/dist/ralplan/runtime.d.ts +25 -0
  250. package/dist/ralplan/runtime.d.ts.map +1 -1
  251. package/dist/ralplan/runtime.js +144 -8
  252. package/dist/ralplan/runtime.js.map +1 -1
  253. package/dist/scripts/__tests__/codex-native-hook.test.js +1358 -79
  254. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  255. package/dist/scripts/__tests__/docs-site-contract.test.d.ts +2 -0
  256. package/dist/scripts/__tests__/docs-site-contract.test.d.ts.map +1 -0
  257. package/dist/scripts/__tests__/docs-site-contract.test.js +42 -0
  258. package/dist/scripts/__tests__/docs-site-contract.test.js.map +1 -0
  259. package/dist/scripts/__tests__/notify-dispatcher.test.js +115 -2
  260. package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -1
  261. package/dist/scripts/__tests__/run-test-files.test.js +57 -0
  262. package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
  263. package/dist/scripts/__tests__/smoke-packed-install.test.js +23 -1
  264. package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
  265. package/dist/scripts/__tests__/verify-native-agents.test.js +18 -3
  266. package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -1
  267. package/dist/scripts/cleanup-explore-harness.js +1 -0
  268. package/dist/scripts/cleanup-explore-harness.js.map +1 -1
  269. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  270. package/dist/scripts/codex-native-hook.js +372 -44
  271. package/dist/scripts/codex-native-hook.js.map +1 -1
  272. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
  273. package/dist/scripts/codex-native-pre-post.js +9 -1
  274. package/dist/scripts/codex-native-pre-post.js.map +1 -1
  275. package/dist/scripts/notify-dispatcher.js +188 -4
  276. package/dist/scripts/notify-dispatcher.js.map +1 -1
  277. package/dist/scripts/notify-hook/process-runner.d.ts.map +1 -1
  278. package/dist/scripts/notify-hook/process-runner.js +39 -17
  279. package/dist/scripts/notify-hook/process-runner.js.map +1 -1
  280. package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
  281. package/dist/scripts/notify-hook/team-dispatch.js +9 -5
  282. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  283. package/dist/scripts/notify-hook/team-tmux-guard.d.ts +1 -1
  284. package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
  285. package/dist/scripts/notify-hook/team-tmux-guard.js +7 -1
  286. package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
  287. package/dist/scripts/run-test-files.js +13 -0
  288. package/dist/scripts/run-test-files.js.map +1 -1
  289. package/dist/scripts/smoke-packed-install.d.ts +3 -0
  290. package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
  291. package/dist/scripts/smoke-packed-install.js +99 -1
  292. package/dist/scripts/smoke-packed-install.js.map +1 -1
  293. package/dist/scripts/sync-plugin-mirror.js +2 -2
  294. package/dist/scripts/sync-plugin-mirror.js.map +1 -1
  295. package/dist/scripts/verify-native-agents.js +2 -2
  296. package/dist/scripts/verify-native-agents.js.map +1 -1
  297. package/dist/sidecar/__tests__/resource-leak-watch.test.d.ts +2 -0
  298. package/dist/sidecar/__tests__/resource-leak-watch.test.d.ts.map +1 -0
  299. package/dist/sidecar/__tests__/resource-leak-watch.test.js +38 -0
  300. package/dist/sidecar/__tests__/resource-leak-watch.test.js.map +1 -0
  301. package/dist/sidecar/index.d.ts +1 -1
  302. package/dist/sidecar/index.d.ts.map +1 -1
  303. package/dist/sidecar/index.js +29 -12
  304. package/dist/sidecar/index.js.map +1 -1
  305. package/dist/state/__tests__/operations-ralph-phase.test.js +88 -1
  306. package/dist/state/__tests__/operations-ralph-phase.test.js.map +1 -1
  307. package/dist/state/__tests__/workflow-transition.test.js +6 -0
  308. package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
  309. package/dist/state/operations.d.ts.map +1 -1
  310. package/dist/state/operations.js +11 -0
  311. package/dist/state/operations.js.map +1 -1
  312. package/dist/state/workflow-transition.d.ts +1 -1
  313. package/dist/state/workflow-transition.d.ts.map +1 -1
  314. package/dist/state/workflow-transition.js +7 -0
  315. package/dist/state/workflow-transition.js.map +1 -1
  316. package/dist/subagents/tracker.d.ts.map +1 -1
  317. package/dist/subagents/tracker.js +4 -3
  318. package/dist/subagents/tracker.js.map +1 -1
  319. package/dist/team/__tests__/runtime.test.js +36 -44
  320. package/dist/team/__tests__/runtime.test.js.map +1 -1
  321. package/dist/team/__tests__/tmux-session.test.js +163 -15
  322. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  323. package/dist/team/runtime.d.ts.map +1 -1
  324. package/dist/team/runtime.js +10 -20
  325. package/dist/team/runtime.js.map +1 -1
  326. package/dist/team/tmux-session.d.ts.map +1 -1
  327. package/dist/team/tmux-session.js +51 -21
  328. package/dist/team/tmux-session.js.map +1 -1
  329. package/dist/ultragoal/__tests__/artifacts.test.js +764 -10
  330. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  331. package/dist/ultragoal/__tests__/docs-contract.test.js +57 -1
  332. package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
  333. package/dist/ultragoal/__tests__/steering-fixtures.d.ts +68 -0
  334. package/dist/ultragoal/__tests__/steering-fixtures.d.ts.map +1 -0
  335. package/dist/ultragoal/__tests__/steering-fixtures.js +259 -0
  336. package/dist/ultragoal/__tests__/steering-fixtures.js.map +1 -0
  337. package/dist/ultragoal/__tests__/steering-fixtures.test.d.ts +2 -0
  338. package/dist/ultragoal/__tests__/steering-fixtures.test.d.ts.map +1 -0
  339. package/dist/ultragoal/__tests__/steering-fixtures.test.js +65 -0
  340. package/dist/ultragoal/__tests__/steering-fixtures.test.js.map +1 -0
  341. package/dist/ultragoal/artifacts.d.ts +97 -2
  342. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  343. package/dist/ultragoal/artifacts.js +837 -256
  344. package/dist/ultragoal/artifacts.js.map +1 -1
  345. package/dist/utils/__tests__/sleep-resource.test.d.ts +2 -0
  346. package/dist/utils/__tests__/sleep-resource.test.d.ts.map +1 -0
  347. package/dist/utils/__tests__/sleep-resource.test.js +39 -0
  348. package/dist/utils/__tests__/sleep-resource.test.js.map +1 -0
  349. package/dist/utils/sleep.d.ts.map +1 -1
  350. package/dist/utils/sleep.js +17 -6
  351. package/dist/utils/sleep.js.map +1 -1
  352. package/package.json +2 -1
  353. package/plugins/oh-my-codex/.codex-plugin/plugin.json +4 -3
  354. package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +56 -0
  355. package/plugins/oh-my-codex/hooks/hooks.json +77 -0
  356. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +92 -50
  357. package/plugins/oh-my-codex/skills/autoresearch/SKILL.md +4 -0
  358. package/plugins/oh-my-codex/skills/autoresearch-goal/SKILL.md +1 -1
  359. package/plugins/oh-my-codex/skills/best-practice-research/SKILL.md +1 -1
  360. package/plugins/oh-my-codex/skills/cancel/SKILL.md +2 -2
  361. package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +8 -8
  362. package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +1 -1
  363. package/plugins/oh-my-codex/skills/pipeline/SKILL.md +23 -12
  364. package/plugins/oh-my-codex/skills/plan/SKILL.md +8 -8
  365. package/plugins/oh-my-codex/skills/prometheus-strict/README.md +35 -0
  366. package/plugins/oh-my-codex/skills/prometheus-strict/SKILL.md +219 -0
  367. package/plugins/oh-my-codex/skills/ralph/SKILL.md +7 -0
  368. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +22 -7
  369. package/plugins/oh-my-codex/skills/team/SKILL.md +1 -1
  370. package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +38 -4
  371. package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +1 -1
  372. package/prompts/planner.md +1 -1
  373. package/prompts/prometheus-strict-metis.md +274 -0
  374. package/prompts/prometheus-strict-momus.md +82 -0
  375. package/prompts/prometheus-strict-oracle.md +107 -0
  376. package/prompts/researcher.md +22 -3
  377. package/skills/autopilot/SKILL.md +92 -50
  378. package/skills/autoresearch/SKILL.md +4 -0
  379. package/skills/autoresearch-goal/SKILL.md +1 -1
  380. package/skills/best-practice-research/SKILL.md +1 -1
  381. package/skills/cancel/SKILL.md +2 -2
  382. package/skills/deep-interview/SKILL.md +8 -8
  383. package/skills/omx-setup/SKILL.md +1 -1
  384. package/skills/pipeline/SKILL.md +23 -12
  385. package/skills/plan/SKILL.md +8 -8
  386. package/skills/prometheus-strict/README.md +35 -0
  387. package/skills/prometheus-strict/SKILL.md +219 -0
  388. package/skills/ralph/SKILL.md +7 -0
  389. package/skills/ralplan/SKILL.md +22 -7
  390. package/skills/team/SKILL.md +1 -1
  391. package/skills/ultragoal/SKILL.md +38 -4
  392. package/skills/ultrawork/SKILL.md +1 -1
  393. package/src/scripts/__tests__/codex-native-hook.test.ts +1757 -210
  394. package/src/scripts/__tests__/docs-site-contract.test.ts +47 -0
  395. package/src/scripts/__tests__/notify-dispatcher.test.ts +132 -3
  396. package/src/scripts/__tests__/run-test-files.test.ts +67 -0
  397. package/src/scripts/__tests__/smoke-packed-install.test.ts +31 -0
  398. package/src/scripts/__tests__/verify-native-agents.test.ts +23 -3
  399. package/src/scripts/cleanup-explore-harness.ts +1 -0
  400. package/src/scripts/codex-native-hook.ts +393 -40
  401. package/src/scripts/codex-native-pre-post.ts +16 -1
  402. package/src/scripts/notify-dispatcher.ts +202 -4
  403. package/src/scripts/notify-hook/process-runner.ts +40 -16
  404. package/src/scripts/notify-hook/team-dispatch.ts +9 -5
  405. package/src/scripts/notify-hook/team-tmux-guard.ts +7 -0
  406. package/src/scripts/run-test-files.ts +13 -0
  407. package/src/scripts/smoke-packed-install.ts +105 -0
  408. package/src/scripts/sync-plugin-mirror.ts +3 -3
  409. package/src/scripts/verify-native-agents.ts +2 -2
  410. package/templates/catalog-manifest.json +22 -0
@@ -3,9 +3,9 @@ import { closeSync, existsSync, openSync, readFileSync, readSync } from "fs";
3
3
  import { appendFile, mkdir, readFile, readdir, stat, writeFile } from "fs/promises";
4
4
  import { extname, join, relative, resolve } from "path";
5
5
  import { pathToFileURL } from "url";
6
- import { readModeState, readModeStateForActiveDecision, readModeStateForSession, updateModeState } from "../modes/base.js";
7
- import { extractSessionIdFromInitializedStatePath, getSkillActiveStatePathsForStateDir, listActiveSkills, readSkillActiveState, readVisibleSkillActiveStateForStateDir, } from "../state/skill-active.js";
8
- import { readSubagentSessionSummary, recordSubagentTurnForSession, } from "../subagents/tracker.js";
6
+ import { readModeStateForActiveDecision, readModeStateForSession, updateModeState } from "../modes/base.js";
7
+ import { SKILL_ACTIVE_STATE_FILE, extractSessionIdFromInitializedStatePath, getSkillActiveStatePathsForStateDir, listActiveSkills, readSkillActiveState, readVisibleSkillActiveStateForStateDir, } from "../state/skill-active.js";
8
+ import { readSubagentSessionSummary, readSubagentTrackingState, recordSubagentTurnForSession, } from "../subagents/tracker.js";
9
9
  import { resolveCanonicalTeamStateRoot, resolveWorkerNotifyTeamStateRootPath } from "../team/state-root.js";
10
10
  import { appendToLog, isSessionStateUsable, readSessionState, readUsableSessionState, reconcileNativeSessionStart, } from "../hooks/session.js";
11
11
  import { appendTeamEvent, readTeamLeaderAttention, readTeamManifestV2, readTeamPhase, writeTeamLeaderAttention, writeTeamPhase, } from "../team/state.js";
@@ -20,12 +20,14 @@ import { maybeNudgeLeaderForAllowedWorkerStop } from "./notify-hook/team-worker-
20
20
  import { resolveCodexExecutionSurface, } from "./codex-execution-surface.js";
21
21
  import { buildNativeHookEvent, } from "../hooks/extensibility/events.js";
22
22
  import { dispatchHookEventRuntime } from "../hooks/extensibility/runtime.js";
23
+ import { getNotificationConfig, getVerbosity } from "../notifications/config.js";
23
24
  import { reconcileHudForPromptSubmit } from "../hud/reconcile.js";
24
25
  import { onPreCompact as buildWikiPreCompactContext, onSessionStart as buildWikiSessionStartContext, } from "../wiki/lifecycle.js";
25
26
  import { readAutoresearchCompletionStatus, readAutoresearchModeStateForActiveDecision } from "../autoresearch/skill-validation.js";
26
27
  import { readRunState } from "../runtime/run-state.js";
27
28
  import { evaluateRalphCompletionAuditEvidence, isRalphCompletePhase } from "../ralph/completion-audit.js";
28
29
  import { getRunContinuationSnapshot, shouldContinueRun } from "../runtime/run-loop.js";
30
+ import { parseUltragoalSteeringDirective, steerUltragoal, } from "../ultragoal/artifacts.js";
29
31
  import { triagePrompt } from "../hooks/triage-heuristic.js";
30
32
  import { readTriageConfig } from "../hooks/triage-config.js";
31
33
  import { readTriageState, writeTriageState, shouldSuppressFollowup, promptSignature, } from "../hooks/triage-state.js";
@@ -173,18 +175,36 @@ async function nativeSubagentSessionStartBelongsToCanonicalSession(cwd, canonica
173
175
  return summary.allThreadIds.includes(parentThreadId);
174
176
  }
175
177
  async function isNativeSubagentHook(cwd, canonicalSessionId, nativeSessionId, threadId) {
176
- const sessionId = canonicalSessionId.trim();
177
- if (!sessionId)
178
- return false;
179
- const summary = await readSubagentSessionSummary(cwd, sessionId).catch(() => null);
180
- if (!summary)
181
- return false;
182
178
  const candidateIds = [nativeSessionId, threadId]
183
179
  .map((value) => value.trim())
184
180
  .filter(Boolean);
185
181
  if (candidateIds.length === 0)
186
182
  return false;
187
- return candidateIds.some((id) => summary.allSubagentThreadIds.includes(id));
183
+ const sessionId = canonicalSessionId.trim();
184
+ if (sessionId) {
185
+ const summary = await readSubagentSessionSummary(cwd, sessionId).catch(() => null);
186
+ if (summary && candidateIds.some((id) => summary.allSubagentThreadIds.includes(id))) {
187
+ return true;
188
+ }
189
+ }
190
+ // Native Codex resume can report the child native session as the canonical
191
+ // session id before OMX reconciles it back to the owning session. In that
192
+ // window the per-session summary lookup above misses the child and a
193
+ // subagent UserPromptSubmit can accidentally activate workflow keywords from
194
+ // quoted review context. Fall back to the global tracking index so any known
195
+ // subagent thread is treated as subagent-scoped, regardless of the current
196
+ // hook payload's session-id mapping.
197
+ const trackingState = await readSubagentTrackingState(cwd).catch(() => null);
198
+ if (!trackingState)
199
+ return false;
200
+ return Object.values(trackingState.sessions).some((session) => (candidateIds.some((id) => session.threads[id]?.kind === "subagent")));
201
+ }
202
+ function shouldSuppressSubagentLifecycleHookDispatch() {
203
+ const config = getNotificationConfig();
204
+ if (config?.includeChildAgents === true)
205
+ return false;
206
+ const verbosity = getVerbosity(config);
207
+ return verbosity !== "agent" && verbosity !== "verbose";
188
208
  }
189
209
  async function recordIgnoredNativeSubagentSessionStart(cwd, canonicalSessionId, childSessionId, metadata, transcriptPath) {
190
210
  await appendToLog(cwd, {
@@ -286,6 +306,110 @@ function readPromptText(payload) {
286
306
  }
287
307
  return "";
288
308
  }
309
+ function extractBalancedJsonObject(text, startIndex) {
310
+ let depth = 0;
311
+ let inString = false;
312
+ let escaped = false;
313
+ for (let index = startIndex; index < text.length; index++) {
314
+ const char = text[index];
315
+ if (inString) {
316
+ if (escaped)
317
+ escaped = false;
318
+ else if (char === "\\")
319
+ escaped = true;
320
+ else if (char === '"')
321
+ inString = false;
322
+ continue;
323
+ }
324
+ if (char === '"') {
325
+ inString = true;
326
+ continue;
327
+ }
328
+ if (char === "{")
329
+ depth += 1;
330
+ else if (char === "}") {
331
+ depth -= 1;
332
+ if (depth === 0)
333
+ return text.slice(startIndex, index + 1);
334
+ }
335
+ }
336
+ return null;
337
+ }
338
+ function normalizePromptSteeringProposal(raw, prompt) {
339
+ const candidate = safeObject(raw);
340
+ const nested = candidate.omx_ultragoal_steer ?? candidate.ultragoal_steer ?? candidate.steering ?? candidate;
341
+ const proposal = parseUltragoalSteeringDirective(JSON.stringify(nested));
342
+ if (!proposal)
343
+ return null;
344
+ if (proposal.source !== "user_prompt_submit")
345
+ return null;
346
+ const normalized = prompt.trim().toLowerCase();
347
+ return {
348
+ ...proposal,
349
+ directiveText: proposal.directiveText ?? safeContextSnippet(prompt, 600),
350
+ promptSignature: proposal.promptSignature ?? promptSignature(normalized),
351
+ idempotencyKey: proposal.idempotencyKey ?? `user_prompt_submit:${promptSignature(normalized)}`,
352
+ };
353
+ }
354
+ function parseUserPromptUltragoalSteeringDirective(prompt) {
355
+ const trimmed = prompt.trim();
356
+ if (!trimmed)
357
+ return null;
358
+ const fenced = trimmed.match(/```(?:omx-ultragoal-steer|ultragoal-steer)\s*([\s\S]*?)```/i);
359
+ if (fenced?.[1]) {
360
+ try {
361
+ return normalizePromptSteeringProposal(JSON.parse(fenced[1]), prompt);
362
+ }
363
+ catch {
364
+ return null;
365
+ }
366
+ }
367
+ const label = trimmed.match(/(?:^|\n)\s*(?:OMX_ULTRAGOAL_STEER|omx\.ultragoal\.steer|omx ultragoal steer)\s*:\s*{/i);
368
+ if (label?.index !== undefined) {
369
+ const brace = trimmed.indexOf("{", label.index);
370
+ const json = brace >= 0 ? extractBalancedJsonObject(trimmed, brace) : null;
371
+ if (json) {
372
+ try {
373
+ return normalizePromptSteeringProposal(JSON.parse(json), prompt);
374
+ }
375
+ catch {
376
+ return null;
377
+ }
378
+ }
379
+ }
380
+ if (trimmed.startsWith("{")) {
381
+ try {
382
+ const parsed = JSON.parse(trimmed);
383
+ const object = safeObject(parsed);
384
+ if ("omx_ultragoal_steer" in object || "ultragoal_steer" in object) {
385
+ return normalizePromptSteeringProposal(parsed, prompt);
386
+ }
387
+ }
388
+ catch {
389
+ return null;
390
+ }
391
+ }
392
+ return null;
393
+ }
394
+ async function applyUserPromptUltragoalSteering(cwd, prompt) {
395
+ const proposal = parseUserPromptUltragoalSteeringDirective(prompt);
396
+ if (!proposal)
397
+ return null;
398
+ try {
399
+ const result = await steerUltragoal(cwd, proposal);
400
+ const status = result.deduped ? "deduped" : result.accepted ? "accepted" : "rejected";
401
+ const reasons = result.rejectedReasons.length > 0 ? ` rejectedReasons=${result.rejectedReasons.join("; ")}` : "";
402
+ return [
403
+ `OMX native UserPromptSubmit applied bounded .omx/ultragoal steering for G002-cli-and-prompt-submit-bridge: ${status}.`,
404
+ `mutation=${result.audit.kind}; source=${result.audit.source}; targets=${result.audit.targetGoalIds.join(",") || "none"}; idempotencyKey=${result.audit.idempotencyKey ?? "none"}.${reasons}`,
405
+ "Only explicit structured steering directives are parsed; normal prose is ignored and cannot mutate .omx/ultragoal.",
406
+ ].join(" ");
407
+ }
408
+ catch (error) {
409
+ const message = error instanceof Error ? error.message : String(error);
410
+ return `OMX native UserPromptSubmit rejected bounded .omx/ultragoal steering for G002-cli-and-prompt-submit-bridge: ${message}`;
411
+ }
412
+ }
289
413
  function sanitizePayloadForHookContext(payload, hookEventName, canonicalSessionId = "") {
290
414
  const sanitized = { ...payload };
291
415
  if (hookEventName === "UserPromptSubmit") {
@@ -582,13 +706,12 @@ async function reopenRalphCompletionAuditBlock(block) {
582
706
  const nowIso = new Date().toISOString();
583
707
  const next = {
584
708
  ...block.state,
585
- active: true,
586
- current_phase: "verifying",
709
+ active: false,
710
+ current_phase: "complete",
587
711
  completion_audit_gate: "blocked",
588
712
  completion_audit_missing_reason: block.reason,
589
713
  completion_audit_blocked_at: nowIso,
590
714
  };
591
- delete next.completed_at;
592
715
  await writeFile(block.path, JSON.stringify(next, null, 2));
593
716
  }
594
717
  async function readActiveRalphState(cwd, stateDir, preferredSessionId, ownerContext) {
@@ -1249,6 +1372,17 @@ function buildNativeOutsideTmuxTeamPromptBlockState(prompt, cwd, payload, sessio
1249
1372
  function buildSkillStateCliInstruction(mode, statePath) {
1250
1373
  return `skill: ${mode} activated and initial state initialized at ${statePath}; use CLI-first state updates via \`omx state write/read/clear --input '<json>' --json\`; use omx_state MCP only when explicit MCP compatibility is enabled.`;
1251
1374
  }
1375
+ function buildAutopilotPromptActivationNote(skillState) {
1376
+ if (skillState?.initialized_mode !== "autopilot")
1377
+ return null;
1378
+ return [
1379
+ "Autopilot protocol: the durable default chain is $deep-interview -> $ralplan -> $ultragoal (+ $team if needed) -> $code-review -> $ultraqa (deep-interview -> ralplan -> ultragoal -> code-review -> ultraqa).",
1380
+ "Start/resume at current_phase=deep-interview unless the task is clear and bounded; if deep-interview is intentionally skipped, persist and state an explicit deep_interview_gate.skip_reason before moving to ralplan.",
1381
+ "The ralplan phase is not complete until Planner output has been reviewed sequentially by Architect and then Critic; do not hand off to Ultragoal or implementation until the ralplan state/artifact records both ralplan_architect_review and ralplan_critic_review with approval or an explicit blocker.",
1382
+ "Do not silently fall back to ordinary $plan/ralplan-only handling; keep autopilot-state.json, skill-active-state.json, HUD/statusline, and Codex goal-mode handoff guidance visible while the workflow is active.",
1383
+ "When Codex goal tools are available, call get_goal/create_goal only from the active thread handoff and treat the active goal as the completion contract until code-review and ultraqa are clean.",
1384
+ ].join(" ");
1385
+ }
1252
1386
  function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(), payload) {
1253
1387
  if (!prompt)
1254
1388
  return null;
@@ -1277,8 +1411,9 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
1277
1411
  ? "Ultrawork protocol: ground the task before editing, define pass/fail acceptance criteria, keep shared-file work local, and use direct-tool plus background evidence lanes only for truly independent work. Direct ultrawork provides lightweight verification only; Ralph owns persistence and the full verified-completion promise."
1278
1412
  : null;
1279
1413
  const ultragoalPromptActivationNote = match.skill === "ultragoal"
1280
- ? "Ultragoal protocol: use `omx ultragoal create-goals` / `complete-goals` / `checkpoint` for `.omx/ultragoal` artifacts, then use Codex goal model tools only from the active agent handoff (`get_goal`, `create_goal`, `update_goal`) and never overwrite a different active Codex goal."
1414
+ ? "Ultragoal protocol: use `omx ultragoal create-goals` / `complete-goals` / `checkpoint` for `.omx/ultragoal` artifacts, then use Codex goal model tools only from the active agent handoff (`get_goal`, `create_goal`, `update_goal`) and never overwrite a different active Codex goal. Ultragoal does not call `/goal clear`; for multiple sequential ultragoal runs in one Codex session/thread, manually clear the completed Codex goal in the UI before creating the next aggregate goal."
1281
1415
  : null;
1416
+ const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState);
1282
1417
  const combinedTransitionMessage = (() => {
1283
1418
  if (!skillState?.transition_message)
1284
1419
  return null;
@@ -1307,6 +1442,7 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
1307
1442
  : null,
1308
1443
  promptPriorityMessage,
1309
1444
  ultragoalPromptActivationNote,
1445
+ autopilotPromptActivationNote,
1310
1446
  skillState.initialized_mode && skillState.initialized_state_path
1311
1447
  ? buildSkillStateCliInstruction(skillState.initialized_mode, skillState.initialized_state_path)
1312
1448
  : null,
@@ -1332,6 +1468,7 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
1332
1468
  deepInterviewPromptActivationNote,
1333
1469
  ultraworkPromptActivationNote,
1334
1470
  ultragoalPromptActivationNote,
1471
+ autopilotPromptActivationNote,
1335
1472
  buildTeamRuntimeInstruction(cwd, payload),
1336
1473
  buildTeamHelpInstruction(cwd, payload),
1337
1474
  "Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.",
@@ -1349,11 +1486,12 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
1349
1486
  deepInterviewPromptActivationNote,
1350
1487
  ultraworkPromptActivationNote,
1351
1488
  ultragoalPromptActivationNote,
1489
+ autopilotPromptActivationNote,
1352
1490
  ralphPromptActivationNote,
1353
1491
  "Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.",
1354
1492
  ].join(" ");
1355
1493
  }
1356
- return [detectedKeywordMessage, promptPriorityMessage, ultragoalPromptActivationNote, "Follow AGENTS.md routing and preserve workflow transition and planning-safety rules."].filter(Boolean).join(" ");
1494
+ return [detectedKeywordMessage, promptPriorityMessage, ultragoalPromptActivationNote, autopilotPromptActivationNote, "Follow AGENTS.md routing and preserve workflow transition and planning-safety rules."].filter(Boolean).join(" ");
1357
1495
  }
1358
1496
  function parseTeamWorkerEnv(rawValue) {
1359
1497
  const match = /^([a-z0-9][a-z0-9-]{0,29})\/(worker-\d+)$/.exec(rawValue.trim());
@@ -1489,6 +1627,9 @@ function isStopExempt(payload) {
1489
1627
  || value.includes("limit"));
1490
1628
  }
1491
1629
  async function buildModeBasedStopOutput(mode, cwd, sessionId) {
1630
+ if (await readCanonicalTerminalRunStateForStop(cwd, sessionId, mode)) {
1631
+ return null;
1632
+ }
1492
1633
  const state = await readModeStateForActiveDecision(mode, sessionId?.trim() || undefined, cwd);
1493
1634
  if (!state || !shouldContinueRun(state))
1494
1635
  return null;
@@ -1515,6 +1656,23 @@ function reportsAutoresearchGoalObjectiveMismatch(text) {
1515
1656
  && /\b(?:complete|completion|reconciliation)\b/i.test(text)
1516
1657
  && /objective mismatch/i.test(text);
1517
1658
  }
1659
+ function reportsBlockedPerformanceGoalObjectiveMismatch(state) {
1660
+ const performanceState = safeObject(state);
1661
+ const lastValidation = safeObject(performanceState.lastValidation);
1662
+ if (safeString(performanceState.workflow) !== "performance-goal")
1663
+ return false;
1664
+ if (safeString(performanceState.status) !== "blocked")
1665
+ return false;
1666
+ if (safeString(lastValidation.status) !== "blocked")
1667
+ return false;
1668
+ const evidence = [
1669
+ safeString(lastValidation.evidence),
1670
+ safeString(lastValidation.message),
1671
+ safeString(performanceState.evidence),
1672
+ safeString(performanceState.message),
1673
+ ].join(" ");
1674
+ return /objective mismatch/i.test(evidence);
1675
+ }
1518
1676
  async function findActiveGoalWorkflowReconciliationRequirement(cwd) {
1519
1677
  const ultragoal = await readJsonIfExists(join(cwd, ".omx", "ultragoal", "goals.json"));
1520
1678
  const aggregateCompletion = safeObject(ultragoal?.aggregateCompletion);
@@ -1532,7 +1690,8 @@ async function findActiveGoalWorkflowReconciliationRequirement(cwd) {
1532
1690
  `If get_goal returns a completed task-scoped objective for the same aggregate ultragoal plan, checkpoint ${goalId} with evidence naming ${goalId} plus .omx/ultragoal/goals.json or ledger.jsonl and pass final quality-gate JSON; OMX will reconcile the completed planned scope without mutating Codex goal state.`,
1533
1691
  `If get_goal instead returns a different completed legacy objective and complete checkpointing fails, do not repeat --status complete in this thread.`,
1534
1692
  `Record the non-terminal blocker with: omx ultragoal checkpoint --goal-id ${goalId} --status blocked --codex-goal-json '<different completed get_goal JSON or path>' --evidence '<completed legacy Codex goal blocks create_goal in this thread>'.`,
1535
- "Then continue this ultragoal from a fresh Codex thread in the same repo/worktree and create the intended goal there.",
1693
+ `If get_goal itself is unavailable with a Codex DB/schema/context error such as "no such table: thread_goals", record an auditable safe-recovery blocker instead: omx ultragoal checkpoint --goal-id ${goalId} --status blocked --codex-goal-json '<unavailable get_goal error JSON or path>' --evidence '<get_goal unavailable due to Codex DB/schema/context error; safe recovery requires a working Codex goal context>'.`,
1694
+ "Then continue only from a Codex goal context with no active/completed conflicting goal in the same repo/worktree and create the intended goal there.",
1536
1695
  ].join(" "),
1537
1696
  };
1538
1697
  }
@@ -1542,6 +1701,9 @@ async function findActiveGoalWorkflowReconciliationRequirement(cwd) {
1542
1701
  continue;
1543
1702
  const state = await readJsonIfExists(join(performanceRoot, entry.name, "state.json"));
1544
1703
  const status = safeString(state?.status);
1704
+ if (reportsBlockedPerformanceGoalObjectiveMismatch(state)) {
1705
+ continue;
1706
+ }
1545
1707
  if (state?.workflow === "performance-goal" && status && status !== "complete") {
1546
1708
  return {
1547
1709
  workflow: "performance-goal",
@@ -1566,8 +1728,8 @@ async function findActiveGoalWorkflowReconciliationRequirement(cwd) {
1566
1728
  workflow: "autoresearch-goal",
1567
1729
  command: `omx autoresearch-goal complete --slug ${safeString(mission.slug) || entry.name} --codex-goal-json '<get_goal JSON or path>'`,
1568
1730
  remediation: [
1569
- "If that command fails with a Codex goal objective mismatch after a fresh get_goal snapshot, do not repeat the same complete command blindly in this thread.",
1570
- "Either retry with a correct fresh snapshot or record an explicit blocked verdict for this autoresearch-goal and continue it from a fresh Codex thread.",
1731
+ "If that command fails with a Codex goal objective mismatch after a refreshed get_goal snapshot, do not repeat the same complete command blindly in this thread.",
1732
+ "Either retry with a correct refreshed snapshot or record an explicit blocked verdict for this autoresearch-goal and continue from the explicit blocker path.",
1571
1733
  ].join(" "),
1572
1734
  };
1573
1735
  }
@@ -1609,30 +1771,46 @@ async function buildGoalWorkflowReconciliationStopOutput(payload, cwd) {
1609
1771
  systemMessage,
1610
1772
  };
1611
1773
  }
1612
- async function readTeamModeStateForStop(cwd, stateDir, sessionId) {
1774
+ function teamStateMatchesThreadForStop(state, threadId, options = {}) {
1775
+ const normalizedThreadId = safeString(threadId).trim();
1776
+ if (!normalizedThreadId)
1777
+ return true;
1778
+ const ownerThreadId = safeString(state.owner_codex_thread_id ?? state.thread_id).trim();
1779
+ if (!ownerThreadId)
1780
+ return options.requireOwnerThread !== true;
1781
+ return ownerThreadId === normalizedThreadId;
1782
+ }
1783
+ async function readTeamModeStateForStop(cwd, stateDir, sessionId, threadId) {
1613
1784
  const normalizedSessionId = safeString(sessionId).trim();
1614
- if (!normalizedSessionId) {
1615
- return await readModeState("team", cwd);
1616
- }
1785
+ if (!normalizedSessionId)
1786
+ return null;
1617
1787
  const scopedState = await readStopSessionPinnedState("team-state.json", cwd, normalizedSessionId, stateDir);
1618
- if (scopedState)
1619
- return scopedState;
1788
+ if (scopedState) {
1789
+ return teamStateMatchesThreadForStop(scopedState, threadId)
1790
+ ? { state: scopedState, scope: "session" }
1791
+ : null;
1792
+ }
1620
1793
  const rootState = await readJsonIfExists(join(stateDir, "team-state.json"));
1621
1794
  if (rootState?.active !== true)
1622
1795
  return null;
1796
+ const teamName = safeString(rootState.team_name).trim();
1797
+ if (!teamName)
1798
+ return null;
1623
1799
  const ownerSessionId = safeString(rootState.session_id).trim();
1624
- if (ownerSessionId && ownerSessionId !== normalizedSessionId) {
1800
+ if (!ownerSessionId || ownerSessionId !== normalizedSessionId)
1625
1801
  return null;
1626
- }
1627
- return rootState;
1802
+ if (!teamStateMatchesThreadForStop(rootState, threadId, { requireOwnerThread: true }))
1803
+ return null;
1804
+ return { state: rootState, scope: "root" };
1628
1805
  }
1629
- async function buildTeamStopOutput(cwd, sessionId) {
1806
+ async function buildTeamStopOutput(cwd, sessionId, threadId) {
1630
1807
  if (await readCanonicalTerminalRunStateForStop(cwd, sessionId, "team")) {
1631
1808
  return null;
1632
1809
  }
1633
- const teamState = await readTeamModeStateForStop(cwd, getBaseStateDir(cwd), sessionId);
1634
- if (teamState?.active !== true)
1810
+ const teamStateForStop = await readTeamModeStateForStop(cwd, getBaseStateDir(cwd), sessionId, threadId);
1811
+ if (!teamStateForStop || teamStateForStop.state.active !== true)
1635
1812
  return null;
1813
+ const teamState = teamStateForStop.state;
1636
1814
  const teamName = safeString(teamState.team_name).trim();
1637
1815
  if (teamName) {
1638
1816
  const canonicalTeamDir = join(resolveCanonicalTeamStateRoot(cwd), "team", teamName);
@@ -1641,7 +1819,10 @@ async function buildTeamStopOutput(cwd, sessionId) {
1641
1819
  }
1642
1820
  }
1643
1821
  const coarsePhase = teamState.current_phase;
1644
- const canonicalPhase = teamName ? (await readTeamPhase(teamName, cwd))?.current_phase ?? coarsePhase : coarsePhase;
1822
+ const canonicalPhaseState = teamName ? await readTeamPhase(teamName, cwd) : null;
1823
+ if (teamStateForStop.scope === "root" && !canonicalPhaseState)
1824
+ return null;
1825
+ const canonicalPhase = canonicalPhaseState?.current_phase ?? coarsePhase;
1645
1826
  if (!isNonTerminalPhase(canonicalPhase))
1646
1827
  return null;
1647
1828
  return buildTeamStopOutputForPhase(teamName, formatPhase(canonicalPhase));
@@ -1724,6 +1905,137 @@ async function readStopSessionPinnedState(fileName, cwd, sessionId, stateDir) {
1724
1905
  : getStateFilePath(fileName, cwd, sessionId || undefined);
1725
1906
  return readJsonIfExists(statePath);
1726
1907
  }
1908
+ const DEEP_INTERVIEW_ALLOWED_WRITE_PREFIXES = [
1909
+ ".omx/context",
1910
+ ".omx/interviews",
1911
+ ".omx/specs",
1912
+ ".omx/state",
1913
+ ];
1914
+ const DEEP_INTERVIEW_IMPLEMENTATION_TOOL_NAMES = new Set([
1915
+ "Write",
1916
+ "Edit",
1917
+ "MultiEdit",
1918
+ "apply_patch",
1919
+ "ApplyPatch",
1920
+ ]);
1921
+ function isActiveDeepInterviewPhase(state) {
1922
+ if (!state || state.active !== true)
1923
+ return false;
1924
+ const mode = safeString(state.mode).trim();
1925
+ if (mode && mode !== "deep-interview")
1926
+ return false;
1927
+ const phase = safeString(state.current_phase ?? state.currentPhase).trim().toLowerCase();
1928
+ if (phase && (TERMINAL_MODE_PHASES.has(phase) || phase === "completing"))
1929
+ return false;
1930
+ return true;
1931
+ }
1932
+ function isAllowedDeepInterviewArtifactPath(cwd, rawPath) {
1933
+ const trimmed = rawPath.trim().replace(/^['"]|['"]$/g, "");
1934
+ if (!trimmed || trimmed.includes("\0"))
1935
+ return false;
1936
+ let relativePath;
1937
+ try {
1938
+ const absolute = resolve(cwd, trimmed);
1939
+ relativePath = relative(cwd, absolute).replace(/\\/g, "/");
1940
+ }
1941
+ catch {
1942
+ return false;
1943
+ }
1944
+ if (!relativePath || relativePath.startsWith("..") || relativePath.startsWith("/"))
1945
+ return false;
1946
+ return DEEP_INTERVIEW_ALLOWED_WRITE_PREFIXES.some((prefix) => (relativePath === prefix || relativePath.startsWith(`${prefix}/`)));
1947
+ }
1948
+ function readPreToolUseCommand(payload) {
1949
+ const toolInput = safeObject(payload.tool_input);
1950
+ return safeString(toolInput.command).trim();
1951
+ }
1952
+ function readPreToolUsePathCandidates(payload) {
1953
+ const input = safeObject(payload.tool_input);
1954
+ const candidates = [
1955
+ input.file_path,
1956
+ input.filePath,
1957
+ input.path,
1958
+ input.target_path,
1959
+ input.targetPath,
1960
+ ];
1961
+ return candidates.map((candidate) => safeString(candidate).trim()).filter(Boolean);
1962
+ }
1963
+ function commandHasDeepInterviewWriteIntent(command) {
1964
+ return /\bapply_patch\b/.test(command)
1965
+ || /(?:^|[;&|]\s*)(?:cat|printf|echo)\b[\s\S]{0,240}>\s*[^\s&|;]+/.test(command)
1966
+ || /\btee\s+(?:-a\s+)?[^\s&|;]+/.test(command)
1967
+ || /\bsed\s+(?:[^\n;&|]*\s)?-i(?:\b|['"])/.test(command)
1968
+ || /\b(?:python3?|node|perl|ruby)\b[\s\S]{0,260}\b(?:writeFileSync|writeFile|write_text|open\([^)]*["']w|File\.write|Path\()/.test(command)
1969
+ || /\b(?:git\s+(?:checkout|switch|restore|reset|apply|am|merge|rebase)|npm\s+(?:install|i|ci)|pnpm\s+(?:install|i)|yarn\s+(?:install|add))\b/.test(command);
1970
+ }
1971
+ function extractDeepInterviewCommandWriteTargets(command) {
1972
+ const targets = [];
1973
+ for (const match of command.matchAll(/(?:^|[^>])>{1,2}\s*(["']?)([^\s&|;<>]+)\1/g)) {
1974
+ const candidate = safeString(match[2]).trim();
1975
+ if (candidate)
1976
+ targets.push(candidate);
1977
+ }
1978
+ for (const match of command.matchAll(/\btee\s+(?:-a\s+)?(["']?)([^\s&|;<>]+)\1/g)) {
1979
+ const candidate = safeString(match[2]).trim();
1980
+ if (candidate)
1981
+ targets.push(candidate);
1982
+ }
1983
+ return targets;
1984
+ }
1985
+ function isAllowedDeepInterviewBashWrite(cwd, command) {
1986
+ if (!commandHasDeepInterviewWriteIntent(command))
1987
+ return true;
1988
+ if (/\bomx\s+(?:state\s+(?:write|read|clear)|question)\b/.test(command))
1989
+ return true;
1990
+ const targets = extractDeepInterviewCommandWriteTargets(command);
1991
+ return targets.length > 0 && targets.every((target) => isAllowedDeepInterviewArtifactPath(cwd, target));
1992
+ }
1993
+ async function readActiveDeepInterviewStateForPreToolUse(cwd, stateDir, sessionId, threadId) {
1994
+ const modeState = sessionId
1995
+ ? await readStopSessionPinnedState("deep-interview-state.json", cwd, sessionId, stateDir)
1996
+ : await readJsonIfExists(join(stateDir, "deep-interview-state.json"));
1997
+ if (!isActiveDeepInterviewPhase(modeState) || !modeState)
1998
+ return null;
1999
+ if (!modeStateMatchesSkillStopContext(modeState, cwd, sessionId))
2000
+ return null;
2001
+ const canonicalState = sessionId
2002
+ ? await readVisibleSkillActiveStateForStateDir(stateDir, sessionId)
2003
+ : await readSkillActiveState(join(stateDir, SKILL_ACTIVE_STATE_FILE));
2004
+ if (!canonicalState)
2005
+ return modeState;
2006
+ const hasActiveDeepInterviewSkill = listActiveSkills(canonicalState).some((entry) => (entry.skill === "deep-interview"
2007
+ && matchesSkillStopContext(entry, canonicalState, sessionId, threadId)));
2008
+ return hasActiveDeepInterviewSkill ? modeState : null;
2009
+ }
2010
+ async function buildDeepInterviewPreToolUseBoundaryOutput(payload, cwd, stateDir) {
2011
+ const sessionId = readPayloadSessionId(payload);
2012
+ const threadId = readPayloadThreadId(payload);
2013
+ const activeState = await readActiveDeepInterviewStateForPreToolUse(cwd, stateDir, sessionId, threadId);
2014
+ if (!activeState)
2015
+ return null;
2016
+ const toolName = safeString(payload.tool_name).trim();
2017
+ const command = readPreToolUseCommand(payload);
2018
+ const pathCandidates = readPreToolUsePathCandidates(payload);
2019
+ let blocked = false;
2020
+ if (toolName === "Bash") {
2021
+ blocked = !isAllowedDeepInterviewBashWrite(cwd, command);
2022
+ }
2023
+ else if (DEEP_INTERVIEW_IMPLEMENTATION_TOOL_NAMES.has(toolName)) {
2024
+ blocked = pathCandidates.length === 0
2025
+ || !pathCandidates.every((candidate) => isAllowedDeepInterviewArtifactPath(cwd, candidate));
2026
+ }
2027
+ if (!blocked)
2028
+ return null;
2029
+ const phase = formatPhase(activeState.current_phase ?? activeState.currentPhase, "planning");
2030
+ return {
2031
+ decision: "block",
2032
+ reason: `Deep-interview is active (phase: ${phase}); implementation/write tools are blocked until an explicit handoff workflow is activated.`,
2033
+ hookSpecificOutput: {
2034
+ hookEventName: "PreToolUse",
2035
+ additionalContext: "Deep-interview is requirements/spec mode. Treat detailed user answers as interview/spec material, not implicit implementation authorization. You may write only deep-interview artifacts under `.omx/context/`, `.omx/interviews/`, `.omx/specs/`, or required `.omx/state/` files. To implement, first ask for or process an explicit transition such as `$ralplan`, `$autopilot`, `$ralph`, `$team`, or `$ultragoal`.",
2036
+ },
2037
+ };
2038
+ }
1727
2039
  function matchesSkillStopContext(entry, state, sessionId, threadId) {
1728
2040
  const entrySessionId = safeString(entry.session_id ?? state.session_id).trim();
1729
2041
  const entryThreadId = safeString(entry.thread_id ?? state.thread_id).trim();
@@ -2175,7 +2487,7 @@ async function maybeReturnRepeatableStopOutput(payload, stateDir, signature, out
2175
2487
  async function returnPersistentStopBlock(payload, stateDir, signatureKind, signatureValue, output, canonicalSessionId, options = { allowRepeatDuringStopHook: true }) {
2176
2488
  return await maybeReturnRepeatableStopOutput(payload, stateDir, buildRepeatableStopSignature(payload, signatureKind, signatureValue, canonicalSessionId), output, canonicalSessionId, options);
2177
2489
  }
2178
- async function findCanonicalActiveTeamForSession(cwd, sessionId) {
2490
+ async function findCanonicalActiveTeamForSession(cwd, sessionId, threadId) {
2179
2491
  if (!sessionId.trim())
2180
2492
  return null;
2181
2493
  const teamsRoot = join(resolveCanonicalTeamStateRoot(cwd), "team");
@@ -2197,6 +2509,8 @@ async function findCanonicalActiveTeamForSession(cwd, sessionId) {
2197
2509
  const ownerSessionId = (manifest.leader?.session_id ?? "").trim();
2198
2510
  if (ownerSessionId && ownerSessionId !== sessionId.trim())
2199
2511
  continue;
2512
+ if (!teamStateMatchesThreadForStop(manifest.leader, threadId))
2513
+ continue;
2200
2514
  if (!isNonTerminalPhase(phaseState.current_phase))
2201
2515
  continue;
2202
2516
  return {
@@ -2206,18 +2520,18 @@ async function findCanonicalActiveTeamForSession(cwd, sessionId) {
2206
2520
  }
2207
2521
  return null;
2208
2522
  }
2209
- async function resolveActiveTeamNameForStop(cwd, stateDir, sessionId) {
2210
- const directState = await readTeamModeStateForStop(cwd, stateDir, sessionId);
2211
- const directTeamName = safeString(directState?.team_name).trim();
2212
- if (directState?.active === true && directTeamName)
2523
+ async function resolveActiveTeamNameForStop(cwd, stateDir, sessionId, threadId) {
2524
+ const directState = await readTeamModeStateForStop(cwd, stateDir, sessionId, threadId);
2525
+ const directTeamName = safeString(directState?.state.team_name).trim();
2526
+ if (directState?.state.active === true && directTeamName)
2213
2527
  return directTeamName;
2214
- const canonicalTeam = await findCanonicalActiveTeamForSession(cwd, sessionId);
2528
+ const canonicalTeam = await findCanonicalActiveTeamForSession(cwd, sessionId, threadId);
2215
2529
  return canonicalTeam?.teamName ?? "";
2216
2530
  }
2217
2531
  async function maybeBuildReleaseReadinessFinalizeStopOutput(payload, cwd, stateDir, sessionId) {
2218
2532
  if (!sessionId)
2219
2533
  return { matched: false, output: null };
2220
- const teamName = await resolveActiveTeamNameForStop(cwd, stateDir, sessionId);
2534
+ const teamName = await resolveActiveTeamNameForStop(cwd, stateDir, sessionId, readPayloadThreadId(payload));
2221
2535
  if (!teamName)
2222
2536
  return { matched: false, output: null };
2223
2537
  const explicitReleaseReadinessContext = hasReleaseReadinessMode(payload)
@@ -2373,7 +2687,7 @@ async function buildStopHookOutput(payload, cwd, stateDir, options = {}) {
2373
2687
  `OMX Ralph completion audit is missing required evidence (${ralphCompletionAuditBlock.reason}; state: ${blockingPath}).`,
2374
2688
  "Continue verification and do not report complete yet.",
2375
2689
  "Record machine-readable completion evidence before stopping:",
2376
- "- either set state.completion_audit = { passed: true, prompt_to_artifact_checklist: [...], verification_evidence: [...] }",
2690
+ '- either set "completion_audit" on the Ralph state object, for example: omx state write --input \'{"mode":"ralph","active":false,"current_phase":"complete","completion_audit":{"passed":true,"prompt_to_artifact_checklist":["..."],"verification_evidence":["..."]}}\' --json',
2377
2691
  "- or set completion_audit_path / completion_audit_evidence_path to a repo-relative JSON file with those same fields.",
2378
2692
  "Markdown artifacts and flat top-level checklist/evidence fields are not accepted by the Ralph Stop gate.",
2379
2693
  ].join(" ");
@@ -2434,7 +2748,7 @@ async function buildStopHookOutput(payload, cwd, stateDir, options = {}) {
2434
2748
  const releaseReadinessFinalizeResult = await maybeBuildReleaseReadinessFinalizeStopOutput(payload, cwd, stateDir, canonicalSessionId);
2435
2749
  if (releaseReadinessFinalizeResult.matched)
2436
2750
  return releaseReadinessFinalizeResult.output;
2437
- const teamOutput = await buildTeamStopOutput(cwd, canonicalSessionId);
2751
+ const teamOutput = await buildTeamStopOutput(cwd, canonicalSessionId, threadId);
2438
2752
  if (teamOutput) {
2439
2753
  return await returnPersistentStopBlock(payload, stateDir, "team-stop", safeString(teamOutput.stopReason), teamOutput, canonicalSessionId);
2440
2754
  }
@@ -2445,7 +2759,7 @@ async function buildStopHookOutput(payload, cwd, stateDir, options = {}) {
2445
2759
  }
2446
2760
  const canonicalTeam = await readCanonicalTerminalRunStateForStop(cwd, canonicalSessionId, "team")
2447
2761
  ? null
2448
- : await findCanonicalActiveTeamForSession(cwd, canonicalSessionId);
2762
+ : await findCanonicalActiveTeamForSession(cwd, canonicalSessionId, threadId);
2449
2763
  if (canonicalTeam) {
2450
2764
  const canonicalTeamOutput = buildTeamStopOutputForPhase(canonicalTeam.teamName, canonicalTeam.phase);
2451
2765
  const repeatedCanonicalTeamOutput = await returnPersistentStopBlock(payload, stateDir, "team-stop", `${canonicalTeam.teamName}|${canonicalTeam.phase}`, canonicalTeamOutput, canonicalSessionId);
@@ -2512,6 +2826,7 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
2512
2826
  let skillState = null;
2513
2827
  let triageAdditionalContext = null;
2514
2828
  let goalWorkflowAdditionalContext = null;
2829
+ let ultragoalSteeringAdditionalContext = null;
2515
2830
  const nativeSessionId = safeString(payload.session_id ?? payload.sessionId).trim();
2516
2831
  const threadId = safeString(payload.thread_id ?? payload.threadId).trim();
2517
2832
  const turnId = safeString(payload.turn_id ?? payload.turnId).trim();
@@ -2519,10 +2834,12 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
2519
2834
  let canonicalSessionId = safeString(currentSessionState?.session_id).trim();
2520
2835
  let resolvedNativeSessionId = nativeSessionId;
2521
2836
  let skipCanonicalSessionStartContext = false;
2837
+ let isSubagentSessionStart = false;
2522
2838
  if (hookEventName === "SessionStart" && nativeSessionId) {
2523
2839
  const transcriptPath = safeString(payload.transcript_path ?? payload.transcriptPath).trim();
2524
2840
  const subagentSessionStart = readNativeSubagentSessionStartMetadata(transcriptPath);
2525
2841
  if (subagentSessionStart && canonicalSessionId) {
2842
+ isSubagentSessionStart = true;
2526
2843
  const belongsToCanonicalSession = await nativeSubagentSessionStartBelongsToCanonicalSession(cwd, canonicalSessionId, currentSessionState, subagentSessionStart);
2527
2844
  if (belongsToCanonicalSession) {
2528
2845
  resolvedNativeSessionId = nativeSessionId;
@@ -2570,9 +2887,14 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
2570
2887
  ].filter(Boolean))]
2571
2888
  .map((candidateSessionId) => isNativeSubagentHook(cwd, candidateSessionId, nativeSessionId, threadId)))).some(Boolean)
2572
2889
  : false;
2890
+ const suppressNoisySubagentLifecycleDispatch = (isSubagentSessionStart || isSubagentStop)
2891
+ && shouldSuppressSubagentLifecycleHookDispatch();
2573
2892
  if (hookEventName === "UserPromptSubmit") {
2574
2893
  const prompt = readPromptText(payload);
2575
2894
  goalWorkflowAdditionalContext = await buildGoalWorkflowReconciliationPromptWarning(cwd, prompt).catch(() => null);
2895
+ ultragoalSteeringAdditionalContext = prompt && !isSubagentPromptSubmit
2896
+ ? await applyUserPromptUltragoalSteering(cwd, prompt).catch((error) => `OMX native UserPromptSubmit rejected bounded .omx/ultragoal steering for G002-cli-and-prompt-submit-bridge: ${error instanceof Error ? error.message : String(error)}`)
2897
+ : null;
2576
2898
  if (prompt && !isSubagentPromptSubmit) {
2577
2899
  skillState = buildNativeOutsideTmuxTeamPromptBlockState(prompt, cwd, payload, sessionIdForState, threadId || undefined, turnId || undefined) ?? await recordSkillActivation({
2578
2900
  stateDir,
@@ -2661,7 +2983,7 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
2661
2983
  const reconcileHudForPromptSubmitFn = options.reconcileHudForPromptSubmitFn ?? reconcileHudForPromptSubmit;
2662
2984
  await reconcileHudForPromptSubmitFn(cwd, { sessionId: canonicalSessionId || sessionIdForState || undefined }).catch(() => { });
2663
2985
  }
2664
- if (omxEventName && !skipCanonicalSessionStartContext) {
2986
+ if (omxEventName && !skipCanonicalSessionStartContext && !suppressNoisySubagentLifecycleDispatch) {
2665
2987
  const baseContext = buildBaseContext(cwd, payload, hookEventName, canonicalSessionId);
2666
2988
  if (resolvedNativeSessionId) {
2667
2989
  baseContext.native_session_id = resolvedNativeSessionId;
@@ -2698,7 +3020,12 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
2698
3020
  })
2699
3021
  : isSubagentPromptSubmit
2700
3022
  ? null
2701
- : (buildAdditionalContextMessage(readPromptText(payload), skillState, cwd, payload) ?? goalWorkflowAdditionalContext ?? triageAdditionalContext);
3023
+ : [
3024
+ buildAdditionalContextMessage(readPromptText(payload), skillState, cwd, payload),
3025
+ ultragoalSteeringAdditionalContext,
3026
+ goalWorkflowAdditionalContext,
3027
+ triageAdditionalContext,
3028
+ ].filter((entry) => Boolean(entry)).join("\n\n") || null;
2702
3029
  if (additionalContext) {
2703
3030
  outputJson = {
2704
3031
  hookSpecificOutput: {
@@ -2709,7 +3036,8 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
2709
3036
  }
2710
3037
  }
2711
3038
  else if (hookEventName === "PreToolUse") {
2712
- outputJson = buildNativePreToolUseOutput(payload);
3039
+ outputJson = await buildDeepInterviewPreToolUseBoundaryOutput(payload, cwd, stateDir)
3040
+ ?? buildNativePreToolUseOutput(payload);
2713
3041
  }
2714
3042
  else if (hookEventName === "PostToolUse") {
2715
3043
  if (detectMcpTransportFailure(payload)) {