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
@@ -4,10 +4,11 @@ import { chmod, mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises
4
4
  import { existsSync } from 'node:fs';
5
5
  import { dirname, join } from 'node:path';
6
6
  import { tmpdir } from 'node:os';
7
- import { executeStateOperation } from '../operations.js';
7
+ import { completeRalplanSession, executeStateOperation } from '../operations.js';
8
8
  import { subagentTrackingPath } from '../../subagents/tracker.js';
9
- import { updateModeState } from '../../modes/base.js';
10
- import { WRITABLE_STATE_SCOPE_ERRORS } from '../../mcp/state-paths.js';
9
+ import { startMode, updateModeState } from '../../modes/base.js';
10
+ import { __setWritableStateScopeTestHooksForTests, getBaseStateDir, WRITABLE_STATE_SCOPE_ERRORS, } from '../../mcp/state-paths.js';
11
+ import { __resetSessionPointerTransactionDependenciesForTests, __setSessionPointerTransactionDependenciesForTests, } from '../../hooks/session.js';
11
12
  async function withAmbientTmuxEnv(env, run) {
12
13
  const previousTmux = process.env.TMUX;
13
14
  const previousTmuxPane = process.env.TMUX_PANE;
@@ -172,6 +173,7 @@ function ralplanConsensusGate(sessionId, provenanceKind, threadOverrides = {}) {
172
173
  ralplan_architect_review: {
173
174
  agent_role: 'architect',
174
175
  verdict: 'approve',
176
+ sequence_index: 1,
175
177
  provenance_kind: provenanceKind,
176
178
  session_id: sessionId,
177
179
  thread_id: architectThread,
@@ -181,6 +183,7 @@ function ralplanConsensusGate(sessionId, provenanceKind, threadOverrides = {}) {
181
183
  ralplan_critic_review: {
182
184
  agent_role: 'critic',
183
185
  verdict: 'approve',
186
+ sequence_index: 2,
184
187
  provenance_kind: provenanceKind,
185
188
  session_id: sessionId,
186
189
  thread_id: criticThread,
@@ -793,7 +796,7 @@ describe('state operations directory initialization', () => {
793
796
  const sessionId = 'sess-clear';
794
797
  const sessionDir = join(stateDir, 'sessions', sessionId);
795
798
  await mkdir(sessionDir, { recursive: true });
796
- await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: sessionId }, null, 2));
799
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: sessionId, cwd: wd, state_root: stateDir }, null, 2));
797
800
  await writeFile(join(stateDir, 'deep-interview-state.json'), JSON.stringify({ active: true, mode: 'deep-interview', current_phase: 'legacy-root' }, null, 2));
798
801
  await writeFile(join(sessionDir, 'deep-interview-state.json'), JSON.stringify({ active: true, mode: 'deep-interview', current_phase: 'session-active' }, null, 2));
799
802
  await executeStateOperation('state_clear', {
@@ -854,6 +857,25 @@ describe('state operations directory initialization', () => {
854
857
  await rm(wd, { recursive: true, force: true });
855
858
  }
856
859
  });
860
+ it('excludes derived run-state.json from active mode enumeration while preserving genuine mode state files', async () => {
861
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-derived-run-state-'));
862
+ try {
863
+ const sessionId = 'sess-derived-run-state';
864
+ const sessionDir = join(wd, '.omx', 'state', 'sessions', sessionId);
865
+ await mkdir(sessionDir, { recursive: true });
866
+ await writeFile(join(wd, '.omx', 'state', 'session.json'), JSON.stringify({ session_id: sessionId }, null, 2));
867
+ await writeFile(join(sessionDir, 'run-state.json'), JSON.stringify({ active: true, mode: 'derived' }, null, 2));
868
+ await writeFile(join(sessionDir, 'autopilot-state.json'), JSON.stringify({ active: true, current_phase: 'executing' }, null, 2));
869
+ const response = await executeStateOperation('state_list_active', {
870
+ workingDirectory: wd,
871
+ session_id: sessionId,
872
+ });
873
+ assert.deepEqual(response.payload, { active_modes: ['autopilot'] });
874
+ }
875
+ finally {
876
+ await rm(wd, { recursive: true, force: true });
877
+ }
878
+ });
857
879
  it('does not list a mode active when terminal canonical visibility contradicts an active detail state', async () => {
858
880
  const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-terminal-canonical-wins-'));
859
881
  try {
@@ -893,7 +915,7 @@ describe('state operations directory initialization', () => {
893
915
  const sessionId = 'sess-terminal-implicit';
894
916
  const sessionDir = join(wd, '.omx', 'state', 'sessions', sessionId);
895
917
  await mkdir(sessionDir, { recursive: true });
896
- await writeFile(join(wd, '.omx', 'state', 'session.json'), JSON.stringify({ session_id: sessionId }, null, 2));
918
+ await writeFile(join(wd, '.omx', 'state', 'session.json'), JSON.stringify({ session_id: sessionId, cwd: wd, state_root: join(wd, '.omx', 'state') }, null, 2));
897
919
  await writeFile(join(sessionDir, 'autopilot-state.json'), JSON.stringify({
898
920
  active: true,
899
921
  current_phase: 'deep-interview',
@@ -949,7 +971,7 @@ describe('state operations directory initialization', () => {
949
971
  await rm(wd, { recursive: true, force: true });
950
972
  }
951
973
  });
952
- it('finalizes completed ralplan writes across root and current session state', async () => {
974
+ it('rejects a completed ralplan state transition when only local review lifecycle evidence is present', async () => {
953
975
  const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-complete-'));
954
976
  try {
955
977
  const sessionId = 'sess-ralplan-complete';
@@ -1005,36 +1027,38 @@ describe('state operations directory initialization', () => {
1005
1027
  },
1006
1028
  ralplan_consensus_gate: consensusGate,
1007
1029
  });
1008
- assert.equal(response.isError, undefined);
1030
+ assert.equal(response.isError, true);
1031
+ assert.match(String(response.payload.error ?? ''), /documented_host_consensus_receipt_unavailable/);
1009
1032
  const rootRalplan = JSON.parse(await readFile(join(stateDir, 'ralplan-state.json'), 'utf-8'));
1010
1033
  const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
1011
1034
  for (const state of [rootRalplan, sessionRalplan]) {
1012
- assert.equal(state.active, false);
1013
- assert.equal(state.current_phase, 'complete');
1014
- assert.equal(state.status, 'complete');
1015
- assert.equal(state.terminal_reason, 'consensus approved bounded no-op');
1016
- assert.equal(state.ralplan_consensus_gate.complete, true);
1035
+ assert.equal(state.active, true);
1036
+ assert.equal(state.current_phase, 'planning');
1037
+ assert.equal(state.status, undefined);
1017
1038
  assert.equal(state.session_id, sessionId);
1018
1039
  }
1019
1040
  const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
1020
1041
  const sessionSkill = JSON.parse(await readFile(join(sessionDir, 'skill-active-state.json'), 'utf-8'));
1021
1042
  for (const state of [rootSkill, sessionSkill]) {
1022
- assert.equal(state.active, false);
1023
- assert.equal(state.phase, 'complete');
1024
- assert.equal(state.terminal_reason, 'consensus approved bounded no-op');
1025
- assert.deepEqual(state.active_skills, []);
1043
+ assert.equal(state.active, true);
1044
+ assert.equal(state.phase, 'planning');
1045
+ assert.deepEqual(state.active_skills, [{
1046
+ skill: 'ralplan',
1047
+ phase: 'planning',
1048
+ active: true,
1049
+ session_id: sessionId,
1050
+ }]);
1026
1051
  }
1027
- assert.equal(sessionSkill.session_id, sessionId);
1028
1052
  const listed = await executeStateOperation('state_list_active', {
1029
1053
  workingDirectory: wd,
1030
1054
  });
1031
- assert.deepEqual(listed.payload, { active_modes: [] });
1055
+ assert.deepEqual(listed.payload, { active_modes: ['ralplan'] });
1032
1056
  }
1033
1057
  finally {
1034
1058
  await rm(wd, { recursive: true, force: true });
1035
1059
  }
1036
1060
  });
1037
- it('finalizes ralplan when runtime tracker lags but workspace tracker has completed native reviews', async () => {
1061
+ it('rejects a ralplan release when runtime and workspace trackers only provide local review lifecycle evidence', async () => {
1038
1062
  const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-runtime-lag-complete-'));
1039
1063
  const stateRoot = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-runtime-lag-root-'));
1040
1064
  try {
@@ -1100,13 +1124,12 @@ describe('state operations directory initialization', () => {
1100
1124
  terminal_reason: 'consensus approved despite runtime tracker lag',
1101
1125
  ralplan_consensus_gate: consensusGate,
1102
1126
  });
1103
- assert.equal(response.isError, undefined);
1127
+ assert.equal(response.isError, true);
1128
+ assert.match(String(response.payload.error ?? ''), /documented_host_consensus_receipt_unavailable/);
1104
1129
  const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
1105
- assert.equal(sessionRalplan.active, false);
1106
- assert.equal(sessionRalplan.current_phase, 'complete');
1107
- assert.equal(sessionRalplan.status, 'complete');
1108
- assert.equal(sessionRalplan.terminal_reason, 'consensus approved despite runtime tracker lag');
1109
- assert.equal(sessionRalplan.ralplan_consensus_gate.complete, true);
1130
+ assert.equal(sessionRalplan.active, true);
1131
+ assert.equal(sessionRalplan.current_phase, 'planning');
1132
+ assert.equal(sessionRalplan.status, undefined);
1110
1133
  });
1111
1134
  }
1112
1135
  finally {
@@ -1142,7 +1165,7 @@ describe('state operations directory initialization', () => {
1142
1165
  },
1143
1166
  });
1144
1167
  assert.equal(response.isError, true);
1145
- assert.match(String(response.payload.error ?? ''), /tracker-backed native architect and critic consensus evidence/);
1168
+ assert.match(String(response.payload.error ?? ''), /documented_host_consensus_receipt_unavailable/);
1146
1169
  const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
1147
1170
  assert.equal(sessionRalplan.active, true);
1148
1171
  assert.equal(sessionRalplan.current_phase, 'planning');
@@ -1455,7 +1478,7 @@ describe('state operations directory initialization', () => {
1455
1478
  currentPhase: 'complete',
1456
1479
  });
1457
1480
  assert.equal(response.isError, true);
1458
- assert.match(String(response.payload.error ?? ''), /tracker-backed native architect and critic consensus evidence/);
1481
+ assert.match(String(response.payload.error ?? ''), /documented_host_consensus_receipt_unavailable/);
1459
1482
  const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
1460
1483
  assert.equal(sessionRalplan.active, true);
1461
1484
  assert.equal(sessionRalplan.current_phase, 'planning');
@@ -1465,7 +1488,7 @@ describe('state operations directory initialization', () => {
1465
1488
  await rm(wd, { recursive: true, force: true });
1466
1489
  }
1467
1490
  });
1468
- it('reuses existing tracker-backed ralplan consensus when terminal writes omit gate payload', async () => {
1491
+ it('rejects terminal writes that reuse existing local tracker review lifecycle evidence', async () => {
1469
1492
  const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-existing-consensus-'));
1470
1493
  try {
1471
1494
  const sessionId = 'sess-ralplan-existing-consensus';
@@ -1491,10 +1514,11 @@ describe('state operations directory initialization', () => {
1491
1514
  current_phase: 'complete',
1492
1515
  terminal_reason: 'existing tracker-backed consensus complete',
1493
1516
  });
1494
- assert.equal(response.isError, undefined);
1517
+ assert.equal(response.isError, true);
1518
+ assert.match(String(response.payload.error ?? ''), /documented_host_consensus_receipt_unavailable/);
1495
1519
  const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
1496
- assert.equal(sessionRalplan.active, false);
1497
- assert.equal(sessionRalplan.current_phase, 'complete');
1520
+ assert.equal(sessionRalplan.active, true);
1521
+ assert.equal(sessionRalplan.current_phase, 'planning');
1498
1522
  const finalGate = sessionRalplan.ralplan_consensus_gate;
1499
1523
  assert.equal(finalGate.complete, true);
1500
1524
  assert.deepEqual(finalGate.required_review_roles, ['architect', 'critic']);
@@ -1505,7 +1529,7 @@ describe('state operations directory initialization', () => {
1505
1529
  await rm(wd, { recursive: true, force: true });
1506
1530
  }
1507
1531
  });
1508
- it('finalizes completed ralplan updateModeState writes across root and current session state', async () => {
1532
+ it('updateModeState rejects completed ralplan release without an official host receipt', async () => {
1509
1533
  const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-complete-update-mode-'));
1510
1534
  try {
1511
1535
  const sessionId = 'sess-ralplan-complete-update-mode';
@@ -1544,39 +1568,41 @@ describe('state operations directory initialization', () => {
1544
1568
  };
1545
1569
  await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify(staleSkillState, null, 2));
1546
1570
  await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify(staleSkillState, null, 2));
1547
- await updateModeState('ralplan', {
1571
+ await assert.rejects(() => updateModeState('ralplan', {
1548
1572
  active: false,
1549
1573
  current_phase: 'complete',
1550
1574
  terminal_reason: 'runtime consensus complete',
1551
1575
  ralplan_consensus_gate: consensusGate,
1552
- }, wd);
1576
+ }, wd), /documented_host_consensus_receipt_unavailable/);
1553
1577
  const rootRalplan = JSON.parse(await readFile(join(stateDir, 'ralplan-state.json'), 'utf-8'));
1554
1578
  const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
1555
1579
  for (const state of [rootRalplan, sessionRalplan]) {
1556
- assert.equal(state.active, false);
1557
- assert.equal(state.current_phase, 'complete');
1558
- assert.equal(state.status, 'complete');
1559
- assert.equal(state.terminal_reason, 'runtime consensus complete');
1560
- assert.equal(state.ralplan_consensus_gate.complete, true);
1580
+ assert.equal(state.active, true);
1581
+ assert.equal(state.current_phase, 'planning');
1582
+ assert.equal(state.status, undefined);
1561
1583
  assert.equal(state.session_id, sessionId);
1562
1584
  }
1563
1585
  const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
1564
1586
  const sessionSkill = JSON.parse(await readFile(join(sessionDir, 'skill-active-state.json'), 'utf-8'));
1565
1587
  for (const state of [rootSkill, sessionSkill]) {
1566
- assert.equal(state.active, false);
1567
- assert.equal(state.phase, 'complete');
1568
- assert.equal(state.terminal_reason, 'runtime consensus complete');
1569
- assert.deepEqual(state.active_skills, []);
1588
+ assert.equal(state.active, true);
1589
+ assert.equal(state.phase, 'planning');
1590
+ assert.deepEqual(state.active_skills, [{
1591
+ skill: 'ralplan',
1592
+ phase: 'planning',
1593
+ active: true,
1594
+ session_id: sessionId,
1595
+ }]);
1570
1596
  }
1571
1597
  const rootListed = await executeStateOperation('state_list_active', {
1572
1598
  workingDirectory: wd,
1573
1599
  });
1574
- assert.deepEqual(rootListed.payload, { active_modes: [] });
1600
+ assert.deepEqual(rootListed.payload, { active_modes: ['ralplan'] });
1575
1601
  const sessionListed = await executeStateOperation('state_list_active', {
1576
1602
  workingDirectory: wd,
1577
1603
  session_id: sessionId,
1578
1604
  });
1579
- assert.deepEqual(sessionListed.payload, { active_modes: [] });
1605
+ assert.deepEqual(sessionListed.payload, { active_modes: ['ralplan'] });
1580
1606
  }
1581
1607
  finally {
1582
1608
  await rm(wd, { recursive: true, force: true });
@@ -1606,7 +1632,7 @@ describe('state operations directory initialization', () => {
1606
1632
  ralplan_consensus_gate: {
1607
1633
  complete: true,
1608
1634
  },
1609
- }, wd), /architect and critic consensus evidence/);
1635
+ }, wd), /documented_host_consensus_receipt_unavailable/);
1610
1636
  const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
1611
1637
  assert.equal(sessionRalplan.active, true);
1612
1638
  assert.equal(sessionRalplan.current_phase, 'planning');
@@ -1637,7 +1663,7 @@ describe('state operations directory initialization', () => {
1637
1663
  await writeFile(join(stateDir, 'run-state.json'), JSON.stringify(runState, null, 2));
1638
1664
  const beforeList = await executeStateOperation('state_list_active', { workingDirectory: wd });
1639
1665
  const beforeTeam = await executeStateOperation('state_read', { workingDirectory: wd, mode: 'team' });
1640
- assert.deepEqual(beforeList.payload, { active_modes: ['run'] });
1666
+ assert.deepEqual(beforeList.payload, { active_modes: [] });
1641
1667
  assert.deepEqual(beforeTeam.payload, teamState);
1642
1668
  const response = await executeStateOperation('state_write', {
1643
1669
  workingDirectory: wd,
@@ -1645,844 +1671,125 @@ describe('state operations directory initialization', () => {
1645
1671
  active: true,
1646
1672
  current_phase: 'deep-interview',
1647
1673
  state: { interview_id: 'fixture', profile: 'quick', type: 'brownfield' },
1648
- });
1649
- const payload = responsePayload(response);
1650
- assert.equal(payload.success, true);
1651
- assert.equal(payload.path, join(stateDir, 'deep-interview-state.json'));
1652
- assert.deepEqual(JSON.parse(await readFile(join(stateDir, 'team-state.json'), 'utf-8')), teamState);
1653
- assert.deepEqual(JSON.parse(await readFile(join(stateDir, 'run-state.json'), 'utf-8')), runState);
1654
- assert.equal(existsSync(join(stateDir, 'sessions', 'foreign-team-session', 'deep-interview-state.json')), false);
1655
- assert.deepEqual(JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8')), foreignSkillState);
1656
- const afterList = await executeStateOperation('state_list_active', { workingDirectory: wd });
1657
- assert.deepEqual(afterList.payload, { active_modes: ['deep-interview', 'run'] });
1658
- }
1659
- finally {
1660
- await rm(wd, { recursive: true, force: true });
1661
- }
1662
- });
1663
- });
1664
- it('fails closed without mutating root state when ralplan terminalization sees a foreign session pointer', async () => {
1665
- const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-stale-session-'));
1666
- try {
1667
- const staleSessionId = 'sess-ralplan-stale';
1668
- const consensusGate = await writeNativeRalplanConsensusGate(wd, staleSessionId);
1669
- const stateDir = join(wd, '.omx', 'state');
1670
- const sessionDir = join(stateDir, 'sessions', staleSessionId);
1671
- await mkdir(stateDir, { recursive: true });
1672
- await writeFile(join(stateDir, 'session.json'), JSON.stringify({
1673
- session_id: staleSessionId,
1674
- cwd: join(wd, 'different-project'),
1675
- }, null, 2));
1676
- await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
1677
- mode: 'ralplan',
1678
- active: true,
1679
- current_phase: 'planning',
1680
- session_id: staleSessionId,
1681
- }, null, 2));
1682
- await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
1683
- version: 1,
1684
- active: true,
1685
- skill: 'ralplan',
1686
- phase: 'planning',
1687
- session_id: staleSessionId,
1688
- active_skills: [
1689
- {
1690
- skill: 'ralplan',
1691
- phase: 'planning',
1692
- active: true,
1693
- },
1694
- {
1695
- skill: 'ralplan',
1696
- phase: 'planning',
1697
- active: true,
1698
- session_id: staleSessionId,
1699
- },
1700
- ],
1701
- }, null, 2));
1702
- const response = await executeStateOperation('state_write', {
1703
- workingDirectory: wd,
1704
- mode: 'ralplan',
1705
- active: false,
1706
- current_phase: 'complete',
1707
- status: 'complete',
1708
- terminal_reason: 'consensus approved bounded no-op',
1709
- state: {
1710
- session_id: staleSessionId,
1711
- ralplan_consensus_gate: consensusGate,
1712
- },
1713
- });
1714
- assert.equal(response.isError, true);
1715
- assert.deepEqual(response.payload, { error: WRITABLE_STATE_SCOPE_ERRORS.unusableSession });
1716
- const rootRalplan = JSON.parse(await readFile(join(stateDir, 'ralplan-state.json'), 'utf-8'));
1717
- assert.equal(rootRalplan.active, true);
1718
- assert.equal(rootRalplan.current_phase, 'planning');
1719
- assert.equal(rootRalplan.session_id, staleSessionId);
1720
- const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
1721
- assert.equal(rootSkill.active, true);
1722
- assert.equal(rootSkill.phase, 'planning');
1723
- assert.equal(Array.isArray(rootSkill.active_skills), true);
1724
- assert.equal(existsSync(join(sessionDir, 'ralplan-state.json')), false);
1725
- assert.equal(existsSync(join(sessionDir, 'skill-active-state.json')), false);
1726
- const listed = await executeStateOperation('state_list_active', {
1727
- workingDirectory: wd,
1728
- });
1729
- assert.deepEqual(listed.payload, { active_modes: ['ralplan'] });
1730
- }
1731
- finally {
1732
- await rm(wd, { recursive: true, force: true });
1733
- }
1734
- });
1735
- it('does not hide unrelated root detail state when ralplan terminalizes without canonical state', async () => {
1736
- const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-root-detail-only-'));
1737
- try {
1738
- const sessionId = 'sess-ralplan-root-detail-only';
1739
- const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
1740
- const stateDir = join(wd, '.omx', 'state');
1741
- await mkdir(stateDir, { recursive: true });
1742
- await writeFile(join(stateDir, 'team-state.json'), JSON.stringify({
1743
- mode: 'team',
1744
- active: true,
1745
- current_phase: 'running',
1746
- }, null, 2));
1747
- const response = await executeStateOperation('state_write', {
1748
- workingDirectory: wd,
1749
- mode: 'ralplan',
1750
- active: false,
1751
- current_phase: 'complete',
1752
- state: {
1753
- session_id: sessionId,
1754
- ralplan_consensus_gate: consensusGate,
1755
- },
1756
- });
1757
- assert.equal(response.isError, undefined);
1758
- assert.equal(existsSync(join(stateDir, 'skill-active-state.json')), false);
1759
- const listed = await executeStateOperation('state_list_active', {
1760
- workingDirectory: wd,
1761
- });
1762
- assert.deepEqual(listed.payload, { active_modes: ['team'] });
1763
- }
1764
- finally {
1765
- await rm(wd, { recursive: true, force: true });
1766
- }
1767
- });
1768
- it('preserves an unrelated active root ralplan when a session ralplan terminalizes', async () => {
1769
- const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-preserve-root-'));
1770
- try {
1771
- const sessionId = 'sess-ralplan-preserve-root';
1772
- const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
1773
- const stateDir = join(wd, '.omx', 'state');
1774
- const sessionDir = join(stateDir, 'sessions', sessionId);
1775
- await mkdir(sessionDir, { recursive: true });
1776
- await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
1777
- mode: 'ralplan',
1778
- active: true,
1779
- current_phase: 'planning',
1780
- }, null, 2));
1781
- await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
1782
- mode: 'ralplan',
1783
- active: true,
1784
- current_phase: 'planning',
1785
- session_id: sessionId,
1786
- }, null, 2));
1787
- await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
1788
- version: 1,
1789
- active: true,
1790
- skill: 'ralplan',
1791
- phase: 'planning',
1792
- active_skills: [
1793
- {
1794
- skill: 'ralplan',
1795
- phase: 'planning',
1796
- active: true,
1797
- },
1798
- {
1799
- skill: 'ralplan',
1800
- phase: 'planning',
1801
- active: true,
1802
- session_id: sessionId,
1803
- },
1804
- ],
1805
- }, null, 2));
1806
- await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify({
1807
- version: 1,
1808
- active: true,
1809
- skill: 'ralplan',
1810
- phase: 'planning',
1811
- session_id: sessionId,
1812
- active_skills: [{
1813
- skill: 'ralplan',
1814
- phase: 'planning',
1815
- active: true,
1816
- session_id: sessionId,
1817
- }],
1818
- }, null, 2));
1819
- const response = await executeStateOperation('state_write', {
1820
- workingDirectory: wd,
1821
- session_id: sessionId,
1822
- mode: 'ralplan',
1823
- active: false,
1824
- current_phase: 'complete',
1825
- status: 'complete',
1826
- terminal_reason: 'consensus approved bounded no-op',
1827
- ralplan_consensus_gate: consensusGate,
1828
- });
1829
- assert.equal(response.isError, undefined);
1830
- const rootRalplan = JSON.parse(await readFile(join(stateDir, 'ralplan-state.json'), 'utf-8'));
1831
- assert.equal(rootRalplan.active, true);
1832
- assert.equal(rootRalplan.current_phase, 'planning');
1833
- assert.equal(rootRalplan.session_id, undefined);
1834
- const sessionRalplan = JSON.parse(await readFile(join(sessionDir, 'ralplan-state.json'), 'utf-8'));
1835
- assert.equal(sessionRalplan.active, false);
1836
- assert.equal(sessionRalplan.current_phase, 'complete');
1837
- assert.equal(sessionRalplan.session_id, sessionId);
1838
- const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
1839
- assert.equal(rootSkill.active, true);
1840
- assert.equal(rootSkill.skill, 'ralplan');
1841
- assert.deepEqual(rootSkill.active_skills, [{ skill: 'ralplan', phase: 'planning', active: true }]);
1842
- const rootListed = await executeStateOperation('state_list_active', {
1843
- workingDirectory: wd,
1844
- });
1845
- assert.deepEqual(rootListed.payload, { active_modes: ['ralplan'] });
1846
- const sessionListed = await executeStateOperation('state_list_active', {
1847
- workingDirectory: wd,
1848
- session_id: sessionId,
1849
- });
1850
- assert.deepEqual(sessionListed.payload, { active_modes: [] });
1851
- }
1852
- finally {
1853
- await rm(wd, { recursive: true, force: true });
1854
- }
1855
- });
1856
- it('does not hide a legacy active root ralplan detail state when a session ralplan terminalizes', async () => {
1857
- const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-legacy-root-detail-'));
1858
- try {
1859
- const sessionId = 'sess-ralplan-legacy-root-detail';
1860
- const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
1861
- const stateDir = join(wd, '.omx', 'state');
1862
- const sessionDir = join(stateDir, 'sessions', sessionId);
1863
- await mkdir(sessionDir, { recursive: true });
1864
- await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
1865
- mode: 'ralplan',
1866
- active: true,
1867
- current_phase: 'planning',
1868
- }, null, 2));
1869
- await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
1870
- mode: 'ralplan',
1871
- active: true,
1872
- current_phase: 'planning',
1873
- session_id: sessionId,
1874
- }, null, 2));
1875
- await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify({
1876
- version: 1,
1877
- active: true,
1878
- skill: 'ralplan',
1879
- phase: 'planning',
1880
- session_id: sessionId,
1881
- active_skills: [{
1882
- skill: 'ralplan',
1883
- phase: 'planning',
1884
- active: true,
1885
- session_id: sessionId,
1886
- }],
1887
- }, null, 2));
1888
- const response = await executeStateOperation('state_write', {
1889
- workingDirectory: wd,
1890
- session_id: sessionId,
1891
- mode: 'ralplan',
1892
- active: false,
1893
- current_phase: 'complete',
1894
- ralplan_consensus_gate: consensusGate,
1895
- });
1896
- assert.equal(response.isError, undefined);
1897
- assert.equal(existsSync(join(stateDir, 'skill-active-state.json')), false);
1898
- const rootListed = await executeStateOperation('state_list_active', {
1899
- workingDirectory: wd,
1900
- });
1901
- assert.deepEqual(rootListed.payload, { active_modes: ['ralplan'] });
1902
- const sessionListed = await executeStateOperation('state_list_active', {
1903
- workingDirectory: wd,
1904
- session_id: sessionId,
1905
- });
1906
- assert.deepEqual(sessionListed.payload, { active_modes: [] });
1907
- }
1908
- finally {
1909
- await rm(wd, { recursive: true, force: true });
1910
- }
1911
- });
1912
- it('removes an empty session-only root mirror when a session ralplan terminalizes', async () => {
1913
- const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-empty-root-mirror-'));
1914
- try {
1915
- const sessionId = 'sess-ralplan-empty-root-mirror';
1916
- const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
1917
- const stateDir = join(wd, '.omx', 'state');
1918
- const sessionDir = join(stateDir, 'sessions', sessionId);
1919
- await mkdir(sessionDir, { recursive: true });
1920
- await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
1921
- mode: 'ralplan',
1922
- active: true,
1923
- current_phase: 'planning',
1924
- }, null, 2));
1925
- await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
1926
- mode: 'ralplan',
1927
- active: true,
1928
- current_phase: 'planning',
1929
- session_id: sessionId,
1930
- }, null, 2));
1931
- await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
1932
- version: 1,
1933
- active: true,
1934
- skill: 'ralplan',
1935
- phase: 'planning',
1936
- session_id: sessionId,
1937
- active_skills: [{
1938
- skill: 'ralplan',
1939
- phase: 'planning',
1940
- active: true,
1941
- session_id: sessionId,
1942
- }],
1943
- }, null, 2));
1944
- await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify({
1945
- version: 1,
1946
- active: true,
1947
- skill: 'ralplan',
1948
- phase: 'planning',
1949
- session_id: sessionId,
1950
- active_skills: [{
1951
- skill: 'ralplan',
1952
- phase: 'planning',
1953
- active: true,
1954
- session_id: sessionId,
1955
- }],
1956
- }, null, 2));
1957
- const response = await executeStateOperation('state_write', {
1958
- workingDirectory: wd,
1959
- session_id: sessionId,
1960
- mode: 'ralplan',
1961
- active: false,
1962
- current_phase: 'complete',
1963
- ralplan_consensus_gate: consensusGate,
1964
- });
1965
- assert.equal(response.isError, undefined);
1966
- assert.equal(existsSync(join(stateDir, 'skill-active-state.json')), false);
1967
- const rootListed = await executeStateOperation('state_list_active', {
1968
- workingDirectory: wd,
1969
- });
1970
- assert.deepEqual(rootListed.payload, { active_modes: ['ralplan'] });
1971
- const sessionListed = await executeStateOperation('state_list_active', {
1972
- workingDirectory: wd,
1973
- session_id: sessionId,
1974
- });
1975
- assert.deepEqual(sessionListed.payload, { active_modes: [] });
1976
- }
1977
- finally {
1978
- await rm(wd, { recursive: true, force: true });
1979
- }
1980
- });
1981
- it('preserves run_outcome-only root canonical tombstones when a session ralplan terminalizes', async () => {
1982
- const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-preserve-root-tombstone-'));
1983
- try {
1984
- const sessionId = 'sess-ralplan-root-tombstone';
1985
- const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
1986
- const stateDir = join(wd, '.omx', 'state');
1987
- const sessionDir = join(stateDir, 'sessions', sessionId);
1988
- await mkdir(sessionDir, { recursive: true });
1989
- await writeFile(join(stateDir, 'team-state.json'), JSON.stringify({
1990
- mode: 'team',
1991
- active: true,
1992
- current_phase: 'running',
1993
- }, null, 2));
1994
- await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
1995
- mode: 'ralplan',
1996
- active: true,
1997
- current_phase: 'planning',
1998
- }, null, 2));
1999
- await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
2000
- mode: 'ralplan',
2001
- active: true,
2002
- current_phase: 'planning',
2003
- session_id: sessionId,
2004
- }, null, 2));
2005
- await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
2006
- version: 1,
2007
- active: true,
2008
- skill: 'team',
2009
- run_outcome: 'finish',
2010
- active_skills: [{
2011
- skill: 'team',
2012
- active: true,
2013
- }],
2014
- }, null, 2));
2015
- const before = await executeStateOperation('state_list_active', {
2016
- workingDirectory: wd,
2017
- });
2018
- assert.deepEqual(before.payload, { active_modes: [] });
2019
- const response = await executeStateOperation('state_write', {
2020
- workingDirectory: wd,
2021
- session_id: sessionId,
2022
- mode: 'ralplan',
2023
- active: false,
2024
- current_phase: 'complete',
2025
- ralplan_consensus_gate: consensusGate,
2026
- });
2027
- assert.equal(response.isError, undefined);
2028
- const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
2029
- assert.equal(rootSkill.active, true);
2030
- assert.equal(rootSkill.run_outcome, 'finish');
2031
- const rootListed = await executeStateOperation('state_list_active', {
2032
- workingDirectory: wd,
2033
- });
2034
- assert.deepEqual(rootListed.payload, { active_modes: [] });
2035
- }
2036
- finally {
2037
- await rm(wd, { recursive: true, force: true });
2038
- }
2039
- });
2040
- it('removes terminal_reason-only active root canonical state when a session ralplan terminalizes', async () => {
2041
- const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-terminal-reason-only-'));
2042
- try {
2043
- const sessionId = 'sess-ralplan-terminal-reason-only';
2044
- const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
2045
- const stateDir = join(wd, '.omx', 'state');
2046
- const sessionDir = join(stateDir, 'sessions', sessionId);
2047
- await mkdir(sessionDir, { recursive: true });
2048
- await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
2049
- mode: 'ralplan',
2050
- active: true,
2051
- current_phase: 'planning',
2052
- }, null, 2));
2053
- await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
2054
- mode: 'ralplan',
2055
- active: true,
2056
- current_phase: 'planning',
2057
- session_id: sessionId,
2058
- }, null, 2));
2059
- await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
2060
- version: 1,
2061
- active: true,
2062
- skill: 'ralplan',
2063
- terminal_reason: 'stale reason without terminal marker',
2064
- active_skills: [{
2065
- skill: 'ralplan',
2066
- active: true,
2067
- session_id: sessionId,
2068
- }],
2069
- }, null, 2));
2070
- const before = await executeStateOperation('state_list_active', {
2071
- workingDirectory: wd,
2072
- session_id: sessionId,
2073
- });
2074
- assert.deepEqual(before.payload, { active_modes: ['ralplan'] });
2075
- const response = await executeStateOperation('state_write', {
2076
- workingDirectory: wd,
2077
- session_id: sessionId,
2078
- mode: 'ralplan',
2079
- active: false,
2080
- current_phase: 'complete',
2081
- ralplan_consensus_gate: consensusGate,
2082
- });
2083
- assert.equal(response.isError, undefined);
2084
- assert.equal(existsSync(join(stateDir, 'skill-active-state.json')), false);
2085
- const rootListed = await executeStateOperation('state_list_active', {
2086
- workingDirectory: wd,
2087
- });
2088
- assert.deepEqual(rootListed.payload, { active_modes: ['ralplan'] });
2089
- const sessionListed = await executeStateOperation('state_list_active', {
2090
- workingDirectory: wd,
2091
- session_id: sessionId,
2092
- });
2093
- assert.deepEqual(sessionListed.payload, { active_modes: [] });
2094
- }
2095
- finally {
2096
- await rm(wd, { recursive: true, force: true });
2097
- }
2098
- });
2099
- it('removes non-terminal lifecycle_outcome root canonical state when a session ralplan terminalizes', async () => {
2100
- const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-lifecycle-nonterminal-'));
2101
- try {
2102
- const sessionId = 'sess-ralplan-lifecycle-nonterminal';
2103
- const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
2104
- const stateDir = join(wd, '.omx', 'state');
2105
- const sessionDir = join(stateDir, 'sessions', sessionId);
2106
- await mkdir(sessionDir, { recursive: true });
2107
- await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
2108
- mode: 'ralplan',
2109
- active: true,
2110
- current_phase: 'planning',
2111
- }, null, 2));
2112
- await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
2113
- mode: 'ralplan',
2114
- active: true,
2115
- current_phase: 'planning',
2116
- session_id: sessionId,
2117
- }, null, 2));
2118
- await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
2119
- version: 1,
2120
- active: true,
2121
- skill: 'ralplan',
2122
- lifecycle_outcome: 'progress',
2123
- active_skills: [{
2124
- skill: 'ralplan',
2125
- active: true,
2126
- session_id: sessionId,
2127
- }],
2128
- }, null, 2));
2129
- const before = await executeStateOperation('state_list_active', {
2130
- workingDirectory: wd,
2131
- session_id: sessionId,
2132
- });
2133
- assert.deepEqual(before.payload, { active_modes: ['ralplan'] });
2134
- const response = await executeStateOperation('state_write', {
2135
- workingDirectory: wd,
2136
- session_id: sessionId,
2137
- mode: 'ralplan',
2138
- active: false,
2139
- current_phase: 'complete',
2140
- ralplan_consensus_gate: consensusGate,
2141
- });
2142
- assert.equal(response.isError, undefined);
2143
- assert.equal(existsSync(join(stateDir, 'skill-active-state.json')), false);
2144
- const rootListed = await executeStateOperation('state_list_active', {
2145
- workingDirectory: wd,
2146
- });
2147
- assert.deepEqual(rootListed.payload, { active_modes: ['ralplan'] });
2148
- const sessionListed = await executeStateOperation('state_list_active', {
2149
- workingDirectory: wd,
2150
- session_id: sessionId,
2151
- });
2152
- assert.deepEqual(sessionListed.payload, { active_modes: [] });
2153
- }
2154
- finally {
2155
- await rm(wd, { recursive: true, force: true });
2156
- }
2157
- });
2158
- it('preserves unrelated active session skills when ralplan terminalizes', async () => {
2159
- const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-preserve-'));
2160
- try {
2161
- const sessionId = 'sess-ralplan-preserve';
2162
- const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
2163
- const stateDir = join(wd, '.omx', 'state');
2164
- const sessionDir = join(stateDir, 'sessions', sessionId);
2165
- await mkdir(sessionDir, { recursive: true });
2166
- await writeFile(join(stateDir, 'session.json'), JSON.stringify({
2167
- session_id: sessionId,
2168
- cwd: wd,
2169
- }, null, 2));
2170
- await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
2171
- mode: 'ralplan',
2172
- active: true,
2173
- current_phase: 'planning',
2174
- session_id: sessionId,
2175
- }, null, 2));
2176
- await writeFile(join(sessionDir, 'autoresearch-state.json'), JSON.stringify({
2177
- mode: 'autoresearch',
2178
- active: true,
2179
- current_phase: 'running',
2180
- session_id: sessionId,
2181
- }, null, 2));
2182
- const mixedSkillState = {
2183
- version: 1,
2184
- active: true,
2185
- skill: 'ralplan',
2186
- phase: 'planning',
2187
- updated_at: '2026-06-30T00:00:00.000Z',
2188
- session_id: sessionId,
2189
- active_skills: [
2190
- {
2191
- skill: 'ralplan',
2192
- phase: 'planning',
2193
- active: true,
2194
- session_id: sessionId,
2195
- },
2196
- {
2197
- skill: 'autoresearch',
2198
- phase: 'running',
2199
- active: true,
2200
- session_id: sessionId,
2201
- },
2202
- ],
2203
- };
2204
- await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify(mixedSkillState, null, 2));
2205
- await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify(mixedSkillState, null, 2));
2206
- const response = await executeStateOperation('state_write', {
2207
- workingDirectory: wd,
2208
- mode: 'ralplan',
2209
- active: false,
2210
- current_phase: 'complete',
2211
- status: 'complete',
2212
- terminal_reason: 'consensus approved bounded no-op',
2213
- ralplan_consensus_gate: consensusGate,
2214
- });
2215
- assert.equal(response.isError, undefined);
2216
- const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
2217
- const sessionSkill = JSON.parse(await readFile(join(sessionDir, 'skill-active-state.json'), 'utf-8'));
2218
- for (const state of [rootSkill, sessionSkill]) {
2219
- assert.equal(state.active, true);
2220
- assert.equal(state.skill, 'autoresearch');
2221
- assert.equal(state.phase, 'running');
2222
- assert.deepEqual(state.active_skills?.map((entry) => entry.skill), ['autoresearch']);
2223
- assert.deepEqual(state.active_skills?.map((entry) => entry.session_id), [sessionId]);
2224
- }
2225
- const listed = await executeStateOperation('state_list_active', {
2226
- workingDirectory: wd,
2227
- });
2228
- assert.deepEqual(listed.payload, { active_modes: ['autoresearch'] });
2229
- }
2230
- finally {
2231
- await rm(wd, { recursive: true, force: true });
2232
- }
2233
- });
2234
- it('preserves same-session root mirror skills when session canonical state is partial', async () => {
2235
- const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-partial-session-skill-'));
2236
- try {
2237
- const sessionId = 'sess-ralplan-partial-session-skill';
2238
- const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
2239
- const stateDir = join(wd, '.omx', 'state');
2240
- const sessionDir = join(stateDir, 'sessions', sessionId);
2241
- await mkdir(sessionDir, { recursive: true });
2242
- await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
2243
- mode: 'ralplan',
2244
- active: true,
2245
- current_phase: 'planning',
2246
- session_id: sessionId,
2247
- }, null, 2));
2248
- await writeFile(join(sessionDir, 'team-state.json'), JSON.stringify({
2249
- mode: 'team',
2250
- active: true,
2251
- current_phase: 'running',
2252
- session_id: sessionId,
2253
- }, null, 2));
2254
- await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
2255
- version: 1,
2256
- active: true,
2257
- skill: 'ralplan',
2258
- phase: 'planning',
2259
- session_id: sessionId,
2260
- active_skills: [
2261
- {
2262
- skill: 'ralplan',
2263
- phase: 'planning',
2264
- active: true,
2265
- session_id: sessionId,
2266
- },
2267
- {
2268
- skill: 'team',
2269
- phase: 'running',
2270
- active: true,
2271
- session_id: sessionId,
2272
- },
2273
- ],
2274
- }, null, 2));
2275
- await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify({
2276
- version: 1,
2277
- active: true,
2278
- skill: 'ralplan',
2279
- phase: 'planning',
2280
- session_id: sessionId,
2281
- active_skills: [{
2282
- skill: 'ralplan',
2283
- phase: 'planning',
2284
- active: true,
2285
- session_id: sessionId,
2286
- }],
2287
- }, null, 2));
2288
- const response = await executeStateOperation('state_write', {
2289
- workingDirectory: wd,
2290
- session_id: sessionId,
2291
- mode: 'ralplan',
2292
- active: false,
2293
- current_phase: 'complete',
2294
- ralplan_consensus_gate: consensusGate,
2295
- });
2296
- assert.equal(response.isError, undefined);
2297
- const sessionSkill = JSON.parse(await readFile(join(sessionDir, 'skill-active-state.json'), 'utf-8'));
2298
- assert.equal(sessionSkill.active, true);
2299
- assert.equal(sessionSkill.skill, 'team');
2300
- assert.equal(sessionSkill.phase, 'running');
2301
- assert.equal(sessionSkill.session_id, sessionId);
2302
- assert.deepEqual(sessionSkill.active_skills?.map((entry) => entry.skill), ['team']);
2303
- assert.deepEqual(sessionSkill.active_skills?.map((entry) => entry.session_id), [sessionId]);
2304
- const sessionListed = await executeStateOperation('state_list_active', {
2305
- workingDirectory: wd,
2306
- session_id: sessionId,
2307
- });
2308
- assert.deepEqual(sessionListed.payload, { active_modes: ['team'] });
2309
- }
2310
- finally {
2311
- await rm(wd, { recursive: true, force: true });
2312
- }
1674
+ });
1675
+ const payload = responsePayload(response);
1676
+ assert.equal(payload.success, true);
1677
+ assert.equal(payload.path, join(stateDir, 'deep-interview-state.json'));
1678
+ assert.deepEqual(JSON.parse(await readFile(join(stateDir, 'team-state.json'), 'utf-8')), teamState);
1679
+ assert.deepEqual(JSON.parse(await readFile(join(stateDir, 'run-state.json'), 'utf-8')), runState);
1680
+ assert.equal(existsSync(join(stateDir, 'sessions', 'foreign-team-session', 'deep-interview-state.json')), false);
1681
+ assert.deepEqual(JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8')), foreignSkillState);
1682
+ const afterList = await executeStateOperation('state_list_active', { workingDirectory: wd });
1683
+ assert.deepEqual(afterList.payload, { active_modes: ['deep-interview'] });
1684
+ }
1685
+ finally {
1686
+ await rm(wd, { recursive: true, force: true });
1687
+ }
1688
+ });
2313
1689
  });
2314
- it('clears stale terminal phase aliases when preserving same-session root mirror skills', async () => {
2315
- const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-terminal-session-skill-'));
1690
+ it('fails closed without mutating root state when ralplan terminalization sees a foreign session pointer', async () => {
1691
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-stale-session-'));
2316
1692
  try {
2317
- const sessionId = 'sess-ralplan-terminal-session-skill';
2318
- const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
1693
+ const staleSessionId = 'sess-ralplan-stale';
1694
+ const consensusGate = await writeNativeRalplanConsensusGate(wd, staleSessionId);
2319
1695
  const stateDir = join(wd, '.omx', 'state');
2320
- const sessionDir = join(stateDir, 'sessions', sessionId);
2321
- await mkdir(sessionDir, { recursive: true });
2322
- await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
1696
+ const sessionDir = join(stateDir, 'sessions', staleSessionId);
1697
+ await mkdir(stateDir, { recursive: true });
1698
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({
1699
+ session_id: staleSessionId,
1700
+ cwd: join(wd, 'different-project'),
1701
+ }, null, 2));
1702
+ await writeFile(join(stateDir, 'ralplan-state.json'), JSON.stringify({
2323
1703
  mode: 'ralplan',
2324
1704
  active: true,
2325
1705
  current_phase: 'planning',
2326
- session_id: sessionId,
2327
- }, null, 2));
2328
- await writeFile(join(sessionDir, 'team-state.json'), JSON.stringify({
2329
- mode: 'team',
2330
- active: true,
2331
- current_phase: 'running',
2332
- session_id: sessionId,
1706
+ session_id: staleSessionId,
2333
1707
  }, null, 2));
2334
1708
  await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
2335
1709
  version: 1,
2336
1710
  active: true,
2337
1711
  skill: 'ralplan',
2338
1712
  phase: 'planning',
2339
- session_id: sessionId,
1713
+ session_id: staleSessionId,
2340
1714
  active_skills: [
2341
1715
  {
2342
1716
  skill: 'ralplan',
2343
1717
  phase: 'planning',
2344
1718
  active: true,
2345
- session_id: sessionId,
2346
1719
  },
2347
1720
  {
2348
- skill: 'team',
1721
+ skill: 'ralplan',
1722
+ phase: 'planning',
2349
1723
  active: true,
2350
- session_id: sessionId,
1724
+ session_id: staleSessionId,
2351
1725
  },
2352
1726
  ],
2353
1727
  }, null, 2));
2354
- await writeFile(join(sessionDir, 'skill-active-state.json'), JSON.stringify({
2355
- version: 1,
2356
- active: false,
2357
- skill: 'ralplan',
2358
- phase: 'blocked',
2359
- session_id: sessionId,
2360
- completed_at: '2026-06-30T00:00:00.000Z',
2361
- terminal_reason: 'stale terminal marker',
2362
- active_skills: [],
2363
- }, null, 2));
2364
- const response = await executeStateOperation('state_write', {
2365
- workingDirectory: wd,
2366
- session_id: sessionId,
2367
- mode: 'ralplan',
2368
- active: false,
2369
- current_phase: 'complete',
2370
- ralplan_consensus_gate: consensusGate,
2371
- });
2372
- assert.equal(response.isError, undefined);
2373
- const sessionSkill = JSON.parse(await readFile(join(sessionDir, 'skill-active-state.json'), 'utf-8'));
2374
- assert.equal(sessionSkill.active, true);
2375
- assert.equal(sessionSkill.skill, 'team');
2376
- assert.equal(sessionSkill.phase, '');
2377
- assert.equal(sessionSkill.completed_at, undefined);
2378
- assert.equal(sessionSkill.terminal_reason, undefined);
2379
- assert.deepEqual(sessionSkill.active_skills?.map((entry) => entry.skill), ['team']);
2380
- const sessionListed = await executeStateOperation('state_list_active', {
2381
- workingDirectory: wd,
2382
- session_id: sessionId,
2383
- });
2384
- assert.deepEqual(sessionListed.payload, { active_modes: ['team'] });
2385
- }
2386
- finally {
2387
- await rm(wd, { recursive: true, force: true });
2388
- }
2389
- });
2390
- it('does not hide detail-only active session state when ralplan terminalizes', async () => {
2391
- const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-session-detail-only-'));
2392
- try {
2393
- const sessionId = 'sess-ralplan-session-detail-only';
2394
- const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
2395
- const sessionDir = join(wd, '.omx', 'state', 'sessions', sessionId);
2396
- await mkdir(sessionDir, { recursive: true });
2397
- await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
2398
- mode: 'ralplan',
2399
- active: true,
2400
- current_phase: 'planning',
2401
- session_id: sessionId,
2402
- }, null, 2));
2403
- await writeFile(join(sessionDir, 'autoresearch-state.json'), JSON.stringify({
2404
- mode: 'autoresearch',
2405
- active: true,
2406
- current_phase: 'running',
2407
- session_id: sessionId,
2408
- }, null, 2));
2409
1728
  const response = await executeStateOperation('state_write', {
2410
1729
  workingDirectory: wd,
2411
- session_id: sessionId,
2412
1730
  mode: 'ralplan',
2413
1731
  active: false,
2414
1732
  current_phase: 'complete',
2415
- ralplan_consensus_gate: consensusGate,
1733
+ status: 'complete',
1734
+ terminal_reason: 'consensus approved bounded no-op',
1735
+ state: {
1736
+ session_id: staleSessionId,
1737
+ ralplan_consensus_gate: consensusGate,
1738
+ },
2416
1739
  });
2417
- assert.equal(response.isError, undefined);
1740
+ assert.equal(response.isError, true);
1741
+ assert.deepEqual(response.payload, { error: WRITABLE_STATE_SCOPE_ERRORS.unusableSession });
1742
+ const rootRalplan = JSON.parse(await readFile(join(stateDir, 'ralplan-state.json'), 'utf-8'));
1743
+ assert.equal(rootRalplan.active, true);
1744
+ assert.equal(rootRalplan.current_phase, 'planning');
1745
+ assert.equal(rootRalplan.session_id, staleSessionId);
1746
+ const rootSkill = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
1747
+ assert.equal(rootSkill.active, true);
1748
+ assert.equal(rootSkill.phase, 'planning');
1749
+ assert.equal(Array.isArray(rootSkill.active_skills), true);
1750
+ assert.equal(existsSync(join(sessionDir, 'ralplan-state.json')), false);
2418
1751
  assert.equal(existsSync(join(sessionDir, 'skill-active-state.json')), false);
2419
1752
  const listed = await executeStateOperation('state_list_active', {
2420
1753
  workingDirectory: wd,
2421
- session_id: sessionId,
2422
1754
  });
2423
- assert.deepEqual(listed.payload, { active_modes: ['autoresearch'] });
1755
+ assert.deepEqual(listed.payload, { active_modes: ['ralplan'] });
2424
1756
  }
2425
1757
  finally {
2426
1758
  await rm(wd, { recursive: true, force: true });
2427
1759
  }
2428
1760
  });
2429
- it('does not seed session canonical state from root-only skills when ralplan terminalizes', async () => {
2430
- const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-ralplan-root-only-skill-'));
1761
+ it('reconciles a stale-dead selected pointer with an explicit exact-current OMX_SESSION_ID (issue #3272)', async () => {
1762
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-stale-dead-repro-'));
1763
+ const previousEnv = process.env.OMX_SESSION_ID;
1764
+ __setSessionPointerTransactionDependenciesForTests({ probePid: () => 'dead' });
2431
1765
  try {
2432
- const sessionId = 'sess-ralplan-root-only-skill';
2433
- const consensusGate = await writeNativeRalplanConsensusGate(wd, sessionId);
2434
1766
  const stateDir = join(wd, '.omx', 'state');
2435
- const sessionDir = join(stateDir, 'sessions', sessionId);
2436
- await mkdir(sessionDir, { recursive: true });
2437
- await writeFile(join(stateDir, 'autoresearch-state.json'), JSON.stringify({
2438
- mode: 'autoresearch',
2439
- active: true,
2440
- current_phase: 'running',
2441
- }, null, 2));
2442
- await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({
2443
- version: 1,
2444
- active: true,
2445
- skill: 'autoresearch',
2446
- phase: 'running',
2447
- active_skills: [{
2448
- skill: 'autoresearch',
2449
- phase: 'running',
2450
- active: true,
2451
- }],
2452
- }, null, 2));
2453
- await writeFile(join(sessionDir, 'ralplan-state.json'), JSON.stringify({
2454
- mode: 'ralplan',
2455
- active: true,
2456
- current_phase: 'planning',
2457
- session_id: sessionId,
2458
- }, null, 2));
2459
- await writeFile(join(sessionDir, 'team-state.json'), JSON.stringify({
2460
- mode: 'team',
2461
- active: true,
2462
- current_phase: 'running',
2463
- session_id: sessionId,
2464
- }, null, 2));
1767
+ await mkdir(stateDir, { recursive: true });
1768
+ // Repro of comment 5069023665: the selected pointer names a session whose
1769
+ // PID is dead; the exact current session is bound through OMX_SESSION_ID.
1770
+ const pointerBody = JSON.stringify({ session_id: 'sess-stale-dead', cwd: wd, pid: 8388607 });
1771
+ await writeFile(join(stateDir, 'session.json'), pointerBody);
1772
+ process.env.OMX_SESSION_ID = 'sess-current';
2465
1773
  const response = await executeStateOperation('state_write', {
2466
1774
  workingDirectory: wd,
2467
- session_id: sessionId,
2468
- mode: 'ralplan',
2469
- active: false,
2470
- current_phase: 'complete',
2471
- ralplan_consensus_gate: consensusGate,
2472
- });
2473
- assert.equal(response.isError, undefined);
2474
- assert.equal(existsSync(join(sessionDir, 'skill-active-state.json')), false);
2475
- const rootListed = await executeStateOperation('state_list_active', {
2476
- workingDirectory: wd,
2477
- });
2478
- assert.deepEqual(rootListed.payload, { active_modes: ['autoresearch'] });
2479
- const sessionListed = await executeStateOperation('state_list_active', {
2480
- workingDirectory: wd,
2481
- session_id: sessionId,
1775
+ mode: 'ultragoal',
1776
+ active: true,
1777
+ current_phase: 'reviewing',
1778
+ state: { goal_id: 'G001' },
2482
1779
  });
2483
- assert.deepEqual(sessionListed.payload, { active_modes: ['team'] });
1780
+ const payload = responsePayload(response);
1781
+ assert.equal(payload.success, true);
1782
+ assert.equal(payload.path, join(stateDir, 'sessions', 'sess-current', 'ultragoal-state.json'));
1783
+ assert.equal(existsSync(payload.path), true);
1784
+ // The selected pointer is never rewritten by a scope-resolution read path.
1785
+ assert.equal(await readFile(join(stateDir, 'session.json'), 'utf-8'), pointerBody);
2484
1786
  }
2485
1787
  finally {
1788
+ if (typeof previousEnv === 'string')
1789
+ process.env.OMX_SESSION_ID = previousEnv;
1790
+ else
1791
+ delete process.env.OMX_SESSION_ID;
1792
+ __resetSessionPointerTransactionDependenciesForTests();
2486
1793
  await rm(wd, { recursive: true, force: true });
2487
1794
  }
2488
1795
  });
@@ -3772,7 +3079,7 @@ describe('state operations directory initialization', () => {
3772
3079
  current_phase: 'ultragoal',
3773
3080
  });
3774
3081
  assert.equal(response.isError, true);
3775
- assert.match(String(response.payload.error || ''), /tracker-backed native architect and critic lanes/i);
3082
+ assert.match(String(response.payload.error || ''), /documented_host_consensus_receipt_unavailable/);
3776
3083
  const state = JSON.parse(await readFile(join(sessionDir, 'autopilot-state.json'), 'utf-8'));
3777
3084
  assert.equal(state.current_phase, 'ralplan');
3778
3085
  });
@@ -3904,7 +3211,7 @@ describe('state operations directory initialization', () => {
3904
3211
  });
3905
3212
  assert.equal(response.isError, true);
3906
3213
  const error = String(response.payload.error || '');
3907
- assert.match(error, new RegExp(`${lane}.*verdict=iterate`, 'i'));
3214
+ assert.match(error, /documented_host_consensus_receipt_unavailable/);
3908
3215
  const state = JSON.parse(await readFile(join(sessionDir, 'autopilot-state.json'), 'utf-8'));
3909
3216
  assert.equal(state.current_phase, 'ralplan');
3910
3217
  });
@@ -3944,8 +3251,8 @@ describe('state operations directory initialization', () => {
3944
3251
  });
3945
3252
  assert.equal(response.isError, true);
3946
3253
  const error = String(response.payload.error || '');
3947
- assert.match(error, /subagent-tracking\.json/);
3948
- assert.match(error, /only reviews recorded in OMX subagent-tracking\.json count as native lanes/i);
3254
+ assert.match(error, /documented_host_consensus_receipt_unavailable/);
3255
+ assert.match(error, /official host consensus receipt verifier is unavailable/i);
3949
3256
  });
3950
3257
  }
3951
3258
  finally {
@@ -3984,7 +3291,7 @@ describe('state operations directory initialization', () => {
3984
3291
  current_phase: 'ultragoal',
3985
3292
  });
3986
3293
  assert.equal(response.isError, true);
3987
- assert.match(String(response.payload.error || ''), /tracker-backed native architect and critic lanes/i);
3294
+ assert.match(String(response.payload.error || ''), /documented_host_consensus_receipt_unavailable/);
3988
3295
  const state = JSON.parse(await readFile(join(sessionDir, 'autopilot-state.json'), 'utf-8'));
3989
3296
  assert.equal(state.current_phase, 'ralplan');
3990
3297
  });
@@ -4013,7 +3320,7 @@ describe('state operations directory initialization', () => {
4013
3320
  current_phase: 'ultragoal',
4014
3321
  });
4015
3322
  assert.equal(response.isError, true);
4016
- assert.match(String(response.payload.error || ''), /ralplan consensus/i);
3323
+ assert.match(String(response.payload.error || ''), /documented_host_consensus_receipt_unavailable/);
4017
3324
  const state = JSON.parse(await readFile(join(sessionDir, 'autopilot-state.json'), 'utf-8'));
4018
3325
  assert.equal(state.current_phase, 'planning');
4019
3326
  });
@@ -4638,7 +3945,7 @@ describe('state operations directory initialization', () => {
4638
3945
  await rm(wd, { recursive: true, force: true });
4639
3946
  }
4640
3947
  });
4641
- it('allows Autopilot ralplan to ultragoal self-write with tracker-backed native consensus evidence', async () => {
3948
+ it('denies Autopilot ralplan to ultragoal self-write with tracker-backed native lifecycle evidence', async () => {
4642
3949
  const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-autopilot-ralplan-native-allow-'));
4643
3950
  try {
4644
3951
  await withOmxRootEnv(wd, async () => {
@@ -4667,9 +3974,10 @@ describe('state operations directory initialization', () => {
4667
3974
  active: true,
4668
3975
  current_phase: 'ultragoal',
4669
3976
  });
4670
- assert.equal(response.isError, undefined);
3977
+ assert.equal(response.isError, true);
3978
+ assert.match(String(response.payload.error || ''), /documented_host_consensus_receipt_unavailable/);
4671
3979
  const state = JSON.parse(await readFile(join(sessionDir, 'autopilot-state.json'), 'utf-8'));
4672
- assert.equal(state.current_phase, 'ultragoal');
3980
+ assert.equal(state.current_phase, 'ralplan');
4673
3981
  });
4674
3982
  }
4675
3983
  finally {
@@ -4745,7 +4053,7 @@ describe('state operations directory initialization', () => {
4745
4053
  const sessionId = 'sess-resume-root-fallback';
4746
4054
  const sessionDir = join(stateDir, 'sessions', sessionId);
4747
4055
  await mkdir(sessionDir, { recursive: true });
4748
- await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: sessionId }, null, 2));
4056
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: sessionId, cwd: wd, state_root: stateDir }, null, 2));
4749
4057
  await writeFile(join(stateDir, 'ralph-state.json'), JSON.stringify({
4750
4058
  active: true,
4751
4059
  current_phase: 'executing',
@@ -4776,5 +4084,309 @@ describe('state operations directory initialization', () => {
4776
4084
  await rm(wd, { recursive: true, force: true });
4777
4085
  }
4778
4086
  });
4087
+ function installScopeTakeover(stateDir, expected, replacementPointer) {
4088
+ const events = [];
4089
+ __setWritableStateScopeTestHooksForTests({
4090
+ beforeScopeRevalidation: async (event) => {
4091
+ const actual = [event.commitOrdinal, event.site, event.kind, event.path];
4092
+ events.push(actual);
4093
+ if (event.commitOrdinal === expected[0] && event.site === expected[1]) {
4094
+ await writeFile(join(stateDir, 'session.json'), replacementPointer);
4095
+ return;
4096
+ }
4097
+ if (event.commitOrdinal === expected[0] || event.site === expected[1]) {
4098
+ throw new Error(`takeover drift: expected (${expected[0]}, ${expected[1]}), got (${event.commitOrdinal}, ${event.site})`);
4099
+ }
4100
+ },
4101
+ });
4102
+ return events;
4103
+ }
4104
+ async function seedWritableScope(wd, sessionId = 'sess-current') {
4105
+ const stateDir = getBaseStateDir(wd);
4106
+ await mkdir(join(stateDir, 'sessions', sessionId), { recursive: true });
4107
+ await writeFile(join(stateDir, 'session.json'), JSON.stringify({ session_id: sessionId, cwd: wd, state_root: stateDir }));
4108
+ return { stateDir, sessionId };
4109
+ }
4110
+ function assertPrefix(events, expected) {
4111
+ assert.deepEqual(events.slice(0, expected.length), expected);
4112
+ }
4113
+ it('fails closed before primary session persistence on malformed root skill-active state', async () => {
4114
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-malformed-root-'));
4115
+ try {
4116
+ const { stateDir, sessionId } = await seedWritableScope(wd);
4117
+ const rootPath = join(stateDir, 'skill-active-state.json');
4118
+ const sessionPath = join(stateDir, 'sessions', sessionId, 'skill-active-state.json');
4119
+ const rootBytes = '{"active":true,\n';
4120
+ const sessionBytes = '{"active":true,"skill":"old"}\n';
4121
+ await writeFile(rootPath, rootBytes);
4122
+ await writeFile(sessionPath, sessionBytes);
4123
+ const response = await executeStateOperation('state_write', {
4124
+ workingDirectory: wd,
4125
+ session_id: sessionId,
4126
+ mode: 'skill-active',
4127
+ active: true,
4128
+ skill: 'new',
4129
+ phase: 'executing',
4130
+ active_skills: [{ skill: 'new', phase: 'executing', active: true, session_id: sessionId }],
4131
+ });
4132
+ assert.equal(response.isError, true);
4133
+ assert.match(String(response.payload.error || ''), /malformed root skill-active state/i);
4134
+ assert.equal(await readFile(rootPath, 'utf8'), rootBytes);
4135
+ assert.equal(await readFile(sessionPath, 'utf8'), sessionBytes);
4136
+ }
4137
+ finally {
4138
+ await rm(wd, { recursive: true, force: true });
4139
+ }
4140
+ });
4141
+ it('fails closed before primary session persistence on root lock timeout', async () => {
4142
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-lock-timeout-'));
4143
+ try {
4144
+ const { stateDir, sessionId } = await seedWritableScope(wd);
4145
+ const rootPath = join(stateDir, 'skill-active-state.json');
4146
+ const sessionPath = join(stateDir, 'sessions', sessionId, 'skill-active-state.json');
4147
+ const rootBytes = `${JSON.stringify({ version: 1, active: true, skill: 'old', session_id: sessionId, active_skills: [] }, null, 2)}\n`;
4148
+ const sessionBytes = '{"active":true,"skill":"old"}\n';
4149
+ await writeFile(rootPath, rootBytes);
4150
+ await writeFile(sessionPath, sessionBytes);
4151
+ await mkdir(`${rootPath}.lock`);
4152
+ const response = await executeStateOperation('state_write', {
4153
+ workingDirectory: wd,
4154
+ session_id: sessionId,
4155
+ mode: 'skill-active',
4156
+ active: true,
4157
+ skill: 'new',
4158
+ phase: 'executing',
4159
+ active_skills: [{ skill: 'new', phase: 'executing', active: true, session_id: sessionId }],
4160
+ });
4161
+ assert.equal(response.isError, true);
4162
+ assert.match(String(response.payload.error || ''), /lock|timeout/i);
4163
+ assert.equal(await readFile(rootPath, 'utf8'), rootBytes);
4164
+ assert.equal(await readFile(sessionPath, 'utf8'), sessionBytes);
4165
+ }
4166
+ finally {
4167
+ await rm(wd, { recursive: true, force: true });
4168
+ }
4169
+ });
4170
+ it('T4 records the full pinned state_write commit prefix', async () => {
4171
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-t4-'));
4172
+ try {
4173
+ const { stateDir, sessionId } = await seedWritableScope(wd);
4174
+ const events = [];
4175
+ __setWritableStateScopeTestHooksForTests({ beforeScopeRevalidation: async (event) => { events.push([event.commitOrdinal, event.site, event.kind, event.path]); } });
4176
+ const response = await executeStateOperation('state_write', { workingDirectory: wd, mode: 'autoresearch', active: true, current_phase: 'running' });
4177
+ assert.equal(response.isError, undefined);
4178
+ const sessionDir = join(stateDir, 'sessions', sessionId);
4179
+ assertPrefix(events, [
4180
+ [1, 'mode.primary', 'write', join(sessionDir, 'autoresearch-state.json')],
4181
+ [2, 'skill-active.root-copy', 'write', join(stateDir, 'skill-active-state.json')],
4182
+ [3, 'skill-active.session-copy', 'write', join(sessionDir, 'skill-active-state.json')],
4183
+ ]);
4184
+ }
4185
+ finally {
4186
+ __setWritableStateScopeTestHooksForTests({});
4187
+ await rm(wd, { recursive: true, force: true });
4188
+ }
4189
+ });
4190
+ it('T5 rejects a state_write takeover at its first commit', async () => {
4191
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-t5-'));
4192
+ try {
4193
+ const { stateDir, sessionId } = await seedWritableScope(wd);
4194
+ installScopeTakeover(stateDir, [1, 'mode.primary'], JSON.stringify({ session_id: 'sess-replacement', cwd: wd, state_root: stateDir }));
4195
+ const response = await executeStateOperation('state_write', { workingDirectory: wd, mode: 'autoresearch', active: true });
4196
+ assert.equal(response.isError, true);
4197
+ assert.deepEqual(response.payload, { error: WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite });
4198
+ assert.equal(existsSync(join(stateDir, 'sessions', sessionId, 'autoresearch-state.json')), false);
4199
+ }
4200
+ finally {
4201
+ __setWritableStateScopeTestHooksForTests({});
4202
+ await rm(wd, { recursive: true, force: true });
4203
+ }
4204
+ });
4205
+ it('T6 rejects a later state_write takeover after the non-atomic primary commit', async () => {
4206
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-t6-'));
4207
+ try {
4208
+ const { stateDir, sessionId } = await seedWritableScope(wd);
4209
+ installScopeTakeover(stateDir, [2, 'skill-active.root-copy'], JSON.stringify({ session_id: 'sess-replacement', cwd: wd, state_root: stateDir }));
4210
+ const response = await executeStateOperation('state_write', { workingDirectory: wd, mode: 'autoresearch', active: true });
4211
+ assert.deepEqual(response.payload, { error: WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite });
4212
+ // Earlier multi-file commits are not rolled back; each later site still performs its own point-in-time check, without closing the post-check race.
4213
+ assert.equal(existsSync(join(stateDir, 'sessions', sessionId, 'autoresearch-state.json')), true);
4214
+ assert.equal(existsSync(join(stateDir, 'skill-active-state.json')), false);
4215
+ }
4216
+ finally {
4217
+ __setWritableStateScopeTestHooksForTests({});
4218
+ await rm(wd, { recursive: true, force: true });
4219
+ }
4220
+ });
4221
+ it('T7 records state_clear commits and rejects its native-stop takeover', async () => {
4222
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-t7-'));
4223
+ try {
4224
+ const { stateDir, sessionId } = await seedWritableScope(wd);
4225
+ await writeFile(join(stateDir, 'native-stop-state.json'), JSON.stringify({ sessions: { [sessionId]: {} } }));
4226
+ await writeFile(join(stateDir, 'sessions', sessionId, 'native-stop-state.json'), JSON.stringify({ sessions: { [sessionId]: {} } }));
4227
+ await executeStateOperation('state_write', { workingDirectory: wd, mode: 'autoresearch', active: true });
4228
+ const events = [];
4229
+ __setWritableStateScopeTestHooksForTests({ beforeScopeRevalidation: async (event) => { events.push([event.commitOrdinal, event.site, event.kind, event.path]); } });
4230
+ await executeStateOperation('state_clear', { workingDirectory: wd, mode: 'autoresearch' });
4231
+ const sessionDir = join(stateDir, 'sessions', sessionId);
4232
+ assertPrefix(events, [
4233
+ [1, 'state-clear.primary', 'unlink', join(sessionDir, 'autoresearch-state.json')],
4234
+ [2, 'native-stop.root', 'write', join(stateDir, 'native-stop-state.json')],
4235
+ [3, 'native-stop.session', 'write', join(sessionDir, 'native-stop-state.json')],
4236
+ [4, 'skill-active.root-copy', 'write', join(stateDir, 'skill-active-state.json')],
4237
+ [5, 'skill-active.session-copy', 'write', join(sessionDir, 'skill-active-state.json')],
4238
+ ]);
4239
+ await executeStateOperation('state_write', { workingDirectory: wd, mode: 'autoresearch', active: true });
4240
+ await writeFile(join(stateDir, 'native-stop-state.json'), JSON.stringify({ sessions: { [sessionId]: {} } }));
4241
+ await writeFile(join(sessionDir, 'native-stop-state.json'), JSON.stringify({ sessions: { [sessionId]: {} } }));
4242
+ installScopeTakeover(stateDir, [2, 'native-stop.root'], JSON.stringify({ session_id: 'sess-replacement', cwd: wd, state_root: stateDir }));
4243
+ const rejected = await executeStateOperation('state_clear', { workingDirectory: wd, mode: 'autoresearch' });
4244
+ assert.deepEqual(rejected.payload, { error: WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite });
4245
+ }
4246
+ finally {
4247
+ __setWritableStateScopeTestHooksForTests({});
4248
+ await rm(wd, { recursive: true, force: true });
4249
+ }
4250
+ });
4251
+ it('T15 fails loudly when a takeover ordinal-site pair drifts', async () => {
4252
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-t15-'));
4253
+ try {
4254
+ const { stateDir } = await seedWritableScope(wd);
4255
+ installScopeTakeover(stateDir, [2, 'mode.primary'], JSON.stringify({ session_id: 'sess-replacement', cwd: wd, state_root: stateDir }));
4256
+ const response = await executeStateOperation('state_write', { workingDirectory: wd, mode: 'autoresearch', active: true });
4257
+ assert.equal(response.isError, true);
4258
+ const error = String(response.payload.error);
4259
+ assert.match(error, /takeover drift: expected \(2, mode.primary\), got \(1, mode.primary\)/);
4260
+ assert.notEqual(error, WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite);
4261
+ }
4262
+ finally {
4263
+ __setWritableStateScopeTestHooksForTests({});
4264
+ await rm(wd, { recursive: true, force: true });
4265
+ }
4266
+ });
4267
+ it('T14 revalidates the transition source-mode detail commit', async () => {
4268
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-t14-'));
4269
+ try {
4270
+ const { stateDir, sessionId } = await seedWritableScope(wd);
4271
+ await startMode('deep-interview', 'clarify contract', 3, wd);
4272
+ await updateModeState('deep-interview', { deep_interview_gate: { status: 'complete', rationale: 'ready' } }, wd);
4273
+ const events = [];
4274
+ __setWritableStateScopeTestHooksForTests({ beforeScopeRevalidation: async (event) => { events.push([event.commitOrdinal, event.site, event.kind, event.path]); } });
4275
+ await startMode('ralplan', 'plan contract', 5, wd);
4276
+ assert.deepEqual(events[0], [1, 'transition.source-mode-detail', 'write', join(stateDir, 'sessions', sessionId, 'deep-interview-state.json')]);
4277
+ await rm(join(stateDir, 'ralplan-state.json'), { force: true });
4278
+ await writeFile(join(stateDir, 'sessions', sessionId, 'deep-interview-state.json'), JSON.stringify({ active: true, current_phase: 'starting', deep_interview_gate: { status: 'complete', rationale: 'ready' } }));
4279
+ await writeFile(join(stateDir, 'skill-active-state.json'), JSON.stringify({ active: true, active_skills: [{ skill: 'deep-interview', active: true, session_id: sessionId }] }));
4280
+ await writeFile(join(stateDir, 'sessions', sessionId, 'skill-active-state.json'), JSON.stringify({ active: true, active_skills: [{ skill: 'deep-interview', active: true, session_id: sessionId }] }));
4281
+ const detail = await readFile(join(stateDir, 'sessions', sessionId, 'deep-interview-state.json'), 'utf-8');
4282
+ const skill = await readFile(join(stateDir, 'sessions', sessionId, 'skill-active-state.json'), 'utf-8');
4283
+ installScopeTakeover(stateDir, [1, 'transition.source-mode-detail'], JSON.stringify({ session_id: 'sess-replacement', cwd: wd, state_root: stateDir }));
4284
+ await assert.rejects(() => startMode('ralplan', 'plan again', 5, wd), new Error(WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite));
4285
+ assert.equal(await readFile(join(stateDir, 'sessions', sessionId, 'deep-interview-state.json'), 'utf-8'), detail);
4286
+ assert.equal(await readFile(join(stateDir, 'sessions', sessionId, 'skill-active-state.json'), 'utf-8'), skill);
4287
+ }
4288
+ finally {
4289
+ __setWritableStateScopeTestHooksForTests({});
4290
+ await rm(wd, { recursive: true, force: true });
4291
+ }
4292
+ });
4293
+ it('requires capturedScope before checking either terminal or non-terminal ralplan state', async () => {
4294
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-f14-guard-'));
4295
+ try {
4296
+ const { sessionId } = await seedWritableScope(wd);
4297
+ const terminal = { active: false, current_phase: 'complete', session_id: sessionId, ralplan_consensus_gate: { complete: true } };
4298
+ const beforeCommit = async () => { };
4299
+ await assert.rejects(() => completeRalplanSession({ cwd: wd, baseStateDir: getBaseStateDir(wd), state: terminal, beforeCommit }), new Error('completeRalplanSession requires capturedScope when beforeCommit is provided'));
4300
+ await assert.rejects(() => completeRalplanSession({ cwd: wd, baseStateDir: getBaseStateDir(wd), state: { active: true, current_phase: 'planning' }, beforeCommit }), new Error('completeRalplanSession requires capturedScope when beforeCommit is provided'));
4301
+ }
4302
+ finally {
4303
+ __setWritableStateScopeTestHooksForTests({});
4304
+ await rm(wd, { recursive: true, force: true });
4305
+ }
4306
+ });
4307
+ it('keeps mode and run-state writes pinned to session A across transient A-B-A pointer movement', async () => {
4308
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-f14-pinned-run-state-'));
4309
+ try {
4310
+ const { stateDir, sessionId } = await seedWritableScope(wd, 'sess-a');
4311
+ const sessionADir = join(stateDir, 'sessions', sessionId);
4312
+ const sessionBId = 'sess-b';
4313
+ const sessionBDir = join(stateDir, 'sessions', sessionBId);
4314
+ await mkdir(sessionBDir, { recursive: true });
4315
+ const pointerA = await readFile(join(stateDir, 'session.json'), 'utf-8');
4316
+ const pointerB = JSON.stringify({ session_id: sessionBId, cwd: wd, state_root: stateDir });
4317
+ const events = [];
4318
+ __setWritableStateScopeTestHooksForTests({
4319
+ beforeScopeRevalidation: async (event) => {
4320
+ events.push([event.commitOrdinal, event.site, event.kind, event.path]);
4321
+ if (event.site === 'mode.primary') {
4322
+ await writeFile(join(stateDir, 'session.json'), pointerB);
4323
+ await writeFile(join(stateDir, 'session.json'), pointerA);
4324
+ }
4325
+ },
4326
+ });
4327
+ await startMode('autoresearch', 'verify pinned run-state target', 3, wd);
4328
+ assert.deepEqual(events.find(([, site]) => site === 'run-state.mode-sync'), [2, 'run-state.mode-sync', 'write', join(sessionADir, 'run-state.json')]);
4329
+ assert.deepEqual(events.find(([, site]) => site === 'mode.primary'), [1, 'mode.primary', 'write', join(sessionADir, 'autoresearch-state.json')]);
4330
+ assert.equal(existsSync(join(sessionADir, 'run-state.json')), true);
4331
+ assert.equal(existsSync(join(sessionADir, 'autoresearch-state.json')), true);
4332
+ assert.equal(existsSync(join(sessionBDir, 'run-state.json')), false);
4333
+ assert.equal(existsSync(join(sessionBDir, 'autoresearch-state.json')), false);
4334
+ }
4335
+ finally {
4336
+ __setWritableStateScopeTestHooksForTests({});
4337
+ await rm(wd, { recursive: true, force: true });
4338
+ }
4339
+ });
4340
+ it('revalidates the root-scoped session skill-state unlink', async () => {
4341
+ const wd = await mkdtemp(join(tmpdir(), 'omx-state-ops-session-unlink-'));
4342
+ try {
4343
+ const stateDir = getBaseStateDir(wd);
4344
+ const sessionId = 'sess-current';
4345
+ const sessionDir = join(stateDir, 'sessions', sessionId);
4346
+ const sessionPath = join(sessionDir, 'skill-active-state.json');
4347
+ const writeFixture = async () => {
4348
+ const rootSkillState = JSON.stringify({
4349
+ active: true,
4350
+ skill: 'autoresearch',
4351
+ active_skills: [{ skill: 'autoresearch', active: true }],
4352
+ });
4353
+ const sessionSkillState = JSON.stringify({
4354
+ active: false,
4355
+ skill: 'autoresearch',
4356
+ session_id: sessionId,
4357
+ });
4358
+ await mkdir(sessionDir, { recursive: true });
4359
+ await writeFile(join(stateDir, 'autoresearch-state.json'), JSON.stringify({ active: true }));
4360
+ await writeFile(join(stateDir, 'skill-active-state.json'), rootSkillState);
4361
+ await writeFile(sessionPath, sessionSkillState);
4362
+ };
4363
+ await writeFixture();
4364
+ const events = [];
4365
+ __setWritableStateScopeTestHooksForTests({
4366
+ beforeScopeRevalidation: async (event) => {
4367
+ events.push([event.commitOrdinal, event.site, event.kind, event.path]);
4368
+ },
4369
+ });
4370
+ const response = await executeStateOperation('state_clear', { workingDirectory: wd, mode: 'autoresearch' });
4371
+ assert.equal(response.isError, undefined);
4372
+ assertPrefix(events, [
4373
+ [1, 'state-clear.primary', 'unlink', join(stateDir, 'autoresearch-state.json')],
4374
+ [2, 'skill-active.root-copy', 'write', join(stateDir, 'skill-active-state.json')],
4375
+ [3, 'skill-active.session-unlink', 'unlink', sessionPath],
4376
+ ]);
4377
+ assert.equal(existsSync(sessionPath), false);
4378
+ await writeFixture();
4379
+ installScopeTakeover(stateDir, [3, 'skill-active.session-unlink'], JSON.stringify({ session_id: 'sess-replacement', cwd: wd, state_root: stateDir }));
4380
+ const rejected = await executeStateOperation('state_clear', { workingDirectory: wd, mode: 'autoresearch' });
4381
+ assert.equal(rejected.isError, true);
4382
+ assert.deepEqual(rejected.payload, { error: WRITABLE_STATE_SCOPE_ERRORS.scopeChangedDuringWrite });
4383
+ // Earlier commits in the sequence are not rolled back; each site performs its own point-in-time check.
4384
+ assert.equal(existsSync(sessionPath), true);
4385
+ }
4386
+ finally {
4387
+ __setWritableStateScopeTestHooksForTests({});
4388
+ await rm(wd, { recursive: true, force: true });
4389
+ }
4390
+ });
4779
4391
  });
4780
4392
  //# sourceMappingURL=operations.test.js.map