oh-my-codex 0.20.2 → 0.20.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (805) hide show
  1. package/Cargo.lock +36 -18
  2. package/Cargo.toml +1 -1
  3. package/README.md +28 -2
  4. package/crates/omx-runtime/Cargo.toml +4 -0
  5. package/crates/omx-runtime/src/main.rs +415 -2
  6. package/crates/omx-runtime/tests/execution.rs +483 -0
  7. package/crates/omx-runtime-core/src/dispatch.rs +96 -10
  8. package/crates/omx-runtime-core/src/engine.rs +839 -29
  9. package/crates/omx-runtime-core/src/lib.rs +8 -0
  10. package/dist/adapt/__tests__/herdr-target.test.d.ts +2 -0
  11. package/dist/adapt/__tests__/herdr-target.test.d.ts.map +1 -0
  12. package/dist/adapt/__tests__/herdr-target.test.js +72 -0
  13. package/dist/adapt/__tests__/herdr-target.test.js.map +1 -0
  14. package/dist/adapt/contracts.d.ts +1 -1
  15. package/dist/adapt/contracts.d.ts.map +1 -1
  16. package/dist/adapt/contracts.js +1 -1
  17. package/dist/adapt/contracts.js.map +1 -1
  18. package/dist/adapt/herdr/__tests__/authority.test.d.ts +2 -0
  19. package/dist/adapt/herdr/__tests__/authority.test.d.ts.map +1 -0
  20. package/dist/adapt/herdr/__tests__/authority.test.js +49 -0
  21. package/dist/adapt/herdr/__tests__/authority.test.js.map +1 -0
  22. package/dist/adapt/herdr/__tests__/bridge.test.d.ts +2 -0
  23. package/dist/adapt/herdr/__tests__/bridge.test.d.ts.map +1 -0
  24. package/dist/adapt/herdr/__tests__/bridge.test.js +176 -0
  25. package/dist/adapt/herdr/__tests__/bridge.test.js.map +1 -0
  26. package/dist/adapt/herdr/__tests__/sanitize.test.d.ts +2 -0
  27. package/dist/adapt/herdr/__tests__/sanitize.test.d.ts.map +1 -0
  28. package/dist/adapt/herdr/__tests__/sanitize.test.js +45 -0
  29. package/dist/adapt/herdr/__tests__/sanitize.test.js.map +1 -0
  30. package/dist/adapt/herdr/__tests__/semantic.test.d.ts +2 -0
  31. package/dist/adapt/herdr/__tests__/semantic.test.d.ts.map +1 -0
  32. package/dist/adapt/herdr/__tests__/semantic.test.js +130 -0
  33. package/dist/adapt/herdr/__tests__/semantic.test.js.map +1 -0
  34. package/dist/adapt/herdr/__tests__/seq-store.test.d.ts +2 -0
  35. package/dist/adapt/herdr/__tests__/seq-store.test.d.ts.map +1 -0
  36. package/dist/adapt/herdr/__tests__/seq-store.test.js +54 -0
  37. package/dist/adapt/herdr/__tests__/seq-store.test.js.map +1 -0
  38. package/dist/adapt/herdr/__tests__/socket-live.test.d.ts +2 -0
  39. package/dist/adapt/herdr/__tests__/socket-live.test.d.ts.map +1 -0
  40. package/dist/adapt/herdr/__tests__/socket-live.test.js +104 -0
  41. package/dist/adapt/herdr/__tests__/socket-live.test.js.map +1 -0
  42. package/dist/adapt/herdr/__tests__/team-map.test.d.ts +2 -0
  43. package/dist/adapt/herdr/__tests__/team-map.test.d.ts.map +1 -0
  44. package/dist/adapt/herdr/__tests__/team-map.test.js +46 -0
  45. package/dist/adapt/herdr/__tests__/team-map.test.js.map +1 -0
  46. package/dist/adapt/herdr/__tests__/transport.test.d.ts +2 -0
  47. package/dist/adapt/herdr/__tests__/transport.test.d.ts.map +1 -0
  48. package/dist/adapt/herdr/__tests__/transport.test.js +160 -0
  49. package/dist/adapt/herdr/__tests__/transport.test.js.map +1 -0
  50. package/dist/adapt/herdr/__tests__/wiring.test.d.ts +2 -0
  51. package/dist/adapt/herdr/__tests__/wiring.test.d.ts.map +1 -0
  52. package/dist/adapt/herdr/__tests__/wiring.test.js +118 -0
  53. package/dist/adapt/herdr/__tests__/wiring.test.js.map +1 -0
  54. package/dist/adapt/herdr/authority.d.ts +34 -0
  55. package/dist/adapt/herdr/authority.d.ts.map +1 -0
  56. package/dist/adapt/herdr/authority.js +71 -0
  57. package/dist/adapt/herdr/authority.js.map +1 -0
  58. package/dist/adapt/herdr/bridge.d.ts +84 -0
  59. package/dist/adapt/herdr/bridge.d.ts.map +1 -0
  60. package/dist/adapt/herdr/bridge.js +222 -0
  61. package/dist/adapt/herdr/bridge.js.map +1 -0
  62. package/dist/adapt/herdr/sanitize.d.ts +20 -0
  63. package/dist/adapt/herdr/sanitize.d.ts.map +1 -0
  64. package/dist/adapt/herdr/sanitize.js +70 -0
  65. package/dist/adapt/herdr/sanitize.js.map +1 -0
  66. package/dist/adapt/herdr/semantic.d.ts +67 -0
  67. package/dist/adapt/herdr/semantic.d.ts.map +1 -0
  68. package/dist/adapt/herdr/semantic.js +170 -0
  69. package/dist/adapt/herdr/semantic.js.map +1 -0
  70. package/dist/adapt/herdr/seq-store.d.ts +32 -0
  71. package/dist/adapt/herdr/seq-store.d.ts.map +1 -0
  72. package/dist/adapt/herdr/seq-store.js +126 -0
  73. package/dist/adapt/herdr/seq-store.js.map +1 -0
  74. package/dist/adapt/herdr/team-map.d.ts +30 -0
  75. package/dist/adapt/herdr/team-map.d.ts.map +1 -0
  76. package/dist/adapt/herdr/team-map.js +37 -0
  77. package/dist/adapt/herdr/team-map.js.map +1 -0
  78. package/dist/adapt/herdr/transport.d.ts +115 -0
  79. package/dist/adapt/herdr/transport.d.ts.map +1 -0
  80. package/dist/adapt/herdr/transport.js +260 -0
  81. package/dist/adapt/herdr/transport.js.map +1 -0
  82. package/dist/adapt/herdr/wiring.d.ts +24 -0
  83. package/dist/adapt/herdr/wiring.d.ts.map +1 -0
  84. package/dist/adapt/herdr/wiring.js +62 -0
  85. package/dist/adapt/herdr/wiring.js.map +1 -0
  86. package/dist/adapt/herdr.d.ts +19 -0
  87. package/dist/adapt/herdr.d.ts.map +1 -0
  88. package/dist/adapt/herdr.js +115 -0
  89. package/dist/adapt/herdr.js.map +1 -0
  90. package/dist/adapt/index.d.ts +4 -0
  91. package/dist/adapt/index.d.ts.map +1 -1
  92. package/dist/adapt/index.js +48 -0
  93. package/dist/adapt/index.js.map +1 -1
  94. package/dist/adapt/registry.d.ts.map +1 -1
  95. package/dist/adapt/registry.js +11 -0
  96. package/dist/adapt/registry.js.map +1 -1
  97. package/dist/agents/__tests__/definitions.test.js +81 -0
  98. package/dist/agents/__tests__/definitions.test.js.map +1 -1
  99. package/dist/agents/__tests__/native-config.test.js +25 -0
  100. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  101. package/dist/agents/native-config.d.ts +2 -1
  102. package/dist/agents/native-config.d.ts.map +1 -1
  103. package/dist/agents/native-config.js.map +1 -1
  104. package/dist/auth/__tests__/hotswap.test.js +60 -1
  105. package/dist/auth/__tests__/hotswap.test.js.map +1 -1
  106. package/dist/auth/__tests__/storage.test.js +33 -1
  107. package/dist/auth/__tests__/storage.test.js.map +1 -1
  108. package/dist/auth/hotswap.d.ts +22 -2
  109. package/dist/auth/hotswap.d.ts.map +1 -1
  110. package/dist/auth/hotswap.js +107 -22
  111. package/dist/auth/hotswap.js.map +1 -1
  112. package/dist/auth/storage.js +1 -1
  113. package/dist/auth/storage.js.map +1 -1
  114. package/dist/autopilot/__tests__/ralplan-gate.test.js +86 -1333
  115. package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -1
  116. package/dist/autopilot/ralplan-gate.d.ts.map +1 -1
  117. package/dist/autopilot/ralplan-gate.js +7 -6
  118. package/dist/autopilot/ralplan-gate.js.map +1 -1
  119. package/dist/cli/__tests__/agents-init.test.js +4 -23
  120. package/dist/cli/__tests__/agents-init.test.js.map +1 -1
  121. package/dist/cli/__tests__/api.test.js +61 -24
  122. package/dist/cli/__tests__/api.test.js.map +1 -1
  123. package/dist/cli/__tests__/auth.test.js +63 -7
  124. package/dist/cli/__tests__/auth.test.js.map +1 -1
  125. package/dist/cli/__tests__/codex-feature-probe.test.js +66 -1
  126. package/dist/cli/__tests__/codex-feature-probe.test.js.map +1 -1
  127. package/dist/cli/__tests__/codex-plugin-layout.test.js +150 -2
  128. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  129. package/dist/cli/__tests__/detached-leader-teardown.test.d.ts +2 -0
  130. package/dist/cli/__tests__/detached-leader-teardown.test.d.ts.map +1 -0
  131. package/dist/cli/__tests__/detached-leader-teardown.test.js +473 -0
  132. package/dist/cli/__tests__/detached-leader-teardown.test.js.map +1 -0
  133. package/dist/cli/__tests__/doctor-process-identity-readiness.test.d.ts +2 -0
  134. package/dist/cli/__tests__/doctor-process-identity-readiness.test.d.ts.map +1 -0
  135. package/dist/cli/__tests__/doctor-process-identity-readiness.test.js +103 -0
  136. package/dist/cli/__tests__/doctor-process-identity-readiness.test.js.map +1 -0
  137. package/dist/cli/__tests__/doctor-state-root-binding.test.d.ts +2 -0
  138. package/dist/cli/__tests__/doctor-state-root-binding.test.d.ts.map +1 -0
  139. package/dist/cli/__tests__/doctor-state-root-binding.test.js +139 -0
  140. package/dist/cli/__tests__/doctor-state-root-binding.test.js.map +1 -0
  141. package/dist/cli/__tests__/doctor-warning-copy.test.js +135 -1
  142. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  143. package/dist/cli/__tests__/exec.test.js +211 -0
  144. package/dist/cli/__tests__/exec.test.js.map +1 -1
  145. package/dist/cli/__tests__/index.test.js +878 -463
  146. package/dist/cli/__tests__/index.test.js.map +1 -1
  147. package/dist/cli/__tests__/launch-fallback.test.js +1290 -127
  148. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  149. package/dist/cli/__tests__/mcp-parity.test.js +8 -4
  150. package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
  151. package/dist/cli/__tests__/native-assets.test.js +398 -16
  152. package/dist/cli/__tests__/native-assets.test.js.map +1 -1
  153. package/dist/cli/__tests__/native-hook-claim-journal.test.js +132 -6
  154. package/dist/cli/__tests__/native-hook-claim-journal.test.js.map +1 -1
  155. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +3 -3
  156. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
  157. package/dist/cli/__tests__/ralph.test.js +3 -3
  158. package/dist/cli/__tests__/ralph.test.js.map +1 -1
  159. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js +49 -164
  160. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js.map +1 -1
  161. package/dist/cli/__tests__/ralplan-child-binding-3212.test.d.ts +2 -0
  162. package/dist/cli/__tests__/ralplan-child-binding-3212.test.d.ts.map +1 -0
  163. package/dist/cli/__tests__/ralplan-child-binding-3212.test.js +56 -0
  164. package/dist/cli/__tests__/ralplan-child-binding-3212.test.js.map +1 -0
  165. package/dist/cli/__tests__/ralplan.test.js +107 -109
  166. package/dist/cli/__tests__/ralplan.test.js.map +1 -1
  167. package/dist/cli/__tests__/resume.test.js +11 -10
  168. package/dist/cli/__tests__/resume.test.js.map +1 -1
  169. package/dist/cli/__tests__/session-scoped-runtime.test.js +1118 -43
  170. package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -1
  171. package/dist/cli/__tests__/session-search-help.test.js +25 -1
  172. package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
  173. package/dist/cli/__tests__/setup-agents-overwrite.test.js +8 -55
  174. package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
  175. package/dist/cli/__tests__/setup-install-mode.test.js +224 -7
  176. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  177. package/dist/cli/__tests__/sparkshell-cli.test.js +93 -41
  178. package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -1
  179. package/dist/cli/__tests__/team.test.js +150 -8
  180. package/dist/cli/__tests__/team.test.js.map +1 -1
  181. package/dist/cli/__tests__/ultragoal.test.js +117 -2
  182. package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
  183. package/dist/cli/__tests__/uninstall.test.js +95 -4
  184. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  185. package/dist/cli/__tests__/update.test.js +669 -177
  186. package/dist/cli/__tests__/update.test.js.map +1 -1
  187. package/dist/cli/__tests__/windows-popup-loop-contract.test.js +33 -2
  188. package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
  189. package/dist/cli/api.d.ts.map +1 -1
  190. package/dist/cli/api.js +9 -10
  191. package/dist/cli/api.js.map +1 -1
  192. package/dist/cli/codex-feature-probe.d.ts +16 -0
  193. package/dist/cli/codex-feature-probe.d.ts.map +1 -1
  194. package/dist/cli/codex-feature-probe.js +44 -0
  195. package/dist/cli/codex-feature-probe.js.map +1 -1
  196. package/dist/cli/codex-home.d.ts.map +1 -1
  197. package/dist/cli/codex-home.js +7 -4
  198. package/dist/cli/codex-home.js.map +1 -1
  199. package/dist/cli/doctor.d.ts +20 -0
  200. package/dist/cli/doctor.d.ts.map +1 -1
  201. package/dist/cli/doctor.js +290 -3
  202. package/dist/cli/doctor.js.map +1 -1
  203. package/dist/cli/index.d.ts +234 -12
  204. package/dist/cli/index.d.ts.map +1 -1
  205. package/dist/cli/index.js +2409 -746
  206. package/dist/cli/index.js.map +1 -1
  207. package/dist/cli/mcp-parity.js +2 -2
  208. package/dist/cli/mcp-parity.js.map +1 -1
  209. package/dist/cli/native-assets.d.ts +25 -0
  210. package/dist/cli/native-assets.d.ts.map +1 -1
  211. package/dist/cli/native-assets.js +448 -51
  212. package/dist/cli/native-assets.js.map +1 -1
  213. package/dist/cli/native-hook-claim-journal.d.ts +20 -5
  214. package/dist/cli/native-hook-claim-journal.d.ts.map +1 -1
  215. package/dist/cli/native-hook-claim-journal.js +67 -32
  216. package/dist/cli/native-hook-claim-journal.js.map +1 -1
  217. package/dist/cli/package-manager-ownership.d.ts +63 -0
  218. package/dist/cli/package-manager-ownership.d.ts.map +1 -0
  219. package/dist/cli/package-manager-ownership.js +323 -0
  220. package/dist/cli/package-manager-ownership.js.map +1 -0
  221. package/dist/cli/ralph.js +2 -2
  222. package/dist/cli/ralph.js.map +1 -1
  223. package/dist/cli/ralplan.d.ts +5 -7
  224. package/dist/cli/ralplan.d.ts.map +1 -1
  225. package/dist/cli/ralplan.js +83 -134
  226. package/dist/cli/ralplan.js.map +1 -1
  227. package/dist/cli/session-search.d.ts +5 -0
  228. package/dist/cli/session-search.d.ts.map +1 -1
  229. package/dist/cli/session-search.js +87 -0
  230. package/dist/cli/session-search.js.map +1 -1
  231. package/dist/cli/setup-preferences.d.ts +15 -0
  232. package/dist/cli/setup-preferences.d.ts.map +1 -1
  233. package/dist/cli/setup-preferences.js +27 -1
  234. package/dist/cli/setup-preferences.js.map +1 -1
  235. package/dist/cli/setup.d.ts +8 -0
  236. package/dist/cli/setup.d.ts.map +1 -1
  237. package/dist/cli/setup.js +119 -47
  238. package/dist/cli/setup.js.map +1 -1
  239. package/dist/cli/sparkshell.d.ts.map +1 -1
  240. package/dist/cli/sparkshell.js +52 -9
  241. package/dist/cli/sparkshell.js.map +1 -1
  242. package/dist/cli/ultragoal.d.ts.map +1 -1
  243. package/dist/cli/ultragoal.js +2 -2
  244. package/dist/cli/ultragoal.js.map +1 -1
  245. package/dist/cli/uninstall.d.ts +9 -0
  246. package/dist/cli/uninstall.d.ts.map +1 -1
  247. package/dist/cli/uninstall.js +71 -30
  248. package/dist/cli/uninstall.js.map +1 -1
  249. package/dist/cli/update-worker.d.ts +2 -0
  250. package/dist/cli/update-worker.d.ts.map +1 -0
  251. package/dist/cli/update-worker.js +142 -0
  252. package/dist/cli/update-worker.js.map +1 -0
  253. package/dist/cli/update.d.ts +14 -22
  254. package/dist/cli/update.d.ts.map +1 -1
  255. package/dist/cli/update.js +192 -241
  256. package/dist/cli/update.js.map +1 -1
  257. package/dist/compat/__tests__/rust-runtime-compat.test.js +1 -1
  258. package/dist/config/__tests__/generator-idempotent.test.js +503 -30
  259. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  260. package/dist/config/__tests__/generator-notify.test.js +5 -3
  261. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  262. package/dist/config/__tests__/models.test.js +67 -3
  263. package/dist/config/__tests__/models.test.js.map +1 -1
  264. package/dist/config/generator.d.ts +27 -21
  265. package/dist/config/generator.d.ts.map +1 -1
  266. package/dist/config/generator.js +610 -152
  267. package/dist/config/generator.js.map +1 -1
  268. package/dist/config/models.d.ts +12 -2
  269. package/dist/config/models.d.ts.map +1 -1
  270. package/dist/config/models.js +15 -1
  271. package/dist/config/models.js.map +1 -1
  272. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js +25 -0
  273. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js.map +1 -1
  274. package/dist/goal-workflows/codex-goal-snapshot.d.ts +1 -1
  275. package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -1
  276. package/dist/goal-workflows/codex-goal-snapshot.js +2 -0
  277. package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -1
  278. package/dist/hooks/__tests__/agents-overlay.test.js +5 -3
  279. package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
  280. package/dist/hooks/__tests__/autopilot-skill-contract.test.js +27 -4
  281. package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
  282. package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.d.ts +2 -0
  283. package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.d.ts.map +1 -0
  284. package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.js +172 -0
  285. package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.js.map +1 -0
  286. package/dist/hooks/__tests__/keyword-detector.test.js +176 -37
  287. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  288. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +402 -545
  289. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  290. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +39 -4
  291. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  292. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +161 -26
  293. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  294. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +27 -0
  295. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
  296. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +10 -118
  297. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
  298. package/dist/hooks/__tests__/notify-hook-regression-205.test.js +7 -0
  299. package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
  300. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +533 -14
  301. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  302. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +159 -24
  303. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  304. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +482 -32
  305. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  306. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js +2 -1
  307. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js.map +1 -1
  308. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +68 -1
  309. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  310. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +7 -1
  311. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -1
  312. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +44 -4
  313. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  314. package/dist/hooks/__tests__/prompt-guidance-contract.test.js +9 -0
  315. package/dist/hooks/__tests__/prompt-guidance-contract.test.js.map +1 -1
  316. package/dist/hooks/__tests__/session.test.js +3130 -365
  317. package/dist/hooks/__tests__/session.test.js.map +1 -1
  318. package/dist/hooks/agents-overlay.js +1 -1
  319. package/dist/hooks/agents-overlay.js.map +1 -1
  320. package/dist/hooks/extensibility/__tests__/dispatcher.test.js +108 -2
  321. package/dist/hooks/extensibility/__tests__/dispatcher.test.js.map +1 -1
  322. package/dist/hooks/extensibility/__tests__/sdk.test.js +151 -1
  323. package/dist/hooks/extensibility/__tests__/sdk.test.js.map +1 -1
  324. package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -1
  325. package/dist/hooks/extensibility/dispatcher.js +20 -3
  326. package/dist/hooks/extensibility/dispatcher.js.map +1 -1
  327. package/dist/hooks/extensibility/plugin-runner.js +1 -0
  328. package/dist/hooks/extensibility/plugin-runner.js.map +1 -1
  329. package/dist/hooks/extensibility/runtime.d.ts.map +1 -1
  330. package/dist/hooks/extensibility/runtime.js.map +1 -1
  331. package/dist/hooks/extensibility/sdk/paths.d.ts +1 -1
  332. package/dist/hooks/extensibility/sdk/paths.d.ts.map +1 -1
  333. package/dist/hooks/extensibility/sdk/paths.js +2 -2
  334. package/dist/hooks/extensibility/sdk/paths.js.map +1 -1
  335. package/dist/hooks/extensibility/sdk/runtime-state.d.ts +1 -1
  336. package/dist/hooks/extensibility/sdk/runtime-state.d.ts.map +1 -1
  337. package/dist/hooks/extensibility/sdk/runtime-state.js +55 -15
  338. package/dist/hooks/extensibility/sdk/runtime-state.js.map +1 -1
  339. package/dist/hooks/extensibility/sdk.d.ts +1 -0
  340. package/dist/hooks/extensibility/sdk.d.ts.map +1 -1
  341. package/dist/hooks/extensibility/sdk.js +1 -1
  342. package/dist/hooks/extensibility/sdk.js.map +1 -1
  343. package/dist/hooks/extensibility/types.d.ts +7 -0
  344. package/dist/hooks/extensibility/types.d.ts.map +1 -1
  345. package/dist/hooks/keyword-detector.d.ts +10 -3
  346. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  347. package/dist/hooks/keyword-detector.js +116 -20
  348. package/dist/hooks/keyword-detector.js.map +1 -1
  349. package/dist/hooks/session.d.ts +204 -14
  350. package/dist/hooks/session.d.ts.map +1 -1
  351. package/dist/hooks/session.js +1500 -223
  352. package/dist/hooks/session.js.map +1 -1
  353. package/dist/hud/__tests__/hud-tmux-injection.test.js +6 -6
  354. package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
  355. package/dist/hud/__tests__/index.test.js +26 -16
  356. package/dist/hud/__tests__/index.test.js.map +1 -1
  357. package/dist/hud/__tests__/reconcile.test.js +83 -78
  358. package/dist/hud/__tests__/reconcile.test.js.map +1 -1
  359. package/dist/hud/__tests__/state.test.js +36 -31
  360. package/dist/hud/__tests__/state.test.js.map +1 -1
  361. package/dist/hud/__tests__/tmux.test.js +155 -198
  362. package/dist/hud/__tests__/tmux.test.js.map +1 -1
  363. package/dist/hud/tmux.d.ts +42 -4
  364. package/dist/hud/tmux.d.ts.map +1 -1
  365. package/dist/hud/tmux.js +1017 -139
  366. package/dist/hud/tmux.js.map +1 -1
  367. package/dist/leader/__tests__/contract.test.js +124 -37
  368. package/dist/leader/__tests__/contract.test.js.map +1 -1
  369. package/dist/leader/contract.d.ts +17 -6
  370. package/dist/leader/contract.d.ts.map +1 -1
  371. package/dist/leader/contract.js +102 -26
  372. package/dist/leader/contract.js.map +1 -1
  373. package/dist/mcp/__tests__/code-intel-server.test.js +31 -3
  374. package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -1
  375. package/dist/mcp/__tests__/hermes-bridge.test.js +17 -0
  376. package/dist/mcp/__tests__/hermes-bridge.test.js.map +1 -1
  377. package/dist/mcp/__tests__/server-lifecycle.test.js +4 -4
  378. package/dist/mcp/__tests__/state-paths.test.js +735 -4
  379. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  380. package/dist/mcp/__tests__/state-server.test.js +1 -1
  381. package/dist/mcp/__tests__/state-server.test.js.map +1 -1
  382. package/dist/mcp/__tests__/trace-server.test.js +2 -2
  383. package/dist/mcp/__tests__/trace-server.test.js.map +1 -1
  384. package/dist/mcp/__tests__/wiki-server.test.js +18 -0
  385. package/dist/mcp/__tests__/wiki-server.test.js.map +1 -1
  386. package/dist/mcp/code-intel-server.d.ts.map +1 -1
  387. package/dist/mcp/code-intel-server.js +13 -3
  388. package/dist/mcp/code-intel-server.js.map +1 -1
  389. package/dist/mcp/hermes-bridge.d.ts.map +1 -1
  390. package/dist/mcp/hermes-bridge.js +2 -2
  391. package/dist/mcp/hermes-bridge.js.map +1 -1
  392. package/dist/mcp/state-paths.d.ts +78 -4
  393. package/dist/mcp/state-paths.d.ts.map +1 -1
  394. package/dist/mcp/state-paths.js +543 -40
  395. package/dist/mcp/state-paths.js.map +1 -1
  396. package/dist/mcp/state-server.d.ts +4 -4
  397. package/dist/mcp/state-server.d.ts.map +1 -1
  398. package/dist/mcp/wiki-server.d.ts +11 -0
  399. package/dist/mcp/wiki-server.d.ts.map +1 -1
  400. package/dist/mcp/wiki-server.js +9 -2
  401. package/dist/mcp/wiki-server.js.map +1 -1
  402. package/dist/modes/__tests__/base-autopilot-gates.test.js +36 -7
  403. package/dist/modes/__tests__/base-autopilot-gates.test.js.map +1 -1
  404. package/dist/modes/__tests__/base-multi-state-compat.test.js +1 -1
  405. package/dist/modes/__tests__/base-multi-state-compat.test.js.map +1 -1
  406. package/dist/modes/__tests__/base-session-scope.test.js +17 -8
  407. package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
  408. package/dist/modes/__tests__/base-tmux-pane.test.js +4 -4
  409. package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
  410. package/dist/modes/base.d.ts +5 -5
  411. package/dist/modes/base.d.ts.map +1 -1
  412. package/dist/modes/base.js +76 -21
  413. package/dist/modes/base.js.map +1 -1
  414. package/dist/native-assets/archive.d.ts +17 -0
  415. package/dist/native-assets/archive.d.ts.map +1 -0
  416. package/dist/native-assets/archive.js +238 -0
  417. package/dist/native-assets/archive.js.map +1 -0
  418. package/dist/native-assets/policy.d.ts +42 -0
  419. package/dist/native-assets/policy.d.ts.map +1 -0
  420. package/dist/native-assets/policy.js +155 -0
  421. package/dist/native-assets/policy.js.map +1 -0
  422. package/dist/notifications/temp-contract.d.ts.map +1 -1
  423. package/dist/notifications/temp-contract.js +4 -0
  424. package/dist/notifications/temp-contract.js.map +1 -1
  425. package/dist/pipeline/__tests__/orchestrator.test.js +164 -42
  426. package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
  427. package/dist/pipeline/__tests__/stages.test.js +72 -155
  428. package/dist/pipeline/__tests__/stages.test.js.map +1 -1
  429. package/dist/pipeline/orchestrator.d.ts.map +1 -1
  430. package/dist/pipeline/orchestrator.js +124 -18
  431. package/dist/pipeline/orchestrator.js.map +1 -1
  432. package/dist/pipeline/stages/ralplan.d.ts.map +1 -1
  433. package/dist/pipeline/stages/ralplan.js +36 -8
  434. package/dist/pipeline/stages/ralplan.js.map +1 -1
  435. package/dist/ralplan/__tests__/consensus-gate.test.js +73 -1316
  436. package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
  437. package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts +2 -0
  438. package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts.map +1 -0
  439. package/dist/ralplan/__tests__/documented-leader-preflight.test.js +335 -0
  440. package/dist/ralplan/__tests__/documented-leader-preflight.test.js.map +1 -0
  441. package/dist/ralplan/__tests__/runtime.test.js +85 -101
  442. package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
  443. package/dist/ralplan/consensus-gate.d.ts +9 -1
  444. package/dist/ralplan/consensus-gate.d.ts.map +1 -1
  445. package/dist/ralplan/consensus-gate.js +82 -338
  446. package/dist/ralplan/consensus-gate.js.map +1 -1
  447. package/dist/ralplan/documented-leader-preflight.d.ts +41 -0
  448. package/dist/ralplan/documented-leader-preflight.d.ts.map +1 -0
  449. package/dist/ralplan/documented-leader-preflight.js +360 -0
  450. package/dist/ralplan/documented-leader-preflight.js.map +1 -0
  451. package/dist/ralplan/runtime.d.ts +2 -1
  452. package/dist/ralplan/runtime.d.ts.map +1 -1
  453. package/dist/ralplan/runtime.js +67 -168
  454. package/dist/ralplan/runtime.js.map +1 -1
  455. package/dist/runtime/__tests__/bridge.test.js +42 -1
  456. package/dist/runtime/__tests__/bridge.test.js.map +1 -1
  457. package/dist/runtime/bridge.d.ts +12 -0
  458. package/dist/runtime/bridge.d.ts.map +1 -1
  459. package/dist/runtime/bridge.js +52 -1
  460. package/dist/runtime/bridge.js.map +1 -1
  461. package/dist/runtime/run-state.d.ts +5 -1
  462. package/dist/runtime/run-state.d.ts.map +1 -1
  463. package/dist/runtime/run-state.js +15 -8
  464. package/dist/runtime/run-state.js.map +1 -1
  465. package/dist/scripts/__tests__/codex-native-hook.test.js +16323 -8978
  466. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  467. package/dist/scripts/__tests__/issue-3293-callsite-parity.test.d.ts +2 -0
  468. package/dist/scripts/__tests__/issue-3293-callsite-parity.test.d.ts.map +1 -0
  469. package/dist/scripts/__tests__/issue-3293-callsite-parity.test.js +225 -0
  470. package/dist/scripts/__tests__/issue-3293-callsite-parity.test.js.map +1 -0
  471. package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.d.ts +2 -0
  472. package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.d.ts.map +1 -0
  473. package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.js +188 -0
  474. package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.js.map +1 -0
  475. package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.d.ts +2 -0
  476. package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.d.ts.map +1 -0
  477. package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.js +259 -0
  478. package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.js.map +1 -0
  479. package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.d.ts +2 -0
  480. package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.d.ts.map +1 -0
  481. package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.js +491 -0
  482. package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.js.map +1 -0
  483. package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.d.ts +2 -0
  484. package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.d.ts.map +1 -0
  485. package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.js +708 -0
  486. package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.js.map +1 -0
  487. package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.d.ts +2 -0
  488. package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.d.ts.map +1 -0
  489. package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.js +208 -0
  490. package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.js.map +1 -0
  491. package/dist/scripts/__tests__/notify-state-io.test.js +26 -0
  492. package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -1
  493. package/dist/scripts/__tests__/notify-tmux-injection.test.js +23 -1
  494. package/dist/scripts/__tests__/notify-tmux-injection.test.js.map +1 -1
  495. package/dist/scripts/__tests__/postinstall.test.js +19 -1
  496. package/dist/scripts/__tests__/postinstall.test.js.map +1 -1
  497. package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts +2 -0
  498. package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts.map +1 -0
  499. package/dist/scripts/__tests__/reasoning-artifact-contract.test.js +108 -0
  500. package/dist/scripts/__tests__/reasoning-artifact-contract.test.js.map +1 -0
  501. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js +63 -173
  502. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js.map +1 -1
  503. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js +74 -159
  504. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js.map +1 -1
  505. package/dist/scripts/__tests__/smoke-packed-install.test.js +404 -13
  506. package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
  507. package/dist/scripts/__tests__/verify-native-release-assets.test.d.ts +2 -0
  508. package/dist/scripts/__tests__/verify-native-release-assets.test.d.ts.map +1 -0
  509. package/dist/scripts/__tests__/verify-native-release-assets.test.js +235 -0
  510. package/dist/scripts/__tests__/verify-native-release-assets.test.js.map +1 -0
  511. package/dist/scripts/codex-native-hook.d.ts +53 -1
  512. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  513. package/dist/scripts/codex-native-hook.js +14448 -1480
  514. package/dist/scripts/codex-native-hook.js.map +1 -1
  515. package/dist/scripts/codex-native-pre-post.d.ts +9 -0
  516. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
  517. package/dist/scripts/codex-native-pre-post.js +35 -12
  518. package/dist/scripts/codex-native-pre-post.js.map +1 -1
  519. package/dist/scripts/generate-native-release-manifest.js +80 -51
  520. package/dist/scripts/generate-native-release-manifest.js.map +1 -1
  521. package/dist/scripts/notify-fallback-watcher.js +78 -115
  522. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  523. package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
  524. package/dist/scripts/notify-hook/auto-nudge.js +74 -3
  525. package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
  526. package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
  527. package/dist/scripts/notify-hook/state-io.js +5 -0
  528. package/dist/scripts/notify-hook/state-io.js.map +1 -1
  529. package/dist/scripts/notify-hook/team-dispatch.d.ts +9 -0
  530. package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
  531. package/dist/scripts/notify-hook/team-dispatch.js +234 -79
  532. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  533. package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
  534. package/dist/scripts/notify-hook/team-leader-nudge.js +71 -16
  535. package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
  536. package/dist/scripts/notify-hook/team-tmux-guard.d.ts +12 -4
  537. package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
  538. package/dist/scripts/notify-hook/team-tmux-guard.js +365 -44
  539. package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
  540. package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -1
  541. package/dist/scripts/notify-hook/team-worker-stop.js +42 -21
  542. package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -1
  543. package/dist/scripts/notify-hook/team-worker.d.ts +3 -0
  544. package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
  545. package/dist/scripts/notify-hook/team-worker.js +82 -33
  546. package/dist/scripts/notify-hook/team-worker.js.map +1 -1
  547. package/dist/scripts/notify-hook/tmux-injection.d.ts +1 -0
  548. package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
  549. package/dist/scripts/notify-hook/tmux-injection.js +32 -3
  550. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  551. package/dist/scripts/notify-hook.js +79 -82
  552. package/dist/scripts/notify-hook.js.map +1 -1
  553. package/dist/scripts/postinstall-advisory.d.ts +14 -0
  554. package/dist/scripts/postinstall-advisory.d.ts.map +1 -0
  555. package/dist/scripts/postinstall-advisory.js +49 -0
  556. package/dist/scripts/postinstall-advisory.js.map +1 -0
  557. package/dist/scripts/postinstall.d.ts +1 -1
  558. package/dist/scripts/postinstall.d.ts.map +1 -1
  559. package/dist/scripts/postinstall.js +1 -1
  560. package/dist/scripts/postinstall.js.map +1 -1
  561. package/dist/scripts/smoke-packed-install.d.ts +80 -4
  562. package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
  563. package/dist/scripts/smoke-packed-install.js +3162 -26
  564. package/dist/scripts/smoke-packed-install.js.map +1 -1
  565. package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
  566. package/dist/scripts/sync-plugin-mirror.js +16 -1
  567. package/dist/scripts/sync-plugin-mirror.js.map +1 -1
  568. package/dist/scripts/verify-native-release-assets.js +37 -23
  569. package/dist/scripts/verify-native-release-assets.js.map +1 -1
  570. package/dist/state/__tests__/mode-state-context.test.js +61 -0
  571. package/dist/state/__tests__/mode-state-context.test.js.map +1 -1
  572. package/dist/state/__tests__/operations.test.js +462 -850
  573. package/dist/state/__tests__/operations.test.js.map +1 -1
  574. package/dist/state/__tests__/skill-active.test.js +400 -2
  575. package/dist/state/__tests__/skill-active.test.js.map +1 -1
  576. package/dist/state/mode-state-context.d.ts +8 -0
  577. package/dist/state/mode-state-context.d.ts.map +1 -1
  578. package/dist/state/mode-state-context.js +73 -0
  579. package/dist/state/mode-state-context.js.map +1 -1
  580. package/dist/state/operations.d.ts +3 -0
  581. package/dist/state/operations.d.ts.map +1 -1
  582. package/dist/state/operations.js +144 -40
  583. package/dist/state/operations.js.map +1 -1
  584. package/dist/state/skill-active.d.ts +18 -1
  585. package/dist/state/skill-active.d.ts.map +1 -1
  586. package/dist/state/skill-active.js +420 -23
  587. package/dist/state/skill-active.js.map +1 -1
  588. package/dist/state/workflow-transition-reconcile.d.ts +3 -0
  589. package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
  590. package/dist/state/workflow-transition-reconcile.js +10 -4
  591. package/dist/state/workflow-transition-reconcile.js.map +1 -1
  592. package/dist/state/workflow-transition.d.ts.map +1 -1
  593. package/dist/state/workflow-transition.js +3 -1
  594. package/dist/state/workflow-transition.js.map +1 -1
  595. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js +53 -247
  596. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js.map +1 -1
  597. package/dist/subagents/__tests__/tracker.test.js +837 -1048
  598. package/dist/subagents/__tests__/tracker.test.js.map +1 -1
  599. package/dist/subagents/tracker.d.ts +58 -135
  600. package/dist/subagents/tracker.d.ts.map +1 -1
  601. package/dist/subagents/tracker.js +811 -632
  602. package/dist/subagents/tracker.js.map +1 -1
  603. package/dist/team/__tests__/api-interop.test.js +91 -1
  604. package/dist/team/__tests__/api-interop.test.js.map +1 -1
  605. package/dist/team/__tests__/delivery-e2e-smoke.test.js +58 -17
  606. package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
  607. package/dist/team/__tests__/idle-nudge.test.js +45 -15
  608. package/dist/team/__tests__/idle-nudge.test.js.map +1 -1
  609. package/dist/team/__tests__/mcp-comm.test.js +197 -30
  610. package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
  611. package/dist/team/__tests__/model-contract.test.js +110 -3
  612. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  613. package/dist/team/__tests__/notice-ledger.test.d.ts +2 -0
  614. package/dist/team/__tests__/notice-ledger.test.d.ts.map +1 -0
  615. package/dist/team/__tests__/notice-ledger.test.js +131 -0
  616. package/dist/team/__tests__/notice-ledger.test.js.map +1 -0
  617. package/dist/team/__tests__/pane-teardown-residue-e2e.test.d.ts +2 -0
  618. package/dist/team/__tests__/pane-teardown-residue-e2e.test.d.ts.map +1 -0
  619. package/dist/team/__tests__/pane-teardown-residue-e2e.test.js +410 -0
  620. package/dist/team/__tests__/pane-teardown-residue-e2e.test.js.map +1 -0
  621. package/dist/team/__tests__/phase-controller.test.js +20 -0
  622. package/dist/team/__tests__/phase-controller.test.js.map +1 -1
  623. package/dist/team/__tests__/runtime-cli.test.js +9 -0
  624. package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
  625. package/dist/team/__tests__/runtime.test.js +3963 -428
  626. package/dist/team/__tests__/runtime.test.js.map +1 -1
  627. package/dist/team/__tests__/scaling.test.js +2405 -203
  628. package/dist/team/__tests__/scaling.test.js.map +1 -1
  629. package/dist/team/__tests__/state-root.test.js +117 -2
  630. package/dist/team/__tests__/state-root.test.js.map +1 -1
  631. package/dist/team/__tests__/state.test.js +804 -36
  632. package/dist/team/__tests__/state.test.js.map +1 -1
  633. package/dist/team/__tests__/team-ops-contract.test.js +6 -0
  634. package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
  635. package/dist/team/__tests__/tmux-session.test.js +4099 -1039
  636. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  637. package/dist/team/__tests__/tmux-source-authority-realtmux.test.d.ts +2 -0
  638. package/dist/team/__tests__/tmux-source-authority-realtmux.test.d.ts.map +1 -0
  639. package/dist/team/__tests__/tmux-source-authority-realtmux.test.js +149 -0
  640. package/dist/team/__tests__/tmux-source-authority-realtmux.test.js.map +1 -0
  641. package/dist/team/__tests__/tmux-test-fixture.d.ts +69 -0
  642. package/dist/team/__tests__/tmux-test-fixture.d.ts.map +1 -1
  643. package/dist/team/__tests__/tmux-test-fixture.js +242 -15
  644. package/dist/team/__tests__/tmux-test-fixture.js.map +1 -1
  645. package/dist/team/__tests__/tmux-test-fixture.test.js +177 -1
  646. package/dist/team/__tests__/tmux-test-fixture.test.js.map +1 -1
  647. package/dist/team/__tests__/worker-runtime-identity.test.js +53 -44
  648. package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
  649. package/dist/team/__tests__/worktree.test.js +6 -0
  650. package/dist/team/__tests__/worktree.test.js.map +1 -1
  651. package/dist/team/api-interop.d.ts.map +1 -1
  652. package/dist/team/api-interop.js +15 -9
  653. package/dist/team/api-interop.js.map +1 -1
  654. package/dist/team/exact-pane.d.ts +23 -0
  655. package/dist/team/exact-pane.d.ts.map +1 -0
  656. package/dist/team/exact-pane.js +133 -0
  657. package/dist/team/exact-pane.js.map +1 -0
  658. package/dist/team/idle-nudge.d.ts +12 -1
  659. package/dist/team/idle-nudge.d.ts.map +1 -1
  660. package/dist/team/idle-nudge.js +41 -14
  661. package/dist/team/idle-nudge.js.map +1 -1
  662. package/dist/team/model-contract.d.ts +2 -5
  663. package/dist/team/model-contract.d.ts.map +1 -1
  664. package/dist/team/model-contract.js +59 -17
  665. package/dist/team/model-contract.js.map +1 -1
  666. package/dist/team/notice-ledger.d.ts +54 -0
  667. package/dist/team/notice-ledger.d.ts.map +1 -0
  668. package/dist/team/notice-ledger.js +259 -0
  669. package/dist/team/notice-ledger.js.map +1 -0
  670. package/dist/team/phase-controller.d.ts.map +1 -1
  671. package/dist/team/phase-controller.js +2 -0
  672. package/dist/team/phase-controller.js.map +1 -1
  673. package/dist/team/runtime.d.ts +4 -1
  674. package/dist/team/runtime.d.ts.map +1 -1
  675. package/dist/team/runtime.js +1527 -291
  676. package/dist/team/runtime.js.map +1 -1
  677. package/dist/team/scaling.d.ts +13 -1
  678. package/dist/team/scaling.d.ts.map +1 -1
  679. package/dist/team/scaling.js +1503 -387
  680. package/dist/team/scaling.js.map +1 -1
  681. package/dist/team/state/dispatch.d.ts.map +1 -1
  682. package/dist/team/state/dispatch.js +26 -8
  683. package/dist/team/state/dispatch.js.map +1 -1
  684. package/dist/team/state/locks.d.ts.map +1 -1
  685. package/dist/team/state/locks.js +61 -13
  686. package/dist/team/state/locks.js.map +1 -1
  687. package/dist/team/state/monitor.d.ts +10 -0
  688. package/dist/team/state/monitor.d.ts.map +1 -1
  689. package/dist/team/state/monitor.js +13 -0
  690. package/dist/team/state/monitor.js.map +1 -1
  691. package/dist/team/state/tasks.d.ts.map +1 -1
  692. package/dist/team/state/tasks.js +4 -3
  693. package/dist/team/state/tasks.js.map +1 -1
  694. package/dist/team/state/types.d.ts +15 -0
  695. package/dist/team/state/types.d.ts.map +1 -1
  696. package/dist/team/state/types.js.map +1 -1
  697. package/dist/team/state-root.d.ts +12 -0
  698. package/dist/team/state-root.d.ts.map +1 -1
  699. package/dist/team/state-root.js +177 -0
  700. package/dist/team/state-root.js.map +1 -1
  701. package/dist/team/state.d.ts +85 -1
  702. package/dist/team/state.d.ts.map +1 -1
  703. package/dist/team/state.js +672 -129
  704. package/dist/team/state.js.map +1 -1
  705. package/dist/team/team-ops.d.ts +5 -0
  706. package/dist/team/team-ops.d.ts.map +1 -1
  707. package/dist/team/team-ops.js +4 -0
  708. package/dist/team/team-ops.js.map +1 -1
  709. package/dist/team/tmux-session.d.ts +163 -27
  710. package/dist/team/tmux-session.d.ts.map +1 -1
  711. package/dist/team/tmux-session.js +1682 -376
  712. package/dist/team/tmux-session.js.map +1 -1
  713. package/dist/team/worktree.d.ts.map +1 -1
  714. package/dist/team/worktree.js +4 -0
  715. package/dist/team/worktree.js.map +1 -1
  716. package/dist/ultragoal/__tests__/artifacts.test.js +950 -2
  717. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  718. package/dist/ultragoal/__tests__/docs-contract.test.js +1 -0
  719. package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
  720. package/dist/ultragoal/artifacts.d.ts +35 -1
  721. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  722. package/dist/ultragoal/artifacts.js +232 -46
  723. package/dist/ultragoal/artifacts.js.map +1 -1
  724. package/dist/utils/__tests__/file-durability.test.d.ts +2 -0
  725. package/dist/utils/__tests__/file-durability.test.d.ts.map +1 -0
  726. package/dist/utils/__tests__/file-durability.test.js +114 -0
  727. package/dist/utils/__tests__/file-durability.test.js.map +1 -0
  728. package/dist/utils/__tests__/paths.test.js +21 -1
  729. package/dist/utils/__tests__/paths.test.js.map +1 -1
  730. package/dist/utils/file-durability.d.ts +25 -0
  731. package/dist/utils/file-durability.d.ts.map +1 -0
  732. package/dist/utils/file-durability.js +67 -0
  733. package/dist/utils/file-durability.js.map +1 -0
  734. package/dist/utils/paths.d.ts.map +1 -1
  735. package/dist/utils/paths.js +14 -6
  736. package/dist/utils/paths.js.map +1 -1
  737. package/dist/verification/__tests__/ci-rust-gates.test.js +49 -4
  738. package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
  739. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +3 -0
  740. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -1
  741. package/dist/verification/__tests__/explore-harness-release-workflow.test.js +60 -0
  742. package/dist/verification/__tests__/explore-harness-release-workflow.test.js.map +1 -1
  743. package/dist/verification/__tests__/native-release-manifest.test.js +157 -4
  744. package/dist/verification/__tests__/native-release-manifest.test.js.map +1 -1
  745. package/dist/wiki/lint.d.ts +4 -1
  746. package/dist/wiki/lint.d.ts.map +1 -1
  747. package/dist/wiki/lint.js +3 -2
  748. package/dist/wiki/lint.js.map +1 -1
  749. package/package.json +13 -5
  750. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  751. package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +105 -17
  752. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +13 -5
  753. package/plugins/oh-my-codex/skills/cancel/SKILL.md +30 -85
  754. package/plugins/oh-my-codex/skills/ralph/SKILL.md +6 -4
  755. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +16 -17
  756. package/plugins/oh-my-codex/skills/team/SKILL.md +13 -9
  757. package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +3 -2
  758. package/skills/autopilot/SKILL.md +13 -5
  759. package/skills/cancel/SKILL.md +30 -85
  760. package/skills/ralph/SKILL.md +6 -4
  761. package/skills/ralplan/SKILL.md +16 -17
  762. package/skills/team/SKILL.md +13 -9
  763. package/skills/ultragoal/SKILL.md +3 -2
  764. package/src/scripts/__tests__/codex-native-hook.test.ts +8831 -951
  765. package/src/scripts/__tests__/issue-3293-callsite-parity.test.ts +187 -0
  766. package/src/scripts/__tests__/issue-3293-cancel-transaction.test.ts +189 -0
  767. package/src/scripts/__tests__/issue-3293-hook-owned-cancel.test.ts +187 -0
  768. package/src/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.ts +591 -0
  769. package/src/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.ts +701 -0
  770. package/src/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.ts +211 -0
  771. package/src/scripts/__tests__/notify-state-io.test.ts +29 -0
  772. package/src/scripts/__tests__/notify-tmux-injection.test.ts +26 -1
  773. package/src/scripts/__tests__/postinstall.test.ts +23 -1
  774. package/src/scripts/__tests__/reasoning-artifact-contract.test.ts +129 -0
  775. package/src/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.ts +67 -185
  776. package/src/scripts/__tests__/role-intent-durable-recovery-3181.test.ts +79 -178
  777. package/src/scripts/__tests__/smoke-packed-install.test.ts +525 -16
  778. package/src/scripts/__tests__/verify-native-release-assets.test.ts +240 -0
  779. package/src/scripts/codex-native-hook.ts +14238 -1429
  780. package/src/scripts/codex-native-pre-post.ts +43 -12
  781. package/src/scripts/generate-native-release-manifest.ts +83 -79
  782. package/src/scripts/notify-fallback-watcher.ts +91 -122
  783. package/src/scripts/notify-hook/auto-nudge.ts +71 -3
  784. package/src/scripts/notify-hook/state-io.ts +11 -0
  785. package/src/scripts/notify-hook/team-dispatch.ts +242 -75
  786. package/src/scripts/notify-hook/team-leader-nudge.ts +72 -22
  787. package/src/scripts/notify-hook/team-tmux-guard.ts +366 -39
  788. package/src/scripts/notify-hook/team-worker-stop.ts +43 -20
  789. package/src/scripts/notify-hook/team-worker.ts +82 -31
  790. package/src/scripts/notify-hook/tmux-injection.ts +33 -3
  791. package/src/scripts/notify-hook.ts +84 -82
  792. package/src/scripts/postinstall-advisory.ts +67 -0
  793. package/src/scripts/postinstall.ts +1 -1
  794. package/src/scripts/smoke-packed-install.ts +3608 -39
  795. package/src/scripts/sync-plugin-mirror.ts +17 -1
  796. package/src/scripts/verify-native-release-assets.ts +39 -31
  797. package/templates/AGENTS.md +1 -0
  798. package/dist/subagents/__tests__/adapted-role-binding.test.d.ts +0 -2
  799. package/dist/subagents/__tests__/adapted-role-binding.test.d.ts.map +0 -1
  800. package/dist/subagents/__tests__/adapted-role-binding.test.js +0 -988
  801. package/dist/subagents/__tests__/adapted-role-binding.test.js.map +0 -1
  802. package/dist/subagents/adapted-role-binding.d.ts +0 -17
  803. package/dist/subagents/adapted-role-binding.d.ts.map +0 -1
  804. package/dist/subagents/adapted-role-binding.js +0 -75
  805. package/dist/subagents/adapted-role-binding.js.map +0 -1
@@ -1,11 +1,24 @@
1
1
  import { describe, it } from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import { mkdirSync, writeFileSync } from 'node:fs';
4
- import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
3
+ import { createHash } from 'node:crypto';
4
+ import { existsSync, realpathSync } from 'node:fs';
5
+ import { chmod, mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
6
+ import { spawnSync } from 'node:child_process';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { tmpdir as osTmpdir } from 'node:os';
5
9
  import { dirname, join } from 'node:path';
6
- import { tmpdir } from 'node:os';
7
- import { isInstallVersionBump, isNewerVersion, maybeCheckAndPromptUpdate, readUserInstallStamp, resolveAutoUpdateMode, resolveGlobalInstallRoot, resolveInstalledCliEntry, formatDeferredSetupCommand, resolveSetupRefreshArgs, runDeferredGlobalUpdate, runGlobalUpdate, runImmediateUpdate, shouldCheckForUpdates, spawnInstalledSetupRefresh, writeUserInstallStamp, } from '../update.js';
10
+ import { isInstallVersionBump, isNewerVersion, maybeCheckAndPromptUpdate, readUserInstallStamp, resolveAutoUpdateMode, resolveInstalledCliEntry, formatDeferredSetupCommand, resolveSetupRefreshArgs, runDeferredGlobalUpdate, runGlobalUpdate, runImmediateUpdate, shouldCheckForUpdates, spawnInstalledSetupRefresh, writeUserInstallStamp, } from '../update.js';
11
+ import { resolveBunGlobalBin, resolvePackageManagerOwnership, } from '../package-manager-ownership.js';
12
+ const tmpdir = () => realpathSync(osTmpdir());
8
13
  const PACKAGE_NAME = 'oh-my-codex';
14
+ const frozenNpmOwnership = {
15
+ manager: 'npm',
16
+ npmCommand: { kind: 'node-script', command: process.execPath, commandArgs: ['/configured/npm-cli.js'] },
17
+ npmPrefix: '/configured',
18
+ globalInstallRoot: '/configured/node_modules',
19
+ packageRoot: '/configured/node_modules/oh-my-codex',
20
+ environment: { OMX_UPDATE_TEST: '1' },
21
+ };
9
22
  describe('isNewerVersion', () => {
10
23
  it('returns true when latest has higher major', () => {
11
24
  assert.equal(isNewerVersion('1.0.0', '2.0.0'), true);
@@ -523,165 +536,47 @@ describe('maybeCheckAndPromptUpdate', () => {
523
536
  }
524
537
  });
525
538
  });
526
- describe('direct npm spawn fallback', () => {
527
- function spawnErrorResult(code) {
528
- const error = Object.assign(new Error(`spawnSync npm ${code}`), { code });
529
- return { status: null, signal: null, error, stdout: '', stderr: '', output: [null, '', ''], pid: 0 };
530
- }
531
- function enoentResult() {
532
- return spawnErrorResult('ENOENT');
533
- }
534
- function einvalResult() {
535
- return spawnErrorResult('EINVAL');
536
- }
539
+ describe('frozen package-manager update ownership', () => {
537
540
  function okResult(stdout = '') {
538
541
  return { status: 0, signal: null, error: undefined, stdout, stderr: '', output: [null, stdout, ''], pid: 0 };
539
542
  }
540
- it('falls back to npm.cmd for win32 global installs when direct npm spawn returns ENOENT', () => {
541
- const calls = [];
542
- const result = runGlobalUpdate(((command, args) => {
543
- calls.push({ command, args: args });
544
- return command === 'npm' ? enoentResult() : okResult();
545
- }), 'win32');
546
- assert.equal(result.ok, true);
547
- assert.deepEqual(calls.map((call) => call.command), ['npm', 'npm.cmd']);
548
- assert.deepEqual(calls[0].args, ['install', '-g', 'oh-my-codex@latest']);
549
- assert.deepEqual(calls[1].args, ['install', '-g', 'oh-my-codex@latest']);
550
- });
551
- it('falls back through cmd.exe when win32 npm.cmd cannot be spawned', () => {
552
- const calls = [];
553
- const result = runGlobalUpdate(((command, args) => {
554
- calls.push({ command, args: args });
555
- if (command === 'npm')
556
- return enoentResult();
557
- if (command === 'npm.cmd')
558
- return einvalResult();
559
- return okResult();
560
- }), 'win32');
561
- assert.equal(result.ok, true);
562
- assert.deepEqual(calls.map((call) => call.command), ['npm', 'npm.cmd', 'cmd.exe']);
563
- assert.deepEqual(calls[0].args, ['install', '-g', 'oh-my-codex@latest']);
564
- assert.deepEqual(calls[1].args, ['install', '-g', 'oh-my-codex@latest']);
565
- assert.deepEqual(calls[2].args, ['/d', '/s', '/c', 'npm', 'install', '-g', 'oh-my-codex@latest']);
566
- });
567
- it('uses cmd.exe for win32 global installs when direct npm returns EINVAL', () => {
568
- const calls = [];
569
- const result = runGlobalUpdate(((command, args) => {
570
- calls.push({ command, args: args });
571
- return command === 'npm' ? einvalResult() : okResult();
572
- }), 'win32');
573
- assert.equal(result.ok, true);
574
- assert.deepEqual(calls.map((call) => call.command), ['npm', 'cmd.exe']);
575
- assert.deepEqual(calls[1].args, ['/d', '/s', '/c', 'npm', 'install', '-g', 'oh-my-codex@latest']);
576
- });
577
- it('does not shell-wrap non-target win32 npm operations when npm.cmd returns EINVAL', () => {
578
- const calls = [];
579
- const root = resolveGlobalInstallRoot(((command, args) => {
580
- calls.push({ command, args: args });
581
- if (command === 'npm')
582
- return enoentResult();
583
- if (command === 'npm.cmd')
584
- return einvalResult();
585
- return okResult('unexpected');
586
- }), 'win32');
587
- assert.equal(root, null);
588
- assert.deepEqual(calls.map((call) => call.command), ['npm', 'npm.cmd']);
589
- assert.deepEqual(calls[0].args, ['root', '-g']);
590
- assert.deepEqual(calls[1].args, ['root', '-g']);
591
- });
592
- it('keeps the direct npm path when it succeeds', () => {
593
- const calls = [];
594
- const result = runGlobalUpdate(((command, args) => {
595
- calls.push({ command, args: args });
596
- return okResult();
597
- }), 'win32');
598
- assert.equal(result.ok, true);
599
- assert.deepEqual(calls.map((call) => call.command), ['npm']);
600
- assert.deepEqual(calls[0].args, ['install', '-g', 'oh-my-codex@latest']);
601
- });
602
- it('does not fall back to npm.cmd for non-Windows ENOENT failures', () => {
543
+ it('rejects legacy unowned update calls without selecting an ambient manager', () => {
603
544
  const calls = [];
604
545
  const result = runGlobalUpdate(((command) => {
605
546
  calls.push(command);
606
- return enoentResult();
607
- }), 'linux');
547
+ return okResult();
548
+ }));
608
549
  assert.equal(result.ok, false);
609
- assert.match(result.stderr, /ENOENT/);
610
- assert.deepEqual(calls, ['npm']);
550
+ assert.match(result.stderr, /validated package-manager ownership/);
551
+ assert.deepEqual(calls, []);
611
552
  });
612
- it('packs the dev branch from a local checkout instead of globally installing the git dependency spec', () => {
613
- const originalNpmLocation = process.env.npm_config_location;
614
- const calls = [];
615
- process.env.npm_config_location = 'global';
616
- try {
617
- const result = runGlobalUpdate('github:Yeachan-Heo/oh-my-codex#dev', ((command, args, options) => {
618
- calls.push({ command, args: args, cwd: options?.cwd, env: options?.env });
619
- if (command === 'git' && args[0] === 'clone') {
620
- mkdirSync(String(args[args.length - 1]), { recursive: true });
621
- }
622
- if (command === 'git' && args[0] === 'rev-parse') {
623
- return okResult('1234567890abcdef\n');
624
- }
625
- if (command === 'npm' && args[0] === 'pack') {
626
- writeFileSync(join(options?.cwd ?? process.cwd(), 'oh-my-codex-0.18.9.tgz'), 'packed');
627
- return okResult(JSON.stringify([{ filename: 'oh-my-codex-0.18.9.tgz' }]));
628
- }
629
- return okResult();
630
- }), 'linux');
631
- assert.equal(result.ok, true);
632
- assert.deepEqual(calls.map((call) => [call.command, ...call.args.slice(0, 3)]), [
633
- ['git', 'clone', '--depth', '1'],
634
- ['git', 'rev-parse', 'HEAD'],
635
- ['npm', 'install', '--global=false', '--location=project'],
636
- ['npm', 'run', 'prepack'],
637
- ['npm', 'pack', '--ignore-scripts', '--json'],
638
- ['npm', 'install', '-g', join(calls[2].cwd ?? '', 'oh-my-codex-0.18.9.tgz')],
639
- ]);
640
- const dependencyInstall = calls.find((call) => call.command === 'npm' && call.args[0] === 'install' && call.args.includes('--include=dev'));
641
- assert.equal(dependencyInstall?.env?.npm_config_global, 'false');
642
- assert.equal(dependencyInstall?.env?.npm_config_location, 'project');
643
- assert.equal(calls.some((call) => call.args.includes('github:Yeachan-Heo/oh-my-codex#dev')), false);
644
- }
645
- finally {
646
- if (typeof originalNpmLocation === 'string') {
647
- process.env.npm_config_location = originalNpmLocation;
648
- }
649
- else {
650
- delete process.env.npm_config_location;
651
- }
652
- }
553
+ it('requires ownership when the native updater remains selected beside an explicit setup seam', async () => {
554
+ const result = await runImmediateUpdate('/tmp/omx-unowned-update', {
555
+ getCurrentVersion: async () => '0.14.0',
556
+ fetchLatestVersion: async () => '0.14.1',
557
+ resolvePackageManagerOwnership: async () => null,
558
+ runSetupRefresh: async () => ({ ok: true, stderr: '' }),
559
+ });
560
+ assert.equal(result.status, 'failed');
653
561
  });
654
- it('does not use cmd.exe for win32 dev-channel npm packaging when npm.cmd returns EINVAL', () => {
562
+ it('uses only the selected frozen npm command for dev packaging and installation', () => {
655
563
  const calls = [];
564
+ const owner = {
565
+ ...frozenNpmOwnership,
566
+ npmCommand: { kind: 'node-script', command: '/configured/node', commandArgs: ['/configured/npm-cli.js'] },
567
+ };
656
568
  const result = runGlobalUpdate('github:Yeachan-Heo/oh-my-codex#dev', ((command, args) => {
657
- calls.push({ command, args: args });
658
- if (command === 'git' && args[0] === 'clone') {
659
- mkdirSync(String(args[args.length - 1]), { recursive: true });
660
- return okResult();
661
- }
662
- if (command === 'git' && args[0] === 'rev-parse')
663
- return okResult('1234567890abcdef\n');
664
- if (command === 'npm')
665
- return enoentResult();
666
- if (command === 'npm.cmd')
667
- return einvalResult();
668
- return okResult();
669
- }), 'win32');
569
+ calls.push({ command, args: [...args] });
570
+ return command === 'git' ? { ...okResult(), stdout: args[0] === 'rev-parse' ? '1234567890abcdef\n' : '' } : okResult();
571
+ }), 'win32', owner);
670
572
  assert.equal(result.ok, false);
671
- assert.match(result.stderr, /EINVAL/);
672
- assert.deepEqual(calls.map((call) => call.command), ['git', 'git', 'npm', 'npm.cmd']);
673
- assert.equal(calls.some((call) => call.command === 'cmd.exe'), false);
674
- });
675
- it('falls back to npm.cmd for win32 global-root lookup when direct npm spawn returns ENOENT', () => {
676
- const calls = [];
677
- const root = resolveGlobalInstallRoot(((command, args) => {
678
- calls.push({ command, args: args });
679
- return command === 'npm' ? enoentResult() : okResult('C:\\Users\\alice\\AppData\\Roaming\\npm\\node_modules\r\n');
680
- }), 'win32');
681
- assert.equal(root, 'C:\\Users\\alice\\AppData\\Roaming\\npm\\node_modules');
682
- assert.deepEqual(calls.map((call) => call.command), ['npm', 'npm.cmd']);
683
- assert.deepEqual(calls[0].args, ['root', '-g']);
684
- assert.deepEqual(calls[1].args, ['root', '-g']);
573
+ assert.match(result.stderr, /npm pack did not produce/);
574
+ assert.deepEqual(calls.map((call) => call.command), [
575
+ 'git', 'git', '/configured/node', '/configured/node', '/configured/node',
576
+ ]);
577
+ for (const call of calls.slice(2)) {
578
+ assert.deepEqual(call.args.slice(0, 1), ['/configured/npm-cli.js']);
579
+ }
685
580
  });
686
581
  });
687
582
  describe('runImmediateUpdate', () => {
@@ -1054,9 +949,9 @@ describe('runImmediateUpdate failure diagnostics', () => {
1054
949
  });
1055
950
  assert.equal(result.status, 'failed');
1056
951
  assert.equal(refreshCalls, 0);
1057
- assert.match(logs.join('\n'), /Update failed while running npm install -g oh-my-codex@latest/);
952
+ assert.match(logs.join('\n'), /Update failed while running the selected npm transaction \(npm install -g oh-my-codex@latest\)/);
1058
953
  assert.match(logs.join('\n'), /npm stderr: EPERM: file is locked/);
1059
- assert.match(logs.join('\n'), /npm install -g oh-my-codex@latest && omx setup/);
954
+ assert.match(logs.join('\n'), /ownership-safe recovery command: omx update/);
1060
955
  }
1061
956
  finally {
1062
957
  console.log = originalLog;
@@ -1065,7 +960,7 @@ describe('runImmediateUpdate failure diagnostics', () => {
1065
960
  });
1066
961
  });
1067
962
  describe('runDeferredGlobalUpdate', () => {
1068
- it('launches a detached Windows PowerShell updater that waits for the parent and runs setup after npm', async () => {
963
+ it('launches a detached Node worker with a frozen ownership payload on Windows', async () => {
1069
964
  const cwd = await mkdtemp(join(tmpdir(), 'omx-deferred-update-'));
1070
965
  const calls = [];
1071
966
  const listeners = [];
@@ -1079,23 +974,50 @@ describe('runDeferredGlobalUpdate', () => {
1079
974
  },
1080
975
  unref() { },
1081
976
  };
1082
- }), 'win32', 12345);
977
+ }), 'win32', 12345, frozenNpmOwnership);
1083
978
  assert.equal(result.ok, true);
1084
979
  assert.match(result.logPath ?? '', /\.omx[\\/]logs[\\/]update-/);
1085
980
  assert.equal(calls.length, 1);
1086
- assert.equal(calls[0].command, 'powershell.exe');
1087
- assert.deepEqual(calls[0].args.slice(0, 4), ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command']);
981
+ assert.equal(calls[0]?.command, process.execPath);
982
+ assert.match(calls[0]?.args[0] ?? '', /update-worker\.js$/);
983
+ const payloadPath = calls[0]?.args[1];
984
+ assert.equal(typeof payloadPath, 'string');
985
+ const payload = JSON.parse(await readFile(String(payloadPath), 'utf-8'));
986
+ assert.deepEqual(payload, {
987
+ cwd,
988
+ logPath: result.logPath,
989
+ parentPid: 12345,
990
+ ownership: frozenNpmOwnership,
991
+ setupArgs: ['setup'],
992
+ });
1088
993
  assert.deepEqual(listeners, ['error']);
1089
- assert.equal(calls[0].options.detached, true);
1090
- assert.equal(calls[0].options.stdio, 'ignore');
1091
- assert.equal(calls[0].options.windowsHide, true);
1092
- assert.equal(calls[0].options.cwd, cwd);
1093
- assert.equal(calls[0].options.env?.OMX_DEFERRED_UPDATE_PARENT_PID, '12345');
1094
- assert.equal(calls[0].options.env?.OMX_DEFERRED_UPDATE_LOG, result.logPath);
1095
- assert.equal(calls[0].options.env?.OMX_SKIP_NATIVE_AGENT_REFRESH, '1');
1096
- assert.match(calls[0].args[4], /Get-Process -Id \$parentPid/);
1097
- assert.match(calls[0].args[4], /npm install -g oh-my-codex@latest/);
1098
- assert.match(calls[0].args[4], /& 'omx' 'setup'/);
994
+ assert.equal(calls[0]?.options.detached, true);
995
+ assert.equal(calls[0]?.options.stdio, 'ignore');
996
+ assert.equal(calls[0]?.options.windowsHide, true);
997
+ assert.equal(calls[0]?.options.cwd, cwd);
998
+ assert.deepEqual(calls[0]?.options.env, { OMX_UPDATE_TEST: '1', OMX_SKIP_NATIVE_AGENT_REFRESH: '1' });
999
+ }
1000
+ finally {
1001
+ await rm(cwd, { recursive: true, force: true });
1002
+ }
1003
+ });
1004
+ it('removes the frozen staged payload when the detached launcher emits an error', async () => {
1005
+ const cwd = await mkdtemp(join(tmpdir(), 'omx-deferred-update-launcher-error-'));
1006
+ let payloadPath = '';
1007
+ try {
1008
+ const result = runDeferredGlobalUpdate(cwd, ((_command, args) => {
1009
+ payloadPath = String(args[1]);
1010
+ return {
1011
+ once(event, listener) {
1012
+ if (event === 'error')
1013
+ listener(new Error('launcher failed'));
1014
+ return this;
1015
+ },
1016
+ unref() { },
1017
+ };
1018
+ }), 'linux', 12345, frozenNpmOwnership);
1019
+ assert.equal(result.ok, true);
1020
+ assert.equal(existsSync(payloadPath), false);
1099
1021
  }
1100
1022
  finally {
1101
1023
  await rm(cwd, { recursive: true, force: true });
@@ -1115,10 +1037,11 @@ describe('runDeferredGlobalUpdate', () => {
1115
1037
  },
1116
1038
  unref() { },
1117
1039
  };
1118
- }), 'linux', 12345);
1040
+ }), 'linux', 12345, frozenNpmOwnership);
1119
1041
  assert.equal(result.ok, true);
1120
1042
  assert.equal(calls.length, 1);
1121
- assert.match(calls[0].args[1], /'omx' 'setup' '--scope' 'user' '--plugin' '--mcp' 'none' '--disable-team'/);
1043
+ const payload = JSON.parse(await readFile(calls[0]?.args[1] ?? '', 'utf-8'));
1044
+ assert.deepEqual(payload.setupArgs, ['setup', '--scope', 'user', '--plugin', '--mcp', 'none', '--disable-team']);
1122
1045
  assert.equal(calls[0].options?.env?.OMX_SKIP_NATIVE_AGENT_REFRESH, '1');
1123
1046
  }
1124
1047
  finally {
@@ -1140,13 +1063,12 @@ describe('runDeferredGlobalUpdate', () => {
1140
1063
  },
1141
1064
  unref() { },
1142
1065
  };
1143
- }), 'linux', 12345);
1066
+ }), 'linux', 12345, frozenNpmOwnership);
1144
1067
  await writeFile(setupScopePath, JSON.stringify({ scope: 'project', installMode: 'legacy', mcpMode: 'compat' }, null, 2));
1145
1068
  assert.equal(result.ok, true);
1146
1069
  assert.equal(calls.length, 1);
1147
- assert.match(calls[0].args[1], /'omx' 'setup' '--scope' 'user' '--plugin' '--mcp' 'none' '--disable-team'/);
1148
- assert.doesNotMatch(calls[0].args[1], /compat/);
1149
- assert.doesNotMatch(calls[0].args[1], /legacy/);
1070
+ const payload = JSON.parse(await readFile(calls[0]?.args[1] ?? '', 'utf-8'));
1071
+ assert.deepEqual(payload.setupArgs, ['setup', '--scope', 'user', '--plugin', '--mcp', 'none', '--disable-team']);
1150
1072
  }
1151
1073
  finally {
1152
1074
  await rm(cwd, { recursive: true, force: true });
@@ -1157,6 +1079,176 @@ describe('runDeferredGlobalUpdate', () => {
1157
1079
  assert.equal(formatDeferredSetupCommand('linux', 'omx tool', args), "'omx tool' 'setup' '--scope' 'user project' '--mcp' 'none'\\''; echo pwned #' '--flag' ''");
1158
1080
  assert.equal(formatDeferredSetupCommand('win32', 'omx tool', args), "& 'omx tool' 'setup' '--scope' 'user project' '--mcp' 'none''; echo pwned #' '--flag' ''");
1159
1081
  });
1082
+ describe('deferred update worker', () => {
1083
+ it('retains refresh suppression and removes the verified staging directory after execution', async () => {
1084
+ const root = await mkdtemp(join(tmpdir(), 'omx-update-worker-'));
1085
+ const globalRoot = join(root, 'global');
1086
+ const packageRoot = join(globalRoot, PACKAGE_NAME);
1087
+ const stage = join(root, 'omx-update-stage');
1088
+ const payloadPath = join(stage, 'transaction.json');
1089
+ const capturePath = join(root, 'setup-capture.json');
1090
+ const codexHome = join(root, 'codex-home');
1091
+ const stampPath = join(codexHome, '.omx', 'install-state.json');
1092
+ const npmCliPath = join(root, 'npm-cli.js');
1093
+ const cliPath = join(packageRoot, 'dist', 'cli.js');
1094
+ const workerPath = join(dirname(fileURLToPath(import.meta.url)), '..', 'update-worker.js');
1095
+ try {
1096
+ await mkdir(dirname(cliPath), { recursive: true });
1097
+ await writeFile(join(packageRoot, 'package.json'), JSON.stringify({ name: PACKAGE_NAME, version: '0.14.1', bin: { omx: 'dist/cli.js' } }));
1098
+ await writeFile(cliPath, [
1099
+ "import { existsSync, writeFileSync } from 'node:fs';",
1100
+ "writeFileSync(process.env.OMX_UPDATE_CAPTURE_PATH, JSON.stringify({ args: process.argv.slice(2), skip: process.env.OMX_SKIP_NATIVE_AGENT_REFRESH, stampPresent: existsSync(process.env.OMX_UPDATE_STAMP_PATH) }));",
1101
+ ].join('\n'));
1102
+ await writeFile(npmCliPath, [
1103
+ "const args = process.argv.slice(2);",
1104
+ "if (args[0] === 'root') process.stdout.write(process.env.OMX_UPDATE_GLOBAL_ROOT + '\\n');",
1105
+ "else if (args[0] === 'prefix') process.stdout.write(process.env.OMX_UPDATE_PREFIX + '\\n');",
1106
+ ].join('\n'));
1107
+ await mkdir(stage, { recursive: true });
1108
+ await chmod(stage, 0o700);
1109
+ const ownership = {
1110
+ manager: 'npm',
1111
+ npmCommand: { kind: 'node-script', command: process.execPath, commandArgs: [npmCliPath] },
1112
+ npmPrefix: root,
1113
+ globalInstallRoot: globalRoot,
1114
+ packageRoot,
1115
+ environment: {
1116
+ OMX_UPDATE_CAPTURE_PATH: capturePath,
1117
+ OMX_UPDATE_GLOBAL_ROOT: globalRoot,
1118
+ OMX_UPDATE_PREFIX: root,
1119
+ CODEX_HOME: codexHome,
1120
+ OMX_UPDATE_STAMP_PATH: stampPath,
1121
+ },
1122
+ };
1123
+ const serialized = JSON.stringify({ cwd: root, logPath: join(root, 'update.log'), parentPid: 999999, ownership, setupArgs: ['setup', '--scope', 'project'] });
1124
+ await writeFile(payloadPath, serialized, { mode: 0o600 });
1125
+ const digest = (contents) => createHash('sha256').update(contents).digest('hex');
1126
+ const result = spawnSync(process.execPath, [workerPath, payloadPath, digest(serialized), digest(await readFile(workerPath))], {
1127
+ encoding: 'utf-8',
1128
+ timeout: 10000,
1129
+ });
1130
+ assert.equal(result.status, 0, result.stderr);
1131
+ assert.deepEqual(JSON.parse(await readFile(capturePath, 'utf-8')), {
1132
+ args: ['setup', '--scope', 'project'],
1133
+ skip: '1',
1134
+ stampPresent: false,
1135
+ });
1136
+ const stamp = JSON.parse(await readFile(stampPath, 'utf-8'));
1137
+ assert.deepEqual({ ...stamp, updated_at: undefined }, {
1138
+ installed_version: '0.14.1',
1139
+ setup_completed_version: '0.14.1',
1140
+ install_channel: 'stable',
1141
+ install_source: 'oh-my-codex@latest',
1142
+ package_manager: 'npm',
1143
+ updated_at: undefined,
1144
+ });
1145
+ assert.match(stamp.updated_at, /^\d{4}-\d{2}-\d{2}T/);
1146
+ await assert.rejects(readFile(payloadPath), { code: 'ENOENT' });
1147
+ await assert.rejects(readFile(stage), { code: 'ENOENT' });
1148
+ await writeFile(join(packageRoot, 'package.json'), JSON.stringify({ name: 'unexpected-package', version: '0.14.1', bin: { omx: 'dist/cli.js' } }));
1149
+ await mkdir(stage, { recursive: true });
1150
+ await chmod(stage, 0o700);
1151
+ await writeFile(payloadPath, serialized, { mode: 0o600 });
1152
+ const rejected = spawnSync(process.execPath, [workerPath, payloadPath, digest(serialized), digest(await readFile(workerPath))], {
1153
+ encoding: 'utf-8',
1154
+ timeout: 10000,
1155
+ });
1156
+ assert.equal(rejected.status, 1, rejected.stderr);
1157
+ await assert.rejects(readFile(stage), { code: 'ENOENT' });
1158
+ }
1159
+ finally {
1160
+ await rm(root, { recursive: true, force: true });
1161
+ }
1162
+ });
1163
+ it('rejects a worker whose frozen identity digest no longer matches', async () => {
1164
+ const root = await mkdtemp(join(tmpdir(), 'omx-update-worker-integrity-'));
1165
+ const stage = join(root, 'omx-update-integrity');
1166
+ const payloadPath = join(stage, 'transaction.json');
1167
+ const workerPath = join(dirname(fileURLToPath(import.meta.url)), '..', 'update-worker.js');
1168
+ try {
1169
+ await mkdir(stage, { recursive: true });
1170
+ await chmod(stage, 0o700);
1171
+ const serialized = '{}';
1172
+ await writeFile(payloadPath, serialized, { mode: 0o600 });
1173
+ const digest = (contents) => createHash('sha256').update(contents).digest('hex');
1174
+ const result = spawnSync(process.execPath, [workerPath, payloadPath, digest(serialized), digest('different worker')], {
1175
+ encoding: 'utf-8',
1176
+ timeout: 10000,
1177
+ });
1178
+ assert.equal(result.status, 1);
1179
+ assert.equal(existsSync(join(root, 'update.log')), false);
1180
+ }
1181
+ finally {
1182
+ await rm(root, { recursive: true, force: true });
1183
+ }
1184
+ });
1185
+ it('rejects a signed deferred payload with an invalid parent transaction boundary', async () => {
1186
+ const root = await mkdtemp(join(tmpdir(), 'omx-update-worker-payload-'));
1187
+ const stage = join(root, 'omx-update-payload');
1188
+ const payloadPath = join(stage, 'transaction.json');
1189
+ const workerPath = join(dirname(fileURLToPath(import.meta.url)), '..', 'update-worker.js');
1190
+ try {
1191
+ await mkdir(stage, { recursive: true });
1192
+ await chmod(stage, 0o700);
1193
+ const serialized = JSON.stringify({ cwd: root, logPath: join(root, 'update.log'), parentPid: 0, setupArgs: [], ownership: frozenNpmOwnership });
1194
+ await writeFile(payloadPath, serialized, { mode: 0o600 });
1195
+ const digest = (contents) => createHash('sha256').update(contents).digest('hex');
1196
+ const result = spawnSync(process.execPath, [workerPath, payloadPath, digest(serialized), digest(await readFile(workerPath))], {
1197
+ encoding: 'utf-8',
1198
+ timeout: 10000,
1199
+ });
1200
+ assert.equal(result.status, 1, result.stderr);
1201
+ assert.equal(await readFile(payloadPath, 'utf-8'), serialized);
1202
+ }
1203
+ finally {
1204
+ await rm(root, { recursive: true, force: true });
1205
+ }
1206
+ });
1207
+ it('rejects a noncanonical payload path without removing its owner-only directory', async () => {
1208
+ const root = await mkdtemp(join(tmpdir(), 'omx-update-worker-noncanonical-'));
1209
+ const stage = join(root, 'omx-update-noncanonical');
1210
+ const payloadPath = join(stage, 'unrelated.json');
1211
+ const workerPath = join(dirname(fileURLToPath(import.meta.url)), '..', 'update-worker.js');
1212
+ try {
1213
+ await mkdir(stage, { recursive: true });
1214
+ await chmod(stage, 0o700);
1215
+ const serialized = '{}';
1216
+ await writeFile(payloadPath, serialized, { mode: 0o600 });
1217
+ const digest = (contents) => createHash('sha256').update(contents).digest('hex');
1218
+ const result = spawnSync(process.execPath, [workerPath, payloadPath, digest(serialized), digest(await readFile(workerPath))], {
1219
+ encoding: 'utf-8',
1220
+ timeout: 10000,
1221
+ });
1222
+ assert.equal(result.status, 1, result.stderr);
1223
+ assert.equal(await readFile(payloadPath, 'utf-8'), serialized);
1224
+ }
1225
+ finally {
1226
+ await rm(root, { recursive: true, force: true });
1227
+ }
1228
+ });
1229
+ it('preserves an owner-only directory outside the scheduler staging namespace', async () => {
1230
+ const root = await mkdtemp(join(tmpdir(), 'omx-update-worker-foreign-stage-'));
1231
+ const stage = join(root, 'foreign-stage');
1232
+ const payloadPath = join(stage, 'transaction.json');
1233
+ const workerPath = join(dirname(fileURLToPath(import.meta.url)), '..', 'update-worker.js');
1234
+ try {
1235
+ await mkdir(stage, { recursive: true });
1236
+ await chmod(stage, 0o700);
1237
+ const serialized = '{}';
1238
+ await writeFile(payloadPath, serialized, { mode: 0o600 });
1239
+ const digest = (contents) => createHash('sha256').update(contents).digest('hex');
1240
+ const result = spawnSync(process.execPath, [workerPath, payloadPath, digest(serialized), digest(await readFile(workerPath))], {
1241
+ encoding: 'utf-8',
1242
+ timeout: 10000,
1243
+ });
1244
+ assert.equal(result.status, 1, result.stderr);
1245
+ assert.equal(await readFile(payloadPath, 'utf-8'), serialized);
1246
+ }
1247
+ finally {
1248
+ await rm(root, { recursive: true, force: true });
1249
+ }
1250
+ });
1251
+ });
1160
1252
  });
1161
1253
  describe('post-update setup refresh handoff', () => {
1162
1254
  it('uses the installed package bin entry when resolving the refreshed CLI', async () => {
@@ -1206,6 +1298,20 @@ describe('post-update setup refresh handoff', () => {
1206
1298
  assert.equal(result.ok, true);
1207
1299
  assert.equal(receivedTimeout, undefined);
1208
1300
  });
1301
+ it('passes only the frozen ownership environment to the immediate setup child', () => {
1302
+ const frozenEnvironment = {
1303
+ CODEX_HOME: '/frozen/codex-home',
1304
+ OMX_SKIP_NATIVE_AGENT_REFRESH: '1',
1305
+ };
1306
+ let receivedEnvironment;
1307
+ const result = spawnInstalledSetupRefresh('/tmp/omx.js', '/tmp/project', ((_command, _args, options) => {
1308
+ receivedEnvironment = options?.env;
1309
+ return { status: 0, error: undefined };
1310
+ }), process.execPath, frozenEnvironment);
1311
+ assert.equal(result.ok, true);
1312
+ assert.deepEqual(receivedEnvironment, frozenEnvironment);
1313
+ assert.equal(receivedEnvironment?.OMX_SKIP_NATIVE_AGENT_REFRESH, '1');
1314
+ });
1209
1315
  it('passes persisted plugin setup choices to the updated CLI refresh', async () => {
1210
1316
  const cwd = await mkdtemp(join(tmpdir(), 'omx-update-plugin-refresh-'));
1211
1317
  const received = [];
@@ -1297,7 +1403,7 @@ describe('persisted merge policy update replay', () => {
1297
1403
  await rm(cwd, { recursive: true, force: true });
1298
1404
  }
1299
1405
  });
1300
- it('snapshots the same merge-policy argv for deferred POSIX and PowerShell commands', async () => {
1406
+ it('snapshots merge-policy argv in the detached Node-worker payload on every platform', async () => {
1301
1407
  const cwd = await mkdtemp(join(tmpdir(), 'omx-update-merge-policy-snapshot-'));
1302
1408
  const calls = [];
1303
1409
  try {
@@ -1308,10 +1414,396 @@ describe('persisted merge policy update replay', () => {
1308
1414
  const result = runDeferredGlobalUpdate(cwd, ((_, args) => {
1309
1415
  calls.push({ args: args });
1310
1416
  return { once() { return this; }, unref() { } };
1311
- }), platform, 12345);
1417
+ }), platform, 12345, frozenNpmOwnership);
1312
1418
  assert.equal(result.ok, true);
1313
- assert.match(calls[0]?.args.at(-1) ?? '', /--no-merge-agents/);
1314
- assert.doesNotMatch(calls[0]?.args.at(-1) ?? '', /--force/);
1419
+ const payload = JSON.parse(await readFile(calls[0]?.args[1] ?? '', 'utf-8'));
1420
+ assert.deepEqual(payload.setupArgs, ['setup', '--scope', 'user', '--no-merge-agents']);
1421
+ }
1422
+ }
1423
+ finally {
1424
+ await rm(cwd, { recursive: true, force: true });
1425
+ }
1426
+ });
1427
+ });
1428
+ describe('package-manager ownership', () => {
1429
+ const executable = '/configured/node_modules/oh-my-codex/dist/cli/omx.js';
1430
+ const packageRoot = '/configured/node_modules/oh-my-codex';
1431
+ function ownershipDependencies(stamp, roots) {
1432
+ return {
1433
+ currentExecutable: executable,
1434
+ currentPackageRoot: packageRoot,
1435
+ readInstallStamp: async () => stamp
1436
+ ? { installed_version: '0.20.3', updated_at: '2026-07-22T00:00:00.000Z', package_manager: stamp }
1437
+ : null,
1438
+ realpath: (path) => path,
1439
+ resolveNpmGlobalInstallRoot: () => roots.npm ?? null,
1440
+ resolveBunGlobalBin: () => roots.bunBin ?? null,
1441
+ resolveBunCommand: () => '/configured/runtime/bun',
1442
+ resolveNpmCommand: () => ({ kind: 'node-script', command: '/canonical/node', commandArgs: ['/canonical/npm-cli.js'] }),
1443
+ resolveNpmPrefix: () => '/configured',
1444
+ environment: { OMX_UPDATE_TEST: '1' },
1445
+ };
1446
+ }
1447
+ it('selects a validated npm owner from isolated roots', async () => {
1448
+ assert.deepEqual(await resolvePackageManagerOwnership(ownershipDependencies('npm', {
1449
+ npm: '/configured/node_modules',
1450
+ })), {
1451
+ manager: 'npm',
1452
+ npmCommand: { kind: 'node-script', command: '/canonical/node', commandArgs: ['/canonical/npm-cli.js'] },
1453
+ npmPrefix: '/configured',
1454
+ globalInstallRoot: '/configured/node_modules',
1455
+ packageRoot: '/configured/node_modules/oh-my-codex',
1456
+ environment: {},
1457
+ });
1458
+ });
1459
+ it('recovers an npm owner from a stale Bun stamp without deleting the stamp', async () => {
1460
+ const ownership = await resolvePackageManagerOwnership(ownershipDependencies('bun', {
1461
+ npm: '/configured/node_modules',
1462
+ }));
1463
+ assert.equal(ownership?.manager, 'npm');
1464
+ });
1465
+ it('freezes CODEX_HOME for deferred setup and update finalization', async () => {
1466
+ const ownership = await resolvePackageManagerOwnership({
1467
+ ...ownershipDependencies('npm', { npm: '/configured/node_modules' }),
1468
+ environment: { CODEX_HOME: '/configured/codex-home' },
1469
+ });
1470
+ assert.deepEqual(ownership?.environment, { CODEX_HOME: '/configured/codex-home' });
1471
+ });
1472
+ it('resolves a normal npm Node-shebang launch from its installed npm CLI without lifecycle provenance', async () => {
1473
+ let npmCommand;
1474
+ const ownership = await resolvePackageManagerOwnership({
1475
+ ...ownershipDependencies('npm', { npm: '/fake/npm/lib/node_modules' }),
1476
+ currentExecutable: '/fake/npm/lib/node_modules/oh-my-codex/dist/cli/omx.js',
1477
+ currentPackageRoot: '/fake/npm/lib/node_modules/oh-my-codex',
1478
+ currentNodeExecutable: '/fake/npm/bin/node',
1479
+ resolveNpmCommand: () => null,
1480
+ resolveNpmGlobalInstallRoot: (command) => {
1481
+ npmCommand = command;
1482
+ return '/fake/npm/lib/node_modules';
1483
+ },
1484
+ resolveNpmPrefix: () => '/fake/npm',
1485
+ environment: {},
1486
+ });
1487
+ assert.deepEqual(npmCommand, {
1488
+ kind: 'node-script', command: '/fake/npm/bin/node', commandArgs: ['/fake/npm/lib/node_modules/npm/bin/npm-cli.js'],
1489
+ });
1490
+ assert.deepEqual(ownership, {
1491
+ manager: 'npm',
1492
+ npmCommand: npmCommand,
1493
+ npmPrefix: '/fake/npm',
1494
+ globalInstallRoot: '/fake/npm/lib/node_modules',
1495
+ packageRoot: '/fake/npm/lib/node_modules/oh-my-codex',
1496
+ environment: {},
1497
+ });
1498
+ assert.equal(await resolvePackageManagerOwnership({
1499
+ ...ownershipDependencies('npm', { npm: '/fake/npm/lib/node_modules' }),
1500
+ currentExecutable: '/fake/npm/lib/node_modules/oh-my-codex/dist/cli/omx.js',
1501
+ currentPackageRoot: '/fake/npm/lib/node_modules/oh-my-codex',
1502
+ currentNodeExecutable: '/fake/npm/bin/node',
1503
+ resolveNpmCommand: () => null,
1504
+ realpath: (path) => {
1505
+ if (path.endsWith('/npm/bin/npm-cli.js'))
1506
+ throw new Error('missing npm CLI');
1507
+ return path;
1508
+ },
1509
+ environment: {},
1510
+ }), null, 'missing installed npm CLI must fail closed');
1511
+ });
1512
+ it('resolves npm from the selected global OMX root before a Node runtime sibling on Windows', async () => {
1513
+ let npmCommand;
1514
+ const ownership = await resolvePackageManagerOwnership({
1515
+ ...ownershipDependencies('npm', { npm: 'C:\\Users\\alice\\AppData\\Roaming\\npm\\node_modules' }),
1516
+ platform: 'win32',
1517
+ currentExecutable: 'C:\\Users\\alice\\AppData\\Roaming\\npm\\node_modules\\oh-my-codex\\dist\\cli\\omx.js',
1518
+ currentPackageRoot: 'C:\\Users\\alice\\AppData\\Roaming\\npm\\node_modules\\oh-my-codex',
1519
+ currentNodeExecutable: 'C:\\Program Files\\nodejs\\node.exe',
1520
+ resolveNpmCommand: () => null,
1521
+ resolveNpmGlobalInstallRoot: (command) => {
1522
+ npmCommand = command;
1523
+ return 'C:\\Users\\alice\\AppData\\Roaming\\npm\\node_modules';
1524
+ },
1525
+ resolveNpmPrefix: () => 'C:\\Users\\alice\\AppData\\Roaming\\npm',
1526
+ environment: {},
1527
+ });
1528
+ assert.deepEqual(npmCommand, {
1529
+ kind: 'node-script',
1530
+ command: 'C:\\Program Files\\nodejs\\node.exe',
1531
+ commandArgs: ['C:\\Users\\alice\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\npm-cli.js'],
1532
+ });
1533
+ assert.equal(ownership?.manager, 'npm');
1534
+ });
1535
+ it('resolves a normal Bun Node-shebang launch only from its configured install root and matching shim', async () => {
1536
+ const ownership = await resolvePackageManagerOwnership({
1537
+ ...ownershipDependencies('bun', { bunBin: '/fake/bun/bin' }),
1538
+ currentExecutable: '/fake/bun/install/global/node_modules/oh-my-codex/dist/cli/omx.js',
1539
+ currentPackageRoot: '/fake/bun/install/global/node_modules/oh-my-codex',
1540
+ bunInstallRoot: '/fake/bun',
1541
+ resolveBunCommand: () => null,
1542
+ environment: {},
1543
+ realpath: (path) => ({
1544
+ '/fake/bun/bin/omx': '/fake/bun/install/global/node_modules/oh-my-codex/dist/cli/omx.js',
1545
+ }[path] ?? path),
1546
+ });
1547
+ assert.deepEqual(ownership, {
1548
+ manager: 'bun',
1549
+ bunCommand: '/fake/bun/bin/bun',
1550
+ bunGlobalBin: '/fake/bun/bin',
1551
+ bunShim: '/fake/bun/bin/omx',
1552
+ bunInstallRoot: '/fake/bun',
1553
+ npmPrefix: '/fake/bun/install/global/node_modules',
1554
+ globalInstallRoot: '/fake/bun/install/global/node_modules',
1555
+ packageRoot: '/fake/bun/install/global/node_modules/oh-my-codex',
1556
+ environment: { BUN_INSTALL: '/fake/bun' },
1557
+ });
1558
+ assert.equal(await resolvePackageManagerOwnership({
1559
+ ...ownershipDependencies('bun', { bunBin: '/fake/bun/bin' }),
1560
+ currentExecutable: '/fake/bun/install/global/node_modules/oh-my-codex/dist/cli/omx.js',
1561
+ currentPackageRoot: '/fake/bun/install/global/node_modules/oh-my-codex',
1562
+ resolveBunCommand: () => null,
1563
+ bunInstallRoot: undefined,
1564
+ environment: {},
1565
+ }), null, 'missing Bun command provenance must fail closed');
1566
+ });
1567
+ it('queries Bun global-bin under the frozen configured environment', () => {
1568
+ const calls = [];
1569
+ const bin = resolveBunGlobalBin('/fake/bun/bin/bun', { BUN_INSTALL: '/fake/bun', PATH: '/frozen/path' }, ((command, args, options) => {
1570
+ calls.push({ command, args: args, environment: options?.env });
1571
+ return { status: 0, stdout: '/fake/bun/bin\n', stderr: '', error: undefined };
1572
+ }));
1573
+ assert.equal(bin, '/fake/bun/bin');
1574
+ assert.deepEqual(calls, [{
1575
+ command: '/fake/bun/bin/bun',
1576
+ args: ['pm', 'bin', '-g'],
1577
+ environment: { BUN_INSTALL: '/fake/bun', PATH: '/frozen/path' },
1578
+ }]);
1579
+ });
1580
+ it('resolves an unstamped Bun install after confirming its canonical shim and configured root', async () => {
1581
+ const ownership = await resolvePackageManagerOwnership({
1582
+ ...ownershipDependencies(undefined, { bunBin: '/fake/bun/bin' }),
1583
+ currentExecutable: '/fake/bun/install/global/node_modules/oh-my-codex/dist/cli/omx.js',
1584
+ currentPackageRoot: '/fake/bun/install/global/node_modules/oh-my-codex',
1585
+ bunInstallRoot: '/fake/bun',
1586
+ resolveBunCommand: () => '/fake/bun/bin/bun',
1587
+ environment: {},
1588
+ realpath: (path) => ({
1589
+ '/fake/bun/bin/omx': '/fake/bun/install/global/node_modules/oh-my-codex/dist/cli/omx.js',
1590
+ }[path] ?? path),
1591
+ });
1592
+ assert.deepEqual(ownership, {
1593
+ manager: 'bun',
1594
+ bunCommand: '/fake/bun/bin/bun',
1595
+ bunGlobalBin: '/fake/bun/bin',
1596
+ bunShim: '/fake/bun/bin/omx',
1597
+ bunInstallRoot: '/fake/bun',
1598
+ npmPrefix: '/fake/bun/install/global/node_modules',
1599
+ globalInstallRoot: '/fake/bun/install/global/node_modules',
1600
+ packageRoot: '/fake/bun/install/global/node_modules/oh-my-codex',
1601
+ environment: { BUN_INSTALL: '/fake/bun' },
1602
+ });
1603
+ });
1604
+ it('recovers a Bun owner from a stale npm stamp without deleting the stamp', async () => {
1605
+ const ownership = await resolvePackageManagerOwnership({
1606
+ ...ownershipDependencies('npm', { bunBin: '/fake/bun/bin' }),
1607
+ currentExecutable: '/fake/bun/install/global/node_modules/oh-my-codex/dist/cli/omx.js',
1608
+ currentPackageRoot: '/fake/bun/install/global/node_modules/oh-my-codex',
1609
+ bunInstallRoot: '/fake/bun',
1610
+ resolveBunCommand: () => '/fake/bun/bin/bun',
1611
+ environment: {},
1612
+ realpath: (path) => ({
1613
+ '/fake/bun/bin/omx': '/fake/bun/install/global/node_modules/oh-my-codex/dist/cli/omx.js',
1614
+ }[path] ?? path),
1615
+ });
1616
+ assert.equal(ownership?.manager, 'bun');
1617
+ });
1618
+ it('fails closed when npm and Bun ownership both validate, even with a manager stamp', async () => {
1619
+ for (const stamp of [undefined, 'npm', 'bun']) {
1620
+ const ownership = await resolvePackageManagerOwnership({
1621
+ ...ownershipDependencies(stamp, {
1622
+ npm: '/fake/bun/install/global/node_modules',
1623
+ bunBin: '/fake/bun/bin',
1624
+ }),
1625
+ currentExecutable: '/fake/bun/install/global/node_modules/oh-my-codex/dist/cli/omx.js',
1626
+ currentPackageRoot: '/fake/bun/install/global/node_modules/oh-my-codex',
1627
+ bunInstallRoot: '/fake/bun',
1628
+ resolveBunCommand: () => '/fake/bun/bin/bun',
1629
+ resolveNpmPrefix: () => '/fake/bun/install/global',
1630
+ environment: {},
1631
+ realpath: (path) => ({
1632
+ '/fake/bun/bin/omx': '/fake/bun/install/global/node_modules/oh-my-codex/dist/cli/omx.js',
1633
+ }[path] ?? path),
1634
+ });
1635
+ assert.equal(ownership, null);
1636
+ }
1637
+ });
1638
+ it('uses platform-correct canonical paths for a Windows Bun .cmd shim', async () => {
1639
+ const ownership = await resolvePackageManagerOwnership({
1640
+ ...ownershipDependencies('bun', { bunBin: 'C:\\Users\\alice\\.bun\\bin' }),
1641
+ platform: 'win32',
1642
+ bunInstallRoot: 'C:\\Users\\alice\\.bun',
1643
+ currentExecutable: 'C:\\Users\\alice\\.bun\\install\\global\\node_modules\\oh-my-codex\\dist\\cli\\omx.js',
1644
+ currentPackageRoot: 'C:\\Users\\alice\\.bun\\install\\global\\node_modules\\oh-my-codex',
1645
+ resolveBunCommand: () => null,
1646
+ environment: {},
1647
+ realpath: (path) => path,
1648
+ });
1649
+ assert.deepEqual(ownership, {
1650
+ manager: 'bun',
1651
+ bunCommand: 'C:\\Users\\alice\\.bun\\bin\\bun.exe',
1652
+ bunGlobalBin: 'C:\\Users\\alice\\.bun\\bin',
1653
+ bunShim: 'C:\\Users\\alice\\.bun\\bin\\omx.cmd',
1654
+ bunInstallRoot: 'C:\\Users\\alice\\.bun',
1655
+ npmPrefix: 'C:\\Users\\alice\\.bun\\install\\global\\node_modules',
1656
+ globalInstallRoot: 'C:\\Users\\alice\\.bun\\install\\global\\node_modules',
1657
+ packageRoot: 'C:\\Users\\alice\\.bun\\install\\global\\node_modules\\oh-my-codex',
1658
+ environment: { BUN_INSTALL: 'C:\\Users\\alice\\.bun' },
1659
+ });
1660
+ });
1661
+ it('derives a fresh Bun installation root from its canonical executable without ambient PATH lookup', async () => {
1662
+ const ownership = await resolvePackageManagerOwnership({
1663
+ ...ownershipDependencies('bun', { bunBin: 'C:\\Users\\alice\\.bun\\bin' }),
1664
+ platform: 'win32',
1665
+ currentExecutable: 'C:\\Users\\alice\\.bun\\install\\global\\node_modules\\oh-my-codex\\dist\\cli\\omx.js',
1666
+ currentPackageRoot: 'C:\\Users\\alice\\.bun\\install\\global\\node_modules\\oh-my-codex',
1667
+ bunInstallRoot: undefined,
1668
+ resolveBunCommand: () => 'C:\\Users\\alice\\.bun\\bin\\bun.exe',
1669
+ environment: {},
1670
+ realpath: (path) => path,
1671
+ });
1672
+ assert.deepEqual(ownership, {
1673
+ manager: 'bun',
1674
+ bunCommand: 'C:\\Users\\alice\\.bun\\bin\\bun.exe',
1675
+ bunGlobalBin: 'C:\\Users\\alice\\.bun\\bin',
1676
+ bunShim: 'C:\\Users\\alice\\.bun\\bin\\omx.cmd',
1677
+ bunInstallRoot: 'C:\\Users\\alice\\.bun',
1678
+ npmPrefix: 'C:\\Users\\alice\\.bun\\install\\global\\node_modules',
1679
+ globalInstallRoot: 'C:\\Users\\alice\\.bun\\install\\global\\node_modules',
1680
+ packageRoot: 'C:\\Users\\alice\\.bun\\install\\global\\node_modules\\oh-my-codex',
1681
+ environment: { BUN_INSTALL: 'C:\\Users\\alice\\.bun' },
1682
+ });
1683
+ });
1684
+ it('rejects Bun shim evidence when BUN_INSTALL cannot bind the command and global target', async () => {
1685
+ let npmCalls = 0;
1686
+ const ownership = await resolvePackageManagerOwnership({
1687
+ ...ownershipDependencies('bun', { bunBin: '/configured/bun/bin' }),
1688
+ bunInstallRoot: '/missing/developer-bun',
1689
+ currentExecutable: '/links/omx.js',
1690
+ currentPackageRoot: '/links/package',
1691
+ realpath: (path) => {
1692
+ if (path === '/missing/developer-bun')
1693
+ throw new Error('missing BUN_INSTALL');
1694
+ return path;
1695
+ },
1696
+ resolveNpmGlobalInstallRoot: () => { npmCalls += 1; return null; },
1697
+ });
1698
+ assert.equal(ownership, null);
1699
+ assert.equal(npmCalls, 1, 'A stale stamp cannot suppress independent live ownership validation.');
1700
+ });
1701
+ it('fails closed for missing, ambiguous, stale, or non-shim Bun ownership evidence', async () => {
1702
+ assert.equal(await resolvePackageManagerOwnership(ownershipDependencies(undefined, {})), null);
1703
+ assert.equal((await resolvePackageManagerOwnership(ownershipDependencies('bun', {
1704
+ npm: '/configured/node_modules',
1705
+ })))?.manager, 'npm', 'a stale Bun stamp must yield to one uniquely validated npm owner');
1706
+ assert.equal(await resolvePackageManagerOwnership({
1707
+ ...ownershipDependencies('bun', { bunBin: '/configured/bun/bin' }),
1708
+ resolveBunGlobalBin: () => '/configured/bun/bin',
1709
+ realpath: (path) => path,
1710
+ }), null);
1711
+ assert.equal(await resolvePackageManagerOwnership({
1712
+ ...ownershipDependencies('bun', { bunBin: '/fake/bun/bin' }),
1713
+ currentExecutable: '/fake/bun/install/global/node_modules/oh-my-codex/dist/cli/omx.js',
1714
+ currentPackageRoot: '/fake/bun/install/global/node_modules/oh-my-codex',
1715
+ bunInstallRoot: '/fake/bun',
1716
+ resolveBunCommand: () => '/other/bun',
1717
+ environment: {},
1718
+ }), null, 'Bun executable provenance must bind to the configured installation target.');
1719
+ });
1720
+ it('uses the frozen Bun command for stable and deferred updates and rejects Bun dev before spawning', async () => {
1721
+ const owner = {
1722
+ manager: 'bun',
1723
+ bunCommand: '/configured/runtime/bun',
1724
+ bunGlobalBin: '/configured/bun/bin',
1725
+ bunShim: '/configured/bun/bin/omx',
1726
+ bunInstallRoot: '/configured/bun',
1727
+ globalInstallRoot: '/configured/node_modules',
1728
+ packageRoot: '/configured/node_modules/oh-my-codex',
1729
+ npmPrefix: '/configured',
1730
+ environment: { OMX_UPDATE_TEST: '1', BUN_INSTALL: '/configured/bun' },
1731
+ };
1732
+ const calls = [];
1733
+ const spawnProcess = ((command, args) => {
1734
+ calls.push({ command, args });
1735
+ return { status: 0, stdout: '', stderr: '' };
1736
+ });
1737
+ assert.deepEqual(runGlobalUpdate('oh-my-codex@latest', spawnProcess, 'linux', owner), { ok: true, stderr: '' });
1738
+ assert.deepEqual(calls, [{ command: '/configured/runtime/bun', args: ['add', '--global', '--ignore-scripts', 'oh-my-codex@latest'] }]);
1739
+ calls.length = 0;
1740
+ const incompleteOwner = {
1741
+ ...owner,
1742
+ bunInstallRoot: undefined,
1743
+ environment: { OMX_UPDATE_TEST: '1' },
1744
+ };
1745
+ assert.deepEqual(runGlobalUpdate('oh-my-codex@latest', spawnProcess, 'linux', incompleteOwner), {
1746
+ ok: false,
1747
+ stderr: 'The package-manager ownership transaction is incomplete.',
1748
+ });
1749
+ assert.deepEqual(calls, []);
1750
+ assert.deepEqual(runGlobalUpdate('github:Yeachan-Heo/oh-my-codex#dev', spawnProcess, 'linux', owner), {
1751
+ ok: false, stderr: 'Bun dev updates are not yet supported',
1752
+ });
1753
+ assert.deepEqual(calls, []);
1754
+ const cwd = await mkdtemp(join(tmpdir(), 'omx-deferred-bun-'));
1755
+ try {
1756
+ const deferredCalls = [];
1757
+ const deferred = runDeferredGlobalUpdate(cwd, ((command, args) => {
1758
+ deferredCalls.push({ command, args: args });
1759
+ return { once() { return this; }, unref() { } };
1760
+ }), 'linux', 12345, owner);
1761
+ assert.equal(deferred.ok, true);
1762
+ assert.equal(deferredCalls[0]?.command, process.execPath);
1763
+ assert.match(deferredCalls[0]?.args[0] ?? '', /update-worker\.js$/);
1764
+ const payload = JSON.parse(await readFile(deferredCalls[0]?.args[1] ?? '', 'utf-8'));
1765
+ assert.deepEqual(payload.ownership, owner);
1766
+ assert.deepEqual(payload.setupArgs, ['setup']);
1767
+ }
1768
+ finally {
1769
+ await rm(cwd, { recursive: true, force: true });
1770
+ }
1771
+ });
1772
+ it('rejects malformed frozen npm and Bun ownership before spawning a manager or deferred worker', async () => {
1773
+ const malformedOwners = [
1774
+ {
1775
+ ...frozenNpmOwnership,
1776
+ npmCommand: { kind: 'node-script', command: '/untrusted/npm-launcher', commandArgs: [] },
1777
+ },
1778
+ {
1779
+ manager: 'bun',
1780
+ bunCommand: '/untrusted/bun-launcher',
1781
+ bunGlobalBin: '',
1782
+ bunShim: '',
1783
+ bunInstallRoot: '/configured/bun',
1784
+ globalInstallRoot: '/configured/node_modules',
1785
+ packageRoot: '/configured/node_modules/oh-my-codex',
1786
+ npmPrefix: '/configured',
1787
+ environment: { BUN_INSTALL: '/configured/bun' },
1788
+ },
1789
+ ];
1790
+ const cwd = await mkdtemp(join(tmpdir(), 'omx-malformed-frozen-ownership-'));
1791
+ try {
1792
+ for (const ownership of malformedOwners) {
1793
+ const managerCalls = [];
1794
+ const result = runGlobalUpdate('oh-my-codex@latest', ((command) => {
1795
+ managerCalls.push(command);
1796
+ return { status: 0, signal: null, error: undefined, stdout: '', stderr: '', output: [null, '', ''], pid: 0 };
1797
+ }), 'linux', ownership);
1798
+ assert.deepEqual(result, { ok: false, stderr: 'The package-manager ownership transaction is incomplete.' });
1799
+ assert.deepEqual(managerCalls, []);
1800
+ const workerCalls = [];
1801
+ const deferred = runDeferredGlobalUpdate(cwd, ((command) => {
1802
+ workerCalls.push(command);
1803
+ return { once() { return this; }, unref() { } };
1804
+ }), 'linux', 12345, ownership);
1805
+ assert.deepEqual(deferred.ok, false);
1806
+ assert.deepEqual(workerCalls, []);
1315
1807
  }
1316
1808
  }
1317
1809
  finally {