oh-my-codex 0.20.1 → 0.20.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 (654) hide show
  1. package/Cargo.lock +6 -6
  2. package/Cargo.toml +1 -1
  3. package/README.md +10 -1
  4. package/dist/adapt/__tests__/hermes.test.js.map +1 -1
  5. package/dist/adapt/contracts.d.ts.map +1 -1
  6. package/dist/agents/native-config.js.map +1 -1
  7. package/dist/auth/__tests__/hotswap.test.d.ts +2 -0
  8. package/dist/auth/__tests__/hotswap.test.d.ts.map +1 -0
  9. package/dist/auth/__tests__/hotswap.test.js +183 -0
  10. package/dist/auth/__tests__/hotswap.test.js.map +1 -0
  11. package/dist/auth/hotswap.d.ts.map +1 -1
  12. package/dist/auth/hotswap.js +17 -4
  13. package/dist/auth/hotswap.js.map +1 -1
  14. package/dist/auth/paths.js.map +1 -1
  15. package/dist/auth/storage.js.map +1 -1
  16. package/dist/autopilot/__tests__/ralplan-gate.test.js +4 -4
  17. package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -1
  18. package/dist/autopilot/completion-gate.js.map +1 -1
  19. package/dist/autopilot/fsm.d.ts +1 -1
  20. package/dist/autopilot/fsm.d.ts.map +1 -1
  21. package/dist/autoresearch/goal.js.map +1 -1
  22. package/dist/autoresearch/runtime.js.map +1 -1
  23. package/dist/capabilities/lockfile.js.map +1 -1
  24. package/dist/catalog/reader.js.map +1 -1
  25. package/dist/catalog/skill-mirror.js.map +1 -1
  26. package/dist/cli/__tests__/adapt-help.test.js.map +1 -1
  27. package/dist/cli/__tests__/agents-init.test.js.map +1 -1
  28. package/dist/cli/__tests__/agents.test.js.map +1 -1
  29. package/dist/cli/__tests__/api.test.js.map +1 -1
  30. package/dist/cli/__tests__/ask.test.js.map +1 -1
  31. package/dist/cli/__tests__/auth.test.js.map +1 -1
  32. package/dist/cli/__tests__/autoresearch-guided.test.js.map +1 -1
  33. package/dist/cli/__tests__/autoresearch.test.js.map +1 -1
  34. package/dist/cli/__tests__/capabilities.test.js.map +1 -1
  35. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  36. package/dist/cli/__tests__/doctor-context-window-warning.test.js.map +1 -1
  37. package/dist/cli/__tests__/doctor-invalid-config.test.js +47 -4
  38. package/dist/cli/__tests__/doctor-invalid-config.test.js.map +1 -1
  39. package/dist/cli/__tests__/doctor-team.test.js.map +1 -1
  40. package/dist/cli/__tests__/doctor-warning-copy.test.js +650 -15
  41. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  42. package/dist/cli/__tests__/exec.test.js.map +1 -1
  43. package/dist/cli/__tests__/imagegen-continuation.test.js.map +1 -1
  44. package/dist/cli/__tests__/index.test.js +216 -11
  45. package/dist/cli/__tests__/index.test.js.map +1 -1
  46. package/dist/cli/__tests__/launch-fallback.test.js +49 -3
  47. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  48. package/dist/cli/__tests__/mcp-parity.test.js +84 -12
  49. package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
  50. package/dist/cli/__tests__/native-hook-claim-journal.test.d.ts +2 -0
  51. package/dist/cli/__tests__/native-hook-claim-journal.test.d.ts.map +1 -0
  52. package/dist/cli/__tests__/native-hook-claim-journal.test.js +128 -0
  53. package/dist/cli/__tests__/native-hook-claim-journal.test.js.map +1 -0
  54. package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
  55. package/dist/cli/__tests__/question.test.js.map +1 -1
  56. package/dist/cli/__tests__/ralph-deslop-contract.test.js.map +1 -1
  57. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +6 -0
  58. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
  59. package/dist/cli/__tests__/ralph-prd-deep-interview.test.js.map +1 -1
  60. package/dist/cli/__tests__/ralph-prd-smoke.test.js.map +1 -1
  61. package/dist/cli/__tests__/ralph.test.js +8 -3
  62. package/dist/cli/__tests__/ralph.test.js.map +1 -1
  63. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.d.ts +2 -0
  64. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.d.ts.map +1 -0
  65. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js +187 -0
  66. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js.map +1 -0
  67. package/dist/cli/__tests__/ralplan.test.d.ts +2 -0
  68. package/dist/cli/__tests__/ralplan.test.d.ts.map +1 -0
  69. package/dist/cli/__tests__/ralplan.test.js +129 -0
  70. package/dist/cli/__tests__/ralplan.test.js.map +1 -0
  71. package/dist/cli/__tests__/resume.test.js +6 -1
  72. package/dist/cli/__tests__/resume.test.js.map +1 -1
  73. package/dist/cli/__tests__/session-scoped-runtime.test.js +25 -0
  74. package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -1
  75. package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
  76. package/dist/cli/__tests__/session-search.test.js.map +1 -1
  77. package/dist/cli/__tests__/setup-agents-overwrite.test.js +79 -0
  78. package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
  79. package/dist/cli/__tests__/setup-gh-star.test.js.map +1 -1
  80. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +77 -3
  81. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
  82. package/dist/cli/__tests__/setup-hooks-trust-e2e.test.d.ts +2 -0
  83. package/dist/cli/__tests__/setup-hooks-trust-e2e.test.d.ts.map +1 -0
  84. package/dist/cli/__tests__/setup-hooks-trust-e2e.test.js +285 -0
  85. package/dist/cli/__tests__/setup-hooks-trust-e2e.test.js.map +1 -0
  86. package/dist/cli/__tests__/setup-install-mode.test.js +2261 -14
  87. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  88. package/dist/cli/__tests__/setup-preferences.test.d.ts +2 -0
  89. package/dist/cli/__tests__/setup-preferences.test.d.ts.map +1 -0
  90. package/dist/cli/__tests__/setup-preferences.test.js +79 -0
  91. package/dist/cli/__tests__/setup-preferences.test.js.map +1 -0
  92. package/dist/cli/__tests__/setup-refresh.test.js +33 -2
  93. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  94. package/dist/cli/__tests__/setup-scope.test.js +46 -3
  95. package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
  96. package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -1
  97. package/dist/cli/__tests__/state.test.js +37 -0
  98. package/dist/cli/__tests__/state.test.js.map +1 -1
  99. package/dist/cli/__tests__/team.test.js.map +1 -1
  100. package/dist/cli/__tests__/ultragoal.test.js +61 -1
  101. package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
  102. package/dist/cli/__tests__/uninstall.test.js +1771 -24
  103. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  104. package/dist/cli/__tests__/update.test.js +58 -0
  105. package/dist/cli/__tests__/update.test.js.map +1 -1
  106. package/dist/cli/__tests__/url.test.js.map +1 -1
  107. package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
  108. package/dist/cli/adapt.js.map +1 -1
  109. package/dist/cli/agents-init.js.map +1 -1
  110. package/dist/cli/agents.js.map +1 -1
  111. package/dist/cli/api.js.map +1 -1
  112. package/dist/cli/ask.d.ts +1 -1
  113. package/dist/cli/ask.d.ts.map +1 -1
  114. package/dist/cli/ask.js.map +1 -1
  115. package/dist/cli/auth.js.map +1 -1
  116. package/dist/cli/autoresearch-guided.js.map +1 -1
  117. package/dist/cli/autoresearch-intake.js.map +1 -1
  118. package/dist/cli/capabilities.js.map +1 -1
  119. package/dist/cli/cleanup.js.map +1 -1
  120. package/dist/cli/codex-feature-probe.js.map +1 -1
  121. package/dist/cli/codex-home.js.map +1 -1
  122. package/dist/cli/doctor.d.ts +18 -0
  123. package/dist/cli/doctor.d.ts.map +1 -1
  124. package/dist/cli/doctor.js +594 -130
  125. package/dist/cli/doctor.js.map +1 -1
  126. package/dist/cli/explore.js.map +1 -1
  127. package/dist/cli/index.d.ts +11 -3
  128. package/dist/cli/index.d.ts.map +1 -1
  129. package/dist/cli/index.js +108 -20
  130. package/dist/cli/index.js.map +1 -1
  131. package/dist/cli/mcp-serve.js.map +1 -1
  132. package/dist/cli/mission.js.map +1 -1
  133. package/dist/cli/native-assets.js.map +1 -1
  134. package/dist/cli/native-hook-claim-journal.d.ts +18 -0
  135. package/dist/cli/native-hook-claim-journal.d.ts.map +1 -0
  136. package/dist/cli/native-hook-claim-journal.js +239 -0
  137. package/dist/cli/native-hook-claim-journal.js.map +1 -0
  138. package/dist/cli/omx.js.map +1 -1
  139. package/dist/cli/plugin-marketplace.js.map +1 -1
  140. package/dist/cli/project-runtime-codex-homes.js.map +1 -1
  141. package/dist/cli/question.js.map +1 -1
  142. package/dist/cli/ralph.d.ts.map +1 -1
  143. package/dist/cli/ralph.js +3 -2
  144. package/dist/cli/ralph.js.map +1 -1
  145. package/dist/cli/ralplan.d.ts +14 -0
  146. package/dist/cli/ralplan.d.ts.map +1 -0
  147. package/dist/cli/ralplan.js +203 -0
  148. package/dist/cli/ralplan.js.map +1 -0
  149. package/dist/cli/setup-preferences.d.ts +11 -0
  150. package/dist/cli/setup-preferences.d.ts.map +1 -1
  151. package/dist/cli/setup-preferences.js +32 -0
  152. package/dist/cli/setup-preferences.js.map +1 -1
  153. package/dist/cli/setup.d.ts +53 -0
  154. package/dist/cli/setup.d.ts.map +1 -1
  155. package/dist/cli/setup.js +1401 -398
  156. package/dist/cli/setup.js.map +1 -1
  157. package/dist/cli/sparkshell.js.map +1 -1
  158. package/dist/cli/star-prompt.js.map +1 -1
  159. package/dist/cli/state.d.ts.map +1 -1
  160. package/dist/cli/state.js +2 -1
  161. package/dist/cli/state.js.map +1 -1
  162. package/dist/cli/team.js.map +1 -1
  163. package/dist/cli/ultragoal.d.ts +5 -1
  164. package/dist/cli/ultragoal.d.ts.map +1 -1
  165. package/dist/cli/ultragoal.js +34 -2
  166. package/dist/cli/ultragoal.js.map +1 -1
  167. package/dist/cli/uninstall.d.ts +8 -0
  168. package/dist/cli/uninstall.d.ts.map +1 -1
  169. package/dist/cli/uninstall.js +944 -95
  170. package/dist/cli/uninstall.js.map +1 -1
  171. package/dist/cli/update.d.ts.map +1 -1
  172. package/dist/cli/update.js +8 -1
  173. package/dist/cli/update.js.map +1 -1
  174. package/dist/cli/url.js.map +1 -1
  175. package/dist/compat/__tests__/doctor-contract.test.js +5 -1
  176. package/dist/compat/__tests__/doctor-contract.test.js.map +1 -1
  177. package/dist/compat/__tests__/rust-runtime-compat.test.js.map +1 -1
  178. package/dist/config/__tests__/codex-hooks.test.js +1287 -11
  179. package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
  180. package/dist/config/__tests__/generator-idempotent.test.js +850 -32
  181. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  182. package/dist/config/__tests__/generator-notify.test.js +6 -1
  183. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  184. package/dist/config/codex-feature-flags.d.ts.map +1 -1
  185. package/dist/config/codex-feature-flags.js.map +1 -1
  186. package/dist/config/codex-hooks.d.ts +124 -1
  187. package/dist/config/codex-hooks.d.ts.map +1 -1
  188. package/dist/config/codex-hooks.js +2142 -265
  189. package/dist/config/codex-hooks.js.map +1 -1
  190. package/dist/config/commit-lore-guard.js.map +1 -1
  191. package/dist/config/generator.d.ts +21 -16
  192. package/dist/config/generator.d.ts.map +1 -1
  193. package/dist/config/generator.js +991 -137
  194. package/dist/config/generator.js.map +1 -1
  195. package/dist/config/mcp-registry.js.map +1 -1
  196. package/dist/config/models.d.ts +2 -2
  197. package/dist/config/models.d.ts.map +1 -1
  198. package/dist/config/models.js.map +1 -1
  199. package/dist/config/omx-first-party-mcp.js.map +1 -1
  200. package/dist/config/team-mode.d.ts.map +1 -1
  201. package/dist/document-refresh/__tests__/enforcer.test.js.map +1 -1
  202. package/dist/document-refresh/enforcer.js.map +1 -1
  203. package/dist/exec/followup.js.map +1 -1
  204. package/dist/goal-workflows/artifacts.js.map +1 -1
  205. package/dist/hooks/__tests__/agents-overlay.test.js +7 -4
  206. package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
  207. package/dist/hooks/__tests__/analyze-routing-contract.test.js.map +1 -1
  208. package/dist/hooks/__tests__/analyze-skill-contract.test.js.map +1 -1
  209. package/dist/hooks/__tests__/anti-slop-workflow.test.js.map +1 -1
  210. package/dist/hooks/__tests__/autopilot-skill-contract.test.js +9 -3
  211. package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
  212. package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +1 -1
  213. package/dist/hooks/__tests__/consensus-execution-handoff.test.js.map +1 -1
  214. package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
  215. package/dist/hooks/__tests__/design-skill.test.js.map +1 -1
  216. package/dist/hooks/__tests__/keyword-detector.test.js +1372 -2
  217. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  218. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +14 -0
  219. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  220. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  221. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +669 -1
  222. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  223. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +2 -0
  224. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
  225. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +142 -1
  226. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
  227. package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -1
  228. package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js +48 -2
  229. package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js.map +1 -1
  230. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +61 -44
  231. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -1
  232. package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
  233. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js +3 -2
  234. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js.map +1 -1
  235. package/dist/hooks/__tests__/notify-hook-session-scope.test.js +243 -4
  236. package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
  237. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  238. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +8 -1
  239. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  240. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  241. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  242. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -1
  243. package/dist/hooks/__tests__/notify-hook-visual-verdict.test.js.map +1 -1
  244. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  245. package/dist/hooks/__tests__/openclaw-setup-contract.test.js.map +1 -1
  246. package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -1
  247. package/dist/hooks/__tests__/prometheus-strict-contract.test.js.map +1 -1
  248. package/dist/hooks/__tests__/prompt-guidance-fragments.test.js.map +1 -1
  249. package/dist/hooks/__tests__/prompt-guidance-test-helpers.js.map +1 -1
  250. package/dist/hooks/__tests__/prompt-session-provenance.test.d.ts +2 -0
  251. package/dist/hooks/__tests__/prompt-session-provenance.test.d.ts.map +1 -0
  252. package/dist/hooks/__tests__/prompt-session-provenance.test.js +82 -0
  253. package/dist/hooks/__tests__/prompt-session-provenance.test.js.map +1 -0
  254. package/dist/hooks/__tests__/session.test.js +532 -11
  255. package/dist/hooks/__tests__/session.test.js.map +1 -1
  256. package/dist/hooks/__tests__/skill-catalog-hygiene.test.js.map +1 -1
  257. package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js.map +1 -1
  258. package/dist/hooks/__tests__/visual-ralph-skill.test.js.map +1 -1
  259. package/dist/hooks/__tests__/visual-verdict-loop.test.js.map +1 -1
  260. package/dist/hooks/agents-overlay.js +5 -5
  261. package/dist/hooks/agents-overlay.js.map +1 -1
  262. package/dist/hooks/code-simplifier/index.js.map +1 -1
  263. package/dist/hooks/explore-routing.js.map +1 -1
  264. package/dist/hooks/extensibility/dispatcher.js.map +1 -1
  265. package/dist/hooks/extensibility/events.js.map +1 -1
  266. package/dist/hooks/extensibility/loader.js.map +1 -1
  267. package/dist/hooks/extensibility/plugin-runner-stdin.js.map +1 -1
  268. package/dist/hooks/extensibility/sdk/logging.js.map +1 -1
  269. package/dist/hooks/keyword-detector.d.ts +33 -7
  270. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  271. package/dist/hooks/keyword-detector.js +2228 -119
  272. package/dist/hooks/keyword-detector.js.map +1 -1
  273. package/dist/hooks/keyword-registry.d.ts +12 -0
  274. package/dist/hooks/keyword-registry.d.ts.map +1 -1
  275. package/dist/hooks/keyword-registry.js +41 -0
  276. package/dist/hooks/keyword-registry.js.map +1 -1
  277. package/dist/hooks/prompt-session-provenance.d.ts +87 -0
  278. package/dist/hooks/prompt-session-provenance.d.ts.map +1 -0
  279. package/dist/hooks/prompt-session-provenance.js +180 -0
  280. package/dist/hooks/prompt-session-provenance.js.map +1 -0
  281. package/dist/hooks/session.d.ts +139 -34
  282. package/dist/hooks/session.d.ts.map +1 -1
  283. package/dist/hooks/session.js +1239 -317
  284. package/dist/hooks/session.js.map +1 -1
  285. package/dist/hooks/task-size-detector.js.map +1 -1
  286. package/dist/hud/__tests__/state.test.js.map +1 -1
  287. package/dist/hud/authority.js.map +1 -1
  288. package/dist/hud/constants.js.map +1 -1
  289. package/dist/hud/index.js.map +1 -1
  290. package/dist/hud/reconcile.js.map +1 -1
  291. package/dist/hud/render.js.map +1 -1
  292. package/dist/hud/state.js.map +1 -1
  293. package/dist/hud/tmux.js.map +1 -1
  294. package/dist/leader/__tests__/contract.test.js +103 -1
  295. package/dist/leader/__tests__/contract.test.js.map +1 -1
  296. package/dist/leader/contract.d.ts +26 -5
  297. package/dist/leader/contract.d.ts.map +1 -1
  298. package/dist/leader/contract.js +109 -3
  299. package/dist/leader/contract.js.map +1 -1
  300. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  301. package/dist/mcp/__tests__/server-lifecycle.test.js +15 -2
  302. package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
  303. package/dist/mcp/__tests__/state-paths.test.js +98 -1
  304. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  305. package/dist/mcp/bootstrap.js.map +1 -1
  306. package/dist/mcp/code-intel-server.d.ts +58 -58
  307. package/dist/mcp/code-intel-server.d.ts.map +1 -1
  308. package/dist/mcp/code-intel-server.js.map +1 -1
  309. package/dist/mcp/hermes-bridge.js.map +1 -1
  310. package/dist/mcp/hermes-server.d.ts +70 -70
  311. package/dist/mcp/hermes-server.d.ts.map +1 -1
  312. package/dist/mcp/lifecycle-telemetry.js.map +1 -1
  313. package/dist/mcp/memory-server.d.ts +34 -34
  314. package/dist/mcp/memory-server.d.ts.map +1 -1
  315. package/dist/mcp/memory-server.js.map +1 -1
  316. package/dist/mcp/state-paths.d.ts +14 -0
  317. package/dist/mcp/state-paths.d.ts.map +1 -1
  318. package/dist/mcp/state-paths.js +96 -20
  319. package/dist/mcp/state-paths.js.map +1 -1
  320. package/dist/mcp/state-server.d.ts +47 -47
  321. package/dist/mcp/state-server.d.ts.map +1 -1
  322. package/dist/mcp/trace-server.d.ts +4 -4
  323. package/dist/mcp/trace-server.d.ts.map +1 -1
  324. package/dist/mcp/trace-server.js.map +1 -1
  325. package/dist/mcp/wiki-server.d.ts +23 -23
  326. package/dist/mcp/wiki-server.d.ts.map +1 -1
  327. package/dist/mcp/wiki-server.js.map +1 -1
  328. package/dist/modes/__tests__/base-session-scope.test.js +53 -1
  329. package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
  330. package/dist/modes/base.d.ts.map +1 -1
  331. package/dist/modes/base.js +5 -5
  332. package/dist/modes/base.js.map +1 -1
  333. package/dist/notifications/__tests__/lifecycle-dedupe.test.js.map +1 -1
  334. package/dist/notifications/__tests__/reply-listener.test.js.map +1 -1
  335. package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js +177 -85
  336. package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js.map +1 -1
  337. package/dist/notifications/__tests__/session-registry.test.js.map +1 -1
  338. package/dist/notifications/__tests__/template-engine.test.js.map +1 -1
  339. package/dist/notifications/__tests__/verbosity.test.js.map +1 -1
  340. package/dist/notifications/http-client.js.map +1 -1
  341. package/dist/notifications/index.d.ts +4 -1
  342. package/dist/notifications/index.d.ts.map +1 -1
  343. package/dist/notifications/index.js +3 -9
  344. package/dist/notifications/index.js.map +1 -1
  345. package/dist/notifications/lifecycle-dedupe.js.map +1 -1
  346. package/dist/notifications/reply-listener.d.ts.map +1 -1
  347. package/dist/notifications/reply-listener.js.map +1 -1
  348. package/dist/notifications/session-registry.js.map +1 -1
  349. package/dist/notifications/session-status.js.map +1 -1
  350. package/dist/notifications/temp-contract.js.map +1 -1
  351. package/dist/notifications/tmux-detector.js.map +1 -1
  352. package/dist/notifications/tmux.js.map +1 -1
  353. package/dist/openclaw/config.js.map +1 -1
  354. package/dist/openclaw/dispatcher.js.map +1 -1
  355. package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
  356. package/dist/pipeline/__tests__/stages.test.js +8 -5
  357. package/dist/pipeline/__tests__/stages.test.js.map +1 -1
  358. package/dist/pipeline/stages/code-review.js.map +1 -1
  359. package/dist/pipeline/stages/ralph-verify.js.map +1 -1
  360. package/dist/pipeline/stages/ralplan.js.map +1 -1
  361. package/dist/pipeline/stages/team-exec.js.map +1 -1
  362. package/dist/pipeline/stages/ultragoal.js.map +1 -1
  363. package/dist/pipeline/stages/ultraqa.js.map +1 -1
  364. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js.map +1 -1
  365. package/dist/planning/artifact-names.js.map +1 -1
  366. package/dist/planning/artifacts.js.map +1 -1
  367. package/dist/question/__tests__/state.test.js.map +1 -1
  368. package/dist/question/__tests__/ui.test.js.map +1 -1
  369. package/dist/question/autopilot-wait.js.map +1 -1
  370. package/dist/question/client.d.ts.map +1 -1
  371. package/dist/question/client.js.map +1 -1
  372. package/dist/question/deep-interview.js.map +1 -1
  373. package/dist/question/events.js.map +1 -1
  374. package/dist/question/renderer.js.map +1 -1
  375. package/dist/question/state.d.ts.map +1 -1
  376. package/dist/question/state.js.map +1 -1
  377. package/dist/question/ui.js.map +1 -1
  378. package/dist/ralph/contract.d.ts +1 -1
  379. package/dist/ralph/contract.d.ts.map +1 -1
  380. package/dist/ralplan/__tests__/consensus-gate.test.js +403 -8
  381. package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
  382. package/dist/ralplan/__tests__/runtime.test.js +112 -14
  383. package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
  384. package/dist/ralplan/consensus-gate.d.ts +3 -3
  385. package/dist/ralplan/consensus-gate.d.ts.map +1 -1
  386. package/dist/ralplan/consensus-gate.js +155 -60
  387. package/dist/ralplan/consensus-gate.js.map +1 -1
  388. package/dist/ralplan/runtime.d.ts +2 -2
  389. package/dist/ralplan/runtime.d.ts.map +1 -1
  390. package/dist/ralplan/runtime.js +1 -2
  391. package/dist/ralplan/runtime.js.map +1 -1
  392. package/dist/runtime/bridge.d.ts.map +1 -1
  393. package/dist/runtime/bridge.js.map +1 -1
  394. package/dist/runtime/process-tree.js.map +1 -1
  395. package/dist/runtime/run-loop.js.map +1 -1
  396. package/dist/runtime/run-outcome.d.ts +3 -3
  397. package/dist/runtime/run-outcome.d.ts.map +1 -1
  398. package/dist/runtime/run-outcome.js.map +1 -1
  399. package/dist/runtime/run-state.js.map +1 -1
  400. package/dist/scripts/__tests__/codex-native-hook.test.js +4121 -592
  401. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  402. package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.d.ts +2 -0
  403. package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.d.ts.map +1 -0
  404. package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.js +634 -0
  405. package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.js.map +1 -0
  406. package/dist/scripts/__tests__/generate-release-body.test.js.map +1 -1
  407. package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +1 -1
  408. package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -1
  409. package/dist/scripts/__tests__/notify-fallback-delivery.test.d.ts +2 -0
  410. package/dist/scripts/__tests__/notify-fallback-delivery.test.d.ts.map +1 -0
  411. package/dist/scripts/__tests__/notify-fallback-delivery.test.js +174 -0
  412. package/dist/scripts/__tests__/notify-fallback-delivery.test.js.map +1 -0
  413. package/dist/scripts/__tests__/notify-state-io.test.js +57 -1
  414. package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -1
  415. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.d.ts +2 -0
  416. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.d.ts.map +1 -0
  417. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js +205 -0
  418. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js.map +1 -0
  419. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.d.ts +2 -0
  420. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.d.ts.map +1 -0
  421. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js +175 -0
  422. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js.map +1 -0
  423. package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
  424. package/dist/scripts/__tests__/smoke-packed-install.test.js +848 -4
  425. package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
  426. package/dist/scripts/__tests__/test-reply-listener-live.test.js.map +1 -1
  427. package/dist/scripts/build-api.js.map +1 -1
  428. package/dist/scripts/build-explore-harness.js.map +1 -1
  429. package/dist/scripts/build-sparkshell.js.map +1 -1
  430. package/dist/scripts/cleanup-explore-harness.js.map +1 -1
  431. package/dist/scripts/codex-execution-surface.js.map +1 -1
  432. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  433. package/dist/scripts/codex-native-hook.js +689 -156
  434. package/dist/scripts/codex-native-hook.js.map +1 -1
  435. package/dist/scripts/generate-native-release-manifest.js.map +1 -1
  436. package/dist/scripts/generate-release-body.js.map +1 -1
  437. package/dist/scripts/hook-payload-guard.d.ts.map +1 -1
  438. package/dist/scripts/hook-payload-guard.js.map +1 -1
  439. package/dist/scripts/notify-fallback-delivery.d.ts +48 -0
  440. package/dist/scripts/notify-fallback-delivery.d.ts.map +1 -0
  441. package/dist/scripts/notify-fallback-delivery.js +419 -0
  442. package/dist/scripts/notify-fallback-delivery.js.map +1 -0
  443. package/dist/scripts/notify-fallback-watcher.js +136 -30
  444. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  445. package/dist/scripts/notify-hook/auto-nudge.d.ts +18 -9
  446. package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
  447. package/dist/scripts/notify-hook/auto-nudge.js +39 -13
  448. package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
  449. package/dist/scripts/notify-hook/managed-tmux.d.ts +23 -0
  450. package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
  451. package/dist/scripts/notify-hook/managed-tmux.js +122 -12
  452. package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
  453. package/dist/scripts/notify-hook/orchestration-intent.d.ts +7 -7
  454. package/dist/scripts/notify-hook/orchestration-intent.d.ts.map +1 -1
  455. package/dist/scripts/notify-hook/ralph-session-resume.d.ts +5 -2
  456. package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
  457. package/dist/scripts/notify-hook/ralph-session-resume.js +33 -37
  458. package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
  459. package/dist/scripts/notify-hook/state-io.d.ts +17 -0
  460. package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
  461. package/dist/scripts/notify-hook/state-io.js +73 -11
  462. package/dist/scripts/notify-hook/state-io.js.map +1 -1
  463. package/dist/scripts/notify-hook/team-dispatch.d.ts +1 -1
  464. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  465. package/dist/scripts/notify-hook/team-leader-nudge.d.ts +2 -2
  466. package/dist/scripts/notify-hook/team-tmux-guard.d.ts +4 -4
  467. package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -1
  468. package/dist/scripts/notify-hook/team-worker-stop.d.ts +1 -1
  469. package/dist/scripts/notify-hook/team-worker.d.ts +2 -2
  470. package/dist/scripts/notify-hook/tmux-injection.d.ts +8 -1
  471. package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
  472. package/dist/scripts/notify-hook/tmux-injection.js +25 -16
  473. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  474. package/dist/scripts/notify-hook/visual-verdict.d.ts +1 -1
  475. package/dist/scripts/notify-hook/visual-verdict.d.ts.map +1 -1
  476. package/dist/scripts/notify-hook/visual-verdict.js +15 -13
  477. package/dist/scripts/notify-hook/visual-verdict.js.map +1 -1
  478. package/dist/scripts/notify-hook.d.ts +24 -1
  479. package/dist/scripts/notify-hook.d.ts.map +1 -1
  480. package/dist/scripts/notify-hook.js +266 -90
  481. package/dist/scripts/notify-hook.js.map +1 -1
  482. package/dist/scripts/postinstall.js.map +1 -1
  483. package/dist/scripts/prompt-inventory.js.map +1 -1
  484. package/dist/scripts/smoke-packed-install.d.ts +879 -2
  485. package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
  486. package/dist/scripts/smoke-packed-install.js +1528 -7
  487. package/dist/scripts/smoke-packed-install.js.map +1 -1
  488. package/dist/scripts/sync-plugin-mirror.js.map +1 -1
  489. package/dist/scripts/test-reply-listener-live.js.map +1 -1
  490. package/dist/scripts/test-sparkshell.js.map +1 -1
  491. package/dist/scripts/verify-native-agents.js.map +1 -1
  492. package/dist/session-history/friction.js.map +1 -1
  493. package/dist/session-history/search.js.map +1 -1
  494. package/dist/sidecar/__tests__/boundary.test.js.map +1 -1
  495. package/dist/sidecar/collector.js.map +1 -1
  496. package/dist/sidecar/index.js.map +1 -1
  497. package/dist/sidecar/render.js.map +1 -1
  498. package/dist/sidecar/tmux.js.map +1 -1
  499. package/dist/state/__tests__/operations.test.js +64 -15
  500. package/dist/state/__tests__/operations.test.js.map +1 -1
  501. package/dist/state/__tests__/skill-active.test.js +19 -1
  502. package/dist/state/__tests__/skill-active.test.js.map +1 -1
  503. package/dist/state/__tests__/workflow-transition.test.js +61 -0
  504. package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
  505. package/dist/state/mode-state-context.js.map +1 -1
  506. package/dist/state/operations.d.ts +1 -1
  507. package/dist/state/operations.d.ts.map +1 -1
  508. package/dist/state/operations.js +49 -55
  509. package/dist/state/operations.js.map +1 -1
  510. package/dist/state/paths.d.ts +1 -1
  511. package/dist/state/paths.d.ts.map +1 -1
  512. package/dist/state/paths.js +1 -1
  513. package/dist/state/paths.js.map +1 -1
  514. package/dist/state/skill-active.d.ts +13 -1
  515. package/dist/state/skill-active.d.ts.map +1 -1
  516. package/dist/state/skill-active.js +43 -4
  517. package/dist/state/skill-active.js.map +1 -1
  518. package/dist/state/terminal-normalization.js.map +1 -1
  519. package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
  520. package/dist/state/workflow-transition-reconcile.js +20 -4
  521. package/dist/state/workflow-transition-reconcile.js.map +1 -1
  522. package/dist/state/workflow-transition.d.ts +1 -1
  523. package/dist/state/workflow-transition.d.ts.map +1 -1
  524. package/dist/state/workflow-transition.js.map +1 -1
  525. package/dist/subagents/__tests__/adapted-role-binding.test.d.ts +2 -0
  526. package/dist/subagents/__tests__/adapted-role-binding.test.d.ts.map +1 -0
  527. package/dist/subagents/__tests__/adapted-role-binding.test.js +988 -0
  528. package/dist/subagents/__tests__/adapted-role-binding.test.js.map +1 -0
  529. package/dist/subagents/__tests__/leader-bootstrap-3181.test.d.ts +2 -0
  530. package/dist/subagents/__tests__/leader-bootstrap-3181.test.d.ts.map +1 -0
  531. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js +273 -0
  532. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js.map +1 -0
  533. package/dist/subagents/__tests__/tracker.test.js +1550 -10
  534. package/dist/subagents/__tests__/tracker.test.js.map +1 -1
  535. package/dist/subagents/adapted-role-binding.d.ts +17 -0
  536. package/dist/subagents/adapted-role-binding.d.ts.map +1 -0
  537. package/dist/subagents/adapted-role-binding.js +75 -0
  538. package/dist/subagents/adapted-role-binding.js.map +1 -0
  539. package/dist/subagents/role-routing-marker.d.ts +10 -0
  540. package/dist/subagents/role-routing-marker.d.ts.map +1 -0
  541. package/dist/subagents/role-routing-marker.js +136 -0
  542. package/dist/subagents/role-routing-marker.js.map +1 -0
  543. package/dist/subagents/tracker.d.ts +172 -0
  544. package/dist/subagents/tracker.d.ts.map +1 -1
  545. package/dist/subagents/tracker.js +1077 -61
  546. package/dist/subagents/tracker.js.map +1 -1
  547. package/dist/team/__tests__/approved-execution.test.js.map +1 -1
  548. package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
  549. package/dist/team/__tests__/model-contract.test.js +231 -1
  550. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  551. package/dist/team/__tests__/role-router.test.js.map +1 -1
  552. package/dist/team/__tests__/runtime.test.js +401 -1
  553. package/dist/team/__tests__/runtime.test.js.map +1 -1
  554. package/dist/team/__tests__/scaling.test.js +181 -0
  555. package/dist/team/__tests__/scaling.test.js.map +1 -1
  556. package/dist/team/__tests__/state-root.test.js.map +1 -1
  557. package/dist/team/__tests__/tmux-session.test.js +434 -4
  558. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  559. package/dist/team/__tests__/tmux-test-fixture.js.map +1 -1
  560. package/dist/team/api-interop.d.ts +2 -2
  561. package/dist/team/api-interop.d.ts.map +1 -1
  562. package/dist/team/api-interop.js.map +1 -1
  563. package/dist/team/commit-hygiene.js.map +1 -1
  564. package/dist/team/contracts.d.ts +5 -5
  565. package/dist/team/contracts.d.ts.map +1 -1
  566. package/dist/team/delivery-log.js.map +1 -1
  567. package/dist/team/followup-planner.js.map +1 -1
  568. package/dist/team/goal-workflow.js.map +1 -1
  569. package/dist/team/idle-nudge.d.ts.map +1 -1
  570. package/dist/team/model-contract.d.ts +20 -1
  571. package/dist/team/model-contract.d.ts.map +1 -1
  572. package/dist/team/model-contract.js +267 -30
  573. package/dist/team/model-contract.js.map +1 -1
  574. package/dist/team/orchestrator.js.map +1 -1
  575. package/dist/team/pane-status.js.map +1 -1
  576. package/dist/team/phase-controller.js.map +1 -1
  577. package/dist/team/reminder-intents.d.ts +1 -1
  578. package/dist/team/reminder-intents.d.ts.map +1 -1
  579. package/dist/team/reminder-intents.js.map +1 -1
  580. package/dist/team/runtime-cli.js.map +1 -1
  581. package/dist/team/runtime.d.ts.map +1 -1
  582. package/dist/team/runtime.js +83 -52
  583. package/dist/team/runtime.js.map +1 -1
  584. package/dist/team/scaling.d.ts +9 -7
  585. package/dist/team/scaling.d.ts.map +1 -1
  586. package/dist/team/scaling.js +69 -28
  587. package/dist/team/scaling.js.map +1 -1
  588. package/dist/team/state/dispatch-lock.js.map +1 -1
  589. package/dist/team/state/dispatch.js.map +1 -1
  590. package/dist/team/state/events.js.map +1 -1
  591. package/dist/team/state/tasks.js.map +1 -1
  592. package/dist/team/state-root.js.map +1 -1
  593. package/dist/team/state.js.map +1 -1
  594. package/dist/team/team-identity.d.ts.map +1 -1
  595. package/dist/team/team-identity.js.map +1 -1
  596. package/dist/team/tmux-session.d.ts +2 -0
  597. package/dist/team/tmux-session.d.ts.map +1 -1
  598. package/dist/team/tmux-session.js +90 -42
  599. package/dist/team/tmux-session.js.map +1 -1
  600. package/dist/team/worker-bootstrap.js.map +1 -1
  601. package/dist/team/worktree.js.map +1 -1
  602. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  603. package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
  604. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  605. package/dist/ultragoal/artifacts.js +4 -1
  606. package/dist/ultragoal/artifacts.js.map +1 -1
  607. package/dist/url-reader/index.js.map +1 -1
  608. package/dist/utils/agents-model-table.js.map +1 -1
  609. package/dist/utils/package.js.map +1 -1
  610. package/dist/utils/paths.js.map +1 -1
  611. package/dist/utils/platform-command.js.map +1 -1
  612. package/dist/utils/repo-deps.js.map +1 -1
  613. package/dist/utils/version.js.map +1 -1
  614. package/dist/verification/__tests__/ci-rust-gates.test.js +1 -1
  615. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -1
  616. package/dist/verification/verifier.js.map +1 -1
  617. package/dist/visual/constants.d.ts +1 -1
  618. package/dist/visual/constants.d.ts.map +1 -1
  619. package/dist/vscode/__tests__/index.test.js.map +1 -1
  620. package/dist/vscode/index.js.map +1 -1
  621. package/dist/wiki/__tests__/cjk-tokenize.test.js.map +1 -1
  622. package/dist/wiki/__tests__/lint.test.js.map +1 -1
  623. package/dist/wiki/__tests__/query.test.js.map +1 -1
  624. package/dist/wiki/__tests__/storage.test.js.map +1 -1
  625. package/dist/wiki/__tests__/test-helpers.d.ts.map +1 -1
  626. package/dist/wiki/lint.js.map +1 -1
  627. package/dist/wiki/query.js.map +1 -1
  628. package/dist/wiki/storage.js.map +1 -1
  629. package/package.json +2 -2
  630. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  631. package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +10 -5
  632. package/plugins/oh-my-codex/skills/ralph/SKILL.md +4 -2
  633. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +5 -2
  634. package/skills/omx-setup/SKILL.md +10 -5
  635. package/skills/ralph/SKILL.md +4 -2
  636. package/skills/ralplan/SKILL.md +5 -2
  637. package/src/scripts/__tests__/codex-native-hook.test.ts +17522 -10630
  638. package/src/scripts/__tests__/fixtures/issue-3138-installed-smoke.ts +734 -0
  639. package/src/scripts/__tests__/notify-fallback-delivery.test.ts +177 -0
  640. package/src/scripts/__tests__/notify-state-io.test.ts +73 -0
  641. package/src/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.ts +215 -0
  642. package/src/scripts/__tests__/role-intent-durable-recovery-3181.test.ts +193 -0
  643. package/src/scripts/__tests__/smoke-packed-install.test.ts +991 -4
  644. package/src/scripts/codex-native-hook.ts +779 -159
  645. package/src/scripts/notify-fallback-delivery.ts +416 -0
  646. package/src/scripts/notify-fallback-watcher.ts +132 -40
  647. package/src/scripts/notify-hook/auto-nudge.ts +43 -12
  648. package/src/scripts/notify-hook/managed-tmux.ts +149 -12
  649. package/src/scripts/notify-hook/ralph-session-resume.ts +37 -36
  650. package/src/scripts/notify-hook/state-io.ts +100 -13
  651. package/src/scripts/notify-hook/tmux-injection.ts +38 -21
  652. package/src/scripts/notify-hook/visual-verdict.ts +22 -12
  653. package/src/scripts/notify-hook.ts +335 -90
  654. package/src/scripts/smoke-packed-install.ts +1829 -6
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { existsSync } from 'fs';
4
4
  import { appendFile, mkdir, open, readFile, readdir, rename, rm, stat, unlink, writeFile } from 'fs/promises';
5
- import { spawnSync } from 'child_process';
5
+ import { spawn, type ChildProcess } from 'child_process';
6
6
  import { dirname, join, resolve } from 'path';
7
7
  import { homedir } from 'os';
8
8
  import { StringDecoder } from 'string_decoder';
@@ -39,6 +39,7 @@ import { sameFilePath } from '../utils/paths.js';
39
39
  import { validateSessionId } from '../mcp/state-paths.js';
40
40
  import { TEAM_NAME_SAFE_PATTERN } from '../team/contracts.js';
41
41
  import { shouldContinueRun } from '../runtime/run-loop.js';
42
+ import { deliverNotifyFallback, compactNotifyFallbackDeliveries, NOTIFY_FALLBACK_LEASE_MS } from './notify-fallback-delivery.js';
42
43
 
43
44
  function argValue(name: string, fallback = ''): string {
44
45
  const idx = process.argv.indexOf(name);
@@ -132,15 +133,18 @@ const parentPid = Math.trunc(asNumber(argValue('--parent-pid', String(process.pp
132
133
  const startedAt = Date.now();
133
134
  const fileWindowMs = runOnce ? 15000 : 30000;
134
135
  const defaultMaxLifetimeMs = 6 * 60 * 60 * 1000;
135
- const maxLifetimeMs = runOnce
136
- ? 0
137
- : Math.max(
138
- pollMs,
139
- asNumber(
140
- argValue('--max-lifetime-ms', process.env.OMX_NOTIFY_FALLBACK_MAX_LIFETIME_MS || String(defaultMaxLifetimeMs)),
141
- defaultMaxLifetimeMs
142
- )
143
- );
136
+ const requestedMaxLifetimeMs = asNumber(
137
+ argValue('--max-lifetime-ms', process.env.OMX_NOTIFY_FALLBACK_MAX_LIFETIME_MS || String(defaultMaxLifetimeMs)),
138
+ defaultMaxLifetimeMs,
139
+ );
140
+ const configuredMaxLifetimeMs = Number.isSafeInteger(requestedMaxLifetimeMs) && requestedMaxLifetimeMs > 0
141
+ ? requestedMaxLifetimeMs
142
+ : defaultMaxLifetimeMs;
143
+ const maxLifetimeMs = runOnce ? 0 : Math.max(pollMs, configuredMaxLifetimeMs);
144
+ const authorityLifetimeMs = runOnce
145
+ ? NOTIFY_FALLBACK_LEASE_MS
146
+ : Math.min(Math.max(pollMs, configuredMaxLifetimeMs), 24 * 60 * 60 * 1000);
147
+ const authorityDeadlineAtMs = startedAt + authorityLifetimeMs;
144
148
 
145
149
  const runtimeRoot = resolve(process.env.OMX_ROOT || process.env.OMX_STATE_ROOT || cwd);
146
150
  const omxDir = join(runtimeRoot, '.omx');
@@ -284,6 +288,28 @@ const fileState = new Map<string, WatcherFileMeta>();
284
288
  const seenTurnKeys = new Set<string>();
285
289
  let stopping = false;
286
290
  let shutdownPromise: Promise<void> | null = null;
291
+ let activeNotifyHookChild: ChildProcess | null = null;
292
+ let activeNotifyHookClose: Promise<{ status: number | null; signal: string | null }> | null = null;
293
+ let activeNotifyHookTermination: Promise<boolean> | null = null;
294
+ let activeDeliveryPromise: Promise<unknown> | null = null;
295
+ async function terminateActiveNotifyHookChild(): Promise<boolean> {
296
+ if (activeNotifyHookTermination) return activeNotifyHookTermination;
297
+ const child = activeNotifyHookChild;
298
+ const close = activeNotifyHookClose;
299
+ if (!child || !close) return true;
300
+ activeNotifyHookTermination = (async () => {
301
+ child.kill('SIGTERM');
302
+ const termResult = await Promise.race([close.then(() => true), sleep(1_000).then(() => false)]);
303
+ if (termResult) return true;
304
+ child.kill('SIGKILL');
305
+ return Promise.race([close.then(() => true), sleep(2_000).then(() => false)]);
306
+ })();
307
+ try {
308
+ return await activeNotifyHookTermination;
309
+ } finally {
310
+ activeNotifyHookTermination = null;
311
+ }
312
+ }
287
313
  const dispatchTickMax = Math.max(1, asNumber(argValue('--dispatch-max-per-tick', '5'), 5));
288
314
  let dispatchDrainRuns = 0;
289
315
  let lastDispatchDrain: DispatchDrainState = {
@@ -1485,6 +1511,8 @@ async function requestShutdown(reason: string, signal: string | null = null): Pr
1485
1511
  if (shutdownPromise) return shutdownPromise;
1486
1512
  stopping = true;
1487
1513
  shutdownPromise = (async () => {
1514
+ await terminateActiveNotifyHookChild();
1515
+ await activeDeliveryPromise?.catch(() => undefined);
1488
1516
  await writeState({ stop_reason: reason, stop_signal: signal, stopping: true });
1489
1517
  await eventLog({
1490
1518
  type: 'watcher_stop',
@@ -1633,10 +1661,13 @@ function turnKey(threadId: string, turnId: string): string {
1633
1661
  return `${threadId || 'no-thread'}|${turnId || 'no-turn'}`;
1634
1662
  }
1635
1663
 
1636
- function buildNotifyPayload(threadId: string, turnId: string, lastMessage: string): Record<string, unknown> {
1664
+ async function buildNotifyPayload(threadId: string, turnId: string, lastMessage: string): Promise<Record<string, unknown>> {
1665
+ const session = await readSessionState(cwd).catch(() => null);
1666
+ const payloadSessionId = normalizeValidSessionId(session?.session_id) || threadId;
1637
1667
  return {
1638
1668
  type: 'agent-turn-complete',
1639
1669
  cwd,
1670
+ session_id: payloadSessionId,
1640
1671
  'thread-id': threadId,
1641
1672
  'turn-id': turnId,
1642
1673
  'input-messages': ['[notify-fallback] synthesized from rollout task_complete'],
@@ -1645,25 +1676,48 @@ function buildNotifyPayload(threadId: string, turnId: string, lastMessage: strin
1645
1676
  };
1646
1677
  }
1647
1678
 
1648
- async function invokeNotifyHook(payload: Record<string, unknown>, filePath: string): Promise<void> {
1649
- const result = spawnSync(process.execPath, [notifyScript, JSON.stringify(payload)], {
1650
- cwd,
1651
- encoding: 'utf-8',
1652
- env: {
1653
- ...process.env,
1654
- OMX_NOTIFY_HOOK_TRUSTED_MANAGED_CWD: cwd,
1655
- },
1656
- windowsHide: true,
1657
- });
1658
- const ok = result.status === 0;
1659
- await eventLog({
1660
- type: 'fallback_notify',
1661
- ok,
1662
- thread_id: (payload as Record<string, string>)['thread-id'],
1663
- turn_id: (payload as Record<string, string>)['turn-id'],
1664
- file: filePath,
1665
- reason: ok ? 'sent' : 'notify_hook_failed',
1666
- error: ok ? undefined : (result.stderr || result.stdout || '').trim().slice(0, 240),
1679
+ async function invokeNotifyHook(payload: Record<string, unknown>): Promise<{ spawned: boolean; childPid?: number; status?: number | null; signal?: string | null; error?: unknown; timedOut?: boolean; authorityDeadline?: boolean; terminationUnconfirmed?: boolean }> {
1680
+ return new Promise((resolveInvoke) => {
1681
+ let settled = false;
1682
+ let spawned = false;
1683
+ let timedOut = false;
1684
+ let deadlineTimedOut = false;
1685
+ const child = spawn(process.execPath, [notifyScript, JSON.stringify(payload)], {
1686
+ cwd,
1687
+ stdio: 'ignore',
1688
+ env: { ...process.env, OMX_NOTIFY_HOOK_TRUSTED_MANAGED_CWD: cwd },
1689
+ windowsHide: true,
1690
+ });
1691
+ const close = new Promise<{ status: number | null; signal: string | null }>((resolveClose) => {
1692
+ child.once('close', (status, signal) => resolveClose({ status, signal }));
1693
+ });
1694
+ activeNotifyHookChild = child;
1695
+ activeNotifyHookClose = close;
1696
+ const finish = (result: { spawned: boolean; childPid?: number; status?: number | null; signal?: string | null; error?: unknown; timedOut?: boolean; authorityDeadline?: boolean; terminationUnconfirmed?: boolean }) => {
1697
+ if (settled) return;
1698
+ settled = true;
1699
+ clearTimeout(hookTimeout);
1700
+ clearTimeout(deadlineTimeout);
1701
+ if (activeNotifyHookChild === child) {
1702
+ activeNotifyHookChild = null;
1703
+ activeNotifyHookClose = null;
1704
+ activeNotifyHookTermination = null;
1705
+ }
1706
+ resolveInvoke(result);
1707
+ };
1708
+ const stopForTimeout = async (isDeadline: boolean) => {
1709
+ if (settled) return;
1710
+ if (isDeadline) deadlineTimedOut = true;
1711
+ else timedOut = true;
1712
+ const confirmed = await terminateActiveNotifyHookChild();
1713
+ const closed = await Promise.race([close, sleep(2_000).then(() => null)]);
1714
+ finish({ spawned: true, childPid: child.pid, status: closed?.status ?? null, signal: closed?.signal ?? null, timedOut, authorityDeadline: deadlineTimedOut, terminationUnconfirmed: !confirmed || closed === null, error: isDeadline ? new Error('authority_deadline') : new Error('hook_timeout') });
1715
+ };
1716
+ const hookTimeout = setTimeout(() => { void stopForTimeout(false); }, 10_000);
1717
+ const deadlineTimeout = setTimeout(() => { void stopForTimeout(true); }, Math.max(0, authorityDeadlineAtMs - Date.now()));
1718
+ child.once('error', (error) => finish({ spawned, childPid: child.pid, error }));
1719
+ child.once('spawn', () => { spawned = true; });
1720
+ void close.then(({ status, signal }) => finish({ spawned, childPid: child.pid, status, signal }));
1667
1721
  });
1668
1722
  }
1669
1723
 
@@ -1677,23 +1731,58 @@ async function processLine(meta: WatcherFileMeta, line: string, filePath: string
1677
1731
 
1678
1732
  if (!parsed || parsed.type !== 'event_msg' || !parsed.payload) return;
1679
1733
  if ((parsed.payload as Record<string, unknown>).type !== 'task_complete') return;
1680
-
1681
1734
  const turnId = safeString((parsed.payload as Record<string, unknown>).turn_id);
1682
- if (!turnId) return;
1683
-
1684
1735
  const evtTs = Date.parse(safeString(parsed.timestamp));
1685
- if (Number.isFinite(evtTs) && evtTs < startedAt - 3000) return;
1686
-
1687
1736
  const key = turnKey(meta.threadId, turnId);
1737
+ if (!turnId || !Number.isFinite(evtTs) || evtTs > Date.now() + 5 * 60 * 1000 || evtTs < startedAt - 3000) {
1738
+ seenTurnKeys.add(key);
1739
+ return;
1740
+ }
1688
1741
  if (seenTurnKeys.has(key)) return;
1689
- seenTurnKeys.add(key);
1690
-
1691
- const payload = buildNotifyPayload(
1742
+ const payload = await buildNotifyPayload(
1692
1743
  meta.threadId,
1693
1744
  turnId,
1694
- safeString((parsed.payload as Record<string, unknown>).last_agent_message)
1745
+ safeString((parsed.payload as Record<string, unknown>).last_agent_message),
1695
1746
  );
1696
- await invokeNotifyHook(payload, filePath);
1747
+ let spawnResult: Awaited<ReturnType<typeof invokeNotifyHook>> | undefined;
1748
+ const deliveryPromise = deliverNotifyFallback({
1749
+ stateDir,
1750
+ threadId: meta.threadId,
1751
+ turnId,
1752
+ eventTimestampMs: evtTs,
1753
+ rolloutPath: filePath,
1754
+ watcherMode: runOnce ? 'once' : 'persistent',
1755
+ deadlineAtMs: authorityDeadlineAtMs,
1756
+ stopping: () => stopping,
1757
+ spawnHook: async () => {
1758
+ spawnResult = await invokeNotifyHook(payload);
1759
+ return spawnResult;
1760
+ },
1761
+ });
1762
+ activeDeliveryPromise = deliveryPromise;
1763
+ const result = await deliveryPromise.finally(() => {
1764
+ if (activeDeliveryPromise === deliveryPromise) activeDeliveryPromise = null;
1765
+ });
1766
+ if (result.kind === 'retry_eligible' && !stopping && Date.now() + 250 < authorityDeadlineAtMs) {
1767
+ await sleep(250);
1768
+ await processLine(meta, line, filePath);
1769
+ return;
1770
+ }
1771
+ seenTurnKeys.add(key);
1772
+ if (result.kind !== 'acquired_effect') {
1773
+ await eventLog({ type: 'fallback_notify_claim', thread_id: meta.threadId, turn_id: turnId, file: filePath, reason: 'reason' in result ? result.reason : result.kind, attempt: 'attempt' in result ? result.attempt : undefined });
1774
+ }
1775
+ if (spawnResult?.spawned) {
1776
+ await eventLog({
1777
+ type: 'fallback_notify',
1778
+ ok: spawnResult.status === 0,
1779
+ thread_id: meta.threadId,
1780
+ turn_id: turnId,
1781
+ file: filePath,
1782
+ reason: spawnResult.status === 0 ? 'sent' : 'notify_hook_failed',
1783
+ error: spawnResult.status === 0 ? undefined : String(spawnResult.error || '').slice(0, 240),
1784
+ });
1785
+ }
1697
1786
  }
1698
1787
 
1699
1788
  async function ensureTrackedFiles(): Promise<void> {
@@ -1916,6 +2005,9 @@ async function pumpTeamControlPlaneTick(): Promise<CycleActivitySummary> {
1916
2005
 
1917
2006
 
1918
2007
  async function runWatcherCycle(): Promise<number> {
2008
+ await compactNotifyFallbackDeliveries(stateDir).catch(async (error) => {
2009
+ await eventLog({ type: 'fallback_notify_claim', reason: 'compaction_io_skip', error: error instanceof Error ? error.message : String(error) });
2010
+ });
1919
2011
  let processedRolloutCount = 0;
1920
2012
  if (authorityOnly) {
1921
2013
  const authorityBackoff = await resolveAuthorityPrimaryWatcherHealth();
@@ -25,12 +25,17 @@ import { readAutoresearchCompletionStatus } from '../../autoresearch/skill-valid
25
25
  import { persistDeepInterviewModeState } from '../../hooks/keyword-detector.js';
26
26
  import {
27
27
  isManagedOmxSession,
28
+ isManagedOmxSessionAtPromptContext,
28
29
  resolveManagedCurrentPane,
30
+ resolveManagedCurrentPaneAtPromptContext,
29
31
  resolveManagedPaneFromAnchor,
32
+ resolveManagedPaneFromAnchorAtPromptContext,
30
33
  resolveManagedSessionPane,
34
+ resolveManagedSessionPaneAtPromptContext,
31
35
  resolveInvocationSessionId,
32
36
  verifyManagedPaneTarget,
33
37
  } from './managed-tmux.js';
38
+ import type { PromptMutationAuthorization, ResolvedPromptTurnContext } from '../../hooks/prompt-session-provenance.js';
34
39
 
35
40
  export const SKILL_ACTIVE_STATE_FILE = 'skill-active-state.json';
36
41
  export const DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS = ['yes', 'y', 'proceed', 'continue', 'ok', 'sure', 'go ahead', 'next i should'];
@@ -161,6 +166,7 @@ export function normalizeSkillActiveState(raw) {
161
166
  activated_at: safeString(raw.activated_at),
162
167
  updated_at: safeString(raw.updated_at),
163
168
  source: safeString(raw.source),
169
+ owner_codex_session_id: safeString(raw.owner_codex_session_id),
164
170
  input_lock: normalizeInputLock(raw.input_lock),
165
171
  };
166
172
  }
@@ -210,16 +216,28 @@ function cloneSkillActiveState(state) {
210
216
  };
211
217
  }
212
218
 
213
- export async function syncSkillStateFromTurn(stateDir, payload) {
219
+ export async function syncSkillStateFromTurn(stateDir, payload, invocationSessionIdOverride = '', authorization: PromptMutationAuthorization | null = null) {
214
220
  const lastMessage = safeString(payload['last-assistant-message'] || payload.last_assistant_message || '');
215
221
  const latestUserInput = latestUserInputFromPayload(payload);
216
- const invocationSessionId = resolveInvocationSessionId(payload);
222
+ const invocationSessionId = invocationSessionIdOverride || resolveInvocationSessionId(payload);
217
223
  let skillState = await loadSkillActiveState(stateDir, invocationSessionId);
218
224
  let releaseReason = null;
219
225
 
220
226
  if (!skillState) {
221
227
  return { invocationSessionId, skillState: null, releaseReason };
222
228
  }
229
+ if (authorization) {
230
+ const allowedOwners = Array.isArray(authorization.allowedOwnerCodexSessionIds)
231
+ ? authorization.allowedOwnerCodexSessionIds
232
+ : [];
233
+ const existingOwner = safeString(skillState.owner_codex_session_id).trim();
234
+ if (existingOwner && !allowedOwners.includes(existingOwner)) {
235
+ return { invocationSessionId, skillState: null, releaseReason: 'owner_conflict' };
236
+ }
237
+ if (authorization.ownerCodexSessionId) {
238
+ skillState.owner_codex_session_id = authorization.ownerCodexSessionId;
239
+ }
240
+ }
223
241
 
224
242
  const previousSkillState = cloneSkillActiveState(skillState);
225
243
  const previousPhase = normalizeSkillPhase(skillState.phase);
@@ -541,12 +559,16 @@ export async function capturePane(paneId, lines = 10) {
541
559
  }
542
560
  }
543
561
 
544
- export async function resolveNudgePaneTarget(stateDir: any, cwd = '', payload: any = undefined) {
562
+ export async function resolveNudgePaneTarget(stateDir: any, cwd = '', payload: any = undefined, context: ResolvedPromptTurnContext | null = null) {
545
563
  const allowTeamWorker = safeString(process.env.OMX_TEAM_WORKER || '').trim() !== '';
546
- const managedCurrentPane = await resolveManagedCurrentPane(cwd, payload, { allowTeamWorker });
564
+ const managedCurrentPane = context
565
+ ? await resolveManagedCurrentPaneAtPromptContext(cwd, context)
566
+ : await resolveManagedCurrentPane(cwd, payload, { allowTeamWorker });
547
567
  if (managedCurrentPane) return managedCurrentPane;
548
568
 
549
- const invocationSessionId = resolveInvocationSessionId(payload);
569
+ const invocationSessionId = context?.status === 'authorized'
570
+ ? context.authorization.targetSessionId
571
+ : resolveInvocationSessionId(payload);
550
572
  const scopedDirs = await getScopedStateDirsForCurrentSession(stateDir, invocationSessionId).catch(() => []);
551
573
  for (const dir of scopedDirs) {
552
574
  const files = await readdir(dir).catch(() => []);
@@ -558,9 +580,11 @@ export async function resolveNudgePaneTarget(stateDir: any, cwd = '', payload: a
558
580
  if (!state || !state.active || !state.tmux_pane_id) continue;
559
581
  const anchoredPane = safeString(state.tmux_pane_id).trim();
560
582
  if (!anchoredPane) continue;
561
- const managedPane = await resolveManagedPaneFromAnchor(anchoredPane, cwd, payload, { allowTeamWorker });
583
+ const managedPane = context
584
+ ? await resolveManagedPaneFromAnchorAtPromptContext(anchoredPane, cwd, context)
585
+ : await resolveManagedPaneFromAnchor(anchoredPane, cwd, payload, { allowTeamWorker });
562
586
  if (managedPane) return managedPane;
563
- if (allowTeamWorker) {
587
+ if (allowTeamWorker && !context) {
564
588
  const verdict = await verifyManagedPaneTarget(anchoredPane, cwd, payload, { allowTeamWorker });
565
589
  if (verdict.ok) return anchoredPane;
566
590
  }
@@ -570,10 +594,12 @@ export async function resolveNudgePaneTarget(stateDir: any, cwd = '', payload: a
570
594
  }
571
595
  }
572
596
 
573
- return await resolveManagedSessionPane(cwd, payload);
597
+ return context
598
+ ? await resolveManagedSessionPaneAtPromptContext(cwd, context)
599
+ : await resolveManagedSessionPane(cwd, payload);
574
600
  }
575
601
 
576
- export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
602
+ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload, context = null, syncResult = null }: { cwd: string; stateDir: string; logsDir: string; payload: any; context?: ResolvedPromptTurnContext | null; syncResult?: any }) {
577
603
  const config = await loadAutoNudgeConfig();
578
604
  const effectiveResponse = resolveEffectiveAutoNudgeResponse(config.response);
579
605
  if (!config.enabled) return;
@@ -587,7 +613,9 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
587
613
  }
588
614
 
589
615
  const sourceName = safeString(payload?.source || '');
590
- const managedSession = await isManagedOmxSession(cwd, payload, { allowTeamWorker: true });
616
+ const managedSession = context
617
+ ? await isManagedOmxSessionAtPromptContext(cwd, context, { allowTeamWorker: false })
618
+ : await isManagedOmxSession(cwd, payload, { allowTeamWorker: true });
591
619
  if (!managedSession) {
592
620
  if (sourceName === 'notify-fallback-watcher-stall') return;
593
621
  await logTmuxHookEvent(logsDir, {
@@ -599,7 +627,10 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
599
627
  }
600
628
 
601
629
  const lastMessage = safeString(payload['last-assistant-message'] || payload.last_assistant_message || '');
602
- const { invocationSessionId, skillState, releaseReason } = await syncSkillStateFromTurn(stateDir, payload);
630
+ const { invocationSessionId, skillState, releaseReason } = syncResult
631
+ || (context?.status === 'authorized'
632
+ ? { invocationSessionId: context.authorization.targetSessionId, skillState: null, releaseReason: null }
633
+ : await syncSkillStateFromTurn(stateDir, payload));
603
634
 
604
635
  try {
605
636
  const nudgeStatePath = await getScopedStatePath(stateDir, 'auto-nudge-state.json', invocationSessionId);
@@ -607,7 +638,7 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
607
638
  if (!nudgeState || typeof nudgeState !== 'object') {
608
639
  nudgeState = { nudgeCount: 0, lastNudgeAt: '', lastSignature: '', lastSemanticSignature: '' };
609
640
  }
610
- const paneId = await resolveNudgePaneTarget(stateDir, cwd, payload);
641
+ const paneId = await resolveNudgePaneTarget(stateDir, cwd, payload, context);
611
642
 
612
643
  let detected = detectStallPattern(lastMessage, config.patterns, skillState?.phase);
613
644
  let source = 'payload';
@@ -5,6 +5,8 @@ import { readSessionState, isSessionStale } from '../../hooks/session.js';
5
5
  import { runProcess } from './process-runner.js';
6
6
  import { safeString } from './utils.js';
7
7
  import { sameFilePath } from '../../utils/paths.js';
8
+ import type { ResolvedPromptTurnContext } from '../../hooks/prompt-session-provenance.js';
9
+
8
10
 
9
11
  const OMX_INSTANCE_OPTION = '@omx_instance_id';
10
12
  const OMX_PANE_INSTANCE_OPTION = '@omx_pane_instance_id';
@@ -82,20 +84,30 @@ function readCurrentTmuxSessionName(): string {
82
84
  }
83
85
  }
84
86
 
85
- async function readTmuxOption(targetValue: string, optionName: string, { pane = false } = {}): Promise<string> {
87
+ interface TmuxOptionProbe {
88
+ status: 'present' | 'absent' | 'error';
89
+ value: string;
90
+ }
91
+
92
+ async function probeTmuxOption(targetValue: string, optionName: string, { pane = false } = {}): Promise<TmuxOptionProbe> {
86
93
  const target = safeString(targetValue).trim();
87
- if (!target) return '';
94
+ if (!target) return { status: 'absent', value: '' };
88
95
  const args = ['show-option', '-qv'];
89
96
  if (pane) args.push('-p');
90
97
  args.push('-t', target, optionName);
91
98
  try {
92
99
  const result = await runProcess('tmux', args, 2000);
93
- return safeString(result.stdout).trim();
100
+ const value = safeString(result.stdout).trim();
101
+ return { status: value ? 'present' : 'absent', value };
94
102
  } catch {
95
- return '';
103
+ return { status: 'error', value: '' };
96
104
  }
97
105
  }
98
106
 
107
+ async function readTmuxOption(targetValue: string, optionName: string, { pane = false } = {}): Promise<string> {
108
+ return (await probeTmuxOption(targetValue, optionName, { pane })).value;
109
+ }
110
+
99
111
  async function readTmuxSessionInstanceId(sessionTarget: string): Promise<string> {
100
112
  return readTmuxOption(sessionTarget, OMX_INSTANCE_OPTION);
101
113
  }
@@ -104,6 +116,86 @@ async function readTmuxPaneInstanceId(paneTarget: string): Promise<string> {
104
116
  return readTmuxOption(paneTarget, OMX_PANE_INSTANCE_OPTION, { pane: true });
105
117
  }
106
118
 
119
+ export interface ActualTmuxInstanceEvidence {
120
+ paneTarget: string;
121
+ sessionName: string;
122
+ paneInstanceId: string;
123
+ sessionInstanceId: string;
124
+ instanceId: string;
125
+ source: 'none' | 'pane' | 'session';
126
+ paneTagStatus: 'not-requested' | 'present' | 'absent' | 'error';
127
+ }
128
+
129
+ export async function probeActualTmuxInstanceEvidence(paneTarget?: string): Promise<ActualTmuxInstanceEvidence> {
130
+ const resolvedPaneTarget = safeString(paneTarget ?? process.env.TMUX_PANE ?? '').trim();
131
+ let sessionName = '';
132
+ if (resolvedPaneTarget) {
133
+ try {
134
+ const result = await runProcess('tmux', ['display-message', '-p', '-t', resolvedPaneTarget, '#S'], 2000);
135
+ sessionName = safeString(result.stdout).trim();
136
+ } catch {
137
+ // A pane target without a session cannot provide session-tag evidence.
138
+ }
139
+ } else {
140
+ sessionName = readCurrentTmuxSessionName();
141
+ }
142
+
143
+ const paneProbe = resolvedPaneTarget
144
+ ? await probeTmuxOption(resolvedPaneTarget, OMX_PANE_INSTANCE_OPTION, { pane: true })
145
+ : { status: 'absent' as const, value: '' };
146
+ const paneTagStatus = resolvedPaneTarget ? paneProbe.status : 'not-requested';
147
+ if (paneProbe.status === 'present') {
148
+ return {
149
+ paneTarget: resolvedPaneTarget,
150
+ sessionName,
151
+ paneInstanceId: paneProbe.value,
152
+ sessionInstanceId: '',
153
+ instanceId: paneProbe.value,
154
+ source: 'pane',
155
+ paneTagStatus,
156
+ };
157
+ }
158
+ if (paneProbe.status === 'error') {
159
+ return {
160
+ paneTarget: resolvedPaneTarget,
161
+ sessionName,
162
+ paneInstanceId: '',
163
+ sessionInstanceId: '',
164
+ instanceId: '',
165
+ source: 'none',
166
+ paneTagStatus,
167
+ };
168
+ }
169
+
170
+ const sessionInstanceId = sessionName
171
+ ? await readTmuxSessionInstanceId(sessionName)
172
+ : '';
173
+ return {
174
+ paneTarget: resolvedPaneTarget,
175
+ sessionName,
176
+ paneInstanceId: '',
177
+ sessionInstanceId,
178
+ instanceId: sessionInstanceId,
179
+ source: sessionInstanceId ? 'session' : 'none',
180
+ paneTagStatus,
181
+ };
182
+ }
183
+
184
+ export function tmuxEvidenceBindsCandidate(
185
+ evidence: ActualTmuxInstanceEvidence,
186
+ candidateSessionId: string,
187
+ ): boolean {
188
+ const candidate = safeString(candidateSessionId).trim();
189
+ if (!candidate) return false;
190
+ if (evidence.paneTagStatus === 'present') {
191
+ return evidence.source === 'pane' && evidence.paneInstanceId === candidate;
192
+ }
193
+ return evidence.paneTagStatus === 'absent'
194
+ && evidence.source === 'session'
195
+ && evidence.sessionInstanceId === candidate;
196
+ }
197
+
198
+
107
199
  function warnPaneInstanceFallback(paneTarget: string): void {
108
200
  // Notify hooks run inside Codex foreground hook surfaces. Keep this
109
201
  // compatibility fallback silent; downstream tmux-hook events still record
@@ -218,9 +310,10 @@ export async function resolveManagedSessionContext(
218
310
  authoritativeSessionCwd,
219
311
  canonicalSessionId || invocationSessionId,
220
312
  );
221
- const currentTmuxSessionName = readCurrentTmuxSessionName();
222
- const currentTmuxPaneTarget = safeString(paneTarget || process.env.TMUX_PANE || '').trim();
223
- const currentTmuxPaneInstanceId = currentTmuxPaneTarget ? await readTmuxPaneInstanceId(currentTmuxPaneTarget) : '';
313
+ const evidence = await probeActualTmuxInstanceEvidence(paneTarget);
314
+ const currentTmuxSessionName = evidence.sessionName || readCurrentTmuxSessionName();
315
+ const currentTmuxPaneTarget = evidence.paneTarget;
316
+ const currentTmuxPaneInstanceId = evidence.paneInstanceId;
224
317
  if (currentTmuxPaneInstanceId && currentTmuxPaneInstanceId !== invocationSessionId) {
225
318
  return {
226
319
  managed: false,
@@ -248,7 +341,11 @@ export async function resolveManagedSessionContext(
248
341
  };
249
342
  }
250
343
 
251
- const currentTmuxInstanceId = currentTmuxSessionName ? await readTmuxSessionInstanceId(currentTmuxSessionName) : '';
344
+ const currentTmuxInstanceId = evidence.sessionName === currentTmuxSessionName
345
+ ? evidence.sessionInstanceId
346
+ : currentTmuxSessionName
347
+ ? await readTmuxSessionInstanceId(currentTmuxSessionName)
348
+ : '';
252
349
  if (currentTmuxInstanceId && currentTmuxInstanceId !== invocationSessionId) {
253
350
  return {
254
351
  managed: false,
@@ -359,6 +456,39 @@ export async function isManagedOmxSession(cwd: string, payload: any, options: {
359
456
  return context.managed === true;
360
457
  }
361
458
 
459
+ /**
460
+ * Leader-only adapter: tmux ownership is derived from the immutable provenance
461
+ * owner instead of re-reading payload or environment session identity.
462
+ */
463
+ export async function isManagedOmxSessionAtPromptContext(
464
+ cwd: string,
465
+ context: ResolvedPromptTurnContext,
466
+ options: { allowTeamWorker?: boolean } = {},
467
+ ): Promise<boolean> {
468
+ if (context.status !== 'authorized') return false;
469
+ return isManagedOmxSession(cwd, { session_id: context.authorization.ownerCodexSessionId }, options);
470
+ }
471
+
472
+ export async function verifyManagedPaneTargetAtPromptContext(paneId: string, cwd: string, context: ResolvedPromptTurnContext): Promise<any> {
473
+ if (context.status !== 'authorized') return { ok: false, reason: 'prompt_context_unauthorized', paneTarget: safeString(paneId).trim() };
474
+ return verifyManagedPaneTarget(paneId, cwd, { session_id: context.authorization.ownerCodexSessionId }, { allowTeamWorker: false });
475
+ }
476
+
477
+ export async function resolveManagedCurrentPaneAtPromptContext(cwd: string, context: ResolvedPromptTurnContext): Promise<string> {
478
+ if (context.status !== 'authorized') return '';
479
+ return resolveManagedCurrentPane(cwd, { session_id: context.authorization.ownerCodexSessionId }, { allowTeamWorker: false });
480
+ }
481
+
482
+ export async function resolveManagedSessionPaneAtPromptContext(cwd: string, context: ResolvedPromptTurnContext): Promise<string> {
483
+ if (context.status !== 'authorized') return '';
484
+ return resolveManagedSessionPane(cwd, { session_id: context.authorization.ownerCodexSessionId });
485
+ }
486
+
487
+ export async function resolveManagedPaneFromAnchorAtPromptContext(anchorPane: string, cwd: string, context: ResolvedPromptTurnContext): Promise<string> {
488
+ if (context.status !== 'authorized') return '';
489
+ return resolveManagedPaneFromAnchor(anchorPane, cwd, { session_id: context.authorization.ownerCodexSessionId }, { allowTeamWorker: false });
490
+ }
491
+
362
492
  export async function verifyManagedPaneTarget(paneId: string, cwd: string, payload: any, { allowTeamWorker = true } = {}): Promise<any> {
363
493
  const paneTarget = safeString(paneId).trim();
364
494
  if (!paneTarget) {
@@ -380,13 +510,20 @@ export async function verifyManagedPaneTarget(paneId: string, cwd: string, paylo
380
510
  }
381
511
 
382
512
  try {
383
- const sessionResult = await runProcess('tmux', ['display-message', '-p', '-t', paneTarget, '#S'], 2000);
384
- const paneSessionName = safeString(sessionResult.stdout).trim();
513
+ let paneSessionName = safeString(managedContext.currentTmuxSessionName).trim();
514
+ if (!paneSessionName) {
515
+ const sessionResult = await runProcess('tmux', ['display-message', '-p', '-t', paneTarget, '#S'], 2000);
516
+ paneSessionName = safeString(sessionResult.stdout).trim();
517
+ }
385
518
  if (!paneSessionName) {
386
519
  return { ok: false, reason: 'pane_session_missing', paneTarget, managedContext };
387
520
  }
388
- const paneInstanceId = await readTmuxPaneInstanceId(paneTarget);
389
- const sessionInstanceId = paneInstanceId ? '' : await readTmuxSessionInstanceId(paneSessionName);
521
+ const paneInstanceId = safeString(managedContext.currentTmuxPaneInstanceId).trim()
522
+ || await readTmuxPaneInstanceId(paneTarget);
523
+ const sessionInstanceId = paneInstanceId
524
+ ? ''
525
+ : safeString(managedContext.currentTmuxInstanceId).trim()
526
+ || await readTmuxSessionInstanceId(paneSessionName);
390
527
  if (paneInstanceId && paneInstanceId !== managedContext.invocationSessionId) {
391
528
  return { ok: false, reason: 'pane_instance_mismatch', paneTarget, paneSessionName, paneInstanceId, managedContext };
392
529
  }