oh-my-codex 0.20.1 → 0.20.3

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 (791) hide show
  1. package/Cargo.lock +7 -6
  2. package/Cargo.toml +1 -1
  3. package/README.md +36 -1
  4. package/crates/omx-runtime/Cargo.toml +1 -0
  5. package/crates/omx-runtime/src/main.rs +25 -2
  6. package/crates/omx-runtime/tests/execution.rs +219 -0
  7. package/crates/omx-runtime-core/src/dispatch.rs +96 -10
  8. package/crates/omx-runtime-core/src/engine.rs +839 -29
  9. package/crates/omx-runtime-core/src/lib.rs +8 -0
  10. package/dist/adapt/__tests__/hermes.test.js.map +1 -1
  11. package/dist/adapt/contracts.d.ts.map +1 -1
  12. package/dist/agents/__tests__/definitions.test.js +81 -0
  13. package/dist/agents/__tests__/definitions.test.js.map +1 -1
  14. package/dist/agents/__tests__/native-config.test.js +25 -0
  15. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  16. package/dist/agents/native-config.d.ts +2 -1
  17. package/dist/agents/native-config.d.ts.map +1 -1
  18. package/dist/agents/native-config.js.map +1 -1
  19. package/dist/auth/__tests__/hotswap.test.d.ts +2 -0
  20. package/dist/auth/__tests__/hotswap.test.d.ts.map +1 -0
  21. package/dist/auth/__tests__/hotswap.test.js +183 -0
  22. package/dist/auth/__tests__/hotswap.test.js.map +1 -0
  23. package/dist/auth/hotswap.d.ts +6 -0
  24. package/dist/auth/hotswap.d.ts.map +1 -1
  25. package/dist/auth/hotswap.js +102 -19
  26. package/dist/auth/hotswap.js.map +1 -1
  27. package/dist/auth/paths.js.map +1 -1
  28. package/dist/auth/storage.js.map +1 -1
  29. package/dist/autopilot/__tests__/ralplan-gate.test.js +5 -5
  30. package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -1
  31. package/dist/autopilot/completion-gate.js.map +1 -1
  32. package/dist/autopilot/fsm.d.ts +1 -1
  33. package/dist/autopilot/fsm.d.ts.map +1 -1
  34. package/dist/autoresearch/goal.js.map +1 -1
  35. package/dist/autoresearch/runtime.js.map +1 -1
  36. package/dist/capabilities/lockfile.js.map +1 -1
  37. package/dist/catalog/reader.js.map +1 -1
  38. package/dist/catalog/skill-mirror.js.map +1 -1
  39. package/dist/cli/__tests__/adapt-help.test.js.map +1 -1
  40. package/dist/cli/__tests__/agents-init.test.js.map +1 -1
  41. package/dist/cli/__tests__/agents.test.js.map +1 -1
  42. package/dist/cli/__tests__/api.test.js.map +1 -1
  43. package/dist/cli/__tests__/ask.test.js.map +1 -1
  44. package/dist/cli/__tests__/auth.test.js +60 -6
  45. package/dist/cli/__tests__/auth.test.js.map +1 -1
  46. package/dist/cli/__tests__/autoresearch-guided.test.js.map +1 -1
  47. package/dist/cli/__tests__/autoresearch.test.js.map +1 -1
  48. package/dist/cli/__tests__/capabilities.test.js.map +1 -1
  49. package/dist/cli/__tests__/codex-plugin-layout.test.js +80 -0
  50. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  51. package/dist/cli/__tests__/doctor-context-window-warning.test.js.map +1 -1
  52. package/dist/cli/__tests__/doctor-invalid-config.test.js +47 -4
  53. package/dist/cli/__tests__/doctor-invalid-config.test.js.map +1 -1
  54. package/dist/cli/__tests__/doctor-team.test.js.map +1 -1
  55. package/dist/cli/__tests__/doctor-warning-copy.test.js +752 -15
  56. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  57. package/dist/cli/__tests__/exec.test.js +136 -0
  58. package/dist/cli/__tests__/exec.test.js.map +1 -1
  59. package/dist/cli/__tests__/imagegen-continuation.test.js.map +1 -1
  60. package/dist/cli/__tests__/index.test.js +473 -14
  61. package/dist/cli/__tests__/index.test.js.map +1 -1
  62. package/dist/cli/__tests__/launch-fallback.test.js +336 -4
  63. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  64. package/dist/cli/__tests__/mcp-parity.test.js +87 -12
  65. package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
  66. package/dist/cli/__tests__/native-hook-claim-journal.test.d.ts +2 -0
  67. package/dist/cli/__tests__/native-hook-claim-journal.test.d.ts.map +1 -0
  68. package/dist/cli/__tests__/native-hook-claim-journal.test.js +206 -0
  69. package/dist/cli/__tests__/native-hook-claim-journal.test.js.map +1 -0
  70. package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
  71. package/dist/cli/__tests__/question.test.js.map +1 -1
  72. package/dist/cli/__tests__/ralph-deslop-contract.test.js.map +1 -1
  73. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +6 -0
  74. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
  75. package/dist/cli/__tests__/ralph-prd-deep-interview.test.js.map +1 -1
  76. package/dist/cli/__tests__/ralph-prd-smoke.test.js.map +1 -1
  77. package/dist/cli/__tests__/ralph.test.js +8 -3
  78. package/dist/cli/__tests__/ralph.test.js.map +1 -1
  79. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.d.ts +2 -0
  80. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.d.ts.map +1 -0
  81. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js +72 -0
  82. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js.map +1 -0
  83. package/dist/cli/__tests__/ralplan.test.d.ts +2 -0
  84. package/dist/cli/__tests__/ralplan.test.d.ts.map +1 -0
  85. package/dist/cli/__tests__/ralplan.test.js +55 -0
  86. package/dist/cli/__tests__/ralplan.test.js.map +1 -0
  87. package/dist/cli/__tests__/resume.test.js +17 -11
  88. package/dist/cli/__tests__/resume.test.js.map +1 -1
  89. package/dist/cli/__tests__/session-scoped-runtime.test.js +25 -0
  90. package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -1
  91. package/dist/cli/__tests__/session-search-help.test.js +25 -1
  92. package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
  93. package/dist/cli/__tests__/session-search.test.js.map +1 -1
  94. package/dist/cli/__tests__/setup-agents-overwrite.test.js +79 -0
  95. package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
  96. package/dist/cli/__tests__/setup-gh-star.test.js.map +1 -1
  97. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +77 -3
  98. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
  99. package/dist/cli/__tests__/setup-hooks-trust-e2e.test.d.ts +2 -0
  100. package/dist/cli/__tests__/setup-hooks-trust-e2e.test.d.ts.map +1 -0
  101. package/dist/cli/__tests__/setup-hooks-trust-e2e.test.js +285 -0
  102. package/dist/cli/__tests__/setup-hooks-trust-e2e.test.js.map +1 -0
  103. package/dist/cli/__tests__/setup-install-mode.test.js +2579 -294
  104. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  105. package/dist/cli/__tests__/setup-preferences.test.d.ts +2 -0
  106. package/dist/cli/__tests__/setup-preferences.test.d.ts.map +1 -0
  107. package/dist/cli/__tests__/setup-preferences.test.js +79 -0
  108. package/dist/cli/__tests__/setup-preferences.test.js.map +1 -0
  109. package/dist/cli/__tests__/setup-refresh.test.js +33 -2
  110. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  111. package/dist/cli/__tests__/setup-scope.test.js +46 -3
  112. package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
  113. package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -1
  114. package/dist/cli/__tests__/state.test.js +37 -0
  115. package/dist/cli/__tests__/state.test.js.map +1 -1
  116. package/dist/cli/__tests__/team.test.js +105 -7
  117. package/dist/cli/__tests__/team.test.js.map +1 -1
  118. package/dist/cli/__tests__/ultragoal.test.js +61 -1
  119. package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
  120. package/dist/cli/__tests__/uninstall.test.js +1817 -24
  121. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  122. package/dist/cli/__tests__/update.test.js +58 -0
  123. package/dist/cli/__tests__/update.test.js.map +1 -1
  124. package/dist/cli/__tests__/url.test.js.map +1 -1
  125. package/dist/cli/__tests__/windows-popup-loop-contract.test.js +2 -1
  126. package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
  127. package/dist/cli/adapt.js.map +1 -1
  128. package/dist/cli/agents-init.js.map +1 -1
  129. package/dist/cli/agents.js.map +1 -1
  130. package/dist/cli/api.js.map +1 -1
  131. package/dist/cli/ask.d.ts +1 -1
  132. package/dist/cli/ask.d.ts.map +1 -1
  133. package/dist/cli/ask.js.map +1 -1
  134. package/dist/cli/auth.js.map +1 -1
  135. package/dist/cli/autoresearch-guided.js.map +1 -1
  136. package/dist/cli/autoresearch-intake.js.map +1 -1
  137. package/dist/cli/capabilities.js.map +1 -1
  138. package/dist/cli/cleanup.js.map +1 -1
  139. package/dist/cli/codex-feature-probe.js.map +1 -1
  140. package/dist/cli/codex-home.js.map +1 -1
  141. package/dist/cli/doctor.d.ts +21 -0
  142. package/dist/cli/doctor.d.ts.map +1 -1
  143. package/dist/cli/doctor.js +607 -130
  144. package/dist/cli/doctor.js.map +1 -1
  145. package/dist/cli/explore.js.map +1 -1
  146. package/dist/cli/index.d.ts +14 -3
  147. package/dist/cli/index.d.ts.map +1 -1
  148. package/dist/cli/index.js +245 -57
  149. package/dist/cli/index.js.map +1 -1
  150. package/dist/cli/mcp-parity.js +2 -2
  151. package/dist/cli/mcp-parity.js.map +1 -1
  152. package/dist/cli/mcp-serve.js.map +1 -1
  153. package/dist/cli/mission.js.map +1 -1
  154. package/dist/cli/native-assets.js.map +1 -1
  155. package/dist/cli/native-hook-claim-journal.d.ts +29 -0
  156. package/dist/cli/native-hook-claim-journal.d.ts.map +1 -0
  157. package/dist/cli/native-hook-claim-journal.js +252 -0
  158. package/dist/cli/native-hook-claim-journal.js.map +1 -0
  159. package/dist/cli/omx.js.map +1 -1
  160. package/dist/cli/plugin-marketplace.js.map +1 -1
  161. package/dist/cli/project-runtime-codex-homes.js.map +1 -1
  162. package/dist/cli/question.js.map +1 -1
  163. package/dist/cli/ralph.d.ts.map +1 -1
  164. package/dist/cli/ralph.js +3 -2
  165. package/dist/cli/ralph.js.map +1 -1
  166. package/dist/cli/ralplan.d.ts +10 -0
  167. package/dist/cli/ralplan.d.ts.map +1 -0
  168. package/dist/cli/ralplan.js +110 -0
  169. package/dist/cli/ralplan.js.map +1 -0
  170. package/dist/cli/session-search.d.ts +5 -0
  171. package/dist/cli/session-search.d.ts.map +1 -1
  172. package/dist/cli/session-search.js +87 -0
  173. package/dist/cli/session-search.js.map +1 -1
  174. package/dist/cli/setup-preferences.d.ts +11 -0
  175. package/dist/cli/setup-preferences.d.ts.map +1 -1
  176. package/dist/cli/setup-preferences.js +32 -0
  177. package/dist/cli/setup-preferences.js.map +1 -1
  178. package/dist/cli/setup.d.ts +58 -0
  179. package/dist/cli/setup.d.ts.map +1 -1
  180. package/dist/cli/setup.js +1450 -398
  181. package/dist/cli/setup.js.map +1 -1
  182. package/dist/cli/sparkshell.js.map +1 -1
  183. package/dist/cli/star-prompt.js.map +1 -1
  184. package/dist/cli/state.d.ts.map +1 -1
  185. package/dist/cli/state.js +2 -1
  186. package/dist/cli/state.js.map +1 -1
  187. package/dist/cli/team.js.map +1 -1
  188. package/dist/cli/ultragoal.d.ts +5 -1
  189. package/dist/cli/ultragoal.d.ts.map +1 -1
  190. package/dist/cli/ultragoal.js +34 -2
  191. package/dist/cli/ultragoal.js.map +1 -1
  192. package/dist/cli/uninstall.d.ts +17 -0
  193. package/dist/cli/uninstall.d.ts.map +1 -1
  194. package/dist/cli/uninstall.js +986 -95
  195. package/dist/cli/uninstall.js.map +1 -1
  196. package/dist/cli/update.d.ts.map +1 -1
  197. package/dist/cli/update.js +8 -1
  198. package/dist/cli/update.js.map +1 -1
  199. package/dist/cli/url.js.map +1 -1
  200. package/dist/compat/__tests__/doctor-contract.test.js +5 -1
  201. package/dist/compat/__tests__/doctor-contract.test.js.map +1 -1
  202. package/dist/compat/__tests__/rust-runtime-compat.test.js +1 -1
  203. package/dist/compat/__tests__/rust-runtime-compat.test.js.map +1 -1
  204. package/dist/config/__tests__/codex-hooks.test.js +1287 -11
  205. package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
  206. package/dist/config/__tests__/generator-idempotent.test.js +1179 -32
  207. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  208. package/dist/config/__tests__/generator-notify.test.js +6 -1
  209. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  210. package/dist/config/__tests__/models.test.js +67 -3
  211. package/dist/config/__tests__/models.test.js.map +1 -1
  212. package/dist/config/codex-feature-flags.d.ts.map +1 -1
  213. package/dist/config/codex-feature-flags.js.map +1 -1
  214. package/dist/config/codex-hooks.d.ts +124 -1
  215. package/dist/config/codex-hooks.d.ts.map +1 -1
  216. package/dist/config/codex-hooks.js +2142 -265
  217. package/dist/config/codex-hooks.js.map +1 -1
  218. package/dist/config/commit-lore-guard.js.map +1 -1
  219. package/dist/config/generator.d.ts +23 -34
  220. package/dist/config/generator.d.ts.map +1 -1
  221. package/dist/config/generator.js +1480 -246
  222. package/dist/config/generator.js.map +1 -1
  223. package/dist/config/mcp-registry.js.map +1 -1
  224. package/dist/config/models.d.ts +14 -4
  225. package/dist/config/models.d.ts.map +1 -1
  226. package/dist/config/models.js +15 -1
  227. package/dist/config/models.js.map +1 -1
  228. package/dist/config/omx-first-party-mcp.js.map +1 -1
  229. package/dist/config/team-mode.d.ts.map +1 -1
  230. package/dist/document-refresh/__tests__/enforcer.test.js.map +1 -1
  231. package/dist/document-refresh/enforcer.js.map +1 -1
  232. package/dist/exec/followup.js.map +1 -1
  233. package/dist/goal-workflows/artifacts.js.map +1 -1
  234. package/dist/hooks/__tests__/agents-overlay.test.js +7 -4
  235. package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
  236. package/dist/hooks/__tests__/analyze-routing-contract.test.js.map +1 -1
  237. package/dist/hooks/__tests__/analyze-skill-contract.test.js.map +1 -1
  238. package/dist/hooks/__tests__/anti-slop-workflow.test.js.map +1 -1
  239. package/dist/hooks/__tests__/autopilot-skill-contract.test.js +9 -3
  240. package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
  241. package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +1 -1
  242. package/dist/hooks/__tests__/consensus-execution-handoff.test.js.map +1 -1
  243. package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
  244. package/dist/hooks/__tests__/design-skill.test.js.map +1 -1
  245. package/dist/hooks/__tests__/keyword-detector.test.js +1376 -6
  246. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  247. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +252 -543
  248. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  249. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +38 -4
  250. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  251. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +765 -10
  252. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  253. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +2 -0
  254. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
  255. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +142 -1
  256. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
  257. package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -1
  258. package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js +48 -2
  259. package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js.map +1 -1
  260. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +61 -44
  261. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -1
  262. package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
  263. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js +3 -2
  264. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js.map +1 -1
  265. package/dist/hooks/__tests__/notify-hook-session-scope.test.js +243 -4
  266. package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
  267. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +531 -12
  268. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  269. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +163 -24
  270. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  271. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +482 -32
  272. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  273. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +68 -1
  274. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  275. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +7 -1
  276. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -1
  277. package/dist/hooks/__tests__/notify-hook-visual-verdict.test.js.map +1 -1
  278. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +43 -4
  279. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  280. package/dist/hooks/__tests__/openclaw-setup-contract.test.js.map +1 -1
  281. package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -1
  282. package/dist/hooks/__tests__/prometheus-strict-contract.test.js.map +1 -1
  283. package/dist/hooks/__tests__/prompt-guidance-fragments.test.js.map +1 -1
  284. package/dist/hooks/__tests__/prompt-guidance-test-helpers.js.map +1 -1
  285. package/dist/hooks/__tests__/prompt-session-provenance.test.d.ts +2 -0
  286. package/dist/hooks/__tests__/prompt-session-provenance.test.d.ts.map +1 -0
  287. package/dist/hooks/__tests__/prompt-session-provenance.test.js +82 -0
  288. package/dist/hooks/__tests__/prompt-session-provenance.test.js.map +1 -0
  289. package/dist/hooks/__tests__/session.test.js +878 -11
  290. package/dist/hooks/__tests__/session.test.js.map +1 -1
  291. package/dist/hooks/__tests__/skill-catalog-hygiene.test.js.map +1 -1
  292. package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js.map +1 -1
  293. package/dist/hooks/__tests__/visual-ralph-skill.test.js.map +1 -1
  294. package/dist/hooks/__tests__/visual-verdict-loop.test.js.map +1 -1
  295. package/dist/hooks/agents-overlay.js +5 -5
  296. package/dist/hooks/agents-overlay.js.map +1 -1
  297. package/dist/hooks/code-simplifier/index.js.map +1 -1
  298. package/dist/hooks/explore-routing.js.map +1 -1
  299. package/dist/hooks/extensibility/dispatcher.js.map +1 -1
  300. package/dist/hooks/extensibility/events.js.map +1 -1
  301. package/dist/hooks/extensibility/loader.js.map +1 -1
  302. package/dist/hooks/extensibility/plugin-runner-stdin.js.map +1 -1
  303. package/dist/hooks/extensibility/sdk/logging.js.map +1 -1
  304. package/dist/hooks/keyword-detector.d.ts +33 -7
  305. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  306. package/dist/hooks/keyword-detector.js +2228 -119
  307. package/dist/hooks/keyword-detector.js.map +1 -1
  308. package/dist/hooks/keyword-registry.d.ts +12 -0
  309. package/dist/hooks/keyword-registry.d.ts.map +1 -1
  310. package/dist/hooks/keyword-registry.js +41 -0
  311. package/dist/hooks/keyword-registry.js.map +1 -1
  312. package/dist/hooks/prompt-session-provenance.d.ts +87 -0
  313. package/dist/hooks/prompt-session-provenance.d.ts.map +1 -0
  314. package/dist/hooks/prompt-session-provenance.js +180 -0
  315. package/dist/hooks/prompt-session-provenance.js.map +1 -0
  316. package/dist/hooks/session.d.ts +163 -34
  317. package/dist/hooks/session.d.ts.map +1 -1
  318. package/dist/hooks/session.js +1395 -317
  319. package/dist/hooks/session.js.map +1 -1
  320. package/dist/hooks/task-size-detector.js.map +1 -1
  321. package/dist/hud/__tests__/state.test.js.map +1 -1
  322. package/dist/hud/authority.js.map +1 -1
  323. package/dist/hud/constants.js.map +1 -1
  324. package/dist/hud/index.js.map +1 -1
  325. package/dist/hud/reconcile.js.map +1 -1
  326. package/dist/hud/render.js.map +1 -1
  327. package/dist/hud/state.js.map +1 -1
  328. package/dist/hud/tmux.js.map +1 -1
  329. package/dist/leader/__tests__/contract.test.js +153 -1
  330. package/dist/leader/__tests__/contract.test.js.map +1 -1
  331. package/dist/leader/contract.d.ts +42 -5
  332. package/dist/leader/contract.d.ts.map +1 -1
  333. package/dist/leader/contract.js +184 -3
  334. package/dist/leader/contract.js.map +1 -1
  335. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  336. package/dist/mcp/__tests__/code-intel-server.test.js +31 -3
  337. package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -1
  338. package/dist/mcp/__tests__/server-lifecycle.test.js +15 -2
  339. package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
  340. package/dist/mcp/__tests__/state-paths.test.js +98 -1
  341. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  342. package/dist/mcp/__tests__/wiki-server.test.js +18 -0
  343. package/dist/mcp/__tests__/wiki-server.test.js.map +1 -1
  344. package/dist/mcp/bootstrap.js.map +1 -1
  345. package/dist/mcp/code-intel-server.d.ts +58 -58
  346. package/dist/mcp/code-intel-server.d.ts.map +1 -1
  347. package/dist/mcp/code-intel-server.js +13 -3
  348. package/dist/mcp/code-intel-server.js.map +1 -1
  349. package/dist/mcp/hermes-bridge.js.map +1 -1
  350. package/dist/mcp/hermes-server.d.ts +70 -70
  351. package/dist/mcp/hermes-server.d.ts.map +1 -1
  352. package/dist/mcp/lifecycle-telemetry.js.map +1 -1
  353. package/dist/mcp/memory-server.d.ts +34 -34
  354. package/dist/mcp/memory-server.d.ts.map +1 -1
  355. package/dist/mcp/memory-server.js.map +1 -1
  356. package/dist/mcp/state-paths.d.ts +14 -0
  357. package/dist/mcp/state-paths.d.ts.map +1 -1
  358. package/dist/mcp/state-paths.js +96 -20
  359. package/dist/mcp/state-paths.js.map +1 -1
  360. package/dist/mcp/state-server.d.ts +47 -47
  361. package/dist/mcp/state-server.d.ts.map +1 -1
  362. package/dist/mcp/trace-server.d.ts +4 -4
  363. package/dist/mcp/trace-server.d.ts.map +1 -1
  364. package/dist/mcp/trace-server.js.map +1 -1
  365. package/dist/mcp/wiki-server.d.ts +34 -23
  366. package/dist/mcp/wiki-server.d.ts.map +1 -1
  367. package/dist/mcp/wiki-server.js +9 -2
  368. package/dist/mcp/wiki-server.js.map +1 -1
  369. package/dist/modes/__tests__/base-session-scope.test.js +53 -1
  370. package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
  371. package/dist/modes/__tests__/base-tmux-pane.test.js +4 -4
  372. package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
  373. package/dist/modes/base.d.ts.map +1 -1
  374. package/dist/modes/base.js +5 -5
  375. package/dist/modes/base.js.map +1 -1
  376. package/dist/notifications/__tests__/lifecycle-dedupe.test.js.map +1 -1
  377. package/dist/notifications/__tests__/reply-listener.test.js.map +1 -1
  378. package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js +177 -85
  379. package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js.map +1 -1
  380. package/dist/notifications/__tests__/session-registry.test.js.map +1 -1
  381. package/dist/notifications/__tests__/template-engine.test.js.map +1 -1
  382. package/dist/notifications/__tests__/verbosity.test.js.map +1 -1
  383. package/dist/notifications/http-client.js.map +1 -1
  384. package/dist/notifications/index.d.ts +4 -1
  385. package/dist/notifications/index.d.ts.map +1 -1
  386. package/dist/notifications/index.js +3 -9
  387. package/dist/notifications/index.js.map +1 -1
  388. package/dist/notifications/lifecycle-dedupe.js.map +1 -1
  389. package/dist/notifications/reply-listener.d.ts.map +1 -1
  390. package/dist/notifications/reply-listener.js.map +1 -1
  391. package/dist/notifications/session-registry.js.map +1 -1
  392. package/dist/notifications/session-status.js.map +1 -1
  393. package/dist/notifications/temp-contract.d.ts.map +1 -1
  394. package/dist/notifications/temp-contract.js +4 -0
  395. package/dist/notifications/temp-contract.js.map +1 -1
  396. package/dist/notifications/tmux-detector.js.map +1 -1
  397. package/dist/notifications/tmux.js.map +1 -1
  398. package/dist/openclaw/config.js.map +1 -1
  399. package/dist/openclaw/dispatcher.js.map +1 -1
  400. package/dist/pipeline/__tests__/orchestrator.test.js +4 -4
  401. package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
  402. package/dist/pipeline/__tests__/stages.test.js +16 -13
  403. package/dist/pipeline/__tests__/stages.test.js.map +1 -1
  404. package/dist/pipeline/stages/code-review.js.map +1 -1
  405. package/dist/pipeline/stages/ralph-verify.js.map +1 -1
  406. package/dist/pipeline/stages/ralplan.js.map +1 -1
  407. package/dist/pipeline/stages/team-exec.js.map +1 -1
  408. package/dist/pipeline/stages/ultragoal.js.map +1 -1
  409. package/dist/pipeline/stages/ultraqa.js.map +1 -1
  410. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js.map +1 -1
  411. package/dist/planning/artifact-names.js.map +1 -1
  412. package/dist/planning/artifacts.js.map +1 -1
  413. package/dist/question/__tests__/state.test.js.map +1 -1
  414. package/dist/question/__tests__/ui.test.js.map +1 -1
  415. package/dist/question/autopilot-wait.js.map +1 -1
  416. package/dist/question/client.d.ts.map +1 -1
  417. package/dist/question/client.js.map +1 -1
  418. package/dist/question/deep-interview.js.map +1 -1
  419. package/dist/question/events.js.map +1 -1
  420. package/dist/question/renderer.js.map +1 -1
  421. package/dist/question/state.d.ts.map +1 -1
  422. package/dist/question/state.js.map +1 -1
  423. package/dist/question/ui.js.map +1 -1
  424. package/dist/ralph/contract.d.ts +1 -1
  425. package/dist/ralph/contract.d.ts.map +1 -1
  426. package/dist/ralplan/__tests__/consensus-gate.test.js +527 -8
  427. package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
  428. package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts +2 -0
  429. package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts.map +1 -0
  430. package/dist/ralplan/__tests__/documented-leader-preflight.test.js +46 -0
  431. package/dist/ralplan/__tests__/documented-leader-preflight.test.js.map +1 -0
  432. package/dist/ralplan/__tests__/runtime.test.js +116 -14
  433. package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
  434. package/dist/ralplan/consensus-gate.d.ts +3 -3
  435. package/dist/ralplan/consensus-gate.d.ts.map +1 -1
  436. package/dist/ralplan/consensus-gate.js +173 -70
  437. package/dist/ralplan/consensus-gate.js.map +1 -1
  438. package/dist/ralplan/documented-leader-preflight.d.ts +34 -0
  439. package/dist/ralplan/documented-leader-preflight.d.ts.map +1 -0
  440. package/dist/ralplan/documented-leader-preflight.js +58 -0
  441. package/dist/ralplan/documented-leader-preflight.js.map +1 -0
  442. package/dist/ralplan/runtime.d.ts +3 -2
  443. package/dist/ralplan/runtime.d.ts.map +1 -1
  444. package/dist/ralplan/runtime.js +12 -9
  445. package/dist/ralplan/runtime.js.map +1 -1
  446. package/dist/runtime/__tests__/bridge.test.js +42 -1
  447. package/dist/runtime/__tests__/bridge.test.js.map +1 -1
  448. package/dist/runtime/bridge.d.ts +12 -0
  449. package/dist/runtime/bridge.d.ts.map +1 -1
  450. package/dist/runtime/bridge.js +52 -1
  451. package/dist/runtime/bridge.js.map +1 -1
  452. package/dist/runtime/process-tree.js.map +1 -1
  453. package/dist/runtime/run-loop.js.map +1 -1
  454. package/dist/runtime/run-outcome.d.ts +3 -3
  455. package/dist/runtime/run-outcome.d.ts.map +1 -1
  456. package/dist/runtime/run-outcome.js.map +1 -1
  457. package/dist/runtime/run-state.js.map +1 -1
  458. package/dist/scripts/__tests__/codex-native-hook.test.js +6657 -995
  459. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  460. package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.d.ts +2 -0
  461. package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.d.ts.map +1 -0
  462. package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.js +634 -0
  463. package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.js.map +1 -0
  464. package/dist/scripts/__tests__/generate-release-body.test.js.map +1 -1
  465. package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +1 -1
  466. package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -1
  467. package/dist/scripts/__tests__/notify-fallback-delivery.test.d.ts +2 -0
  468. package/dist/scripts/__tests__/notify-fallback-delivery.test.d.ts.map +1 -0
  469. package/dist/scripts/__tests__/notify-fallback-delivery.test.js +174 -0
  470. package/dist/scripts/__tests__/notify-fallback-delivery.test.js.map +1 -0
  471. package/dist/scripts/__tests__/notify-state-io.test.js +57 -1
  472. package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -1
  473. package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts +2 -0
  474. package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts.map +1 -0
  475. package/dist/scripts/__tests__/reasoning-artifact-contract.test.js +108 -0
  476. package/dist/scripts/__tests__/reasoning-artifact-contract.test.js.map +1 -0
  477. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.d.ts +2 -0
  478. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.d.ts.map +1 -0
  479. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js +78 -0
  480. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js.map +1 -0
  481. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.d.ts +2 -0
  482. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.d.ts.map +1 -0
  483. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js +55 -0
  484. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js.map +1 -0
  485. package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
  486. package/dist/scripts/__tests__/smoke-packed-install.test.js +1100 -4
  487. package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
  488. package/dist/scripts/__tests__/test-reply-listener-live.test.js.map +1 -1
  489. package/dist/scripts/build-api.js.map +1 -1
  490. package/dist/scripts/build-explore-harness.js.map +1 -1
  491. package/dist/scripts/build-sparkshell.js.map +1 -1
  492. package/dist/scripts/cleanup-explore-harness.js.map +1 -1
  493. package/dist/scripts/codex-execution-surface.js.map +1 -1
  494. package/dist/scripts/codex-native-hook.d.ts +4 -1
  495. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  496. package/dist/scripts/codex-native-hook.js +11577 -1184
  497. package/dist/scripts/codex-native-hook.js.map +1 -1
  498. package/dist/scripts/generate-native-release-manifest.js.map +1 -1
  499. package/dist/scripts/generate-release-body.js.map +1 -1
  500. package/dist/scripts/hook-payload-guard.d.ts.map +1 -1
  501. package/dist/scripts/hook-payload-guard.js.map +1 -1
  502. package/dist/scripts/notify-fallback-delivery.d.ts +48 -0
  503. package/dist/scripts/notify-fallback-delivery.d.ts.map +1 -0
  504. package/dist/scripts/notify-fallback-delivery.js +419 -0
  505. package/dist/scripts/notify-fallback-delivery.js.map +1 -0
  506. package/dist/scripts/notify-fallback-watcher.js +218 -138
  507. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  508. package/dist/scripts/notify-hook/auto-nudge.d.ts +18 -9
  509. package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
  510. package/dist/scripts/notify-hook/auto-nudge.js +112 -15
  511. package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
  512. package/dist/scripts/notify-hook/managed-tmux.d.ts +23 -0
  513. package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
  514. package/dist/scripts/notify-hook/managed-tmux.js +122 -12
  515. package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
  516. package/dist/scripts/notify-hook/orchestration-intent.d.ts +7 -7
  517. package/dist/scripts/notify-hook/orchestration-intent.d.ts.map +1 -1
  518. package/dist/scripts/notify-hook/ralph-session-resume.d.ts +5 -2
  519. package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
  520. package/dist/scripts/notify-hook/ralph-session-resume.js +33 -37
  521. package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
  522. package/dist/scripts/notify-hook/state-io.d.ts +17 -0
  523. package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
  524. package/dist/scripts/notify-hook/state-io.js +73 -11
  525. package/dist/scripts/notify-hook/state-io.js.map +1 -1
  526. package/dist/scripts/notify-hook/team-dispatch.d.ts +10 -1
  527. package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
  528. package/dist/scripts/notify-hook/team-dispatch.js +234 -79
  529. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  530. package/dist/scripts/notify-hook/team-leader-nudge.d.ts +2 -2
  531. package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
  532. package/dist/scripts/notify-hook/team-leader-nudge.js +39 -13
  533. package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
  534. package/dist/scripts/notify-hook/team-tmux-guard.d.ts +16 -8
  535. package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
  536. package/dist/scripts/notify-hook/team-tmux-guard.js +365 -44
  537. package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
  538. package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -1
  539. package/dist/scripts/notify-hook/team-worker-stop.d.ts +1 -1
  540. package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -1
  541. package/dist/scripts/notify-hook/team-worker-stop.js +19 -18
  542. package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -1
  543. package/dist/scripts/notify-hook/team-worker.d.ts +5 -2
  544. package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
  545. package/dist/scripts/notify-hook/team-worker.js +37 -28
  546. package/dist/scripts/notify-hook/team-worker.js.map +1 -1
  547. package/dist/scripts/notify-hook/tmux-injection.d.ts +8 -1
  548. package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
  549. package/dist/scripts/notify-hook/tmux-injection.js +53 -18
  550. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  551. package/dist/scripts/notify-hook/visual-verdict.d.ts +1 -1
  552. package/dist/scripts/notify-hook/visual-verdict.d.ts.map +1 -1
  553. package/dist/scripts/notify-hook/visual-verdict.js +15 -13
  554. package/dist/scripts/notify-hook/visual-verdict.js.map +1 -1
  555. package/dist/scripts/notify-hook.d.ts +24 -1
  556. package/dist/scripts/notify-hook.d.ts.map +1 -1
  557. package/dist/scripts/notify-hook.js +267 -90
  558. package/dist/scripts/notify-hook.js.map +1 -1
  559. package/dist/scripts/postinstall.js.map +1 -1
  560. package/dist/scripts/prompt-inventory.js.map +1 -1
  561. package/dist/scripts/smoke-packed-install.d.ts +927 -5
  562. package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
  563. package/dist/scripts/smoke-packed-install.js +4317 -13
  564. package/dist/scripts/smoke-packed-install.js.map +1 -1
  565. package/dist/scripts/sync-plugin-mirror.js.map +1 -1
  566. package/dist/scripts/test-reply-listener-live.js.map +1 -1
  567. package/dist/scripts/test-sparkshell.js.map +1 -1
  568. package/dist/scripts/verify-native-agents.js.map +1 -1
  569. package/dist/session-history/friction.js.map +1 -1
  570. package/dist/session-history/search.js.map +1 -1
  571. package/dist/sidecar/__tests__/boundary.test.js.map +1 -1
  572. package/dist/sidecar/collector.js.map +1 -1
  573. package/dist/sidecar/index.js.map +1 -1
  574. package/dist/sidecar/render.js.map +1 -1
  575. package/dist/sidecar/tmux.js.map +1 -1
  576. package/dist/state/__tests__/mode-state-context.test.js +54 -0
  577. package/dist/state/__tests__/mode-state-context.test.js.map +1 -1
  578. package/dist/state/__tests__/operations.test.js +66 -15
  579. package/dist/state/__tests__/operations.test.js.map +1 -1
  580. package/dist/state/__tests__/skill-active.test.js +19 -1
  581. package/dist/state/__tests__/skill-active.test.js.map +1 -1
  582. package/dist/state/__tests__/workflow-transition.test.js +61 -0
  583. package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
  584. package/dist/state/mode-state-context.d.ts +5 -0
  585. package/dist/state/mode-state-context.d.ts.map +1 -1
  586. package/dist/state/mode-state-context.js +59 -0
  587. package/dist/state/mode-state-context.js.map +1 -1
  588. package/dist/state/operations.d.ts +1 -1
  589. package/dist/state/operations.d.ts.map +1 -1
  590. package/dist/state/operations.js +49 -55
  591. package/dist/state/operations.js.map +1 -1
  592. package/dist/state/paths.d.ts +1 -1
  593. package/dist/state/paths.d.ts.map +1 -1
  594. package/dist/state/paths.js +1 -1
  595. package/dist/state/paths.js.map +1 -1
  596. package/dist/state/skill-active.d.ts +13 -1
  597. package/dist/state/skill-active.d.ts.map +1 -1
  598. package/dist/state/skill-active.js +43 -4
  599. package/dist/state/skill-active.js.map +1 -1
  600. package/dist/state/terminal-normalization.js.map +1 -1
  601. package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
  602. package/dist/state/workflow-transition-reconcile.js +20 -4
  603. package/dist/state/workflow-transition-reconcile.js.map +1 -1
  604. package/dist/state/workflow-transition.d.ts +1 -1
  605. package/dist/state/workflow-transition.d.ts.map +1 -1
  606. package/dist/state/workflow-transition.js.map +1 -1
  607. package/dist/subagents/__tests__/leader-bootstrap-3181.test.d.ts +2 -0
  608. package/dist/subagents/__tests__/leader-bootstrap-3181.test.d.ts.map +1 -0
  609. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js +52 -0
  610. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js.map +1 -0
  611. package/dist/subagents/__tests__/tracker.test.js +1550 -10
  612. package/dist/subagents/__tests__/tracker.test.js.map +1 -1
  613. package/dist/subagents/role-routing-marker.d.ts +10 -0
  614. package/dist/subagents/role-routing-marker.d.ts.map +1 -0
  615. package/dist/subagents/role-routing-marker.js +136 -0
  616. package/dist/subagents/role-routing-marker.js.map +1 -0
  617. package/dist/subagents/tracker.d.ts +91 -0
  618. package/dist/subagents/tracker.d.ts.map +1 -1
  619. package/dist/subagents/tracker.js +806 -62
  620. package/dist/subagents/tracker.js.map +1 -1
  621. package/dist/team/__tests__/api-interop.test.js +91 -1
  622. package/dist/team/__tests__/api-interop.test.js.map +1 -1
  623. package/dist/team/__tests__/approved-execution.test.js.map +1 -1
  624. package/dist/team/__tests__/delivery-e2e-smoke.test.js +52 -10
  625. package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
  626. package/dist/team/__tests__/idle-nudge.test.js +45 -15
  627. package/dist/team/__tests__/idle-nudge.test.js.map +1 -1
  628. package/dist/team/__tests__/mcp-comm.test.js +93 -27
  629. package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
  630. package/dist/team/__tests__/model-contract.test.js +341 -4
  631. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  632. package/dist/team/__tests__/role-router.test.js.map +1 -1
  633. package/dist/team/__tests__/runtime-cli.test.js +9 -0
  634. package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
  635. package/dist/team/__tests__/runtime.test.js +3624 -355
  636. package/dist/team/__tests__/runtime.test.js.map +1 -1
  637. package/dist/team/__tests__/scaling.test.js +2516 -118
  638. package/dist/team/__tests__/scaling.test.js.map +1 -1
  639. package/dist/team/__tests__/state-root.test.js.map +1 -1
  640. package/dist/team/__tests__/state.test.js +804 -36
  641. package/dist/team/__tests__/state.test.js.map +1 -1
  642. package/dist/team/__tests__/team-ops-contract.test.js +6 -0
  643. package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
  644. package/dist/team/__tests__/tmux-session.test.js +3664 -969
  645. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  646. package/dist/team/__tests__/tmux-test-fixture.js.map +1 -1
  647. package/dist/team/__tests__/worker-runtime-identity.test.js +38 -2
  648. package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
  649. package/dist/team/__tests__/worktree.test.js +6 -0
  650. package/dist/team/__tests__/worktree.test.js.map +1 -1
  651. package/dist/team/api-interop.d.ts +2 -2
  652. package/dist/team/api-interop.d.ts.map +1 -1
  653. package/dist/team/api-interop.js +15 -9
  654. package/dist/team/api-interop.js.map +1 -1
  655. package/dist/team/commit-hygiene.js.map +1 -1
  656. package/dist/team/contracts.d.ts +5 -5
  657. package/dist/team/contracts.d.ts.map +1 -1
  658. package/dist/team/delivery-log.js.map +1 -1
  659. package/dist/team/exact-pane.d.ts +23 -0
  660. package/dist/team/exact-pane.d.ts.map +1 -0
  661. package/dist/team/exact-pane.js +133 -0
  662. package/dist/team/exact-pane.js.map +1 -0
  663. package/dist/team/followup-planner.js.map +1 -1
  664. package/dist/team/goal-workflow.js.map +1 -1
  665. package/dist/team/idle-nudge.d.ts +12 -1
  666. package/dist/team/idle-nudge.d.ts.map +1 -1
  667. package/dist/team/idle-nudge.js +41 -14
  668. package/dist/team/idle-nudge.js.map +1 -1
  669. package/dist/team/model-contract.d.ts +18 -2
  670. package/dist/team/model-contract.d.ts.map +1 -1
  671. package/dist/team/model-contract.js +314 -35
  672. package/dist/team/model-contract.js.map +1 -1
  673. package/dist/team/orchestrator.js.map +1 -1
  674. package/dist/team/pane-status.js.map +1 -1
  675. package/dist/team/phase-controller.js.map +1 -1
  676. package/dist/team/reminder-intents.d.ts +1 -1
  677. package/dist/team/reminder-intents.d.ts.map +1 -1
  678. package/dist/team/reminder-intents.js.map +1 -1
  679. package/dist/team/runtime-cli.js.map +1 -1
  680. package/dist/team/runtime.d.ts +1 -0
  681. package/dist/team/runtime.d.ts.map +1 -1
  682. package/dist/team/runtime.js +1326 -231
  683. package/dist/team/runtime.js.map +1 -1
  684. package/dist/team/scaling.d.ts +22 -8
  685. package/dist/team/scaling.d.ts.map +1 -1
  686. package/dist/team/scaling.js +1463 -376
  687. package/dist/team/scaling.js.map +1 -1
  688. package/dist/team/state/dispatch-lock.js.map +1 -1
  689. package/dist/team/state/dispatch.d.ts.map +1 -1
  690. package/dist/team/state/dispatch.js +26 -8
  691. package/dist/team/state/dispatch.js.map +1 -1
  692. package/dist/team/state/events.js.map +1 -1
  693. package/dist/team/state/locks.d.ts.map +1 -1
  694. package/dist/team/state/locks.js +61 -13
  695. package/dist/team/state/locks.js.map +1 -1
  696. package/dist/team/state/tasks.d.ts.map +1 -1
  697. package/dist/team/state/tasks.js +4 -3
  698. package/dist/team/state/tasks.js.map +1 -1
  699. package/dist/team/state-root.js.map +1 -1
  700. package/dist/team/state.d.ts +67 -1
  701. package/dist/team/state.d.ts.map +1 -1
  702. package/dist/team/state.js +636 -129
  703. package/dist/team/state.js.map +1 -1
  704. package/dist/team/team-identity.d.ts.map +1 -1
  705. package/dist/team/team-identity.js.map +1 -1
  706. package/dist/team/team-ops.d.ts +5 -0
  707. package/dist/team/team-ops.d.ts.map +1 -1
  708. package/dist/team/team-ops.js +4 -0
  709. package/dist/team/team-ops.js.map +1 -1
  710. package/dist/team/tmux-session.d.ts +125 -23
  711. package/dist/team/tmux-session.d.ts.map +1 -1
  712. package/dist/team/tmux-session.js +1340 -333
  713. package/dist/team/tmux-session.js.map +1 -1
  714. package/dist/team/worker-bootstrap.js.map +1 -1
  715. package/dist/team/worktree.d.ts.map +1 -1
  716. package/dist/team/worktree.js +4 -0
  717. package/dist/team/worktree.js.map +1 -1
  718. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  719. package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
  720. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  721. package/dist/ultragoal/artifacts.js +4 -1
  722. package/dist/ultragoal/artifacts.js.map +1 -1
  723. package/dist/url-reader/index.js.map +1 -1
  724. package/dist/utils/__tests__/file-durability.test.d.ts +2 -0
  725. package/dist/utils/__tests__/file-durability.test.d.ts.map +1 -0
  726. package/dist/utils/__tests__/file-durability.test.js +57 -0
  727. package/dist/utils/__tests__/file-durability.test.js.map +1 -0
  728. package/dist/utils/agents-model-table.js.map +1 -1
  729. package/dist/utils/file-durability.d.ts +15 -0
  730. package/dist/utils/file-durability.d.ts.map +1 -0
  731. package/dist/utils/file-durability.js +37 -0
  732. package/dist/utils/file-durability.js.map +1 -0
  733. package/dist/utils/package.js.map +1 -1
  734. package/dist/utils/paths.js.map +1 -1
  735. package/dist/utils/platform-command.js.map +1 -1
  736. package/dist/utils/repo-deps.js.map +1 -1
  737. package/dist/utils/version.js.map +1 -1
  738. package/dist/verification/__tests__/ci-rust-gates.test.js +1 -1
  739. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +3 -0
  740. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -1
  741. package/dist/verification/verifier.js.map +1 -1
  742. package/dist/visual/constants.d.ts +1 -1
  743. package/dist/visual/constants.d.ts.map +1 -1
  744. package/dist/vscode/__tests__/index.test.js.map +1 -1
  745. package/dist/vscode/index.js.map +1 -1
  746. package/dist/wiki/__tests__/cjk-tokenize.test.js.map +1 -1
  747. package/dist/wiki/__tests__/lint.test.js.map +1 -1
  748. package/dist/wiki/__tests__/query.test.js.map +1 -1
  749. package/dist/wiki/__tests__/storage.test.js.map +1 -1
  750. package/dist/wiki/__tests__/test-helpers.d.ts.map +1 -1
  751. package/dist/wiki/lint.d.ts +4 -1
  752. package/dist/wiki/lint.d.ts.map +1 -1
  753. package/dist/wiki/lint.js +3 -2
  754. package/dist/wiki/lint.js.map +1 -1
  755. package/dist/wiki/query.js.map +1 -1
  756. package/dist/wiki/storage.js.map +1 -1
  757. package/package.json +2 -2
  758. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  759. package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +24 -0
  760. package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +10 -5
  761. package/plugins/oh-my-codex/skills/ralph/SKILL.md +6 -2
  762. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +6 -2
  763. package/plugins/oh-my-codex/skills/team/SKILL.md +13 -9
  764. package/skills/omx-setup/SKILL.md +10 -5
  765. package/skills/ralph/SKILL.md +6 -2
  766. package/skills/ralplan/SKILL.md +6 -2
  767. package/skills/team/SKILL.md +13 -9
  768. package/src/scripts/__tests__/codex-native-hook.test.ts +20048 -10827
  769. package/src/scripts/__tests__/fixtures/issue-3138-installed-smoke.ts +734 -0
  770. package/src/scripts/__tests__/notify-fallback-delivery.test.ts +177 -0
  771. package/src/scripts/__tests__/notify-state-io.test.ts +73 -0
  772. package/src/scripts/__tests__/reasoning-artifact-contract.test.ts +129 -0
  773. package/src/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.ts +78 -0
  774. package/src/scripts/__tests__/role-intent-durable-recovery-3181.test.ts +60 -0
  775. package/src/scripts/__tests__/smoke-packed-install.test.ts +1309 -4
  776. package/src/scripts/codex-native-hook.ts +11429 -1163
  777. package/src/scripts/notify-fallback-delivery.ts +416 -0
  778. package/src/scripts/notify-fallback-watcher.ts +216 -155
  779. package/src/scripts/notify-hook/auto-nudge.ts +113 -14
  780. package/src/scripts/notify-hook/managed-tmux.ts +149 -12
  781. package/src/scripts/notify-hook/ralph-session-resume.ts +37 -36
  782. package/src/scripts/notify-hook/state-io.ts +100 -13
  783. package/src/scripts/notify-hook/team-dispatch.ts +242 -75
  784. package/src/scripts/notify-hook/team-leader-nudge.ts +40 -18
  785. package/src/scripts/notify-hook/team-tmux-guard.ts +366 -39
  786. package/src/scripts/notify-hook/team-worker-stop.ts +20 -16
  787. package/src/scripts/notify-hook/team-worker.ts +39 -26
  788. package/src/scripts/notify-hook/tmux-injection.ts +66 -23
  789. package/src/scripts/notify-hook/visual-verdict.ts +22 -12
  790. package/src/scripts/notify-hook.ts +336 -90
  791. package/src/scripts/smoke-packed-install.ts +5154 -149
package/Cargo.lock CHANGED
@@ -32,7 +32,7 @@ checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
32
32
 
33
33
  [[package]]
34
34
  name = "omx-api"
35
- version = "0.20.1"
35
+ version = "0.20.3"
36
36
  dependencies = [
37
37
  "serde",
38
38
  "serde_json",
@@ -40,14 +40,14 @@ dependencies = [
40
40
 
41
41
  [[package]]
42
42
  name = "omx-explore-harness"
43
- version = "0.20.1"
43
+ version = "0.20.3"
44
44
  dependencies = [
45
45
  "libc",
46
46
  ]
47
47
 
48
48
  [[package]]
49
49
  name = "omx-mux"
50
- version = "0.20.1"
50
+ version = "0.20.3"
51
51
  dependencies = [
52
52
  "serde",
53
53
  "serde_json",
@@ -55,8 +55,9 @@ dependencies = [
55
55
 
56
56
  [[package]]
57
57
  name = "omx-runtime"
58
- version = "0.20.1"
58
+ version = "0.20.3"
59
59
  dependencies = [
60
+ "fs2",
60
61
  "omx-mux",
61
62
  "omx-runtime-core",
62
63
  "serde_json",
@@ -64,7 +65,7 @@ dependencies = [
64
65
 
65
66
  [[package]]
66
67
  name = "omx-runtime-core"
67
- version = "0.20.1"
68
+ version = "0.20.3"
68
69
  dependencies = [
69
70
  "fs2",
70
71
  "serde",
@@ -73,7 +74,7 @@ dependencies = [
73
74
 
74
75
  [[package]]
75
76
  name = "omx-sparkshell"
76
- version = "0.20.1"
77
+ version = "0.20.3"
77
78
  dependencies = [
78
79
  "omx-mux",
79
80
  ]
package/Cargo.toml CHANGED
@@ -11,7 +11,7 @@ resolver = "2"
11
11
 
12
12
  [workspace.package]
13
13
 
14
- version = "0.20.1"
14
+ version = "0.20.3"
15
15
 
16
16
  edition = "2021"
17
17
  rust-version = "1.73"
package/README.md CHANGED
@@ -92,6 +92,15 @@ Choose the setup scope deliberately:
92
92
  - Use `omx setup --scope user` for user-level Codex setup when you are not preparing the current directory as an OMX project.
93
93
  - Avoid running project-scoped setup from a broad home directory or operating hub unless that directory is intentionally the project under review. A home-level `AGENTS.md` often contains global safety and routing rules; keep project-specific OMX runtime guidance in the real repository instead.
94
94
 
95
+ ### Persisting an explicit AGENTS merge policy
96
+
97
+ `omx setup --merge-agents`, `omx setup --no-merge-agents`, and `omx setup --clear-merge-agents-policy` are the only policy selectors; use their bare forms (not `=value` spellings). Repeating an identical selector is harmless, but mixing set and clear choices fails before setup changes anything. An explicit set overrides a saved policy. A successful explicit set records `mergeAgents: true` or `false` in the current working root's `./.omx/setup-scope.json`, even when setup scope is `user`; it never becomes a global user preference or leaks to another root. Later `omx update` replays a valid matching policy for both immediate and deferred refreshes.
98
+
99
+ `true` takes the existing merge branch. `false` only suppresses that branch: it does not promise preservation, replacement, or any new safety mode, so the existing prompt, skip, managed-refresh, plugin-default, and force behavior still applies. A matching-scope review retains the policy while unrelated settings change. Reset or a scope change removes the inherited policy unless the same setup run explicitly sets `true` or `false`; clear always removes the policy and cannot be combined with a set selector. Malformed, unknown, nonboolean, or wrong-scope saved data is ignored safely.
100
+
101
+ `--force` is independent and transient: it is neither recorded nor replayed, and does not override an explicit merge policy. Setup atomically commits explicit set or clear intent only after all setup work succeeds, including when active-session or plugin-symlink safeguards skip the current `AGENTS.md` write, so the next refresh can honor the requested policy. This does not make merge the default or revive the rejected #2892 merge-by-default approach. Older OMX versions safely ignore the field, but may erase it when rewriting their known setup preferences.
102
+
103
+
95
104
  **Codex plugin install note:** this repo also ships an official Codex plugin layout at `plugins/oh-my-codex` with marketplace metadata in `.agents/plugins/marketplace.json`. That plugin bundles the mirrored skill surface plus plugin-scoped companion metadata for official Codex lifecycle hooks, optional MCP compatibility servers, and apps. It is still **not** a replacement for the global `oh-my-codex` CLI plus scoped setup: plugin-scoped hooks launch the installed `omx` CLI, legacy setup mode installs native agents and prompts, and plugin setup mode relies on plugin discovery for bundled skills while archiving/removing legacy OMX-managed prompts/native-agent TOMLs so stale role files cannot shadow plugin behavior. Plugin mode still needs a persistent scope `AGENTS.md` (`~/.codex/AGENTS.md` for user setup or `./AGENTS.md` for project setup) as the durable orchestration guidance layer; session-scoped AGENTS files only compose that durable guidance with runtime overlays and are not a replacement.
96
105
 
97
106
  Then work normally inside Codex:
@@ -156,6 +165,32 @@ created and recovered. `--worktree` also moves the launch into a separate git
156
165
  checkout, which is the safer default when using `--madmax`. Replace
157
166
  `feat/task` with a branch-like name for the task.
158
167
 
168
+ ### Concurrent standard conversations
169
+
170
+ A standard launch owns one writable session pointer under its selected `OMX_ROOT`. A second ordinary `omx` launch from the same checkout therefore fails closed instead of sharing or silently changing that root. Give each additional conversation an explicit, distinct root:
171
+
172
+ ```bash
173
+ omx
174
+ OMX_ROOT="$HOME/.omx/instances/second-conversation" omx
175
+ OMX_ROOT="$HOME/.omx/instances/third-conversation" omx
176
+ ```
177
+
178
+ PowerShell:
179
+
180
+ ```powershell
181
+ $env:OMX_ROOT = "$HOME/.omx/instances/second-conversation"
182
+ omx
183
+ ```
184
+
185
+ Command Prompt:
186
+
187
+ ```bat
188
+ set "OMX_ROOT=%USERPROFILE%\.omx\instances\second-conversation"
189
+ omx
190
+ ```
191
+
192
+ User-specified roots are literal: launching twice with the same explicit `OMX_ROOT` remains a fatal owner conflict. Separate checkouts have separate default roots, while `--worktree` and `--madmax` keep their existing isolation behavior.
193
+
159
194
  ### Madmax and worktree launch safety
160
195
 
161
196
  `--madmax` is OMX shorthand for Codex
@@ -333,7 +368,7 @@ These are operator/support surfaces:
333
368
  - Scoped setup installs prompts, skills, AGENTS scaffolding, `.codex/config.toml`, and (for legacy installs or older Codex without `plugin_hooks`) OMX-managed native Codex hooks in `.codex/hooks.json`
334
369
  - setup refresh preserves non-OMX hook entries in `.codex/hooks.json` and only rewrites OMX-managed wrappers
335
370
  - plugin setup keeps `AGENTS.md` as persistent durable guidance even though bundled skills/hooks come from the plugin cache; `omx doctor` treats a missing persistent scope `AGENTS.md` in plugin mode as a failed check because the session-scoped AGENTS file would otherwise contain only runtime overlay guidance
336
- - `omx setup --scope project --merge-agents` preserves existing project `AGENTS.md` guidance while inserting or refreshing generated OMX sections between `<!-- OMX:AGENTS:START -->` / `<!-- OMX:AGENTS:END -->`; without `--merge-agents` or `--force`, non-interactive setup keeps skipping existing `AGENTS.md` files
371
+ - `omx setup --merge-agents` preserves existing project `AGENTS.md` guidance while inserting or refreshing generated OMX sections between `<!-- OMX:AGENTS:START -->` / `<!-- OMX:AGENTS:END -->`; `--no-merge-agents` records an explicit contextual non-merge choice, and `--clear-merge-agents-policy` always removes the recorded choice and cannot combine with a set selector. The policy is stored per working root (even for user scope), replayed by immediate and deferred updates only when its saved scope is valid and matches, and is never a force/default policy.
337
372
  - `omx uninstall` removes OMX-managed wrappers from `.codex/hooks.json` but keeps the file when user hooks remain
338
373
  - `omx update` checks npm immediately, installs the newest global OMX build, then reruns the same interactive setup refresh path
339
374
  - launch-time update checks are throttled and prompt by default; use `OMX_AUTO_UPDATE=0` to disable them or `OMX_AUTO_UPDATE=defer` to schedule deferred updates without a prompt
@@ -9,5 +9,6 @@ repository.workspace = true
9
9
  [dependencies]
10
10
  omx-mux = { path = "../omx-mux" }
11
11
  omx-runtime-core = { path = "../omx-runtime-core" }
12
+ fs2 = "0.4"
12
13
  serde_json = "1"
13
14
 
@@ -1,3 +1,4 @@
1
+ use fs2::FileExt;
1
2
  use omx_mux::{canonical_contract_summary, MuxAdapter, MuxOperation, MuxTarget, TmuxAdapter};
2
3
  use omx_runtime_core::{runtime_contract_summary, RuntimeCommand, RuntimeEngine};
3
4
  use std::env;
@@ -71,9 +72,31 @@ fn run() -> Result<(), String> {
71
72
  let json_input = second.ok_or("exec requires a JSON command argument")?;
72
73
  let state_dir = args.iter().find_map(|a| a.strip_prefix("--state-dir="));
73
74
  let compact = args.iter().any(|a| a == "--compact");
75
+ let _mutation_lock = if let Some(dir) = state_dir {
76
+ std::fs::create_dir_all(dir).map_err(|e| e.to_string())?;
77
+ let lock =
78
+ std::fs::File::create(std::path::Path::new(dir).join("runtime-mutation.lock"))
79
+ .map_err(|e| e.to_string())?;
80
+ lock.lock_exclusive().map_err(|e| e.to_string())?;
81
+ Some(lock)
82
+ } else {
83
+ None
84
+ };
74
85
  let mut engine = match state_dir {
75
- Some(dir) => RuntimeEngine::load(dir)
76
- .unwrap_or_else(|_| RuntimeEngine::new().with_state_dir(dir)),
86
+ Some(dir) => match RuntimeEngine::load(dir) {
87
+ Ok(engine) => engine,
88
+ Err(error) => {
89
+ let has_persisted_state = ["events.json", "snapshot.json", "mailbox.json"]
90
+ .iter()
91
+ .any(|name| std::path::Path::new(dir).join(name).exists());
92
+ if has_persisted_state {
93
+ return Err(format!(
94
+ "failed to load authoritative runtime state: {error}"
95
+ ));
96
+ }
97
+ RuntimeEngine::new().with_state_dir(dir)
98
+ }
99
+ },
77
100
  None => RuntimeEngine::new(),
78
101
  };
79
102
 
@@ -178,6 +178,56 @@ fn exec_with_state_dir_persists() {
178
178
  let _ = std::fs::remove_dir_all(&dir);
179
179
  }
180
180
 
181
+ #[test]
182
+ fn exec_rejects_missing_seen_ledger_after_persisted_dispatch_history() {
183
+ let dir = std::env::temp_dir().join("omx-runtime-test-exec-missing-seen-ledger");
184
+ let _ = std::fs::remove_dir_all(&dir);
185
+ let state_arg = format!("--state-dir={}", dir.display());
186
+ let queued = Command::new(env!("CARGO_BIN_EXE_omx-runtime"))
187
+ .args([
188
+ "exec",
189
+ r#"{"command":"QueueDispatch","request_id":"request-1","target":"worker"}"#,
190
+ &state_arg,
191
+ ])
192
+ .output()
193
+ .expect("queued dispatch");
194
+ assert!(queued.status.success());
195
+ std::fs::remove_file(dir.join("dispatch-seen.json")).expect("removed seen ledger");
196
+
197
+ let reloaded = Command::new(env!("CARGO_BIN_EXE_omx-runtime"))
198
+ .args(["exec", r#"{"command":"CaptureSnapshot"}"#, &state_arg])
199
+ .output()
200
+ .expect("reloaded persisted state");
201
+ assert!(!reloaded.status.success());
202
+ assert!(String::from_utf8_lossy(&reloaded.stderr).contains("missing dispatch seen ledger"));
203
+ let _ = std::fs::remove_dir_all(&dir);
204
+ }
205
+
206
+ #[test]
207
+ fn exec_ignores_dispatch_compat_without_authoritative_runtime_state() {
208
+ let dir = std::env::temp_dir().join("omx-runtime-test-dispatch-compat-only");
209
+ let _ = std::fs::remove_dir_all(&dir);
210
+ std::fs::create_dir_all(&dir).unwrap();
211
+ std::fs::write(dir.join("dispatch.json"), "[]\n").unwrap();
212
+
213
+ let cmd_json = r#"{"command":"CaptureSnapshot"}"#;
214
+ let state_arg = format!("--state-dir={}", dir.display());
215
+ let output = Command::new(env!("CARGO_BIN_EXE_omx-runtime"))
216
+ .args(["exec", cmd_json, &state_arg])
217
+ .output()
218
+ .expect("ran omx-runtime");
219
+
220
+ assert!(
221
+ output.status.success(),
222
+ "dispatch compatibility output must not poison fresh authoritative state: {}",
223
+ String::from_utf8_lossy(&output.stderr)
224
+ );
225
+ assert!(dir.join("events.json").exists());
226
+ assert!(dir.join("snapshot.json").exists());
227
+
228
+ let _ = std::fs::remove_dir_all(&dir);
229
+ }
230
+
181
231
  #[test]
182
232
  fn snapshot_from_state_dir_reads_persisted_state() {
183
233
  let dir = std::env::temp_dir().join("omx-runtime-test-snapshot-statedir");
@@ -210,3 +260,172 @@ fn snapshot_from_state_dir_reads_persisted_state() {
210
260
 
211
261
  let _ = std::fs::remove_dir_all(&dir);
212
262
  }
263
+
264
+ #[test]
265
+ fn exec_compact_immediately_persists_only_nonterminal_dispatch_records() {
266
+ let dir = std::env::temp_dir().join("omx-runtime-test-exec-compact-dispatch");
267
+ let _ = std::fs::remove_dir_all(&dir);
268
+ let state_arg = format!("--state-dir={}", dir.display());
269
+ let run_exec = |json: &str, compact: bool| {
270
+ let mut command = Command::new(env!("CARGO_BIN_EXE_omx-runtime"));
271
+ command.args(["exec", json, &state_arg]);
272
+ if compact {
273
+ command.arg("--compact");
274
+ }
275
+ let output = command.output().expect("ran omx-runtime");
276
+ assert!(
277
+ output.status.success(),
278
+ "exec failed: {}",
279
+ String::from_utf8_lossy(&output.stderr)
280
+ );
281
+ };
282
+
283
+ run_exec(
284
+ r#"{"command":"QueueDispatch","request_id":"pending","target":"worker-pending"}"#,
285
+ false,
286
+ );
287
+ run_exec(
288
+ r#"{"command":"QueueDispatch","request_id":"notified","target":"worker-notified"}"#,
289
+ false,
290
+ );
291
+ run_exec(
292
+ r#"{"command":"MarkNotified","request_id":"notified","channel":"tmux"}"#,
293
+ false,
294
+ );
295
+ run_exec(
296
+ r#"{"command":"QueueDispatch","request_id":"delivered","target":"worker-delivered"}"#,
297
+ false,
298
+ );
299
+ run_exec(
300
+ r#"{"command":"MarkNotified","request_id":"delivered","channel":"tmux"}"#,
301
+ false,
302
+ );
303
+ run_exec(
304
+ r#"{"command":"MarkDelivered","request_id":"delivered"}"#,
305
+ false,
306
+ );
307
+ run_exec(r#"{"command":"CaptureSnapshot"}"#, false);
308
+ run_exec(
309
+ r#"{"command":"QueueDispatch","request_id":"failed","target":"worker-failed"}"#,
310
+ false,
311
+ );
312
+ run_exec(
313
+ r#"{"command":"MarkFailed","request_id":"failed","reason":"target unavailable"}"#,
314
+ true,
315
+ );
316
+
317
+ let duplicate = Command::new(env!("CARGO_BIN_EXE_omx-runtime"))
318
+ .args([
319
+ "exec",
320
+ r#"{"command":"QueueDispatch","request_id":"failed","target":"replacement"}"#,
321
+ &state_arg,
322
+ ])
323
+ .output()
324
+ .expect("ran duplicate dispatch exec");
325
+ assert!(!duplicate.status.success());
326
+ assert!(String::from_utf8_lossy(&duplicate.stderr)
327
+ .contains("duplicate dispatch request id: failed"));
328
+ assert!(dir.join("dispatch-seen.json").exists());
329
+
330
+ let dispatch: serde_json::Value = serde_json::from_str(
331
+ &std::fs::read_to_string(dir.join("dispatch.json")).expect("read immediate dispatch view"),
332
+ )
333
+ .expect("valid dispatch JSON");
334
+ let records = dispatch["records"]
335
+ .as_array()
336
+ .expect("dispatch records array");
337
+ assert_eq!(records.len(), 2);
338
+ assert_eq!(records[0]["request_id"], "pending");
339
+ assert_eq!(records[0]["status"], "pending");
340
+ assert_eq!(records[1]["request_id"], "notified");
341
+ assert_eq!(records[1]["status"], "notified");
342
+
343
+ run_exec(r#"{"command":"CaptureSnapshot"}"#, false);
344
+ let reloaded_dispatch: serde_json::Value = serde_json::from_str(
345
+ &std::fs::read_to_string(dir.join("dispatch.json"))
346
+ .expect("read reload-persisted dispatch view"),
347
+ )
348
+ .expect("valid reload-persisted dispatch JSON");
349
+ let reloaded_records = reloaded_dispatch["records"]
350
+ .as_array()
351
+ .expect("reload-persisted dispatch records array");
352
+ assert_eq!(reloaded_records.len(), records.len());
353
+ for (immediate, reloaded) in records.iter().zip(reloaded_records) {
354
+ for field in ["request_id", "target", "status", "metadata", "reason"] {
355
+ assert_eq!(reloaded[field], immediate[field], "semantic field {field}");
356
+ }
357
+ }
358
+
359
+ let snapshot: serde_json::Value = serde_json::from_str(
360
+ &std::fs::read_to_string(dir.join("snapshot.json"))
361
+ .expect("read reload-persisted snapshot"),
362
+ )
363
+ .expect("valid reload-persisted snapshot JSON");
364
+ assert_eq!(snapshot["backlog"]["pending"], 1);
365
+ assert_eq!(snapshot["backlog"]["notified"], 1);
366
+ assert_eq!(snapshot["backlog"]["delivered"], 0);
367
+ assert_eq!(snapshot["backlog"]["failed"], 0);
368
+
369
+ let events: serde_json::Value = serde_json::from_str(
370
+ &std::fs::read_to_string(dir.join("events.json")).expect("read compacted events"),
371
+ )
372
+ .expect("valid events JSON");
373
+ let events = events.as_array().expect("events array");
374
+ assert!(events
375
+ .iter()
376
+ .any(|event| event["event"] == "SnapshotCaptured"));
377
+ assert!(events
378
+ .iter()
379
+ .all(|event| { event["request_id"] != "delivered" && event["request_id"] != "failed" }));
380
+
381
+ let event_request_ids: Vec<&str> = events
382
+ .iter()
383
+ .filter_map(|event| event["request_id"].as_str())
384
+ .collect();
385
+ assert_eq!(event_request_ids, vec!["pending", "notified", "notified"]);
386
+ let _ = std::fs::remove_dir_all(&dir);
387
+ }
388
+
389
+ #[test]
390
+ fn concurrent_exec_queue_accepts_exactly_one_request_id() {
391
+ let dir = std::env::temp_dir().join("omx-runtime-test-concurrent-dispatch-id");
392
+ let _ = std::fs::remove_dir_all(&dir);
393
+ let state_arg = format!("--state-dir={}", dir.display());
394
+ let barrier = std::sync::Arc::new(std::sync::Barrier::new(3));
395
+ let mut workers = Vec::new();
396
+ for target in ["worker-a", "worker-b"] {
397
+ let barrier = std::sync::Arc::clone(&barrier);
398
+ let state_arg = state_arg.clone();
399
+ workers.push(std::thread::spawn(move || {
400
+ barrier.wait();
401
+ Command::new(env!("CARGO_BIN_EXE_omx-runtime"))
402
+ .args([
403
+ "exec",
404
+ &format!(
405
+ r#"{{"command":"QueueDispatch","request_id":"concurrent","target":"{target}"}}"#
406
+ ),
407
+ &state_arg,
408
+ ])
409
+ .output()
410
+ .expect("ran concurrent dispatch exec")
411
+ .status
412
+ .success()
413
+ }));
414
+ }
415
+ barrier.wait();
416
+ assert_eq!(
417
+ workers
418
+ .into_iter()
419
+ .map(|worker| worker.join().unwrap())
420
+ .filter(|accepted| *accepted)
421
+ .count(),
422
+ 1
423
+ );
424
+ let dispatch: serde_json::Value = serde_json::from_str(
425
+ &std::fs::read_to_string(dir.join("dispatch.json")).expect("read dispatch view"),
426
+ )
427
+ .expect("valid dispatch JSON");
428
+ assert_eq!(dispatch["records"].as_array().unwrap().len(), 1);
429
+ assert_eq!(dispatch["records"][0]["request_id"], "concurrent");
430
+ let _ = std::fs::remove_dir_all(&dir);
431
+ }
@@ -39,6 +39,12 @@ pub struct DispatchRecord {
39
39
 
40
40
  #[derive(Debug, Clone, PartialEq, Eq)]
41
41
  pub enum DispatchError {
42
+ DuplicateRequestId {
43
+ request_id: String,
44
+ },
45
+ InvalidRequestId {
46
+ request_id: String,
47
+ },
42
48
  NotFound {
43
49
  request_id: String,
44
50
  },
@@ -52,6 +58,12 @@ pub enum DispatchError {
52
58
  impl fmt::Display for DispatchError {
53
59
  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54
60
  match self {
61
+ Self::DuplicateRequestId { request_id } => {
62
+ write!(f, "duplicate dispatch request id: {request_id}")
63
+ }
64
+ Self::InvalidRequestId { request_id } => {
65
+ write!(f, "invalid dispatch request id: {request_id:?}")
66
+ }
55
67
  Self::NotFound { request_id } => {
56
68
  write!(f, "dispatch record not found: {request_id}")
57
69
  }
@@ -85,9 +97,20 @@ impl DispatchLog {
85
97
  request_id: impl Into<String>,
86
98
  target: impl Into<String>,
87
99
  metadata: Option<serde_json::Value>,
88
- ) {
100
+ ) -> Result<(), DispatchError> {
101
+ let request_id = request_id.into();
102
+ if request_id.is_empty() {
103
+ return Err(DispatchError::InvalidRequestId { request_id });
104
+ }
105
+ if self
106
+ .records
107
+ .iter()
108
+ .any(|record| record.request_id == request_id)
109
+ {
110
+ return Err(DispatchError::DuplicateRequestId { request_id });
111
+ }
89
112
  self.records.push(DispatchRecord {
90
- request_id: request_id.into(),
113
+ request_id,
91
114
  target: target.into(),
92
115
  status: DispatchStatus::Pending,
93
116
  created_at: now_iso(),
@@ -97,6 +120,7 @@ impl DispatchLog {
97
120
  reason: None,
98
121
  metadata,
99
122
  });
123
+ Ok(())
100
124
  }
101
125
 
102
126
  pub fn mark_notified(
@@ -156,6 +180,23 @@ impl DispatchLog {
156
180
  &self.records
157
181
  }
158
182
 
183
+ pub fn request_ids(&self) -> impl Iterator<Item = &str> {
184
+ self.records.iter().map(|record| record.request_id.as_str())
185
+ }
186
+
187
+ pub fn contains_request_id(&self, request_id: &str) -> bool {
188
+ self.records
189
+ .iter()
190
+ .any(|record| record.request_id == request_id)
191
+ }
192
+
193
+ /// Remove records that have reached a terminal delivery state.
194
+ pub fn prune_terminal_records(&mut self) {
195
+ self.records.retain(|record| {
196
+ record.status != DispatchStatus::Delivered && record.status != DispatchStatus::Failed
197
+ });
198
+ }
199
+
159
200
  pub fn to_backlog_snapshot(&self) -> BacklogSnapshot {
160
201
  let mut snapshot = BacklogSnapshot::default();
161
202
  for record in &self.records {
@@ -248,7 +289,7 @@ mod tests {
248
289
  #[test]
249
290
  fn queue_and_transition_happy_path() {
250
291
  let mut log = DispatchLog::new();
251
- log.queue("req-1", "worker-1", None);
292
+ log.queue("req-1", "worker-1", None).unwrap();
252
293
  assert_eq!(log.records().len(), 1);
253
294
  assert_eq!(log.records()[0].status, DispatchStatus::Pending);
254
295
 
@@ -262,7 +303,7 @@ mod tests {
262
303
  #[test]
263
304
  fn mark_failed_from_notified() {
264
305
  let mut log = DispatchLog::new();
265
- log.queue("req-1", "worker-1", None);
306
+ log.queue("req-1", "worker-1", None).unwrap();
266
307
  log.mark_notified("req-1", "tmux").unwrap();
267
308
  log.mark_failed("req-1", "send_error").unwrap();
268
309
  assert_eq!(log.records()[0].status, DispatchStatus::Failed);
@@ -271,7 +312,7 @@ mod tests {
271
312
  #[test]
272
313
  fn invalid_transition_errors() {
273
314
  let mut log = DispatchLog::new();
274
- log.queue("req-1", "worker-1", None);
315
+ log.queue("req-1", "worker-1", None).unwrap();
275
316
 
276
317
  // Can't deliver from pending
277
318
  let err = log.mark_delivered("req-1").unwrap_err();
@@ -282,7 +323,7 @@ mod tests {
282
323
  fn mark_failed_from_pending() {
283
324
  // Matches TS behavior: pending -> failed allowed for target resolution failures
284
325
  let mut log = DispatchLog::new();
285
- log.queue("req-1", "worker-1", None);
326
+ log.queue("req-1", "worker-1", None).unwrap();
286
327
  log.mark_failed("req-1", "target_resolution_failed")
287
328
  .unwrap();
288
329
  assert_eq!(log.records()[0].status, DispatchStatus::Failed);
@@ -298,9 +339,9 @@ mod tests {
298
339
  #[test]
299
340
  fn backlog_snapshot_counts() {
300
341
  let mut log = DispatchLog::new();
301
- log.queue("req-1", "w1", None);
302
- log.queue("req-2", "w2", None);
303
- log.queue("req-3", "w3", None);
342
+ log.queue("req-1", "w1", None).unwrap();
343
+ log.queue("req-2", "w2", None).unwrap();
344
+ log.queue("req-3", "w3", None).unwrap();
304
345
  log.mark_notified("req-2", "tmux").unwrap();
305
346
  log.mark_notified("req-3", "tmux").unwrap();
306
347
  log.mark_delivered("req-2").unwrap();
@@ -313,11 +354,34 @@ mod tests {
313
354
  assert_eq!(snap.failed, 1);
314
355
  }
315
356
 
357
+ #[test]
358
+ fn prune_terminal_records_keeps_pending_and_notified_records() {
359
+ let mut log = DispatchLog::new();
360
+ log.queue("pending", "w1", None).unwrap();
361
+ log.queue("notified", "w2", None).unwrap();
362
+ log.queue("delivered", "w3", None).unwrap();
363
+ log.queue("failed", "w4", None).unwrap();
364
+ log.mark_notified("notified", "tmux").unwrap();
365
+ log.mark_notified("delivered", "tmux").unwrap();
366
+ log.mark_delivered("delivered").unwrap();
367
+ log.mark_failed("failed", "target resolution failed")
368
+ .unwrap();
369
+
370
+ log.prune_terminal_records();
371
+
372
+ assert_eq!(log.records().len(), 2);
373
+ assert_eq!(log.records()[0].request_id, "pending");
374
+ assert_eq!(log.records()[0].status, DispatchStatus::Pending);
375
+ assert_eq!(log.records()[1].request_id, "notified");
376
+ assert_eq!(log.records()[1].status, DispatchStatus::Notified);
377
+ }
378
+
316
379
  #[test]
317
380
  fn queue_with_metadata_round_trips() {
318
381
  let mut log = DispatchLog::new();
319
382
  let meta = serde_json::json!({"priority": "high", "tags": ["urgent"]});
320
- log.queue("req-meta", "worker-1", Some(meta.clone()));
383
+ log.queue("req-meta", "worker-1", Some(meta.clone()))
384
+ .unwrap();
321
385
 
322
386
  assert_eq!(log.records()[0].metadata, Some(meta.clone()));
323
387
 
@@ -327,4 +391,26 @@ mod tests {
327
391
  assert_eq!(loaded.records()[0].metadata, Some(meta));
328
392
  assert_eq!(loaded.records()[0].request_id, "req-meta");
329
393
  }
394
+
395
+ #[test]
396
+ fn queue_rejects_duplicate_request_id_after_terminal_transition() {
397
+ let mut log = DispatchLog::new();
398
+ log.queue("req-1", "worker-1", None).unwrap();
399
+ log.mark_failed("req-1", "target unavailable").unwrap();
400
+
401
+ let err = log.queue("req-1", "worker-2", None).unwrap_err();
402
+ assert!(
403
+ matches!(err, DispatchError::DuplicateRequestId { request_id } if request_id == "req-1")
404
+ );
405
+ assert_eq!(log.records().len(), 1);
406
+ }
407
+
408
+ #[test]
409
+ fn queue_rejects_empty_request_id() {
410
+ let mut log = DispatchLog::new();
411
+ assert!(matches!(
412
+ log.queue("", "worker", None),
413
+ Err(DispatchError::InvalidRequestId { request_id }) if request_id.is_empty()
414
+ ));
415
+ }
330
416
  }