oh-my-codex 0.20.2 → 0.20.5

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 (805) hide show
  1. package/Cargo.lock +36 -18
  2. package/Cargo.toml +1 -1
  3. package/README.md +28 -2
  4. package/crates/omx-runtime/Cargo.toml +4 -0
  5. package/crates/omx-runtime/src/main.rs +415 -2
  6. package/crates/omx-runtime/tests/execution.rs +483 -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__/herdr-target.test.d.ts +2 -0
  11. package/dist/adapt/__tests__/herdr-target.test.d.ts.map +1 -0
  12. package/dist/adapt/__tests__/herdr-target.test.js +72 -0
  13. package/dist/adapt/__tests__/herdr-target.test.js.map +1 -0
  14. package/dist/adapt/contracts.d.ts +1 -1
  15. package/dist/adapt/contracts.d.ts.map +1 -1
  16. package/dist/adapt/contracts.js +1 -1
  17. package/dist/adapt/contracts.js.map +1 -1
  18. package/dist/adapt/herdr/__tests__/authority.test.d.ts +2 -0
  19. package/dist/adapt/herdr/__tests__/authority.test.d.ts.map +1 -0
  20. package/dist/adapt/herdr/__tests__/authority.test.js +49 -0
  21. package/dist/adapt/herdr/__tests__/authority.test.js.map +1 -0
  22. package/dist/adapt/herdr/__tests__/bridge.test.d.ts +2 -0
  23. package/dist/adapt/herdr/__tests__/bridge.test.d.ts.map +1 -0
  24. package/dist/adapt/herdr/__tests__/bridge.test.js +176 -0
  25. package/dist/adapt/herdr/__tests__/bridge.test.js.map +1 -0
  26. package/dist/adapt/herdr/__tests__/sanitize.test.d.ts +2 -0
  27. package/dist/adapt/herdr/__tests__/sanitize.test.d.ts.map +1 -0
  28. package/dist/adapt/herdr/__tests__/sanitize.test.js +45 -0
  29. package/dist/adapt/herdr/__tests__/sanitize.test.js.map +1 -0
  30. package/dist/adapt/herdr/__tests__/semantic.test.d.ts +2 -0
  31. package/dist/adapt/herdr/__tests__/semantic.test.d.ts.map +1 -0
  32. package/dist/adapt/herdr/__tests__/semantic.test.js +130 -0
  33. package/dist/adapt/herdr/__tests__/semantic.test.js.map +1 -0
  34. package/dist/adapt/herdr/__tests__/seq-store.test.d.ts +2 -0
  35. package/dist/adapt/herdr/__tests__/seq-store.test.d.ts.map +1 -0
  36. package/dist/adapt/herdr/__tests__/seq-store.test.js +54 -0
  37. package/dist/adapt/herdr/__tests__/seq-store.test.js.map +1 -0
  38. package/dist/adapt/herdr/__tests__/socket-live.test.d.ts +2 -0
  39. package/dist/adapt/herdr/__tests__/socket-live.test.d.ts.map +1 -0
  40. package/dist/adapt/herdr/__tests__/socket-live.test.js +104 -0
  41. package/dist/adapt/herdr/__tests__/socket-live.test.js.map +1 -0
  42. package/dist/adapt/herdr/__tests__/team-map.test.d.ts +2 -0
  43. package/dist/adapt/herdr/__tests__/team-map.test.d.ts.map +1 -0
  44. package/dist/adapt/herdr/__tests__/team-map.test.js +46 -0
  45. package/dist/adapt/herdr/__tests__/team-map.test.js.map +1 -0
  46. package/dist/adapt/herdr/__tests__/transport.test.d.ts +2 -0
  47. package/dist/adapt/herdr/__tests__/transport.test.d.ts.map +1 -0
  48. package/dist/adapt/herdr/__tests__/transport.test.js +160 -0
  49. package/dist/adapt/herdr/__tests__/transport.test.js.map +1 -0
  50. package/dist/adapt/herdr/__tests__/wiring.test.d.ts +2 -0
  51. package/dist/adapt/herdr/__tests__/wiring.test.d.ts.map +1 -0
  52. package/dist/adapt/herdr/__tests__/wiring.test.js +118 -0
  53. package/dist/adapt/herdr/__tests__/wiring.test.js.map +1 -0
  54. package/dist/adapt/herdr/authority.d.ts +34 -0
  55. package/dist/adapt/herdr/authority.d.ts.map +1 -0
  56. package/dist/adapt/herdr/authority.js +71 -0
  57. package/dist/adapt/herdr/authority.js.map +1 -0
  58. package/dist/adapt/herdr/bridge.d.ts +84 -0
  59. package/dist/adapt/herdr/bridge.d.ts.map +1 -0
  60. package/dist/adapt/herdr/bridge.js +222 -0
  61. package/dist/adapt/herdr/bridge.js.map +1 -0
  62. package/dist/adapt/herdr/sanitize.d.ts +20 -0
  63. package/dist/adapt/herdr/sanitize.d.ts.map +1 -0
  64. package/dist/adapt/herdr/sanitize.js +70 -0
  65. package/dist/adapt/herdr/sanitize.js.map +1 -0
  66. package/dist/adapt/herdr/semantic.d.ts +67 -0
  67. package/dist/adapt/herdr/semantic.d.ts.map +1 -0
  68. package/dist/adapt/herdr/semantic.js +170 -0
  69. package/dist/adapt/herdr/semantic.js.map +1 -0
  70. package/dist/adapt/herdr/seq-store.d.ts +32 -0
  71. package/dist/adapt/herdr/seq-store.d.ts.map +1 -0
  72. package/dist/adapt/herdr/seq-store.js +126 -0
  73. package/dist/adapt/herdr/seq-store.js.map +1 -0
  74. package/dist/adapt/herdr/team-map.d.ts +30 -0
  75. package/dist/adapt/herdr/team-map.d.ts.map +1 -0
  76. package/dist/adapt/herdr/team-map.js +37 -0
  77. package/dist/adapt/herdr/team-map.js.map +1 -0
  78. package/dist/adapt/herdr/transport.d.ts +115 -0
  79. package/dist/adapt/herdr/transport.d.ts.map +1 -0
  80. package/dist/adapt/herdr/transport.js +260 -0
  81. package/dist/adapt/herdr/transport.js.map +1 -0
  82. package/dist/adapt/herdr/wiring.d.ts +24 -0
  83. package/dist/adapt/herdr/wiring.d.ts.map +1 -0
  84. package/dist/adapt/herdr/wiring.js +62 -0
  85. package/dist/adapt/herdr/wiring.js.map +1 -0
  86. package/dist/adapt/herdr.d.ts +19 -0
  87. package/dist/adapt/herdr.d.ts.map +1 -0
  88. package/dist/adapt/herdr.js +115 -0
  89. package/dist/adapt/herdr.js.map +1 -0
  90. package/dist/adapt/index.d.ts +4 -0
  91. package/dist/adapt/index.d.ts.map +1 -1
  92. package/dist/adapt/index.js +48 -0
  93. package/dist/adapt/index.js.map +1 -1
  94. package/dist/adapt/registry.d.ts.map +1 -1
  95. package/dist/adapt/registry.js +11 -0
  96. package/dist/adapt/registry.js.map +1 -1
  97. package/dist/agents/__tests__/definitions.test.js +81 -0
  98. package/dist/agents/__tests__/definitions.test.js.map +1 -1
  99. package/dist/agents/__tests__/native-config.test.js +25 -0
  100. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  101. package/dist/agents/native-config.d.ts +2 -1
  102. package/dist/agents/native-config.d.ts.map +1 -1
  103. package/dist/agents/native-config.js.map +1 -1
  104. package/dist/auth/__tests__/hotswap.test.js +60 -1
  105. package/dist/auth/__tests__/hotswap.test.js.map +1 -1
  106. package/dist/auth/__tests__/storage.test.js +33 -1
  107. package/dist/auth/__tests__/storage.test.js.map +1 -1
  108. package/dist/auth/hotswap.d.ts +22 -2
  109. package/dist/auth/hotswap.d.ts.map +1 -1
  110. package/dist/auth/hotswap.js +107 -22
  111. package/dist/auth/hotswap.js.map +1 -1
  112. package/dist/auth/storage.js +1 -1
  113. package/dist/auth/storage.js.map +1 -1
  114. package/dist/autopilot/__tests__/ralplan-gate.test.js +86 -1333
  115. package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -1
  116. package/dist/autopilot/ralplan-gate.d.ts.map +1 -1
  117. package/dist/autopilot/ralplan-gate.js +7 -6
  118. package/dist/autopilot/ralplan-gate.js.map +1 -1
  119. package/dist/cli/__tests__/agents-init.test.js +4 -23
  120. package/dist/cli/__tests__/agents-init.test.js.map +1 -1
  121. package/dist/cli/__tests__/api.test.js +61 -24
  122. package/dist/cli/__tests__/api.test.js.map +1 -1
  123. package/dist/cli/__tests__/auth.test.js +63 -7
  124. package/dist/cli/__tests__/auth.test.js.map +1 -1
  125. package/dist/cli/__tests__/codex-feature-probe.test.js +66 -1
  126. package/dist/cli/__tests__/codex-feature-probe.test.js.map +1 -1
  127. package/dist/cli/__tests__/codex-plugin-layout.test.js +150 -2
  128. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  129. package/dist/cli/__tests__/detached-leader-teardown.test.d.ts +2 -0
  130. package/dist/cli/__tests__/detached-leader-teardown.test.d.ts.map +1 -0
  131. package/dist/cli/__tests__/detached-leader-teardown.test.js +473 -0
  132. package/dist/cli/__tests__/detached-leader-teardown.test.js.map +1 -0
  133. package/dist/cli/__tests__/doctor-process-identity-readiness.test.d.ts +2 -0
  134. package/dist/cli/__tests__/doctor-process-identity-readiness.test.d.ts.map +1 -0
  135. package/dist/cli/__tests__/doctor-process-identity-readiness.test.js +103 -0
  136. package/dist/cli/__tests__/doctor-process-identity-readiness.test.js.map +1 -0
  137. package/dist/cli/__tests__/doctor-state-root-binding.test.d.ts +2 -0
  138. package/dist/cli/__tests__/doctor-state-root-binding.test.d.ts.map +1 -0
  139. package/dist/cli/__tests__/doctor-state-root-binding.test.js +139 -0
  140. package/dist/cli/__tests__/doctor-state-root-binding.test.js.map +1 -0
  141. package/dist/cli/__tests__/doctor-warning-copy.test.js +135 -1
  142. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  143. package/dist/cli/__tests__/exec.test.js +211 -0
  144. package/dist/cli/__tests__/exec.test.js.map +1 -1
  145. package/dist/cli/__tests__/index.test.js +878 -463
  146. package/dist/cli/__tests__/index.test.js.map +1 -1
  147. package/dist/cli/__tests__/launch-fallback.test.js +1290 -127
  148. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  149. package/dist/cli/__tests__/mcp-parity.test.js +8 -4
  150. package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
  151. package/dist/cli/__tests__/native-assets.test.js +398 -16
  152. package/dist/cli/__tests__/native-assets.test.js.map +1 -1
  153. package/dist/cli/__tests__/native-hook-claim-journal.test.js +132 -6
  154. package/dist/cli/__tests__/native-hook-claim-journal.test.js.map +1 -1
  155. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +3 -3
  156. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
  157. package/dist/cli/__tests__/ralph.test.js +3 -3
  158. package/dist/cli/__tests__/ralph.test.js.map +1 -1
  159. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js +49 -164
  160. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js.map +1 -1
  161. package/dist/cli/__tests__/ralplan-child-binding-3212.test.d.ts +2 -0
  162. package/dist/cli/__tests__/ralplan-child-binding-3212.test.d.ts.map +1 -0
  163. package/dist/cli/__tests__/ralplan-child-binding-3212.test.js +56 -0
  164. package/dist/cli/__tests__/ralplan-child-binding-3212.test.js.map +1 -0
  165. package/dist/cli/__tests__/ralplan.test.js +107 -109
  166. package/dist/cli/__tests__/ralplan.test.js.map +1 -1
  167. package/dist/cli/__tests__/resume.test.js +11 -10
  168. package/dist/cli/__tests__/resume.test.js.map +1 -1
  169. package/dist/cli/__tests__/session-scoped-runtime.test.js +1118 -43
  170. package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -1
  171. package/dist/cli/__tests__/session-search-help.test.js +25 -1
  172. package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
  173. package/dist/cli/__tests__/setup-agents-overwrite.test.js +8 -55
  174. package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
  175. package/dist/cli/__tests__/setup-install-mode.test.js +224 -7
  176. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  177. package/dist/cli/__tests__/sparkshell-cli.test.js +93 -41
  178. package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -1
  179. package/dist/cli/__tests__/team.test.js +150 -8
  180. package/dist/cli/__tests__/team.test.js.map +1 -1
  181. package/dist/cli/__tests__/ultragoal.test.js +117 -2
  182. package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
  183. package/dist/cli/__tests__/uninstall.test.js +95 -4
  184. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  185. package/dist/cli/__tests__/update.test.js +669 -177
  186. package/dist/cli/__tests__/update.test.js.map +1 -1
  187. package/dist/cli/__tests__/windows-popup-loop-contract.test.js +33 -2
  188. package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
  189. package/dist/cli/api.d.ts.map +1 -1
  190. package/dist/cli/api.js +9 -10
  191. package/dist/cli/api.js.map +1 -1
  192. package/dist/cli/codex-feature-probe.d.ts +16 -0
  193. package/dist/cli/codex-feature-probe.d.ts.map +1 -1
  194. package/dist/cli/codex-feature-probe.js +44 -0
  195. package/dist/cli/codex-feature-probe.js.map +1 -1
  196. package/dist/cli/codex-home.d.ts.map +1 -1
  197. package/dist/cli/codex-home.js +7 -4
  198. package/dist/cli/codex-home.js.map +1 -1
  199. package/dist/cli/doctor.d.ts +20 -0
  200. package/dist/cli/doctor.d.ts.map +1 -1
  201. package/dist/cli/doctor.js +290 -3
  202. package/dist/cli/doctor.js.map +1 -1
  203. package/dist/cli/index.d.ts +234 -12
  204. package/dist/cli/index.d.ts.map +1 -1
  205. package/dist/cli/index.js +2409 -746
  206. package/dist/cli/index.js.map +1 -1
  207. package/dist/cli/mcp-parity.js +2 -2
  208. package/dist/cli/mcp-parity.js.map +1 -1
  209. package/dist/cli/native-assets.d.ts +25 -0
  210. package/dist/cli/native-assets.d.ts.map +1 -1
  211. package/dist/cli/native-assets.js +448 -51
  212. package/dist/cli/native-assets.js.map +1 -1
  213. package/dist/cli/native-hook-claim-journal.d.ts +20 -5
  214. package/dist/cli/native-hook-claim-journal.d.ts.map +1 -1
  215. package/dist/cli/native-hook-claim-journal.js +67 -32
  216. package/dist/cli/native-hook-claim-journal.js.map +1 -1
  217. package/dist/cli/package-manager-ownership.d.ts +63 -0
  218. package/dist/cli/package-manager-ownership.d.ts.map +1 -0
  219. package/dist/cli/package-manager-ownership.js +323 -0
  220. package/dist/cli/package-manager-ownership.js.map +1 -0
  221. package/dist/cli/ralph.js +2 -2
  222. package/dist/cli/ralph.js.map +1 -1
  223. package/dist/cli/ralplan.d.ts +5 -7
  224. package/dist/cli/ralplan.d.ts.map +1 -1
  225. package/dist/cli/ralplan.js +83 -134
  226. package/dist/cli/ralplan.js.map +1 -1
  227. package/dist/cli/session-search.d.ts +5 -0
  228. package/dist/cli/session-search.d.ts.map +1 -1
  229. package/dist/cli/session-search.js +87 -0
  230. package/dist/cli/session-search.js.map +1 -1
  231. package/dist/cli/setup-preferences.d.ts +15 -0
  232. package/dist/cli/setup-preferences.d.ts.map +1 -1
  233. package/dist/cli/setup-preferences.js +27 -1
  234. package/dist/cli/setup-preferences.js.map +1 -1
  235. package/dist/cli/setup.d.ts +8 -0
  236. package/dist/cli/setup.d.ts.map +1 -1
  237. package/dist/cli/setup.js +119 -47
  238. package/dist/cli/setup.js.map +1 -1
  239. package/dist/cli/sparkshell.d.ts.map +1 -1
  240. package/dist/cli/sparkshell.js +52 -9
  241. package/dist/cli/sparkshell.js.map +1 -1
  242. package/dist/cli/ultragoal.d.ts.map +1 -1
  243. package/dist/cli/ultragoal.js +2 -2
  244. package/dist/cli/ultragoal.js.map +1 -1
  245. package/dist/cli/uninstall.d.ts +9 -0
  246. package/dist/cli/uninstall.d.ts.map +1 -1
  247. package/dist/cli/uninstall.js +71 -30
  248. package/dist/cli/uninstall.js.map +1 -1
  249. package/dist/cli/update-worker.d.ts +2 -0
  250. package/dist/cli/update-worker.d.ts.map +1 -0
  251. package/dist/cli/update-worker.js +142 -0
  252. package/dist/cli/update-worker.js.map +1 -0
  253. package/dist/cli/update.d.ts +14 -22
  254. package/dist/cli/update.d.ts.map +1 -1
  255. package/dist/cli/update.js +192 -241
  256. package/dist/cli/update.js.map +1 -1
  257. package/dist/compat/__tests__/rust-runtime-compat.test.js +1 -1
  258. package/dist/config/__tests__/generator-idempotent.test.js +503 -30
  259. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  260. package/dist/config/__tests__/generator-notify.test.js +5 -3
  261. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  262. package/dist/config/__tests__/models.test.js +67 -3
  263. package/dist/config/__tests__/models.test.js.map +1 -1
  264. package/dist/config/generator.d.ts +27 -21
  265. package/dist/config/generator.d.ts.map +1 -1
  266. package/dist/config/generator.js +610 -152
  267. package/dist/config/generator.js.map +1 -1
  268. package/dist/config/models.d.ts +12 -2
  269. package/dist/config/models.d.ts.map +1 -1
  270. package/dist/config/models.js +15 -1
  271. package/dist/config/models.js.map +1 -1
  272. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js +25 -0
  273. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js.map +1 -1
  274. package/dist/goal-workflows/codex-goal-snapshot.d.ts +1 -1
  275. package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -1
  276. package/dist/goal-workflows/codex-goal-snapshot.js +2 -0
  277. package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -1
  278. package/dist/hooks/__tests__/agents-overlay.test.js +5 -3
  279. package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
  280. package/dist/hooks/__tests__/autopilot-skill-contract.test.js +27 -4
  281. package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
  282. package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.d.ts +2 -0
  283. package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.d.ts.map +1 -0
  284. package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.js +172 -0
  285. package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.js.map +1 -0
  286. package/dist/hooks/__tests__/keyword-detector.test.js +176 -37
  287. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  288. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +402 -545
  289. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  290. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +39 -4
  291. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  292. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +161 -26
  293. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  294. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +27 -0
  295. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
  296. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +10 -118
  297. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
  298. package/dist/hooks/__tests__/notify-hook-regression-205.test.js +7 -0
  299. package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
  300. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +533 -14
  301. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  302. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +159 -24
  303. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  304. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +482 -32
  305. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  306. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js +2 -1
  307. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js.map +1 -1
  308. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +68 -1
  309. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  310. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +7 -1
  311. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -1
  312. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +44 -4
  313. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  314. package/dist/hooks/__tests__/prompt-guidance-contract.test.js +9 -0
  315. package/dist/hooks/__tests__/prompt-guidance-contract.test.js.map +1 -1
  316. package/dist/hooks/__tests__/session.test.js +3130 -365
  317. package/dist/hooks/__tests__/session.test.js.map +1 -1
  318. package/dist/hooks/agents-overlay.js +1 -1
  319. package/dist/hooks/agents-overlay.js.map +1 -1
  320. package/dist/hooks/extensibility/__tests__/dispatcher.test.js +108 -2
  321. package/dist/hooks/extensibility/__tests__/dispatcher.test.js.map +1 -1
  322. package/dist/hooks/extensibility/__tests__/sdk.test.js +151 -1
  323. package/dist/hooks/extensibility/__tests__/sdk.test.js.map +1 -1
  324. package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -1
  325. package/dist/hooks/extensibility/dispatcher.js +20 -3
  326. package/dist/hooks/extensibility/dispatcher.js.map +1 -1
  327. package/dist/hooks/extensibility/plugin-runner.js +1 -0
  328. package/dist/hooks/extensibility/plugin-runner.js.map +1 -1
  329. package/dist/hooks/extensibility/runtime.d.ts.map +1 -1
  330. package/dist/hooks/extensibility/runtime.js.map +1 -1
  331. package/dist/hooks/extensibility/sdk/paths.d.ts +1 -1
  332. package/dist/hooks/extensibility/sdk/paths.d.ts.map +1 -1
  333. package/dist/hooks/extensibility/sdk/paths.js +2 -2
  334. package/dist/hooks/extensibility/sdk/paths.js.map +1 -1
  335. package/dist/hooks/extensibility/sdk/runtime-state.d.ts +1 -1
  336. package/dist/hooks/extensibility/sdk/runtime-state.d.ts.map +1 -1
  337. package/dist/hooks/extensibility/sdk/runtime-state.js +55 -15
  338. package/dist/hooks/extensibility/sdk/runtime-state.js.map +1 -1
  339. package/dist/hooks/extensibility/sdk.d.ts +1 -0
  340. package/dist/hooks/extensibility/sdk.d.ts.map +1 -1
  341. package/dist/hooks/extensibility/sdk.js +1 -1
  342. package/dist/hooks/extensibility/sdk.js.map +1 -1
  343. package/dist/hooks/extensibility/types.d.ts +7 -0
  344. package/dist/hooks/extensibility/types.d.ts.map +1 -1
  345. package/dist/hooks/keyword-detector.d.ts +10 -3
  346. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  347. package/dist/hooks/keyword-detector.js +116 -20
  348. package/dist/hooks/keyword-detector.js.map +1 -1
  349. package/dist/hooks/session.d.ts +204 -14
  350. package/dist/hooks/session.d.ts.map +1 -1
  351. package/dist/hooks/session.js +1500 -223
  352. package/dist/hooks/session.js.map +1 -1
  353. package/dist/hud/__tests__/hud-tmux-injection.test.js +6 -6
  354. package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
  355. package/dist/hud/__tests__/index.test.js +26 -16
  356. package/dist/hud/__tests__/index.test.js.map +1 -1
  357. package/dist/hud/__tests__/reconcile.test.js +83 -78
  358. package/dist/hud/__tests__/reconcile.test.js.map +1 -1
  359. package/dist/hud/__tests__/state.test.js +36 -31
  360. package/dist/hud/__tests__/state.test.js.map +1 -1
  361. package/dist/hud/__tests__/tmux.test.js +155 -198
  362. package/dist/hud/__tests__/tmux.test.js.map +1 -1
  363. package/dist/hud/tmux.d.ts +42 -4
  364. package/dist/hud/tmux.d.ts.map +1 -1
  365. package/dist/hud/tmux.js +1017 -139
  366. package/dist/hud/tmux.js.map +1 -1
  367. package/dist/leader/__tests__/contract.test.js +124 -37
  368. package/dist/leader/__tests__/contract.test.js.map +1 -1
  369. package/dist/leader/contract.d.ts +17 -6
  370. package/dist/leader/contract.d.ts.map +1 -1
  371. package/dist/leader/contract.js +102 -26
  372. package/dist/leader/contract.js.map +1 -1
  373. package/dist/mcp/__tests__/code-intel-server.test.js +31 -3
  374. package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -1
  375. package/dist/mcp/__tests__/hermes-bridge.test.js +17 -0
  376. package/dist/mcp/__tests__/hermes-bridge.test.js.map +1 -1
  377. package/dist/mcp/__tests__/server-lifecycle.test.js +4 -4
  378. package/dist/mcp/__tests__/state-paths.test.js +735 -4
  379. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  380. package/dist/mcp/__tests__/state-server.test.js +1 -1
  381. package/dist/mcp/__tests__/state-server.test.js.map +1 -1
  382. package/dist/mcp/__tests__/trace-server.test.js +2 -2
  383. package/dist/mcp/__tests__/trace-server.test.js.map +1 -1
  384. package/dist/mcp/__tests__/wiki-server.test.js +18 -0
  385. package/dist/mcp/__tests__/wiki-server.test.js.map +1 -1
  386. package/dist/mcp/code-intel-server.d.ts.map +1 -1
  387. package/dist/mcp/code-intel-server.js +13 -3
  388. package/dist/mcp/code-intel-server.js.map +1 -1
  389. package/dist/mcp/hermes-bridge.d.ts.map +1 -1
  390. package/dist/mcp/hermes-bridge.js +2 -2
  391. package/dist/mcp/hermes-bridge.js.map +1 -1
  392. package/dist/mcp/state-paths.d.ts +78 -4
  393. package/dist/mcp/state-paths.d.ts.map +1 -1
  394. package/dist/mcp/state-paths.js +543 -40
  395. package/dist/mcp/state-paths.js.map +1 -1
  396. package/dist/mcp/state-server.d.ts +4 -4
  397. package/dist/mcp/state-server.d.ts.map +1 -1
  398. package/dist/mcp/wiki-server.d.ts +11 -0
  399. package/dist/mcp/wiki-server.d.ts.map +1 -1
  400. package/dist/mcp/wiki-server.js +9 -2
  401. package/dist/mcp/wiki-server.js.map +1 -1
  402. package/dist/modes/__tests__/base-autopilot-gates.test.js +36 -7
  403. package/dist/modes/__tests__/base-autopilot-gates.test.js.map +1 -1
  404. package/dist/modes/__tests__/base-multi-state-compat.test.js +1 -1
  405. package/dist/modes/__tests__/base-multi-state-compat.test.js.map +1 -1
  406. package/dist/modes/__tests__/base-session-scope.test.js +17 -8
  407. package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
  408. package/dist/modes/__tests__/base-tmux-pane.test.js +4 -4
  409. package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
  410. package/dist/modes/base.d.ts +5 -5
  411. package/dist/modes/base.d.ts.map +1 -1
  412. package/dist/modes/base.js +76 -21
  413. package/dist/modes/base.js.map +1 -1
  414. package/dist/native-assets/archive.d.ts +17 -0
  415. package/dist/native-assets/archive.d.ts.map +1 -0
  416. package/dist/native-assets/archive.js +238 -0
  417. package/dist/native-assets/archive.js.map +1 -0
  418. package/dist/native-assets/policy.d.ts +42 -0
  419. package/dist/native-assets/policy.d.ts.map +1 -0
  420. package/dist/native-assets/policy.js +155 -0
  421. package/dist/native-assets/policy.js.map +1 -0
  422. package/dist/notifications/temp-contract.d.ts.map +1 -1
  423. package/dist/notifications/temp-contract.js +4 -0
  424. package/dist/notifications/temp-contract.js.map +1 -1
  425. package/dist/pipeline/__tests__/orchestrator.test.js +164 -42
  426. package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
  427. package/dist/pipeline/__tests__/stages.test.js +72 -155
  428. package/dist/pipeline/__tests__/stages.test.js.map +1 -1
  429. package/dist/pipeline/orchestrator.d.ts.map +1 -1
  430. package/dist/pipeline/orchestrator.js +124 -18
  431. package/dist/pipeline/orchestrator.js.map +1 -1
  432. package/dist/pipeline/stages/ralplan.d.ts.map +1 -1
  433. package/dist/pipeline/stages/ralplan.js +36 -8
  434. package/dist/pipeline/stages/ralplan.js.map +1 -1
  435. package/dist/ralplan/__tests__/consensus-gate.test.js +73 -1316
  436. package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
  437. package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts +2 -0
  438. package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts.map +1 -0
  439. package/dist/ralplan/__tests__/documented-leader-preflight.test.js +335 -0
  440. package/dist/ralplan/__tests__/documented-leader-preflight.test.js.map +1 -0
  441. package/dist/ralplan/__tests__/runtime.test.js +85 -101
  442. package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
  443. package/dist/ralplan/consensus-gate.d.ts +9 -1
  444. package/dist/ralplan/consensus-gate.d.ts.map +1 -1
  445. package/dist/ralplan/consensus-gate.js +82 -338
  446. package/dist/ralplan/consensus-gate.js.map +1 -1
  447. package/dist/ralplan/documented-leader-preflight.d.ts +41 -0
  448. package/dist/ralplan/documented-leader-preflight.d.ts.map +1 -0
  449. package/dist/ralplan/documented-leader-preflight.js +360 -0
  450. package/dist/ralplan/documented-leader-preflight.js.map +1 -0
  451. package/dist/ralplan/runtime.d.ts +2 -1
  452. package/dist/ralplan/runtime.d.ts.map +1 -1
  453. package/dist/ralplan/runtime.js +67 -168
  454. package/dist/ralplan/runtime.js.map +1 -1
  455. package/dist/runtime/__tests__/bridge.test.js +42 -1
  456. package/dist/runtime/__tests__/bridge.test.js.map +1 -1
  457. package/dist/runtime/bridge.d.ts +12 -0
  458. package/dist/runtime/bridge.d.ts.map +1 -1
  459. package/dist/runtime/bridge.js +52 -1
  460. package/dist/runtime/bridge.js.map +1 -1
  461. package/dist/runtime/run-state.d.ts +5 -1
  462. package/dist/runtime/run-state.d.ts.map +1 -1
  463. package/dist/runtime/run-state.js +15 -8
  464. package/dist/runtime/run-state.js.map +1 -1
  465. package/dist/scripts/__tests__/codex-native-hook.test.js +16323 -8978
  466. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  467. package/dist/scripts/__tests__/issue-3293-callsite-parity.test.d.ts +2 -0
  468. package/dist/scripts/__tests__/issue-3293-callsite-parity.test.d.ts.map +1 -0
  469. package/dist/scripts/__tests__/issue-3293-callsite-parity.test.js +225 -0
  470. package/dist/scripts/__tests__/issue-3293-callsite-parity.test.js.map +1 -0
  471. package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.d.ts +2 -0
  472. package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.d.ts.map +1 -0
  473. package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.js +188 -0
  474. package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.js.map +1 -0
  475. package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.d.ts +2 -0
  476. package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.d.ts.map +1 -0
  477. package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.js +259 -0
  478. package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.js.map +1 -0
  479. package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.d.ts +2 -0
  480. package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.d.ts.map +1 -0
  481. package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.js +491 -0
  482. package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.js.map +1 -0
  483. package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.d.ts +2 -0
  484. package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.d.ts.map +1 -0
  485. package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.js +708 -0
  486. package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.js.map +1 -0
  487. package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.d.ts +2 -0
  488. package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.d.ts.map +1 -0
  489. package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.js +208 -0
  490. package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.js.map +1 -0
  491. package/dist/scripts/__tests__/notify-state-io.test.js +26 -0
  492. package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -1
  493. package/dist/scripts/__tests__/notify-tmux-injection.test.js +23 -1
  494. package/dist/scripts/__tests__/notify-tmux-injection.test.js.map +1 -1
  495. package/dist/scripts/__tests__/postinstall.test.js +19 -1
  496. package/dist/scripts/__tests__/postinstall.test.js.map +1 -1
  497. package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts +2 -0
  498. package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts.map +1 -0
  499. package/dist/scripts/__tests__/reasoning-artifact-contract.test.js +108 -0
  500. package/dist/scripts/__tests__/reasoning-artifact-contract.test.js.map +1 -0
  501. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js +63 -173
  502. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js.map +1 -1
  503. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js +74 -159
  504. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js.map +1 -1
  505. package/dist/scripts/__tests__/smoke-packed-install.test.js +404 -13
  506. package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
  507. package/dist/scripts/__tests__/verify-native-release-assets.test.d.ts +2 -0
  508. package/dist/scripts/__tests__/verify-native-release-assets.test.d.ts.map +1 -0
  509. package/dist/scripts/__tests__/verify-native-release-assets.test.js +235 -0
  510. package/dist/scripts/__tests__/verify-native-release-assets.test.js.map +1 -0
  511. package/dist/scripts/codex-native-hook.d.ts +53 -1
  512. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  513. package/dist/scripts/codex-native-hook.js +14448 -1480
  514. package/dist/scripts/codex-native-hook.js.map +1 -1
  515. package/dist/scripts/codex-native-pre-post.d.ts +9 -0
  516. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
  517. package/dist/scripts/codex-native-pre-post.js +35 -12
  518. package/dist/scripts/codex-native-pre-post.js.map +1 -1
  519. package/dist/scripts/generate-native-release-manifest.js +80 -51
  520. package/dist/scripts/generate-native-release-manifest.js.map +1 -1
  521. package/dist/scripts/notify-fallback-watcher.js +78 -115
  522. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  523. package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
  524. package/dist/scripts/notify-hook/auto-nudge.js +74 -3
  525. package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
  526. package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
  527. package/dist/scripts/notify-hook/state-io.js +5 -0
  528. package/dist/scripts/notify-hook/state-io.js.map +1 -1
  529. package/dist/scripts/notify-hook/team-dispatch.d.ts +9 -0
  530. package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
  531. package/dist/scripts/notify-hook/team-dispatch.js +234 -79
  532. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  533. package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
  534. package/dist/scripts/notify-hook/team-leader-nudge.js +71 -16
  535. package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
  536. package/dist/scripts/notify-hook/team-tmux-guard.d.ts +12 -4
  537. package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
  538. package/dist/scripts/notify-hook/team-tmux-guard.js +365 -44
  539. package/dist/scripts/notify-hook/team-tmux-guard.js.map +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 +42 -21
  542. package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -1
  543. package/dist/scripts/notify-hook/team-worker.d.ts +3 -0
  544. package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
  545. package/dist/scripts/notify-hook/team-worker.js +82 -33
  546. package/dist/scripts/notify-hook/team-worker.js.map +1 -1
  547. package/dist/scripts/notify-hook/tmux-injection.d.ts +1 -0
  548. package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
  549. package/dist/scripts/notify-hook/tmux-injection.js +32 -3
  550. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  551. package/dist/scripts/notify-hook.js +79 -82
  552. package/dist/scripts/notify-hook.js.map +1 -1
  553. package/dist/scripts/postinstall-advisory.d.ts +14 -0
  554. package/dist/scripts/postinstall-advisory.d.ts.map +1 -0
  555. package/dist/scripts/postinstall-advisory.js +49 -0
  556. package/dist/scripts/postinstall-advisory.js.map +1 -0
  557. package/dist/scripts/postinstall.d.ts +1 -1
  558. package/dist/scripts/postinstall.d.ts.map +1 -1
  559. package/dist/scripts/postinstall.js +1 -1
  560. package/dist/scripts/postinstall.js.map +1 -1
  561. package/dist/scripts/smoke-packed-install.d.ts +80 -4
  562. package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
  563. package/dist/scripts/smoke-packed-install.js +3162 -26
  564. package/dist/scripts/smoke-packed-install.js.map +1 -1
  565. package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
  566. package/dist/scripts/sync-plugin-mirror.js +16 -1
  567. package/dist/scripts/sync-plugin-mirror.js.map +1 -1
  568. package/dist/scripts/verify-native-release-assets.js +37 -23
  569. package/dist/scripts/verify-native-release-assets.js.map +1 -1
  570. package/dist/state/__tests__/mode-state-context.test.js +61 -0
  571. package/dist/state/__tests__/mode-state-context.test.js.map +1 -1
  572. package/dist/state/__tests__/operations.test.js +462 -850
  573. package/dist/state/__tests__/operations.test.js.map +1 -1
  574. package/dist/state/__tests__/skill-active.test.js +400 -2
  575. package/dist/state/__tests__/skill-active.test.js.map +1 -1
  576. package/dist/state/mode-state-context.d.ts +8 -0
  577. package/dist/state/mode-state-context.d.ts.map +1 -1
  578. package/dist/state/mode-state-context.js +73 -0
  579. package/dist/state/mode-state-context.js.map +1 -1
  580. package/dist/state/operations.d.ts +3 -0
  581. package/dist/state/operations.d.ts.map +1 -1
  582. package/dist/state/operations.js +144 -40
  583. package/dist/state/operations.js.map +1 -1
  584. package/dist/state/skill-active.d.ts +18 -1
  585. package/dist/state/skill-active.d.ts.map +1 -1
  586. package/dist/state/skill-active.js +420 -23
  587. package/dist/state/skill-active.js.map +1 -1
  588. package/dist/state/workflow-transition-reconcile.d.ts +3 -0
  589. package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
  590. package/dist/state/workflow-transition-reconcile.js +10 -4
  591. package/dist/state/workflow-transition-reconcile.js.map +1 -1
  592. package/dist/state/workflow-transition.d.ts.map +1 -1
  593. package/dist/state/workflow-transition.js +3 -1
  594. package/dist/state/workflow-transition.js.map +1 -1
  595. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js +53 -247
  596. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js.map +1 -1
  597. package/dist/subagents/__tests__/tracker.test.js +837 -1048
  598. package/dist/subagents/__tests__/tracker.test.js.map +1 -1
  599. package/dist/subagents/tracker.d.ts +58 -135
  600. package/dist/subagents/tracker.d.ts.map +1 -1
  601. package/dist/subagents/tracker.js +811 -632
  602. package/dist/subagents/tracker.js.map +1 -1
  603. package/dist/team/__tests__/api-interop.test.js +91 -1
  604. package/dist/team/__tests__/api-interop.test.js.map +1 -1
  605. package/dist/team/__tests__/delivery-e2e-smoke.test.js +58 -17
  606. package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
  607. package/dist/team/__tests__/idle-nudge.test.js +45 -15
  608. package/dist/team/__tests__/idle-nudge.test.js.map +1 -1
  609. package/dist/team/__tests__/mcp-comm.test.js +197 -30
  610. package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
  611. package/dist/team/__tests__/model-contract.test.js +110 -3
  612. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  613. package/dist/team/__tests__/notice-ledger.test.d.ts +2 -0
  614. package/dist/team/__tests__/notice-ledger.test.d.ts.map +1 -0
  615. package/dist/team/__tests__/notice-ledger.test.js +131 -0
  616. package/dist/team/__tests__/notice-ledger.test.js.map +1 -0
  617. package/dist/team/__tests__/pane-teardown-residue-e2e.test.d.ts +2 -0
  618. package/dist/team/__tests__/pane-teardown-residue-e2e.test.d.ts.map +1 -0
  619. package/dist/team/__tests__/pane-teardown-residue-e2e.test.js +410 -0
  620. package/dist/team/__tests__/pane-teardown-residue-e2e.test.js.map +1 -0
  621. package/dist/team/__tests__/phase-controller.test.js +20 -0
  622. package/dist/team/__tests__/phase-controller.test.js.map +1 -1
  623. package/dist/team/__tests__/runtime-cli.test.js +9 -0
  624. package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
  625. package/dist/team/__tests__/runtime.test.js +3963 -428
  626. package/dist/team/__tests__/runtime.test.js.map +1 -1
  627. package/dist/team/__tests__/scaling.test.js +2405 -203
  628. package/dist/team/__tests__/scaling.test.js.map +1 -1
  629. package/dist/team/__tests__/state-root.test.js +117 -2
  630. package/dist/team/__tests__/state-root.test.js.map +1 -1
  631. package/dist/team/__tests__/state.test.js +804 -36
  632. package/dist/team/__tests__/state.test.js.map +1 -1
  633. package/dist/team/__tests__/team-ops-contract.test.js +6 -0
  634. package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
  635. package/dist/team/__tests__/tmux-session.test.js +4099 -1039
  636. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  637. package/dist/team/__tests__/tmux-source-authority-realtmux.test.d.ts +2 -0
  638. package/dist/team/__tests__/tmux-source-authority-realtmux.test.d.ts.map +1 -0
  639. package/dist/team/__tests__/tmux-source-authority-realtmux.test.js +149 -0
  640. package/dist/team/__tests__/tmux-source-authority-realtmux.test.js.map +1 -0
  641. package/dist/team/__tests__/tmux-test-fixture.d.ts +69 -0
  642. package/dist/team/__tests__/tmux-test-fixture.d.ts.map +1 -1
  643. package/dist/team/__tests__/tmux-test-fixture.js +242 -15
  644. package/dist/team/__tests__/tmux-test-fixture.js.map +1 -1
  645. package/dist/team/__tests__/tmux-test-fixture.test.js +177 -1
  646. package/dist/team/__tests__/tmux-test-fixture.test.js.map +1 -1
  647. package/dist/team/__tests__/worker-runtime-identity.test.js +53 -44
  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.map +1 -1
  652. package/dist/team/api-interop.js +15 -9
  653. package/dist/team/api-interop.js.map +1 -1
  654. package/dist/team/exact-pane.d.ts +23 -0
  655. package/dist/team/exact-pane.d.ts.map +1 -0
  656. package/dist/team/exact-pane.js +133 -0
  657. package/dist/team/exact-pane.js.map +1 -0
  658. package/dist/team/idle-nudge.d.ts +12 -1
  659. package/dist/team/idle-nudge.d.ts.map +1 -1
  660. package/dist/team/idle-nudge.js +41 -14
  661. package/dist/team/idle-nudge.js.map +1 -1
  662. package/dist/team/model-contract.d.ts +2 -5
  663. package/dist/team/model-contract.d.ts.map +1 -1
  664. package/dist/team/model-contract.js +59 -17
  665. package/dist/team/model-contract.js.map +1 -1
  666. package/dist/team/notice-ledger.d.ts +54 -0
  667. package/dist/team/notice-ledger.d.ts.map +1 -0
  668. package/dist/team/notice-ledger.js +259 -0
  669. package/dist/team/notice-ledger.js.map +1 -0
  670. package/dist/team/phase-controller.d.ts.map +1 -1
  671. package/dist/team/phase-controller.js +2 -0
  672. package/dist/team/phase-controller.js.map +1 -1
  673. package/dist/team/runtime.d.ts +4 -1
  674. package/dist/team/runtime.d.ts.map +1 -1
  675. package/dist/team/runtime.js +1527 -291
  676. package/dist/team/runtime.js.map +1 -1
  677. package/dist/team/scaling.d.ts +13 -1
  678. package/dist/team/scaling.d.ts.map +1 -1
  679. package/dist/team/scaling.js +1503 -387
  680. package/dist/team/scaling.js.map +1 -1
  681. package/dist/team/state/dispatch.d.ts.map +1 -1
  682. package/dist/team/state/dispatch.js +26 -8
  683. package/dist/team/state/dispatch.js.map +1 -1
  684. package/dist/team/state/locks.d.ts.map +1 -1
  685. package/dist/team/state/locks.js +61 -13
  686. package/dist/team/state/locks.js.map +1 -1
  687. package/dist/team/state/monitor.d.ts +10 -0
  688. package/dist/team/state/monitor.d.ts.map +1 -1
  689. package/dist/team/state/monitor.js +13 -0
  690. package/dist/team/state/monitor.js.map +1 -1
  691. package/dist/team/state/tasks.d.ts.map +1 -1
  692. package/dist/team/state/tasks.js +4 -3
  693. package/dist/team/state/tasks.js.map +1 -1
  694. package/dist/team/state/types.d.ts +15 -0
  695. package/dist/team/state/types.d.ts.map +1 -1
  696. package/dist/team/state/types.js.map +1 -1
  697. package/dist/team/state-root.d.ts +12 -0
  698. package/dist/team/state-root.d.ts.map +1 -1
  699. package/dist/team/state-root.js +177 -0
  700. package/dist/team/state-root.js.map +1 -1
  701. package/dist/team/state.d.ts +85 -1
  702. package/dist/team/state.d.ts.map +1 -1
  703. package/dist/team/state.js +672 -129
  704. package/dist/team/state.js.map +1 -1
  705. package/dist/team/team-ops.d.ts +5 -0
  706. package/dist/team/team-ops.d.ts.map +1 -1
  707. package/dist/team/team-ops.js +4 -0
  708. package/dist/team/team-ops.js.map +1 -1
  709. package/dist/team/tmux-session.d.ts +163 -27
  710. package/dist/team/tmux-session.d.ts.map +1 -1
  711. package/dist/team/tmux-session.js +1682 -376
  712. package/dist/team/tmux-session.js.map +1 -1
  713. package/dist/team/worktree.d.ts.map +1 -1
  714. package/dist/team/worktree.js +4 -0
  715. package/dist/team/worktree.js.map +1 -1
  716. package/dist/ultragoal/__tests__/artifacts.test.js +950 -2
  717. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  718. package/dist/ultragoal/__tests__/docs-contract.test.js +1 -0
  719. package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
  720. package/dist/ultragoal/artifacts.d.ts +35 -1
  721. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  722. package/dist/ultragoal/artifacts.js +232 -46
  723. package/dist/ultragoal/artifacts.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 +114 -0
  727. package/dist/utils/__tests__/file-durability.test.js.map +1 -0
  728. package/dist/utils/__tests__/paths.test.js +21 -1
  729. package/dist/utils/__tests__/paths.test.js.map +1 -1
  730. package/dist/utils/file-durability.d.ts +25 -0
  731. package/dist/utils/file-durability.d.ts.map +1 -0
  732. package/dist/utils/file-durability.js +67 -0
  733. package/dist/utils/file-durability.js.map +1 -0
  734. package/dist/utils/paths.d.ts.map +1 -1
  735. package/dist/utils/paths.js +14 -6
  736. package/dist/utils/paths.js.map +1 -1
  737. package/dist/verification/__tests__/ci-rust-gates.test.js +49 -4
  738. package/dist/verification/__tests__/ci-rust-gates.test.js.map +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/__tests__/explore-harness-release-workflow.test.js +60 -0
  742. package/dist/verification/__tests__/explore-harness-release-workflow.test.js.map +1 -1
  743. package/dist/verification/__tests__/native-release-manifest.test.js +157 -4
  744. package/dist/verification/__tests__/native-release-manifest.test.js.map +1 -1
  745. package/dist/wiki/lint.d.ts +4 -1
  746. package/dist/wiki/lint.d.ts.map +1 -1
  747. package/dist/wiki/lint.js +3 -2
  748. package/dist/wiki/lint.js.map +1 -1
  749. package/package.json +13 -5
  750. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  751. package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +105 -17
  752. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +13 -5
  753. package/plugins/oh-my-codex/skills/cancel/SKILL.md +30 -85
  754. package/plugins/oh-my-codex/skills/ralph/SKILL.md +6 -4
  755. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +16 -17
  756. package/plugins/oh-my-codex/skills/team/SKILL.md +13 -9
  757. package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +3 -2
  758. package/skills/autopilot/SKILL.md +13 -5
  759. package/skills/cancel/SKILL.md +30 -85
  760. package/skills/ralph/SKILL.md +6 -4
  761. package/skills/ralplan/SKILL.md +16 -17
  762. package/skills/team/SKILL.md +13 -9
  763. package/skills/ultragoal/SKILL.md +3 -2
  764. package/src/scripts/__tests__/codex-native-hook.test.ts +8831 -951
  765. package/src/scripts/__tests__/issue-3293-callsite-parity.test.ts +187 -0
  766. package/src/scripts/__tests__/issue-3293-cancel-transaction.test.ts +189 -0
  767. package/src/scripts/__tests__/issue-3293-hook-owned-cancel.test.ts +187 -0
  768. package/src/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.ts +591 -0
  769. package/src/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.ts +701 -0
  770. package/src/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.ts +211 -0
  771. package/src/scripts/__tests__/notify-state-io.test.ts +29 -0
  772. package/src/scripts/__tests__/notify-tmux-injection.test.ts +26 -1
  773. package/src/scripts/__tests__/postinstall.test.ts +23 -1
  774. package/src/scripts/__tests__/reasoning-artifact-contract.test.ts +129 -0
  775. package/src/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.ts +67 -185
  776. package/src/scripts/__tests__/role-intent-durable-recovery-3181.test.ts +79 -178
  777. package/src/scripts/__tests__/smoke-packed-install.test.ts +525 -16
  778. package/src/scripts/__tests__/verify-native-release-assets.test.ts +240 -0
  779. package/src/scripts/codex-native-hook.ts +14238 -1429
  780. package/src/scripts/codex-native-pre-post.ts +43 -12
  781. package/src/scripts/generate-native-release-manifest.ts +83 -79
  782. package/src/scripts/notify-fallback-watcher.ts +91 -122
  783. package/src/scripts/notify-hook/auto-nudge.ts +71 -3
  784. package/src/scripts/notify-hook/state-io.ts +11 -0
  785. package/src/scripts/notify-hook/team-dispatch.ts +242 -75
  786. package/src/scripts/notify-hook/team-leader-nudge.ts +72 -22
  787. package/src/scripts/notify-hook/team-tmux-guard.ts +366 -39
  788. package/src/scripts/notify-hook/team-worker-stop.ts +43 -20
  789. package/src/scripts/notify-hook/team-worker.ts +82 -31
  790. package/src/scripts/notify-hook/tmux-injection.ts +33 -3
  791. package/src/scripts/notify-hook.ts +84 -82
  792. package/src/scripts/postinstall-advisory.ts +67 -0
  793. package/src/scripts/postinstall.ts +1 -1
  794. package/src/scripts/smoke-packed-install.ts +3608 -39
  795. package/src/scripts/sync-plugin-mirror.ts +17 -1
  796. package/src/scripts/verify-native-release-assets.ts +39 -31
  797. package/templates/AGENTS.md +1 -0
  798. package/dist/subagents/__tests__/adapted-role-binding.test.d.ts +0 -2
  799. package/dist/subagents/__tests__/adapted-role-binding.test.d.ts.map +0 -1
  800. package/dist/subagents/__tests__/adapted-role-binding.test.js +0 -988
  801. package/dist/subagents/__tests__/adapted-role-binding.test.js.map +0 -1
  802. package/dist/subagents/adapted-role-binding.d.ts +0 -17
  803. package/dist/subagents/adapted-role-binding.d.ts.map +0 -1
  804. package/dist/subagents/adapted-role-binding.js +0 -75
  805. package/dist/subagents/adapted-role-binding.js.map +0 -1
@@ -1,10 +1,11 @@
1
1
  import { afterEach, beforeEach, describe, it } from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import { mkdir, mkdtemp, realpath, rm, symlink, writeFile } from 'fs/promises';
3
+ import { mkdir, mkdtemp, readFile, readdir, realpath, rm, symlink, writeFile } from 'fs/promises';
4
4
  import { existsSync } from 'fs';
5
5
  import { tmpdir } from 'os';
6
6
  import { join, resolve as resolvePath } from 'path';
7
- import { getAllScopedStateDirs, getAllScopedStatePaths, getBaseStateDir, getBaseStateDirWithSource, getAllSessionScopedStateDirs, getAllSessionScopedStatePaths, getReadScopedStateFilePaths, readCurrentSessionId, resolveRuntimeStateScope, resolveStateScope, resolveWritableStateScope, resolveWorkingDirectoryForState, getStateDir, getStateFilePath, getStatePath, normalizeSessionId, validateStateFileName, validateStateModeSegment, validateSessionId, WRITABLE_STATE_SCOPE_ERRORS, } from '../state-paths.js';
7
+ import { getAllScopedStateDirs, getAllScopedStatePaths, getBaseStateDir, getBaseStateDirWithSource, getAllSessionScopedStateDirs, getAllSessionScopedStatePaths, getReadScopedStateFilePaths, readCurrentSessionId, readSessionMetadataFromBaseStateDir, resolveRuntimeStateScope, resolveStateScope, resolveWritableStateScope, createWritableCommitRevalidator, __setWritableStateScopeTestHooksForTests, resolveWorkingDirectoryForState, getStateDir, getStateFilePath, getStatePath, normalizeSessionId, validateStateFileName, validateStateModeSegment, validateSessionId, WRITABLE_STATE_SCOPE_ERRORS, readCanonicalSessionBindingSnapshot, VERIFIED_SESSION_BINDING_FIELDS, } from '../state-paths.js';
8
+ import { __resetSessionPointerTransactionDependenciesForTests, __setSessionPointerTransactionDependenciesForTests, } from '../../hooks/session.js';
8
9
  const isolatedEnvKeys = [
9
10
  'OMX_MCP_WORKDIR_ROOTS',
10
11
  'OMX_ROOT',
@@ -33,6 +34,26 @@ afterEach(() => {
33
34
  async function mkRealTemp(prefix) {
34
35
  return await realpath(await mkdtemp(join(await realpath(tmpdir()), prefix)));
35
36
  }
37
+ function armPointerTakeover(options) {
38
+ const observed = [];
39
+ return {
40
+ observed,
41
+ hook: async (event) => {
42
+ const actual = { commitOrdinal: event.commitOrdinal, site: event.site, kind: event.kind, path: event.path };
43
+ observed.push(actual);
44
+ if (event.commitOrdinal === options.expectedOrdinal && event.site !== options.expectedSite) {
45
+ throw new Error(`Expected takeover at ordinal ${options.expectedOrdinal} site ${options.expectedSite}; received ordinal ${event.commitOrdinal} site ${event.site}.`);
46
+ }
47
+ if (event.site === options.expectedSite && event.commitOrdinal !== options.expectedOrdinal) {
48
+ throw new Error(`Expected takeover at ordinal ${options.expectedOrdinal} site ${options.expectedSite}; received ordinal ${event.commitOrdinal} site ${event.site}.`);
49
+ }
50
+ if (event.commitOrdinal === options.expectedOrdinal && event.site === options.expectedSite) {
51
+ options.beforePublish?.();
52
+ await writeFile(options.sessionPath, options.replacementPointer);
53
+ }
54
+ },
55
+ };
56
+ }
36
57
  describe('validateSessionId', () => {
37
58
  it('accepts undefined and valid ids', () => {
38
59
  assert.equal(validateSessionId(undefined), undefined);
@@ -51,6 +72,110 @@ describe('normalizeSessionId', () => {
51
72
  assert.equal(normalizeSessionId(123), undefined);
52
73
  });
53
74
  });
75
+ describe('canonical session binding snapshot', () => {
76
+ it('accepts a descendant cwd through session authority and keeps the pointer bytes unchanged', async () => {
77
+ const root = await mkRealTemp('omx-binding-descendant-');
78
+ const nested = join(root, 'nested', 'child');
79
+ const env = { OMX_SESSION_ID: 'sess-descendant' };
80
+ try {
81
+ const stateDir = getBaseStateDir(root);
82
+ await mkdir(stateDir, { recursive: true });
83
+ await mkdir(nested, { recursive: true });
84
+ const pointer = JSON.stringify({ session_id: 'sess-descendant', cwd: root, state_root: stateDir });
85
+ await writeFile(join(stateDir, 'session.json'), pointer);
86
+ const snapshot = await readCanonicalSessionBindingSnapshot(nested, env);
87
+ assert.equal(snapshot.status, 'usable');
88
+ assert.equal(snapshot.rootSource, 'session-authority');
89
+ assert.equal(snapshot.recordedCwd, root);
90
+ assert.equal(snapshot.baseStateDir, stateDir);
91
+ assert.equal(await readFile(join(stateDir, 'session.json'), 'utf8'), pointer);
92
+ }
93
+ finally {
94
+ await rm(root, { recursive: true, force: true });
95
+ }
96
+ });
97
+ it('rejects a selected pointer whose explicit state root mismatches the selected root', async () => {
98
+ const root = await mkRealTemp('omx-binding-root-mismatch-');
99
+ const selectedRoot = join(root, 'selected');
100
+ const env = { OMX_ROOT: selectedRoot };
101
+ try {
102
+ const stateDir = getBaseStateDir(root, env);
103
+ await mkdir(stateDir, { recursive: true });
104
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({
105
+ session_id: 'sess-mismatch', cwd: root, state_root: join(root, 'foreign-state'),
106
+ }));
107
+ const snapshot = await readCanonicalSessionBindingSnapshot(root, env);
108
+ assert.equal(snapshot.status, 'root-mismatch');
109
+ assert.equal(snapshot.rootSource, 'omx-root-env');
110
+ assert.equal(snapshot.baseStateDir, stateDir);
111
+ assert.equal(snapshot.selectedSessionJson, join(stateDir, 'session.json'));
112
+ }
113
+ finally {
114
+ await rm(root, { recursive: true, force: true });
115
+ }
116
+ });
117
+ it('uses the legacy cwd-derived root and only exposes the six verified aliases', async () => {
118
+ const root = await mkRealTemp('omx-binding-legacy-aliases-');
119
+ try {
120
+ const stateDir = getBaseStateDir(root);
121
+ await mkdir(stateDir, { recursive: true });
122
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({
123
+ session_id: 'sess-canonical', native_session_id: 'native-id', codex_session_id: 'codex-id',
124
+ previous_native_session_id: 'previous-id', owner_omx_session_id: 'owner-omx', owner_codex_session_id: 'owner-codex',
125
+ owner_codex_thread_id: 'thread-must-not-bind', tmux_pane_id: '%9', tmux_session_name: 'foreign-tmux',
126
+ display_name: 'display-must-not-bind', owner_unknown_id: 'unknown-must-not-bind', cwd: root,
127
+ }));
128
+ const snapshot = await readCanonicalSessionBindingSnapshot(root, {});
129
+ assert.equal(snapshot.status, 'usable');
130
+ assert.equal(snapshot.baseStateDir, stateDir);
131
+ assert.deepEqual(Object.keys(snapshot.verifiedAliases), [...VERIFIED_SESSION_BINDING_FIELDS]);
132
+ assert.deepEqual(snapshot.verifiedAliases, {
133
+ session_id: 'sess-canonical', native_session_id: 'native-id', codex_session_id: 'codex-id',
134
+ previous_native_session_id: 'previous-id', owner_omx_session_id: 'owner-omx', owner_codex_session_id: 'owner-codex',
135
+ });
136
+ assert.equal(snapshot.verifiedAliases.owner_codex_thread_id, undefined);
137
+ }
138
+ finally {
139
+ await rm(root, { recursive: true, force: true });
140
+ }
141
+ });
142
+ it('fails closed when state_root is present but blank', async () => {
143
+ const root = await mkRealTemp('omx-binding-blank-state-root-');
144
+ try {
145
+ const stateDir = getBaseStateDir(root);
146
+ await mkdir(stateDir, { recursive: true });
147
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({
148
+ session_id: 'sess-blank-root', cwd: root, state_root: ' ',
149
+ }));
150
+ const snapshot = await readCanonicalSessionBindingSnapshot(root, {});
151
+ assert.equal(snapshot.status, 'malformed');
152
+ }
153
+ finally {
154
+ await rm(root, { recursive: true, force: true });
155
+ }
156
+ });
157
+ it('compares selected and recorded roots by realpath', async () => {
158
+ const realRoot = await mkRealTemp('omx-binding-real-root-');
159
+ const linkParent = await mkRealTemp('omx-binding-link-parent-');
160
+ const linkedRoot = join(linkParent, 'workspace-link');
161
+ try {
162
+ await symlink(realRoot, linkedRoot, process.platform === 'win32' ? 'junction' : 'dir');
163
+ const stateDir = getBaseStateDir(realRoot);
164
+ await mkdir(stateDir, { recursive: true });
165
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({
166
+ session_id: 'sess-realpath', cwd: realRoot, state_root: stateDir,
167
+ }));
168
+ const snapshot = await readCanonicalSessionBindingSnapshot(linkedRoot, { OMX_ROOT: linkedRoot });
169
+ assert.equal(snapshot.status, 'usable');
170
+ assert.ok(snapshot.baseStateDir);
171
+ assert.equal(await realpath(snapshot.baseStateDir), await realpath(stateDir));
172
+ }
173
+ finally {
174
+ await rm(realRoot, { recursive: true, force: true });
175
+ await rm(linkParent, { recursive: true, force: true });
176
+ }
177
+ });
178
+ });
54
179
  describe('validateStateModeSegment', () => {
55
180
  it('accepts safe mode names', () => {
56
181
  assert.equal(validateStateModeSegment('ralph'), 'ralph');
@@ -136,6 +261,159 @@ describe('state paths', () => {
136
261
  delete process.env.OMX_TEAM_STATE_ROOT;
137
262
  }
138
263
  });
264
+ it('uses the ancestor session pointer matching OMX_SESSION_ID as the authoritative root', async () => {
265
+ const parent = await mkRealTemp('omx-state-authority-parent-');
266
+ const nested = join(parent, 'nested', 'project');
267
+ const parentState = join(parent, '.omx', 'state');
268
+ const nestedState = join(nested, '.omx', 'state');
269
+ try {
270
+ await mkdir(parentState, { recursive: true });
271
+ await mkdir(nestedState, { recursive: true });
272
+ await writeFile(join(parentState, 'session.json'), JSON.stringify({ session_id: 'sess-parent', cwd: parent, state_root: parentState }));
273
+ await writeFile(join(nestedState, 'session.json'), JSON.stringify({ session_id: 'sess-nested', cwd: nested }));
274
+ process.env.OMX_SESSION_ID = 'sess-parent';
275
+ assert.deepEqual(getBaseStateDirWithSource(nested), {
276
+ baseStateDir: parentState,
277
+ rootSource: 'session-authority',
278
+ });
279
+ const writable = await resolveWritableStateScope(nested);
280
+ assert.equal(writable.stateDir, join(parentState, 'sessions', 'sess-parent'));
281
+ }
282
+ finally {
283
+ await rm(parent, { recursive: true, force: true });
284
+ }
285
+ });
286
+ it('uses a live legacy ancestor pointer when its inferred root matches exactly', async () => {
287
+ const parent = await mkRealTemp('omx-state-authority-legacy-');
288
+ const nested = join(parent, 'nested');
289
+ const parentState = join(parent, '.omx', 'state');
290
+ try {
291
+ await mkdir(parentState, { recursive: true });
292
+ await mkdir(nested, { recursive: true });
293
+ await writeFile(join(parentState, 'session.json'), JSON.stringify({ session_id: 'sess-legacy', cwd: parent }));
294
+ process.env.OMX_SESSION_ID = 'sess-legacy';
295
+ assert.deepEqual(getBaseStateDirWithSource(nested), {
296
+ baseStateDir: parentState,
297
+ rootSource: 'session-authority',
298
+ });
299
+ }
300
+ finally {
301
+ await rm(parent, { recursive: true, force: true });
302
+ }
303
+ });
304
+ it('rejects pointers whose persisted or inferred root does not own the selected base', async () => {
305
+ const cwd = await mkRealTemp('omx-state-pointer-root-owner-');
306
+ const selectedState = join(cwd, 'selected-state');
307
+ const claimedState = join(cwd, 'claimed-state');
308
+ try {
309
+ await mkdir(selectedState, { recursive: true });
310
+ await writeFile(join(selectedState, 'session.json'), JSON.stringify({
311
+ session_id: 'sess-mismatch',
312
+ cwd,
313
+ state_root: claimedState,
314
+ }));
315
+ assert.equal(await readSessionMetadataFromBaseStateDir(cwd, selectedState), undefined);
316
+ await writeFile(join(selectedState, 'session.json'), JSON.stringify({ session_id: 'sess-legacy-explicit', cwd }));
317
+ assert.equal(await readSessionMetadataFromBaseStateDir(cwd, selectedState), undefined);
318
+ }
319
+ finally {
320
+ await rm(cwd, { recursive: true, force: true });
321
+ }
322
+ });
323
+ it('fails explicitly when multiple ancestor pointers claim the same session authority', async () => {
324
+ const parent = await mkRealTemp('omx-state-authority-conflict-');
325
+ const nested = join(parent, 'nested');
326
+ const parentState = join(parent, '.omx', 'state');
327
+ const nestedState = join(nested, '.omx', 'state');
328
+ try {
329
+ await mkdir(parentState, { recursive: true });
330
+ await mkdir(nestedState, { recursive: true });
331
+ await writeFile(join(parentState, 'session.json'), JSON.stringify({ session_id: 'sess-conflict', cwd: parent, state_root: parentState }));
332
+ await writeFile(join(nestedState, 'session.json'), JSON.stringify({ session_id: 'sess-conflict', cwd: nested, state_root: nestedState }));
333
+ process.env.OMX_SESSION_ID = 'sess-conflict';
334
+ assert.throws(() => getBaseStateDirWithSource(nested), new RegExp(`Conflicting authoritative state roots.*${parentState}.*${nestedState}|Conflicting authoritative state roots.*${nestedState}.*${parentState}`));
335
+ }
336
+ finally {
337
+ await rm(parent, { recursive: true, force: true });
338
+ }
339
+ });
340
+ it('ignores a dead matching ancestor session pointer', async () => {
341
+ const parent = await mkRealTemp('omx-state-authority-dead-');
342
+ const nested = join(parent, 'nested');
343
+ const parentState = join(parent, '.omx', 'state');
344
+ try {
345
+ await mkdir(parentState, { recursive: true });
346
+ await mkdir(nested, { recursive: true });
347
+ await writeFile(join(parentState, 'session.json'), JSON.stringify({
348
+ session_id: 'sess-dead',
349
+ cwd: parent,
350
+ pid: 2_147_483_647,
351
+ }));
352
+ process.env.OMX_SESSION_ID = 'sess-dead';
353
+ assert.deepEqual(getBaseStateDirWithSource(nested), {
354
+ baseStateDir: join(nested, '.omx', 'state'),
355
+ rootSource: 'cwd-default',
356
+ });
357
+ }
358
+ finally {
359
+ await rm(parent, { recursive: true, force: true });
360
+ }
361
+ });
362
+ it('does not discover ancestor authority outside OMX_MCP_WORKDIR_ROOTS', async () => {
363
+ const parent = await mkRealTemp('omx-state-authority-allowlist-');
364
+ const nested = join(parent, 'nested');
365
+ const parentState = join(parent, '.omx', 'state');
366
+ try {
367
+ await mkdir(parentState, { recursive: true });
368
+ await mkdir(nested, { recursive: true });
369
+ await writeFile(join(parentState, 'session.json'), JSON.stringify({ session_id: 'sess-outside', cwd: parent }));
370
+ process.env.OMX_SESSION_ID = 'sess-outside';
371
+ process.env.OMX_MCP_WORKDIR_ROOTS = nested;
372
+ assert.deepEqual(getBaseStateDirWithSource(nested), {
373
+ baseStateDir: join(nested, '.omx', 'state'),
374
+ rootSource: 'cwd-default',
375
+ });
376
+ }
377
+ finally {
378
+ await rm(parent, { recursive: true, force: true });
379
+ }
380
+ });
381
+ it('does not select an in-allowlist state symlink that escapes the allowed root', async () => {
382
+ const parent = await mkRealTemp('omx-state-authority-symlink-');
383
+ const nested = join(parent, 'nested');
384
+ const outsideState = join(parent, 'outside-state');
385
+ try {
386
+ await mkdir(join(nested, '.omx'), { recursive: true });
387
+ await mkdir(outsideState, { recursive: true });
388
+ await writeFile(join(outsideState, 'session.json'), JSON.stringify({ session_id: 'sess-symlink', cwd: nested }));
389
+ await symlink(outsideState, join(nested, '.omx', 'state'), process.platform === 'win32' ? 'junction' : 'dir');
390
+ process.env.OMX_SESSION_ID = 'sess-symlink';
391
+ process.env.OMX_MCP_WORKDIR_ROOTS = nested;
392
+ assert.throws(() => getBaseStateDirWithSource(nested), /State root .* is outside allowed roots \(OMX_MCP_WORKDIR_ROOTS\)/);
393
+ }
394
+ finally {
395
+ await rm(parent, { recursive: true, force: true });
396
+ }
397
+ });
398
+ it('rejects OMX_ROOT and OMX_STATE_ROOT whose appended state directory escapes the allowlist', async () => {
399
+ const parent = await mkRealTemp('omx-state-override-symlink-');
400
+ const allowed = join(parent, 'allowed');
401
+ const outsideState = join(parent, 'outside-state');
402
+ try {
403
+ await mkdir(join(allowed, '.omx'), { recursive: true });
404
+ await mkdir(outsideState, { recursive: true });
405
+ await symlink(outsideState, join(allowed, '.omx', 'state'), process.platform === 'win32' ? 'junction' : 'dir');
406
+ process.env.OMX_MCP_WORKDIR_ROOTS = allowed;
407
+ process.env.OMX_ROOT = allowed;
408
+ assert.throws(() => getBaseStateDirWithSource(allowed), /State root .* is outside allowed roots/);
409
+ delete process.env.OMX_ROOT;
410
+ process.env.OMX_STATE_ROOT = allowed;
411
+ assert.throws(() => getBaseStateDirWithSource(allowed), /State root .* is outside allowed roots/);
412
+ }
413
+ finally {
414
+ await rm(parent, { recursive: true, force: true });
415
+ }
416
+ });
139
417
  it('fails closed when an explicit state root is outside the allowlist', async () => {
140
418
  const allowedRoot = await mkRealTemp('omx-state-root-allowed-');
141
419
  const disallowedRoot = await mkRealTemp('omx-state-root-disallowed-');
@@ -350,7 +628,11 @@ describe('state paths', () => {
350
628
  const stateDir = getBaseStateDir(wd);
351
629
  await mkdir(join(stateDir, 'sessions', 'sess-current'), { recursive: true });
352
630
  await mkdir(stateDir, { recursive: true });
353
- await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-current' }));
631
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({
632
+ session_id: 'sess-current',
633
+ cwd: wd,
634
+ state_root: stateDir,
635
+ }));
354
636
  const paths = await getReadScopedStateFilePaths('hud-state.json', wd, undefined, {
355
637
  rootFallback: false,
356
638
  });
@@ -427,6 +709,7 @@ describe('state paths', () => {
427
709
  session_id: 'native-id',
428
710
  native_session_id: 'native-id',
429
711
  owner_omx_session_id: 'omx-owner-id',
712
+ owner_codex_session_id: 'codex-owner-id',
430
713
  cwd: wd,
431
714
  }));
432
715
  process.env.OMX_SESSION_ID = 'omx-owner-id';
@@ -439,6 +722,14 @@ describe('state paths', () => {
439
722
  assert.equal(runtimeScope.sessionId, 'native-id');
440
723
  assert.equal(runtimeScope.stateDir, join(stateDir, 'sessions', 'native-id'));
441
724
  assert.equal(runtimeScope.source, 'native-alias');
725
+ process.env.OMX_SESSION_ID = 'codex-owner-id';
726
+ assert.equal(await readCurrentSessionId(wd), 'native-id');
727
+ const codexScope = await resolveStateScope(wd);
728
+ assert.equal(codexScope.sessionId, 'native-id');
729
+ assert.equal(codexScope.stateDir, join(stateDir, 'sessions', 'native-id'));
730
+ const codexRuntimeScope = await resolveRuntimeStateScope(wd);
731
+ assert.equal(codexRuntimeScope.sessionId, 'native-id');
732
+ assert.equal(codexRuntimeScope.stateDir, join(stateDir, 'sessions', 'native-id'));
442
733
  }
443
734
  finally {
444
735
  if (typeof previousOmxSessionId === 'string')
@@ -458,12 +749,16 @@ describe('state paths', () => {
458
749
  session_id: 'native-id',
459
750
  native_session_id: 'native-id',
460
751
  owner_omx_session_id: 'omx-owner-id',
752
+ owner_codex_session_id: 'codex-owner-id',
461
753
  cwd: wd,
462
754
  }));
463
755
  const scope = await resolveStateScope(wd, 'omx-owner-id');
464
756
  assert.equal(scope.sessionId, 'native-id');
465
757
  assert.equal(scope.stateDir, join(stateDir, 'sessions', 'native-id'));
466
758
  assert.notEqual(scope.stateDir, join(stateDir, 'sessions', 'omx-owner-id'));
759
+ const codexScope = await resolveStateScope(wd, 'codex-owner-id');
760
+ assert.equal(codexScope.sessionId, 'native-id');
761
+ assert.equal(codexScope.stateDir, join(stateDir, 'sessions', 'native-id'));
467
762
  }
468
763
  finally {
469
764
  await rm(wd, { recursive: true, force: true });
@@ -517,6 +812,7 @@ describe('state paths', () => {
517
812
  await writeFile(join(teamStateRoot, 'session.json'), JSON.stringify({
518
813
  session_id: 'sess-team-current',
519
814
  cwd: wd,
815
+ state_root: teamStateRoot,
520
816
  }));
521
817
  await mkdir(join(wd, '.omx', 'state'), { recursive: true });
522
818
  await writeFile(join(wd, '.omx', 'state', 'session.json'), JSON.stringify({
@@ -617,7 +913,7 @@ describe('state paths', () => {
617
913
  await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-canonical', cwd: wd }));
618
914
  process.env.OMX_SESSION_ID = 'sess-unmatched';
619
915
  await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
620
- assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unboundEnvironment);
916
+ assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.sessionBindingMismatch);
621
917
  return true;
622
918
  });
623
919
  assert.equal(existsSync(join(stateDir, 'sessions', 'sess-unmatched')), false);
@@ -640,6 +936,7 @@ describe('state paths', () => {
640
936
  session_id: 'sess-canonical',
641
937
  native_session_id: 'native-alias',
642
938
  owner_omx_session_id: 'omx-owner-alias',
939
+ owner_codex_session_id: 'codex-owner-alias',
643
940
  cwd: wd,
644
941
  }));
645
942
  process.env.OMX_SESSION_ID = 'omx-owner-alias';
@@ -648,11 +945,445 @@ describe('state paths', () => {
648
945
  sessionId: 'sess-canonical',
649
946
  stateDir: join(stateDir, 'sessions', 'sess-canonical'),
650
947
  });
948
+ process.env.OMX_SESSION_ID = 'codex-owner-alias';
949
+ assert.deepEqual(await resolveWritableStateScope(wd), {
950
+ source: 'session',
951
+ sessionId: 'sess-canonical',
952
+ stateDir: join(stateDir, 'sessions', 'sess-canonical'),
953
+ });
954
+ }
955
+ finally {
956
+ await rm(wd, { recursive: true, force: true });
957
+ }
958
+ });
959
+ it('binds an explicit exact-current OMX_SESSION_ID when the selected pointer is stale-dead', async () => {
960
+ const wd = await mkRealTemp('omx-writable-stale-dead-env-');
961
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
962
+ try {
963
+ const stateDir = getBaseStateDir(wd);
964
+ await mkdir(stateDir, { recursive: true });
965
+ const pointerBody = JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 });
966
+ await writeFile(join(stateDir, 'session.json'), pointerBody);
967
+ process.env.OMX_SESSION_ID = 'sess-current';
968
+ assert.deepEqual(await resolveWritableStateScope(wd), {
969
+ source: 'session',
970
+ sessionId: 'sess-current',
971
+ stateDir: join(stateDir, 'sessions', 'sess-current'),
972
+ });
973
+ // Scope resolution must never mutate the selected pointer; SessionStart
974
+ // remains the only session.json writer.
975
+ assert.equal(await readFile(join(stateDir, 'session.json'), 'utf-8'), pointerBody);
976
+ }
977
+ finally {
978
+ __resetSessionPointerTransactionDependenciesForTests();
979
+ await rm(wd, { recursive: true, force: true });
980
+ }
981
+ });
982
+ it('still fails closed for a stale-dead pointer without an env binding', async () => {
983
+ const wd = await mkRealTemp('omx-writable-stale-dead-noenv-');
984
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
985
+ try {
986
+ const stateDir = getBaseStateDir(wd);
987
+ await mkdir(stateDir, { recursive: true });
988
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 }));
989
+ await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
990
+ assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
991
+ return true;
992
+ });
993
+ }
994
+ finally {
995
+ __resetSessionPointerTransactionDependenciesForTests();
996
+ await rm(wd, { recursive: true, force: true });
997
+ }
998
+ });
999
+ it('fails closed for malformed and foreign-cwd pointers even with an env binding', async () => {
1000
+ const wd = await mkRealTemp('omx-writable-ambiguous-env-');
1001
+ try {
1002
+ const stateDir = getBaseStateDir(wd);
1003
+ await mkdir(stateDir, { recursive: true });
1004
+ process.env.OMX_SESSION_ID = 'sess-current';
1005
+ await writeFile(join(stateDir, 'session.json'), '{not json');
1006
+ await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
1007
+ assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
1008
+ return true;
1009
+ });
1010
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({
1011
+ session_id: 'sess-foreign',
1012
+ cwd: join(wd, 'other-worktree'),
1013
+ }));
1014
+ await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
1015
+ assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
1016
+ return true;
1017
+ });
651
1018
  }
652
1019
  finally {
653
1020
  await rm(wd, { recursive: true, force: true });
654
1021
  }
655
1022
  });
1023
+ it('fails closed for JSON-valid non-object pointers even with an env binding', async () => {
1024
+ const wd = await mkRealTemp('omx-writable-nonobject-env-');
1025
+ try {
1026
+ const stateDir = getBaseStateDir(wd);
1027
+ await mkdir(stateDir, { recursive: true });
1028
+ const sessionPath = join(stateDir, 'session.json');
1029
+ process.env.OMX_SESSION_ID = 'sess-current';
1030
+ // JSON null, arrays, and scalars parse cleanly but are not pointer
1031
+ // objects. They must surface the same stable unusable-session error as
1032
+ // syntactically malformed bytes rather than throwing on property access.
1033
+ for (const body of ['null', '[]', '42', '"sess-current"']) {
1034
+ await writeFile(sessionPath, body);
1035
+ await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
1036
+ assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
1037
+ return true;
1038
+ });
1039
+ assert.equal(await readFile(sessionPath, 'utf-8'), body);
1040
+ assert.equal(existsSync(join(stateDir, 'sessions', 'sess-current')), false);
1041
+ }
1042
+ }
1043
+ finally {
1044
+ await rm(wd, { recursive: true, force: true });
1045
+ }
1046
+ });
1047
+ it('recovers writable scope for an identity-indeterminate pointer with an exact-match OMX_SESSION_ID', async () => {
1048
+ const wd = await mkRealTemp('omx-writable-indeterminate-exact-');
1049
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'indeterminate' });
1050
+ try {
1051
+ const stateDir = getBaseStateDir(wd);
1052
+ const sessionPath = join(stateDir, 'session.json');
1053
+ await mkdir(stateDir, { recursive: true });
1054
+ const pointerBody = JSON.stringify({ session_id: 'sess-exact', cwd: wd, pid: 8388607 });
1055
+ await writeFile(sessionPath, pointerBody);
1056
+ const beforePointer = await readFile(sessionPath, 'utf-8');
1057
+ const beforeEntries = (await readdir(stateDir)).sort();
1058
+ process.env.OMX_SESSION_ID = 'sess-exact';
1059
+ assert.deepEqual(await resolveWritableStateScope(wd), {
1060
+ source: 'session',
1061
+ sessionId: 'sess-exact',
1062
+ stateDir: join(stateDir, 'sessions', 'sess-exact'),
1063
+ });
1064
+ assert.equal(await readFile(sessionPath, 'utf-8'), beforePointer);
1065
+ assert.deepEqual((await readdir(stateDir)).sort(), beforeEntries);
1066
+ }
1067
+ finally {
1068
+ __resetSessionPointerTransactionDependenciesForTests();
1069
+ await rm(wd, { recursive: true, force: true });
1070
+ }
1071
+ });
1072
+ it('fails closed for an identity-indeterminate pointer even with an env binding', async () => {
1073
+ const wd = await mkRealTemp('omx-writable-indeterminate-env-');
1074
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'indeterminate' });
1075
+ try {
1076
+ const stateDir = getBaseStateDir(wd);
1077
+ await mkdir(stateDir, { recursive: true });
1078
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-unknown', cwd: wd, pid: 8388607 }));
1079
+ process.env.OMX_SESSION_ID = 'sess-current';
1080
+ await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
1081
+ assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
1082
+ return true;
1083
+ });
1084
+ assert.equal(existsSync(join(stateDir, 'sessions', 'sess-current')), false);
1085
+ }
1086
+ finally {
1087
+ __resetSessionPointerTransactionDependenciesForTests();
1088
+ await rm(wd, { recursive: true, force: true });
1089
+ }
1090
+ });
1091
+ it('fails closed for a stale-dead pointer without cwd or state_root authority even with an env binding', async () => {
1092
+ const wd = await mkRealTemp('omx-writable-stale-dead-noauthority-');
1093
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
1094
+ try {
1095
+ const stateDir = getBaseStateDir(wd);
1096
+ await mkdir(stateDir, { recursive: true });
1097
+ process.env.OMX_SESSION_ID = 'sess-current';
1098
+ // A dead PID does not cure a missing recorded cwd: the pointer holds
1099
+ // no selected-root authority, so recovery must stay fail-closed.
1100
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-dead', pid: 8388607 }));
1101
+ await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
1102
+ assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
1103
+ return true;
1104
+ });
1105
+ // A recorded state_root naming another root is equally non-authoritative.
1106
+ const foreignRoot = join(wd, 'other-root');
1107
+ await mkdir(foreignRoot, { recursive: true });
1108
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({
1109
+ session_id: 'sess-dead',
1110
+ cwd: wd,
1111
+ state_root: foreignRoot,
1112
+ pid: 8388607,
1113
+ }));
1114
+ await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
1115
+ assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
1116
+ return true;
1117
+ });
1118
+ assert.equal(existsSync(join(stateDir, 'sessions', 'sess-current')), false);
1119
+ }
1120
+ finally {
1121
+ __resetSessionPointerTransactionDependenciesForTests();
1122
+ await rm(wd, { recursive: true, force: true });
1123
+ }
1124
+ });
1125
+ });
1126
+ });
1127
+ describe('writable state scope recovery and revalidation', () => {
1128
+ it('T10 reads the selected decision snapshot and recovery stability snapshot once', async () => {
1129
+ const wd = await mkRealTemp('omx-writable-single-snapshot-');
1130
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
1131
+ try {
1132
+ const stateDir = getBaseStateDir(wd);
1133
+ await mkdir(stateDir, { recursive: true });
1134
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 }));
1135
+ process.env.OMX_SESSION_ID = 'sess-current';
1136
+ const decisions = [];
1137
+ const stability = [];
1138
+ __setWritableStateScopeTestHooksForTests({
1139
+ onSelectedDecisionSnapshotRead: (event) => decisions.push({ ...event }),
1140
+ onRecoveryStabilityReread: (event) => stability.push({ ...event }),
1141
+ });
1142
+ await resolveWritableStateScope(wd);
1143
+ assert.deepEqual(decisions.map(({ ordinal }) => ordinal), [1]);
1144
+ assert.deepEqual(stability.map(({ ordinal }) => ordinal), [1]);
1145
+ assert.equal(stability[0]?.raw, decisions[0]?.raw);
1146
+ }
1147
+ finally {
1148
+ __setWritableStateScopeTestHooksForTests({});
1149
+ __resetSessionPointerTransactionDependenciesForTests();
1150
+ await rm(wd, { recursive: true, force: true });
1151
+ }
1152
+ });
1153
+ it('T11 fails closed when the pointer bytes change during stale-dead recovery', async () => {
1154
+ const wd = await mkRealTemp('omx-writable-unstable-recovery-');
1155
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
1156
+ try {
1157
+ const stateDir = getBaseStateDir(wd);
1158
+ const sessionPath = join(stateDir, 'session.json');
1159
+ await mkdir(stateDir, { recursive: true });
1160
+ await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 }));
1161
+ process.env.OMX_SESSION_ID = 'sess-current';
1162
+ __setWritableStateScopeTestHooksForTests({
1163
+ beforeRecoveryReread: async () => {
1164
+ await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-replaced', cwd: wd }));
1165
+ },
1166
+ });
1167
+ await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
1168
+ assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
1169
+ return true;
1170
+ });
1171
+ assert.equal(existsSync(join(stateDir, 'sessions', 'sess-current')), false);
1172
+ }
1173
+ finally {
1174
+ __setWritableStateScopeTestHooksForTests({});
1175
+ __resetSessionPointerTransactionDependenciesForTests();
1176
+ await rm(wd, { recursive: true, force: true });
1177
+ }
1178
+ });
1179
+ it('fails closed when the pointer bytes change during identity-indeterminate exact-match recovery', async () => {
1180
+ const wd = await mkRealTemp('omx-writable-indeterminate-unstable-');
1181
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'indeterminate' });
1182
+ try {
1183
+ const stateDir = getBaseStateDir(wd);
1184
+ const sessionPath = join(stateDir, 'session.json');
1185
+ await mkdir(stateDir, { recursive: true });
1186
+ await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-indeterminate', cwd: wd, pid: 8388607 }));
1187
+ process.env.OMX_SESSION_ID = 'sess-indeterminate';
1188
+ __setWritableStateScopeTestHooksForTests({
1189
+ beforeRecoveryReread: async () => {
1190
+ await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-indeterminate', cwd: wd, pid: 9999999 }));
1191
+ },
1192
+ });
1193
+ await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
1194
+ assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession);
1195
+ return true;
1196
+ });
1197
+ assert.equal(existsSync(join(stateDir, 'sessions', 'sess-indeterminate')), false);
1198
+ }
1199
+ finally {
1200
+ __setWritableStateScopeTestHooksForTests({});
1201
+ __resetSessionPointerTransactionDependenciesForTests();
1202
+ await rm(wd, { recursive: true, force: true });
1203
+ }
1204
+ });
1205
+ it('T12 leaves the stale-dead pointer and base state root entries unchanged during recovery', async () => {
1206
+ const wd = await mkRealTemp('omx-writable-pointer-immutable-');
1207
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
1208
+ try {
1209
+ const stateDir = getBaseStateDir(wd);
1210
+ const sessionPath = join(stateDir, 'session.json');
1211
+ await mkdir(stateDir, { recursive: true });
1212
+ await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 }));
1213
+ const beforePointer = await readFile(sessionPath, 'utf-8');
1214
+ const beforeEntries = (await readdir(stateDir)).sort();
1215
+ process.env.OMX_SESSION_ID = 'sess-current';
1216
+ await resolveWritableStateScope(wd);
1217
+ assert.equal(await readFile(sessionPath, 'utf-8'), beforePointer);
1218
+ assert.deepEqual((await readdir(stateDir)).sort(), beforeEntries);
1219
+ }
1220
+ finally {
1221
+ __setWritableStateScopeTestHooksForTests({});
1222
+ __resetSessionPointerTransactionDependenciesForTests();
1223
+ await rm(wd, { recursive: true, force: true });
1224
+ }
1225
+ });
1226
+ it('T13 rejects stale-dead recovery without selected-root authority', async () => {
1227
+ const wd = await mkRealTemp('omx-writable-authority-matrix-');
1228
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
1229
+ try {
1230
+ const stateDir = getBaseStateDir(wd);
1231
+ await mkdir(stateDir, { recursive: true });
1232
+ process.env.OMX_SESSION_ID = 'sess-current';
1233
+ const cases = [
1234
+ { name: 'missing recorded cwd', pointer: { session_id: 'sess-dead', pid: 8388607 } },
1235
+ { name: 'different state root', pointer: { session_id: 'sess-dead', cwd: wd, state_root: join(wd, 'other-root'), pid: 8388607 } },
1236
+ { name: 'recorded cwd does not contain the observed cwd', pointer: { session_id: 'sess-dead', cwd: join(wd, 'other-worktree'), pid: 8388607 } },
1237
+ ];
1238
+ for (const testCase of cases) {
1239
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify(testCase.pointer));
1240
+ await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
1241
+ assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession, testCase.name);
1242
+ return true;
1243
+ });
1244
+ assert.equal(existsSync(join(stateDir, 'sessions', 'sess-current')), false, testCase.name);
1245
+ }
1246
+ }
1247
+ finally {
1248
+ __setWritableStateScopeTestHooksForTests({});
1249
+ __resetSessionPointerTransactionDependenciesForTests();
1250
+ await rm(wd, { recursive: true, force: true });
1251
+ }
1252
+ });
1253
+ it('fails closed for identity-indeterminate pointer without selected-root authority even with an exact-match env binding', async () => {
1254
+ const wd = await mkRealTemp('omx-writable-indeterminate-noauthority-');
1255
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'indeterminate' });
1256
+ try {
1257
+ const stateDir = getBaseStateDir(wd);
1258
+ await mkdir(stateDir, { recursive: true });
1259
+ process.env.OMX_SESSION_ID = 'sess-indeterminate';
1260
+ const cases = [
1261
+ { name: 'missing recorded cwd', pointer: { session_id: 'sess-indeterminate', pid: 8388607 } },
1262
+ { name: 'different state root', pointer: { session_id: 'sess-indeterminate', cwd: wd, state_root: join(wd, 'other-root'), pid: 8388607 } },
1263
+ { name: 'recorded cwd does not contain the observed cwd', pointer: { session_id: 'sess-indeterminate', cwd: join(wd, 'other-worktree'), pid: 8388607 } },
1264
+ ];
1265
+ for (const testCase of cases) {
1266
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify(testCase.pointer));
1267
+ await assert.rejects(() => resolveWritableStateScope(wd), (error) => {
1268
+ assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.unusableSession, testCase.name);
1269
+ return true;
1270
+ });
1271
+ assert.equal(existsSync(join(stateDir, 'sessions', 'sess-indeterminate')), false, testCase.name);
1272
+ }
1273
+ }
1274
+ finally {
1275
+ __setWritableStateScopeTestHooksForTests({});
1276
+ __resetSessionPointerTransactionDependenciesForTests();
1277
+ await rm(wd, { recursive: true, force: true });
1278
+ }
1279
+ });
1280
+ it('T1 gives each writable commit revalidator a closure-local ordinal sequence', async () => {
1281
+ const wd = await mkRealTemp('omx-writable-revalidator-ordinals-');
1282
+ __setSessionPointerTransactionDependenciesForTests({});
1283
+ try {
1284
+ const stateDir = getBaseStateDir(wd);
1285
+ await mkdir(stateDir, { recursive: true });
1286
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-current', cwd: wd }));
1287
+ const capturedScope = await resolveWritableStateScope(wd);
1288
+ const events = [];
1289
+ __setWritableStateScopeTestHooksForTests({
1290
+ beforeScopeRevalidation: async (event) => { events.push({ ...event }); },
1291
+ });
1292
+ const options = { operation: 'state_write', cwd: wd, explicitSessionId: undefined, capturedScope, baseStateDir: stateDir };
1293
+ const revalidate = createWritableCommitRevalidator(options);
1294
+ const attempts = [
1295
+ { site: 'mode.primary', kind: 'write', path: join(stateDir, 'mode-state.json') },
1296
+ { site: 'skill-active.root-copy', kind: 'write', path: join(stateDir, 'skill-active.json') },
1297
+ { site: 'skill-active.session-copy', kind: 'write', path: join(stateDir, 'sessions', 'sess-current', 'skill-active.json') },
1298
+ ];
1299
+ for (const attempt of attempts)
1300
+ await revalidate(attempt);
1301
+ await createWritableCommitRevalidator(options)(attempts[0]);
1302
+ assert.deepEqual(events, [
1303
+ ...attempts.map((attempt, index) => ({ operation: 'state_write', commitOrdinal: index + 1, ...attempt })),
1304
+ { operation: 'state_write', commitOrdinal: 1, ...attempts[0] },
1305
+ ]);
1306
+ }
1307
+ finally {
1308
+ __setWritableStateScopeTestHooksForTests({});
1309
+ __resetSessionPointerTransactionDependenciesForTests();
1310
+ await rm(wd, { recursive: true, force: true });
1311
+ }
1312
+ });
1313
+ it('T2 rejects a writable commit when revalidation observes a replacement scope', async () => {
1314
+ const wd = await mkRealTemp('omx-writable-revalidator-drift-');
1315
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
1316
+ try {
1317
+ const stateDir = getBaseStateDir(wd);
1318
+ const sessionPath = join(stateDir, 'session.json');
1319
+ await mkdir(stateDir, { recursive: true });
1320
+ await writeFile(sessionPath, JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 }));
1321
+ process.env.OMX_SESSION_ID = 'sess-current';
1322
+ const capturedScope = await resolveWritableStateScope(wd);
1323
+ const takeover = armPointerTakeover({
1324
+ expectedOrdinal: 1,
1325
+ expectedSite: 'mode.primary',
1326
+ sessionPath,
1327
+ replacementPointer: JSON.stringify({ session_id: 'sess-replacement', cwd: wd }),
1328
+ beforePublish: () => { process.env.OMX_SESSION_ID = 'sess-replacement'; },
1329
+ });
1330
+ __setWritableStateScopeTestHooksForTests({ beforeScopeRevalidation: takeover.hook });
1331
+ const revalidate = createWritableCommitRevalidator({
1332
+ operation: 'state_write', cwd: wd, explicitSessionId: undefined, capturedScope, baseStateDir: stateDir,
1333
+ });
1334
+ await assert.rejects(() => revalidate({ site: 'mode.primary', kind: 'write', path: join(stateDir, 'mode-state.json') }), (error) => {
1335
+ assert.equal(error.message, WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite);
1336
+ return true;
1337
+ });
1338
+ assert.deepEqual(takeover.observed, [{
1339
+ commitOrdinal: 1,
1340
+ site: 'mode.primary',
1341
+ kind: 'write',
1342
+ path: join(stateDir, 'mode-state.json'),
1343
+ }]);
1344
+ }
1345
+ finally {
1346
+ __setWritableStateScopeTestHooksForTests({});
1347
+ __resetSessionPointerTransactionDependenciesForTests();
1348
+ await rm(wd, { recursive: true, force: true });
1349
+ }
1350
+ });
1351
+ it('T3 clears recovery and revalidation hooks and resets snapshot ordinals', async () => {
1352
+ const wd = await mkRealTemp('omx-writable-hooks-clear-');
1353
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
1354
+ try {
1355
+ const stateDir = getBaseStateDir(wd);
1356
+ await mkdir(stateDir, { recursive: true });
1357
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: 'sess-dead', cwd: wd, pid: 8388607 }));
1358
+ process.env.OMX_SESSION_ID = 'sess-current';
1359
+ const oldCounters = { recovery: 0, revalidation: 0, decision: 0, stability: 0 };
1360
+ __setWritableStateScopeTestHooksForTests({
1361
+ beforeRecoveryReread: async () => { oldCounters.recovery += 1; },
1362
+ beforeScopeRevalidation: async () => { oldCounters.revalidation += 1; },
1363
+ onSelectedDecisionSnapshotRead: () => { oldCounters.decision += 1; },
1364
+ onRecoveryStabilityReread: () => { oldCounters.stability += 1; },
1365
+ });
1366
+ await resolveWritableStateScope(wd);
1367
+ __setWritableStateScopeTestHooksForTests({});
1368
+ await resolveWritableStateScope(wd);
1369
+ assert.deepEqual(oldCounters, { recovery: 1, revalidation: 0, decision: 1, stability: 1 });
1370
+ const restarted = [];
1371
+ __setWritableStateScopeTestHooksForTests({
1372
+ onSelectedDecisionSnapshotRead: ({ ordinal }) => restarted.push({ decision: ordinal, stability: 0 }),
1373
+ onRecoveryStabilityReread: ({ ordinal }) => {
1374
+ const event = restarted.at(-1);
1375
+ assert.ok(event);
1376
+ event.stability = ordinal;
1377
+ },
1378
+ });
1379
+ await resolveWritableStateScope(wd);
1380
+ assert.deepEqual(restarted, [{ decision: 1, stability: 1 }]);
1381
+ }
1382
+ finally {
1383
+ __setWritableStateScopeTestHooksForTests({});
1384
+ __resetSessionPointerTransactionDependenciesForTests();
1385
+ await rm(wd, { recursive: true, force: true });
1386
+ }
656
1387
  });
657
1388
  });
658
1389
  //# sourceMappingURL=state-paths.test.js.map