oh-my-codex 0.18.7 → 0.18.9

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 (307) hide show
  1. package/Cargo.lock +12 -12
  2. package/Cargo.toml +1 -1
  3. package/README.md +5 -5
  4. package/crates/omx-sparkshell/tests/execution.rs +1 -1
  5. package/dist/agents/__tests__/native-config.test.js +42 -1
  6. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  7. package/dist/agents/definitions.d.ts +8 -0
  8. package/dist/agents/definitions.d.ts.map +1 -1
  9. package/dist/agents/definitions.js +1 -0
  10. package/dist/agents/definitions.js.map +1 -1
  11. package/dist/agents/native-config.d.ts +5 -1
  12. package/dist/agents/native-config.d.ts.map +1 -1
  13. package/dist/agents/native-config.js +17 -2
  14. package/dist/agents/native-config.js.map +1 -1
  15. package/dist/autopilot/__tests__/fsm.test.js +3 -0
  16. package/dist/autopilot/__tests__/fsm.test.js.map +1 -1
  17. package/dist/autopilot/fsm.js +2 -2
  18. package/dist/autopilot/fsm.js.map +1 -1
  19. package/dist/cli/__tests__/auth.test.js +4 -2
  20. package/dist/cli/__tests__/auth.test.js.map +1 -1
  21. package/dist/cli/__tests__/codex-plugin-layout.test.js +512 -1
  22. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  23. package/dist/cli/__tests__/doctor-warning-copy.test.js +39 -0
  24. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  25. package/dist/cli/__tests__/index.test.js +98 -6
  26. package/dist/cli/__tests__/index.test.js.map +1 -1
  27. package/dist/cli/__tests__/package-bin-contract.test.js +28 -8
  28. package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
  29. package/dist/cli/__tests__/question.test.js +26 -9
  30. package/dist/cli/__tests__/question.test.js.map +1 -1
  31. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +13 -0
  32. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
  33. package/dist/cli/__tests__/ralph.test.js +14 -0
  34. package/dist/cli/__tests__/ralph.test.js.map +1 -1
  35. package/dist/cli/__tests__/resume.test.js +50 -1
  36. package/dist/cli/__tests__/resume.test.js.map +1 -1
  37. package/dist/cli/__tests__/setup-install-mode.test.js +89 -0
  38. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  39. package/dist/cli/__tests__/setup-refresh.test.js +65 -0
  40. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  41. package/dist/cli/__tests__/state.test.js +21 -0
  42. package/dist/cli/__tests__/state.test.js.map +1 -1
  43. package/dist/cli/__tests__/team.test.js +2 -2
  44. package/dist/cli/__tests__/update.test.js +323 -18
  45. package/dist/cli/__tests__/update.test.js.map +1 -1
  46. package/dist/cli/__tests__/windows-popup-loop-contract.test.js +1 -1
  47. package/dist/cli/doctor.d.ts.map +1 -1
  48. package/dist/cli/doctor.js +8 -1
  49. package/dist/cli/doctor.js.map +1 -1
  50. package/dist/cli/index.d.ts +21 -4
  51. package/dist/cli/index.d.ts.map +1 -1
  52. package/dist/cli/index.js +143 -28
  53. package/dist/cli/index.js.map +1 -1
  54. package/dist/cli/plugin-marketplace.d.ts +14 -2
  55. package/dist/cli/plugin-marketplace.d.ts.map +1 -1
  56. package/dist/cli/plugin-marketplace.js +62 -15
  57. package/dist/cli/plugin-marketplace.js.map +1 -1
  58. package/dist/cli/ralph.d.ts.map +1 -1
  59. package/dist/cli/ralph.js +3 -1
  60. package/dist/cli/ralph.js.map +1 -1
  61. package/dist/cli/setup-preferences.d.ts +2 -0
  62. package/dist/cli/setup-preferences.d.ts.map +1 -1
  63. package/dist/cli/setup-preferences.js +4 -0
  64. package/dist/cli/setup-preferences.js.map +1 -1
  65. package/dist/cli/setup.d.ts +3 -0
  66. package/dist/cli/setup.d.ts.map +1 -1
  67. package/dist/cli/setup.js +166 -27
  68. package/dist/cli/setup.js.map +1 -1
  69. package/dist/cli/state.d.ts.map +1 -1
  70. package/dist/cli/state.js +8 -1
  71. package/dist/cli/state.js.map +1 -1
  72. package/dist/cli/tmux-hook.d.ts.map +1 -1
  73. package/dist/cli/tmux-hook.js +16 -0
  74. package/dist/cli/tmux-hook.js.map +1 -1
  75. package/dist/cli/update.d.ts +22 -3
  76. package/dist/cli/update.d.ts.map +1 -1
  77. package/dist/cli/update.js +312 -26
  78. package/dist/cli/update.js.map +1 -1
  79. package/dist/cli/version.d.ts.map +1 -1
  80. package/dist/cli/version.js +5 -9
  81. package/dist/cli/version.js.map +1 -1
  82. package/dist/compat/__tests__/doctor-contract.test.js +12 -1
  83. package/dist/compat/__tests__/doctor-contract.test.js.map +1 -1
  84. package/dist/config/__tests__/generator-notify.test.js +1 -0
  85. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  86. package/dist/config/generator.d.ts +2 -2
  87. package/dist/config/generator.d.ts.map +1 -1
  88. package/dist/config/generator.js +2 -2
  89. package/dist/config/generator.js.map +1 -1
  90. package/dist/config/team-mode.d.ts +12 -0
  91. package/dist/config/team-mode.d.ts.map +1 -0
  92. package/dist/config/team-mode.js +91 -0
  93. package/dist/config/team-mode.js.map +1 -0
  94. package/dist/hooks/__tests__/agents-overlay.test.js +88 -0
  95. package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
  96. package/dist/hooks/__tests__/code-review-skill-contract.test.js +12 -0
  97. package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +1 -1
  98. package/dist/hooks/__tests__/deep-interview-contract.test.js +30 -1
  99. package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
  100. package/dist/hooks/__tests__/keyword-detector.test.js +423 -3
  101. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  102. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +1 -1
  103. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  104. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +189 -0
  105. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  106. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +35 -2
  107. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  108. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +3 -3
  109. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  110. package/dist/hooks/__tests__/skill-guidance-contract.test.js +21 -0
  111. package/dist/hooks/__tests__/skill-guidance-contract.test.js.map +1 -1
  112. package/dist/hooks/agents-overlay.d.ts.map +1 -1
  113. package/dist/hooks/agents-overlay.js +36 -50
  114. package/dist/hooks/agents-overlay.js.map +1 -1
  115. package/dist/hooks/extensibility/__tests__/plugin-runner.test.js +31 -0
  116. package/dist/hooks/extensibility/__tests__/plugin-runner.test.js.map +1 -1
  117. package/dist/hooks/extensibility/plugin-runner.js +17 -21
  118. package/dist/hooks/extensibility/plugin-runner.js.map +1 -1
  119. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  120. package/dist/hooks/keyword-detector.js +258 -12
  121. package/dist/hooks/keyword-detector.js.map +1 -1
  122. package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
  123. package/dist/hooks/prompt-guidance-contract.js +6 -0
  124. package/dist/hooks/prompt-guidance-contract.js.map +1 -1
  125. package/dist/hooks/session.d.ts +1 -0
  126. package/dist/hooks/session.d.ts.map +1 -1
  127. package/dist/hooks/session.js.map +1 -1
  128. package/dist/hud/__tests__/authority.test.js +435 -32
  129. package/dist/hud/__tests__/authority.test.js.map +1 -1
  130. package/dist/hud/__tests__/hud-tmux-injection.test.js +2 -1
  131. package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
  132. package/dist/hud/__tests__/index.test.js +42 -0
  133. package/dist/hud/__tests__/index.test.js.map +1 -1
  134. package/dist/hud/__tests__/reconcile.test.js +642 -15
  135. package/dist/hud/__tests__/reconcile.test.js.map +1 -1
  136. package/dist/hud/__tests__/render.test.js +61 -0
  137. package/dist/hud/__tests__/render.test.js.map +1 -1
  138. package/dist/hud/__tests__/state.test.js +160 -4
  139. package/dist/hud/__tests__/state.test.js.map +1 -1
  140. package/dist/hud/__tests__/tmux.test.js +180 -21
  141. package/dist/hud/__tests__/tmux.test.js.map +1 -1
  142. package/dist/hud/authority.d.ts +5 -0
  143. package/dist/hud/authority.d.ts.map +1 -1
  144. package/dist/hud/authority.js +324 -28
  145. package/dist/hud/authority.js.map +1 -1
  146. package/dist/hud/index.d.ts +3 -2
  147. package/dist/hud/index.d.ts.map +1 -1
  148. package/dist/hud/index.js +42 -19
  149. package/dist/hud/index.js.map +1 -1
  150. package/dist/hud/reconcile.d.ts +3 -3
  151. package/dist/hud/reconcile.d.ts.map +1 -1
  152. package/dist/hud/reconcile.js +128 -19
  153. package/dist/hud/reconcile.js.map +1 -1
  154. package/dist/hud/render.d.ts.map +1 -1
  155. package/dist/hud/render.js +35 -0
  156. package/dist/hud/render.js.map +1 -1
  157. package/dist/hud/state.d.ts.map +1 -1
  158. package/dist/hud/state.js +65 -80
  159. package/dist/hud/state.js.map +1 -1
  160. package/dist/hud/tmux.d.ts +24 -6
  161. package/dist/hud/tmux.d.ts.map +1 -1
  162. package/dist/hud/tmux.js +136 -38
  163. package/dist/hud/tmux.js.map +1 -1
  164. package/dist/hud/types.d.ts +11 -0
  165. package/dist/hud/types.d.ts.map +1 -1
  166. package/dist/hud/types.js.map +1 -1
  167. package/dist/mcp/__tests__/state-paths.test.js +71 -1
  168. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  169. package/dist/mcp/state-paths.d.ts +32 -0
  170. package/dist/mcp/state-paths.d.ts.map +1 -1
  171. package/dist/mcp/state-paths.js +113 -17
  172. package/dist/mcp/state-paths.js.map +1 -1
  173. package/dist/mcp/state-server.d.ts +4 -4
  174. package/dist/question/__tests__/renderer.test.js +566 -1
  175. package/dist/question/__tests__/renderer.test.js.map +1 -1
  176. package/dist/question/renderer.d.ts +9 -1
  177. package/dist/question/renderer.d.ts.map +1 -1
  178. package/dist/question/renderer.js +246 -70
  179. package/dist/question/renderer.js.map +1 -1
  180. package/dist/scripts/__tests__/codex-native-hook.test.js +837 -101
  181. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  182. package/dist/scripts/__tests__/notify-state-io.test.js +72 -1
  183. package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -1
  184. package/dist/scripts/__tests__/notify-tmux-injection.test.d.ts +2 -0
  185. package/dist/scripts/__tests__/notify-tmux-injection.test.d.ts.map +1 -0
  186. package/dist/scripts/__tests__/notify-tmux-injection.test.js +57 -0
  187. package/dist/scripts/__tests__/notify-tmux-injection.test.js.map +1 -0
  188. package/dist/scripts/__tests__/run-test-files.test.js +74 -0
  189. package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
  190. package/dist/scripts/__tests__/verify-native-agents.test.js +65 -0
  191. package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -1
  192. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  193. package/dist/scripts/codex-native-hook.js +107 -39
  194. package/dist/scripts/codex-native-hook.js.map +1 -1
  195. package/dist/scripts/eval/eval-parity-smoke.js +1 -1
  196. package/dist/scripts/eval/eval-parity-smoke.js.map +1 -1
  197. package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
  198. package/dist/scripts/notify-hook/auto-nudge.js +3 -1
  199. package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
  200. package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
  201. package/dist/scripts/notify-hook/ralph-session-resume.js +3 -10
  202. package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
  203. package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
  204. package/dist/scripts/notify-hook/state-io.js +62 -38
  205. package/dist/scripts/notify-hook/state-io.js.map +1 -1
  206. package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
  207. package/dist/scripts/notify-hook/team-leader-nudge.js +7 -0
  208. package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
  209. package/dist/scripts/notify-hook/tmux-injection.d.ts +7 -0
  210. package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
  211. package/dist/scripts/notify-hook/tmux-injection.js +24 -18
  212. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  213. package/dist/scripts/notify-hook.js +75 -11
  214. package/dist/scripts/notify-hook.js.map +1 -1
  215. package/dist/scripts/run-test-files.js +193 -22
  216. package/dist/scripts/run-test-files.js.map +1 -1
  217. package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
  218. package/dist/scripts/sync-plugin-mirror.js +61 -3
  219. package/dist/scripts/sync-plugin-mirror.js.map +1 -1
  220. package/dist/scripts/verify-native-agents.d.ts.map +1 -1
  221. package/dist/scripts/verify-native-agents.js +58 -1
  222. package/dist/scripts/verify-native-agents.js.map +1 -1
  223. package/dist/state/__tests__/operations.test.js +113 -0
  224. package/dist/state/__tests__/operations.test.js.map +1 -1
  225. package/dist/state/__tests__/skill-active.test.js +3 -16
  226. package/dist/state/__tests__/skill-active.test.js.map +1 -1
  227. package/dist/state/__tests__/workflow-transition.test.js +25 -0
  228. package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
  229. package/dist/state/operations.d.ts.map +1 -1
  230. package/dist/state/operations.js +57 -2
  231. package/dist/state/operations.js.map +1 -1
  232. package/dist/state/skill-active.d.ts.map +1 -1
  233. package/dist/state/skill-active.js +7 -39
  234. package/dist/state/skill-active.js.map +1 -1
  235. package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
  236. package/dist/state/workflow-transition-reconcile.js +10 -14
  237. package/dist/state/workflow-transition-reconcile.js.map +1 -1
  238. package/dist/team/__tests__/runtime.test.js +1 -1
  239. package/dist/team/__tests__/runtime.test.js.map +1 -1
  240. package/dist/team/__tests__/scaling.test.js +9 -4
  241. package/dist/team/__tests__/scaling.test.js.map +1 -1
  242. package/dist/team/__tests__/tmux-session.test.js +195 -2
  243. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  244. package/dist/team/__tests__/worker-runtime-identity.test.js +4 -2
  245. package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
  246. package/dist/team/scaling.d.ts.map +1 -1
  247. package/dist/team/scaling.js +3 -2
  248. package/dist/team/scaling.js.map +1 -1
  249. package/dist/team/tmux-session.d.ts +2 -0
  250. package/dist/team/tmux-session.d.ts.map +1 -1
  251. package/dist/team/tmux-session.js +142 -12
  252. package/dist/team/tmux-session.js.map +1 -1
  253. package/dist/utils/__tests__/platform-command.test.js +16 -1
  254. package/dist/utils/__tests__/platform-command.test.js.map +1 -1
  255. package/dist/utils/__tests__/version.test.d.ts +2 -0
  256. package/dist/utils/__tests__/version.test.d.ts.map +1 -0
  257. package/dist/utils/__tests__/version.test.js +51 -0
  258. package/dist/utils/__tests__/version.test.js.map +1 -0
  259. package/dist/utils/paths.d.ts +8 -1
  260. package/dist/utils/paths.d.ts.map +1 -1
  261. package/dist/utils/paths.js +16 -4
  262. package/dist/utils/paths.js.map +1 -1
  263. package/dist/utils/platform-command.d.ts +9 -0
  264. package/dist/utils/platform-command.d.ts.map +1 -1
  265. package/dist/utils/platform-command.js +15 -0
  266. package/dist/utils/platform-command.js.map +1 -1
  267. package/dist/utils/version.d.ts +7 -0
  268. package/dist/utils/version.d.ts.map +1 -0
  269. package/dist/utils/version.js +67 -0
  270. package/dist/utils/version.js.map +1 -0
  271. package/dist/verification/__tests__/ci-rust-gates.test.js +89 -1
  272. package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
  273. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +16 -2
  274. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -1
  275. package/package.json +11 -10
  276. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  277. package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +334 -21
  278. package/plugins/oh-my-codex/hooks/hooks.json +1 -2
  279. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +3 -1
  280. package/plugins/oh-my-codex/skills/code-review/SKILL.md +7 -7
  281. package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +51 -11
  282. package/plugins/oh-my-codex/skills/ralph/SKILL.md +22 -22
  283. package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +9 -0
  284. package/skills/autopilot/SKILL.md +3 -1
  285. package/skills/code-review/SKILL.md +7 -7
  286. package/skills/deep-interview/SKILL.md +51 -11
  287. package/skills/ralph/SKILL.md +22 -22
  288. package/skills/ultraqa/SKILL.md +9 -0
  289. package/src/scripts/__tests__/codex-native-hook.test.ts +946 -98
  290. package/src/scripts/__tests__/notify-state-io.test.ts +95 -0
  291. package/src/scripts/__tests__/notify-tmux-injection.test.ts +82 -0
  292. package/src/scripts/__tests__/run-test-files.test.ts +102 -0
  293. package/src/scripts/__tests__/verify-native-agents.test.ts +75 -0
  294. package/src/scripts/codex-native-hook.ts +123 -34
  295. package/src/scripts/demo-team-e2e.sh +10 -7
  296. package/src/scripts/eval/eval-parity-smoke.ts +1 -1
  297. package/src/scripts/notify-hook/auto-nudge.ts +3 -1
  298. package/src/scripts/notify-hook/ralph-session-resume.ts +2 -8
  299. package/src/scripts/notify-hook/state-io.ts +75 -37
  300. package/src/scripts/notify-hook/team-leader-nudge.ts +7 -0
  301. package/src/scripts/notify-hook/tmux-injection.ts +35 -19
  302. package/src/scripts/notify-hook.ts +91 -4
  303. package/src/scripts/prepare-build.js +83 -0
  304. package/src/scripts/run-test-files.ts +192 -22
  305. package/src/scripts/sync-plugin-mirror.ts +98 -9
  306. package/src/scripts/verify-native-agents.ts +65 -1
  307. package/src/scripts/postinstall-bootstrap.js +0 -23
@@ -15,6 +15,7 @@ import { findGitLayout } from "../utils/git-layout.js";
15
15
  import { getBaseStateDir, getStateFilePath, getStatePath } from "../mcp/state-paths.js";
16
16
  import { detectKeywords, detectPrimaryKeyword, recordSkillActivation, } from "../hooks/keyword-detector.js";
17
17
  import { buildDeepInterviewConfigInstruction } from "../hooks/deep-interview-config-instruction.js";
18
+ import { readTeamModeConfig } from "../config/team-mode.js";
18
19
  import { detectNativeStopStallPattern, loadAutoNudgeConfig, normalizeAutoNudgeSignatureText, resolveEffectiveAutoNudgeResponse, } from "./notify-hook/auto-nudge.js";
19
20
  import { SLOPPY_FALLBACK_GROUNDING_PATTERNS, SLOPPY_FALLBACK_IMPLEMENTATION_CONTEXT_PATTERNS, SLOPPY_FALLBACK_PHRASE_PATTERNS, buildNativePostToolUseOutput, buildNativePreToolUseOutput, detectMcpTransportFailure, hasAnyPattern, } from "./codex-native-pre-post.js";
20
21
  import { handleTeamWorkerPostToolUseSuccess } from "./notify-hook/team-worker-posttooluse.js";
@@ -26,6 +27,7 @@ import { getNotificationConfig, getVerbosity } from "../notifications/config.js"
26
27
  import { reconcileHudForPromptSubmit } from "../hud/reconcile.js";
27
28
  import { onPreCompact as buildWikiPreCompactContext, onSessionStart as buildWikiSessionStartContext, } from "../wiki/lifecycle.js";
28
29
  import { readAutoresearchCompletionStatus, readAutoresearchModeStateForActiveDecision } from "../autoresearch/skill-validation.js";
30
+ import { normalizeAutopilotPhase } from "../autopilot/fsm.js";
29
31
  import { readRunState } from "../runtime/run-state.js";
30
32
  import { evaluateRalphCompletionAuditEvidence, isRalphCompletePhase } from "../ralph/completion-audit.js";
31
33
  import { getRunContinuationSnapshot, shouldContinueRun } from "../runtime/run-loop.js";
@@ -80,6 +82,19 @@ function resolveHudReconcileSessionId(currentSessionState, canonicalSessionId, s
80
82
  return ownerOmxSessionId;
81
83
  return canonicalSessionId || sessionIdForState || undefined;
82
84
  }
85
+ function resolveHudReconcileSessionIds(currentSessionState, canonicalSessionId, sessionIdForState, nativeSessionId) {
86
+ const ownerOmxSessionId = safeString(currentSessionState?.owner_omx_session_id).trim();
87
+ return uniqueNonEmpty([
88
+ resolveHudReconcileSessionId(currentSessionState, canonicalSessionId, sessionIdForState),
89
+ canonicalSessionId ?? undefined,
90
+ sessionIdForState ?? undefined,
91
+ nativeSessionId ?? undefined,
92
+ safeString(currentSessionState?.session_id),
93
+ safeString(currentSessionState?.native_session_id),
94
+ OMX_OWNER_SESSION_ID_PATTERN.test(ownerOmxSessionId) ? ownerOmxSessionId : undefined,
95
+ safeString(currentSessionState?.owner_codex_session_id),
96
+ ]);
97
+ }
83
98
  function safeContextSnippet(value, maxLength = 300) {
84
99
  const text = safeString(value).replace(/\s+/g, " ").trim();
85
100
  if (text.length <= maxLength)
@@ -1384,6 +1399,8 @@ function buildTeamHelpInstruction(cwd, payload) {
1384
1399
  }).teamHelpInstruction;
1385
1400
  }
1386
1401
  function buildNativeOutsideTmuxTeamPromptBlockState(prompt, cwd, payload, sessionId, threadId, turnId) {
1402
+ if (!readTeamModeConfig(cwd).enabled)
1403
+ return null;
1387
1404
  const match = detectPrimaryKeyword(prompt);
1388
1405
  if (match?.skill !== "team")
1389
1406
  return null;
@@ -1418,8 +1435,11 @@ function buildSkillStateCliInstruction(mode, statePath) {
1418
1435
  function buildAutopilotPromptActivationNote(skillState, options = {}) {
1419
1436
  if (skillState?.initialized_mode !== "autopilot")
1420
1437
  return null;
1438
+ const teamHandoff = readTeamModeConfig(options.cwd).enabled
1439
+ ? " (+ $team if needed)"
1440
+ : "";
1421
1441
  return [
1422
- "Autopilot protocol: the durable default chain is $deep-interview -> $ralplan -> $ultragoal (+ $team if needed) -> $code-review -> $ultraqa (deep-interview -> ralplan -> ultragoal -> code-review -> ultraqa).",
1442
+ `Autopilot protocol: the durable default chain is $deep-interview -> $ralplan -> $ultragoal${teamHandoff} -> $code-review -> $ultraqa (deep-interview -> ralplan -> ultragoal -> code-review -> ultraqa).`,
1423
1443
  "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.",
1424
1444
  "Deep-interview is a structured question chain, not a one-question gate: after an omx question answer, re-score ambiguity against the active threshold, treat max_rounds as a cap, and crystallize once ambiguity is at or below threshold and readiness gates pass.",
1425
1445
  options.markedQuestionAnswer
@@ -1431,12 +1451,18 @@ function buildAutopilotPromptActivationNote(skillState, options = {}) {
1431
1451
  "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.",
1432
1452
  ].filter(Boolean).join(" ");
1433
1453
  }
1454
+ function formatExecutionHandoffList(cwd) {
1455
+ return readTeamModeConfig(cwd).enabled
1456
+ ? "`$ultragoal`, `$team`, or `$ralph`"
1457
+ : "`$ultragoal` or `$ralph`";
1458
+ }
1434
1459
  function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(), payload) {
1435
1460
  if (!prompt)
1436
1461
  return null;
1437
1462
  const promptPriorityMessage = buildPromptPriorityMessage(prompt);
1438
- const matches = detectKeywords(prompt);
1439
- const match = detectPrimaryKeyword(prompt);
1463
+ const teamMode = readTeamModeConfig(cwd);
1464
+ const matches = detectKeywords(prompt).filter((entry) => teamMode.enabled || entry.skill !== "team");
1465
+ const match = matches[0] ?? null;
1440
1466
  if (!match) {
1441
1467
  const continuedSkill = safeString(skillState?.skill).trim();
1442
1468
  if (!continuedSkill)
@@ -1446,7 +1472,7 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
1446
1472
  : null;
1447
1473
  const deepInterviewConfigPromptActivationNote = buildDeepInterviewConfigInstruction(cwd, skillState);
1448
1474
  const markedQuestionAnswer = /^\s*\[omx question answered\]/i.test(prompt);
1449
- const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState, { markedQuestionAnswer });
1475
+ const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState, { markedQuestionAnswer, cwd });
1450
1476
  return [
1451
1477
  `OMX native UserPromptSubmit continued active workflow skill "${continuedSkill}".`,
1452
1478
  promptPriorityMessage,
@@ -1470,7 +1496,7 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
1470
1496
  ? buildDeepInterviewQuestionBridgeInstruction(cwd, payload)
1471
1497
  : null;
1472
1498
  const deepInterviewConfigPromptActivationNote = buildDeepInterviewConfigInstruction(cwd, skillState);
1473
- const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState, { markedQuestionAnswer: true });
1499
+ const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState, { markedQuestionAnswer: true, cwd });
1474
1500
  return [
1475
1501
  `OMX native UserPromptSubmit continued active workflow skill "${continuedSkill}"; workflow-like tokens inside the marked omx question answer are treated as answer text, not a new workflow activation.`,
1476
1502
  promptPriorityMessage,
@@ -1503,7 +1529,7 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
1503
1529
  const ultragoalPromptActivationNote = match.skill === "ultragoal"
1504
1530
  ? "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."
1505
1531
  : null;
1506
- const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState);
1532
+ const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState, { cwd });
1507
1533
  const combinedTransitionMessage = (() => {
1508
1534
  if (!skillState?.transition_message)
1509
1535
  return null;
@@ -2012,8 +2038,10 @@ function readPayloadThreadId(payload) {
2012
2038
  function readPayloadTurnId(payload) {
2013
2039
  return safeString(payload.turn_id ?? payload.turnId).trim();
2014
2040
  }
2015
- async function resolveInternalSessionIdForPayload(cwd, payloadSessionId) {
2016
- const currentSession = await readUsableSessionState(cwd);
2041
+ async function resolveInternalSessionIdForPayload(cwd, payloadSessionId, stateDir) {
2042
+ const currentSession = stateDir
2043
+ ? await readUsableSessionStateFromStateDir(cwd, stateDir)
2044
+ : await readUsableSessionState(cwd);
2017
2045
  const canonicalSessionId = safeString(currentSession?.session_id).trim();
2018
2046
  if (!canonicalSessionId)
2019
2047
  return payloadSessionId;
@@ -2026,6 +2054,19 @@ async function resolveInternalSessionIdForPayload(cwd, payloadSessionId) {
2026
2054
  return canonicalSessionId;
2027
2055
  return payloadSessionId;
2028
2056
  }
2057
+ async function readUsableSessionStateFromStateDir(cwd, stateDir) {
2058
+ const sessionPath = join(stateDir, "session.json");
2059
+ if (!existsSync(sessionPath))
2060
+ return null;
2061
+ try {
2062
+ const content = await readFile(sessionPath, "utf-8");
2063
+ const state = JSON.parse(content);
2064
+ return isSessionStateUsable(state, cwd) ? state : null;
2065
+ }
2066
+ catch {
2067
+ return null;
2068
+ }
2069
+ }
2029
2070
  async function readStopSessionPinnedState(fileName, cwd, sessionId, stateDir) {
2030
2071
  const statePath = stateDir && sessionId
2031
2072
  ? join(stateDir, "sessions", sessionId, fileName)
@@ -2054,7 +2095,8 @@ const PLANNING_MODE_IMPLEMENTATION_TOOL_NAMES = new Set([
2054
2095
  ]);
2055
2096
  const DEEP_INTERVIEW_IMPLEMENTATION_TOOL_NAMES = PLANNING_MODE_IMPLEMENTATION_TOOL_NAMES;
2056
2097
  const RALPLAN_EXECUTION_HANDOFF_SKILLS = new Set([
2057
- "autopilot",
2098
+ // Autopilot is intentionally excluded: it supervises planning phases such as
2099
+ // ralplan/replan and is not by itself an execution authorization.
2058
2100
  "autoresearch",
2059
2101
  "ralph",
2060
2102
  "team",
@@ -2084,14 +2126,11 @@ function isActiveRalplanPhase(state) {
2084
2126
  return false;
2085
2127
  return true;
2086
2128
  }
2087
- function isActiveAutopilotRalplanPhase(state) {
2088
- if (!state || state.active !== true)
2089
- return false;
2090
- const mode = safeString(state.mode).trim();
2091
- if (mode && mode !== "autopilot")
2092
- return false;
2093
- const phase = safeString(state.current_phase ?? state.currentPhase).trim().toLowerCase();
2094
- return phase === "ralplan";
2129
+ function isAutopilotRalplanLikePhase(phase) {
2130
+ return normalizeAutopilotPhase(phase) === "ralplan";
2131
+ }
2132
+ function canAutopilotSkillMirrorSupplyRalplanPhase(phase) {
2133
+ return phase === "" || normalizeAutopilotPhase(phase) === "ralplan";
2095
2134
  }
2096
2135
  function hasExplicitExecutionHandoffSkill(state, sessionId, threadId) {
2097
2136
  return listActiveSkills(state ?? {}).some((entry) => (RALPLAN_EXECUTION_HANDOFF_SKILLS.has(entry.skill)
@@ -2176,7 +2215,7 @@ async function readActiveDeepInterviewStateForPreToolUse(cwd, stateDir, sessionI
2176
2215
  ? await readVisibleSkillActiveStateForStateDir(stateDir, sessionId)
2177
2216
  : await readSkillActiveState(join(stateDir, SKILL_ACTIVE_STATE_FILE));
2178
2217
  if (!canonicalState)
2179
- return modeState;
2218
+ return null;
2180
2219
  const hasActiveDeepInterviewSkill = listActiveSkills(canonicalState).some((entry) => (entry.skill === "deep-interview"
2181
2220
  && matchesSkillStopContext(entry, canonicalState, sessionId, threadId)));
2182
2221
  return hasActiveDeepInterviewSkill ? modeState : null;
@@ -2192,7 +2231,7 @@ async function readActiveRalplanStateForPreToolUse(cwd, stateDir, sessionId, thr
2192
2231
  if (hasExplicitExecutionHandoffSkill(canonicalState, sessionId, threadId))
2193
2232
  return null;
2194
2233
  if (!canonicalState)
2195
- return modeState;
2234
+ return null;
2196
2235
  const hasActiveRalplanSkill = listActiveSkills(canonicalState).some((entry) => (entry.skill === "ralplan"
2197
2236
  && matchesSkillStopContext(entry, canonicalState, sessionId, threadId)));
2198
2237
  if (hasActiveRalplanSkill)
@@ -2201,7 +2240,10 @@ async function readActiveRalplanStateForPreToolUse(cwd, stateDir, sessionId, thr
2201
2240
  const autopilotState = sessionId
2202
2241
  ? await readStopSessionPinnedState("autopilot-state.json", cwd, sessionId, stateDir)
2203
2242
  : await readJsonIfExists(join(stateDir, "autopilot-state.json"));
2204
- if (!isActiveAutopilotRalplanPhase(autopilotState) || !autopilotState)
2243
+ if (!autopilotState || autopilotState.active !== true)
2244
+ return null;
2245
+ const autopilotMode = safeString(autopilotState.mode).trim();
2246
+ if (autopilotMode && autopilotMode !== "autopilot")
2205
2247
  return null;
2206
2248
  if (!modeStateMatchesSkillStopContext(autopilotState, cwd, sessionId))
2207
2249
  return null;
@@ -2209,9 +2251,19 @@ async function readActiveRalplanStateForPreToolUse(cwd, stateDir, sessionId, thr
2209
2251
  if (terminalAutopilotRunState)
2210
2252
  return null;
2211
2253
  if (!canonicalState)
2212
- return autopilotState;
2254
+ return null;
2213
2255
  const hasActiveAutopilotSkill = listActiveSkills(canonicalState).some((entry) => (entry.skill === "autopilot"
2214
2256
  && matchesSkillStopContext(entry, canonicalState, sessionId, threadId)));
2257
+ if (!hasActiveAutopilotSkill)
2258
+ return null;
2259
+ const autopilotStatePhase = safeString(autopilotState.current_phase ?? autopilotState.currentPhase).trim().toLowerCase();
2260
+ if (!canAutopilotSkillMirrorSupplyRalplanPhase(autopilotStatePhase))
2261
+ return null;
2262
+ const hasRalplanScopedAutopilotSkill = listActiveSkills(canonicalState).some((entry) => (entry.skill === "autopilot"
2263
+ && isAutopilotRalplanLikePhase(safeString(entry.phase).trim().toLowerCase())
2264
+ && matchesSkillStopContext(entry, canonicalState, sessionId, threadId)));
2265
+ if (!isAutopilotRalplanLikePhase(autopilotStatePhase) && !hasRalplanScopedAutopilotSkill)
2266
+ return null;
2215
2267
  return hasActiveAutopilotSkill ? autopilotState : null;
2216
2268
  }
2217
2269
  function isAllowedRalplanBashWrite(cwd, command) {
@@ -2222,8 +2274,8 @@ function isAllowedRalplanBashWrite(cwd, command) {
2222
2274
  const targets = extractDeepInterviewCommandWriteTargets(command);
2223
2275
  return targets.length > 0 && targets.every((target) => isAllowedRalplanArtifactPath(cwd, target));
2224
2276
  }
2225
- async function buildRalplanPreToolUseBoundaryOutput(payload, cwd, stateDir) {
2226
- const sessionId = readPayloadSessionId(payload);
2277
+ async function buildRalplanPreToolUseBoundaryOutput(payload, cwd, stateDir, resolvedSessionId) {
2278
+ const sessionId = safeString(resolvedSessionId ?? readPayloadSessionId(payload)).trim();
2227
2279
  const threadId = readPayloadThreadId(payload);
2228
2280
  const activeState = await readActiveRalplanStateForPreToolUse(cwd, stateDir, sessionId, threadId);
2229
2281
  if (!activeState)
@@ -2242,17 +2294,25 @@ async function buildRalplanPreToolUseBoundaryOutput(payload, cwd, stateDir) {
2242
2294
  if (!blocked)
2243
2295
  return null;
2244
2296
  const phase = formatPhase(activeState.current_phase ?? activeState.currentPhase, "planning");
2297
+ const activeMode = safeString(activeState.mode).trim().toLowerCase();
2298
+ const planningModeLabel = activeMode === "autopilot" ? "Autopilot planning" : "Ralplan";
2299
+ const planningModeDescription = activeMode === "autopilot"
2300
+ ? "Autopilot is supervising a planning phase"
2301
+ : "Ralplan is consensus-planning mode";
2245
2302
  return {
2246
2303
  decision: "block",
2247
- reason: `Ralplan is active (phase: ${phase}); implementation/write tools are blocked until an explicit execution handoff workflow is activated.`,
2304
+ reason: `${planningModeLabel} is active (phase: ${phase}); implementation/write tools are blocked until an explicit execution handoff workflow is activated.`,
2248
2305
  hookSpecificOutput: {
2249
2306
  hookEventName: "PreToolUse",
2250
- additionalContext: "Ralplan is consensus-planning mode. Write only planning artifacts under `.omx/context/`, `.omx/plans/`, `.omx/specs/`, or required `.omx/state/` files. Do not edit implementation files or run implementation-focused writes from ralplan. To execute, first process an explicit handoff such as `$ultragoal`, `$team`, or `$ralph`, which must emit terminal ralplan state before implementation begins.",
2307
+ additionalContext: `${planningModeDescription}. `
2308
+ + "Write only planning artifacts under `.omx/context/`, `.omx/plans/`, `.omx/specs/`, or required `.omx/state/` files. "
2309
+ + "Do not edit implementation files or run implementation-focused writes from planning phases. "
2310
+ + `To execute, first process an explicit handoff such as ${formatExecutionHandoffList(cwd)}, which must emit terminal planning state before implementation begins.`,
2251
2311
  },
2252
2312
  };
2253
2313
  }
2254
- async function buildDeepInterviewPreToolUseBoundaryOutput(payload, cwd, stateDir) {
2255
- const sessionId = readPayloadSessionId(payload);
2314
+ async function buildDeepInterviewPreToolUseBoundaryOutput(payload, cwd, stateDir, resolvedSessionId) {
2315
+ const sessionId = safeString(resolvedSessionId ?? readPayloadSessionId(payload)).trim();
2256
2316
  const threadId = readPayloadThreadId(payload);
2257
2317
  const activeState = await readActiveDeepInterviewStateForPreToolUse(cwd, stateDir, sessionId, threadId);
2258
2318
  if (!activeState)
@@ -2276,7 +2336,7 @@ async function buildDeepInterviewPreToolUseBoundaryOutput(payload, cwd, stateDir
2276
2336
  reason: `Deep-interview is active (phase: ${phase}); implementation/write tools are blocked until an explicit handoff workflow is activated.`,
2277
2337
  hookSpecificOutput: {
2278
2338
  hookEventName: "PreToolUse",
2279
- 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`.",
2339
+ 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\`, ${formatExecutionHandoffList(cwd)}.`,
2280
2340
  },
2281
2341
  };
2282
2342
  }
@@ -2465,7 +2525,7 @@ async function reconcileStaleRootSkillActiveStateForStop(cwd, stateDir, sessionI
2465
2525
  }
2466
2526
  await writeFile(rootPath, JSON.stringify(nextRoot, null, 2));
2467
2527
  }
2468
- function buildRalplanContinuationStatus(blocker, activeSubagentCount) {
2528
+ function buildRalplanContinuationStatus(blocker, activeSubagentCount, cwd) {
2469
2529
  const phase = blocker.phase || "planning";
2470
2530
  const artifact = blocker.latestPlanPath
2471
2531
  ? ` Artifact: ${blocker.latestPlanPath}.`
@@ -2491,7 +2551,7 @@ function buildRalplanContinuationStatus(blocker, activeSubagentCount) {
2491
2551
  };
2492
2552
  }
2493
2553
  const completeHint = blocker.planningComplete
2494
- ? " The planning artifacts are present; if consensus is approved, emit terminal ralplan complete/approved handoff state and stop planning. Implementation must wait for an explicit $ultragoal, $team, or $ralph handoff."
2554
+ ? ` The planning artifacts are present; if consensus is approved, emit terminal ralplan complete/approved handoff state and stop planning. Implementation must wait for an explicit ${formatExecutionHandoffList(cwd).replaceAll("`", "")} handoff.`
2495
2555
  : "";
2496
2556
  return {
2497
2557
  reason: `Status: continue_from_artifact — ralplan is still active (phase: ${phase}) and has not emitted a terminal complete/paused/waiting status. Continue from the current ralplan artifact, resolve any review ambiguity conservatively or ask the user if needed, and proceed to the next planning/review step before stopping; do not begin implementation from ralplan.${artifact}${completeHint}`,
@@ -2650,6 +2710,9 @@ function readIsoTimeMs(value) {
2650
2710
  return Number.isFinite(parsed) ? parsed : null;
2651
2711
  }
2652
2712
  async function maybeBuildOrdinaryStopNoProgressOutput(payload, stateDir, canonicalSessionId) {
2713
+ const lastAssistantMessage = safeString(payload.last_assistant_message ?? payload.lastAssistantMessage).trim();
2714
+ if (!lastAssistantMessage)
2715
+ return null;
2653
2716
  const statePath = join(stateDir, NATIVE_STOP_STATE_FILE);
2654
2717
  const state = await readJsonIfExists(statePath) ?? {};
2655
2718
  const sessions = safeObject(state.sessions);
@@ -2679,9 +2742,6 @@ async function maybeBuildOrdinaryStopNoProgressOutput(payload, stateDir, canonic
2679
2742
  };
2680
2743
  await mkdir(stateDir, { recursive: true });
2681
2744
  await writeFile(statePath, JSON.stringify({ ...state, sessions }, null, 2));
2682
- const stopHookActive = payload.stop_hook_active === true || payload.stopHookActive === true;
2683
- if (!stopHookActive)
2684
- return null;
2685
2745
  const maxRepeats = parseBoundedPositiveInteger(process.env.OMX_NATIVE_STOP_NO_PROGRESS_MAX_REPEATS, ORDINARY_STOP_NO_PROGRESS_DEFAULT_MAX_REPEATS);
2686
2746
  const idleMs = parseBoundedNonNegativeInteger(process.env.OMX_NATIVE_STOP_NO_PROGRESS_IDLE_MS, ORDINARY_STOP_NO_PROGRESS_DEFAULT_IDLE_MS);
2687
2747
  const firstSeenMs = readIsoTimeMs(firstSeenAt) ?? Date.now();
@@ -2811,7 +2871,7 @@ async function buildSkillStopOutput(cwd, stateDir, sessionId, threadId) {
2811
2871
  const subagentSummary = await readSubagentSessionSummary(cwd, sessionId).catch(() => null);
2812
2872
  const activeSubagentCount = subagentSummary?.activeSubagentThreadIds.length ?? 0;
2813
2873
  if (blocker.skill === "ralplan") {
2814
- const status = buildRalplanContinuationStatus(blocker, activeSubagentCount);
2874
+ const status = buildRalplanContinuationStatus(blocker, activeSubagentCount, cwd);
2815
2875
  return {
2816
2876
  decision: "block",
2817
2877
  reason: status.reason,
@@ -3076,7 +3136,9 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
3076
3136
  // Native hooks must use the same authoritative runtime state root as HUD/MCP
3077
3137
  // when boxed/team roots are active; do not bypass it with cwd/.omx/state.
3078
3138
  const stateDir = getBaseStateDir(cwd);
3079
- await mkdir(stateDir, { recursive: true });
3139
+ if (hookEventName !== "Stop") {
3140
+ await mkdir(stateDir, { recursive: true });
3141
+ }
3080
3142
  const omxEventName = mapCodexHookEventToOmxEvent(hookEventName);
3081
3143
  let skillState = null;
3082
3144
  let triageAdditionalContext = null;
@@ -3237,12 +3299,14 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
3237
3299
  triageAdditionalContext = null;
3238
3300
  }
3239
3301
  }
3302
+ const skipHudReconcileForDoctorSmoke = process.env.OMX_NATIVE_HOOK_DOCTOR_SMOKE === "1";
3240
3303
  const skipHudReconcileForTeamWorkerPane = !isSubagentPromptSubmit
3241
3304
  && await isConfirmedTeamWorkerPromptSubmitPane(cwd).catch(() => false);
3242
- if (!skipHudReconcileForTeamWorkerPane) {
3305
+ if (!skipHudReconcileForDoctorSmoke && !skipHudReconcileForTeamWorkerPane) {
3243
3306
  const reconcileHudForPromptSubmitFn = options.reconcileHudForPromptSubmitFn ?? reconcileHudForPromptSubmit;
3244
3307
  const hudSessionId = resolveHudReconcileSessionId(currentSessionState, canonicalSessionId, sessionIdForState);
3245
- await reconcileHudForPromptSubmitFn(cwd, { sessionId: hudSessionId }).catch(() => { });
3308
+ const hudSessionIds = resolveHudReconcileSessionIds(currentSessionState, canonicalSessionId, sessionIdForState, nativeSessionId);
3309
+ await reconcileHudForPromptSubmitFn(cwd, { sessionId: hudSessionId, sessionIds: hudSessionIds }).catch(() => { });
3246
3310
  }
3247
3311
  }
3248
3312
  if (omxEventName && !skipCanonicalSessionStartContext && !suppressNoisySubagentLifecycleDispatch) {
@@ -3298,8 +3362,12 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
3298
3362
  }
3299
3363
  }
3300
3364
  else if (hookEventName === "PreToolUse") {
3301
- outputJson = await buildDeepInterviewPreToolUseBoundaryOutput(payload, cwd, stateDir)
3302
- ?? await buildRalplanPreToolUseBoundaryOutput(payload, cwd, stateDir)
3365
+ const payloadSessionId = readPayloadSessionId(payload);
3366
+ const preToolUseSessionId = payloadSessionId
3367
+ ? await resolveInternalSessionIdForPayload(cwd, payloadSessionId, stateDir)
3368
+ : "";
3369
+ outputJson = await buildDeepInterviewPreToolUseBoundaryOutput(payload, cwd, stateDir, preToolUseSessionId)
3370
+ ?? await buildRalplanPreToolUseBoundaryOutput(payload, cwd, stateDir, preToolUseSessionId)
3303
3371
  ?? buildNativePreToolUseOutput(payload);
3304
3372
  }
3305
3373
  else if (hookEventName === "PostToolUse") {