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,7 +1,8 @@
1
- import { appendFile, readFile, writeFile, mkdir, rm, rename, readdir } from 'fs/promises';
2
- import { join, dirname, resolve, sep } from 'path';
1
+ import { appendFile, readFile, writeFile, mkdir, rm, rename, readdir, open, realpath } from 'fs/promises';
2
+ import { basename, join, dirname, resolve, sep } from 'path';
3
3
  import { existsSync } from 'fs';
4
4
  import { randomUUID } from 'crypto';
5
+ import { AsyncLocalStorage } from 'async_hooks';
5
6
  import { readUsableSessionState } from '../hooks/session.js';
6
7
  import { isTerminalPhase } from './orchestrator.js';
7
8
  import { computeTaskReadiness as computeTaskReadinessImpl, claimTask as claimTaskImpl, transitionTaskStatus as transitionTaskStatusImpl, releaseTaskClaim as releaseTaskClaimImpl, reclaimExpiredTaskClaim as reclaimExpiredTaskClaimImpl, listTasks as listTasksImpl, } from './state/tasks.js';
@@ -16,6 +17,20 @@ import { TEAM_NAME_SAFE_PATTERN, WORKER_NAME_SAFE_PATTERN, TASK_ID_SAFE_PATTERN,
16
17
  import { resolveCanonicalTeamStateRoot } from './state-root.js';
17
18
  import { normalizeTeamTaskCoordinationPlanForStorage } from './coordination-protocol.js';
18
19
  let renameForAtomicWrite = rename;
20
+ let openForAtomicWrite = open;
21
+ let platformForAtomicWrite = process.platform;
22
+ export function setWriteAtomicOpenForTests(fn) {
23
+ openForAtomicWrite = fn;
24
+ }
25
+ export function resetWriteAtomicOpenForTests() {
26
+ openForAtomicWrite = open;
27
+ }
28
+ export function setWriteAtomicPlatformForTests(platform) {
29
+ platformForAtomicWrite = platform;
30
+ }
31
+ export function resetWriteAtomicPlatformForTests() {
32
+ platformForAtomicWrite = process.platform;
33
+ }
19
34
  export function setWriteAtomicRenameForTests(fn) {
20
35
  renameForAtomicWrite = fn;
21
36
  }
@@ -314,6 +329,12 @@ function isTeamManifestV2(value) {
314
329
  return false;
315
330
  if (!(typeof v.hud_pane_id === 'string' || v.hud_pane_id === null))
316
331
  return false;
332
+ if (!(typeof v.leader_pane_pid === 'number' || v.leader_pane_pid === null || v.leader_pane_pid === undefined))
333
+ return false;
334
+ if (!(typeof v.hud_pane_pid === 'number' || v.hud_pane_pid === null || v.hud_pane_pid === undefined))
335
+ return false;
336
+ if (v.startup_cleanup_panes !== undefined && !normalizeStartupCleanupPanes(v.startup_cleanup_panes))
337
+ return false;
317
338
  if (!(typeof v.resize_hook_name === 'string' || v.resize_hook_name === null))
318
339
  return false;
319
340
  if (!(typeof v.resize_hook_target === 'string' || v.resize_hook_target === null))
@@ -326,14 +347,54 @@ function isTeamManifestV2(value) {
326
347
  return false;
327
348
  return true;
328
349
  }
329
- // Atomic write: write to {path}.tmp.{pid}, then rename
350
+ // Atomic write: write to {path}.tmp.{pid}, fsync it, rename, then fsync parent.
351
+ function isUnsupportedParentDirectorySyncError(error) {
352
+ const code = error.code;
353
+ return (code === 'EINVAL'
354
+ || code === 'ENOTSUP'
355
+ || code === 'EISDIR'
356
+ || (code === 'EPERM' && platformForAtomicWrite === 'win32'));
357
+ }
358
+ async function syncParentDirectory(path) {
359
+ let handle;
360
+ try {
361
+ handle = await openForAtomicWrite(dirname(path), 'r');
362
+ }
363
+ catch (error) {
364
+ if (isUnsupportedParentDirectorySyncError(error))
365
+ return;
366
+ throw error;
367
+ }
368
+ try {
369
+ await handle.sync();
370
+ }
371
+ catch (error) {
372
+ if (!isUnsupportedParentDirectorySyncError(error))
373
+ throw error;
374
+ }
375
+ finally {
376
+ await handle.close();
377
+ }
378
+ }
379
+ export async function removeDurableFile(path) {
380
+ await rm(path, { force: true });
381
+ await syncParentDirectory(path);
382
+ }
330
383
  export async function writeAtomic(filePath, data) {
331
384
  const parent = dirname(filePath);
332
385
  await mkdir(parent, { recursive: true });
333
386
  const tmpPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}`;
334
387
  await writeFile(tmpPath, data, 'utf8');
388
+ const handle = await openForAtomicWrite(tmpPath, 'r');
389
+ try {
390
+ await handle.sync();
391
+ }
392
+ finally {
393
+ await handle.close();
394
+ }
335
395
  try {
336
396
  await renameForAtomicWrite(tmpPath, filePath);
397
+ await syncParentDirectory(filePath);
337
398
  }
338
399
  catch (error) {
339
400
  const err = error;
@@ -350,6 +411,205 @@ export async function writeAtomic(filePath, data) {
350
411
  throw error;
351
412
  }
352
413
  }
414
+ function membershipTransactionPath(teamName, cwd) {
415
+ return join(teamDir(teamName, cwd), '.membership-task-transaction.json');
416
+ }
417
+ async function applyMembershipTransactionFiles(files, useNewBytes) {
418
+ for (const file of files) {
419
+ const bytes = useNewBytes ? file.newBytes : file.oldBytes;
420
+ if (bytes === null)
421
+ await removeDurableFile(file.path);
422
+ else
423
+ await writeAtomic(file.path, bytes);
424
+ }
425
+ }
426
+ async function validateMembershipTransactionFiles(teamName, cwd, files) {
427
+ const expectedConfigPath = resolve(teamConfigPath(teamName, cwd));
428
+ const expectedManifestPath = resolve(teamManifestV2Path(teamName, cwd));
429
+ const expectedTasksDir = resolve(teamDir(teamName, cwd), 'tasks');
430
+ const seenPaths = new Set();
431
+ let configCount = 0;
432
+ const canonicalStateRoot = await realpath(resolveTeamStateRoot(cwd));
433
+ const canonicalTeamRoot = await realpath(teamDir(teamName, cwd));
434
+ if (canonicalTeamRoot !== canonicalStateRoot && !canonicalTeamRoot.startsWith(`${canonicalStateRoot}${sep}`)) {
435
+ throw new Error(`Membership transaction team root escapes canonical state root for ${teamName}`);
436
+ }
437
+ const canonicalTasksDir = await realpath(resolve(teamDir(teamName, cwd), 'tasks'));
438
+ if (!canonicalTasksDir.startsWith(`${canonicalTeamRoot}${sep}`)) {
439
+ throw new Error(`Membership transaction tasks root escapes canonical team root for ${teamName}`);
440
+ }
441
+ for (const file of files) {
442
+ if (!file || typeof file.path !== 'string'
443
+ || (file.oldBytes !== null && typeof file.oldBytes !== 'string')
444
+ || (file.newBytes !== null && typeof file.newBytes !== 'string')) {
445
+ throw new Error(`Invalid membership transaction file entry for ${teamName}`);
446
+ }
447
+ const resolvedPath = resolve(file.path);
448
+ if (resolvedPath !== file.path || seenPaths.has(resolvedPath)) {
449
+ throw new Error(`Invalid membership transaction path for ${teamName}`);
450
+ }
451
+ seenPaths.add(resolvedPath);
452
+ let expectedParent;
453
+ if (resolvedPath === expectedConfigPath) {
454
+ configCount += 1;
455
+ expectedParent = canonicalTeamRoot;
456
+ }
457
+ else if (resolvedPath === expectedManifestPath) {
458
+ expectedParent = canonicalTeamRoot;
459
+ }
460
+ else {
461
+ if (dirname(resolvedPath) !== expectedTasksDir) {
462
+ throw new Error(`Membership transaction path escapes expected team files for ${teamName}`);
463
+ }
464
+ const match = basename(resolvedPath).match(/^task-([A-Za-z0-9_-]+)\.json$/);
465
+ if (!match || resolve(taskFilePath(teamName, match[1], cwd)) !== resolvedPath) {
466
+ throw new Error(`Invalid membership transaction task path for ${teamName}`);
467
+ }
468
+ expectedParent = canonicalTasksDir;
469
+ }
470
+ const canonicalParent = await realpath(dirname(resolvedPath));
471
+ if (canonicalParent !== expectedParent) {
472
+ throw new Error(`Membership transaction path traverses a symlink for ${teamName}`);
473
+ }
474
+ }
475
+ if (configCount !== 1) {
476
+ throw new Error(`Membership transaction must contain exactly one config path for ${teamName}`);
477
+ }
478
+ }
479
+ /**
480
+ * Resolve an interrupted membership/task commit before a reader or writer observes
481
+ * its files. Prepared transactions roll back; committed transactions roll forward.
482
+ */
483
+ export async function recoverTeamMembershipTaskTransaction(teamName, cwd, options = {}) {
484
+ const journalPath = membershipTransactionPath(teamName, cwd);
485
+ let journal;
486
+ try {
487
+ journal = JSON.parse(await readFile(journalPath, 'utf8'));
488
+ }
489
+ catch (error) {
490
+ if (error.code === 'ENOENT')
491
+ return;
492
+ throw error;
493
+ }
494
+ if (journal.schemaVersion !== 1 || (journal.phase !== 'prepared' && journal.phase !== 'committed') || !Array.isArray(journal.files)) {
495
+ throw new Error(`Invalid membership transaction journal for ${teamName}`);
496
+ }
497
+ await validateMembershipTransactionFiles(teamName, cwd, journal.files);
498
+ await applyMembershipTransactionFiles(journal.files, journal.phase === 'committed');
499
+ if (!options.retainJournal)
500
+ await removeDurableFile(journalPath);
501
+ }
502
+ /** Finalize a previously committed membership transaction after caller verification. */
503
+ export async function finalizeTeamMembershipTaskTransaction(teamName, cwd) {
504
+ const journalPath = membershipTransactionPath(teamName, cwd);
505
+ const journal = JSON.parse(await readFile(journalPath, 'utf8'));
506
+ if (journal.schemaVersion !== 1 || journal.phase !== 'committed' || !Array.isArray(journal.files)) {
507
+ throw new Error(`Cannot finalize non-committed membership transaction for ${teamName}`);
508
+ }
509
+ await validateMembershipTransactionFiles(teamName, cwd, journal.files);
510
+ await removeDurableFile(journalPath);
511
+ }
512
+ /**
513
+ * Persist config/manifest and task membership changes as an old-or-new journaled
514
+ * generation. Callers must hold the team membership barrier for the whole call.
515
+ */
516
+ export async function commitTeamMembershipTaskTransaction(teamName, cwd, transaction) {
517
+ if (!taskMembershipBarrierContext.getStore()?.has(taskMembershipBarrierKey(teamName, cwd))) {
518
+ throw new Error(`membership_transaction_barrier_required:${teamName}`);
519
+ }
520
+ const currentGeneration = await readConfigGenerationRaw(teamName, cwd);
521
+ if (currentGeneration === null)
522
+ throw new Error(`team_config_missing:${teamName}`);
523
+ if (transaction.baseGeneration !== currentGeneration) {
524
+ throw new Error(`team_membership_stale_generation:${teamName}:${transaction.baseGeneration}:${currentGeneration}`);
525
+ }
526
+ const acceptedGeneration = currentGeneration + 1;
527
+ const nextConfig = JSON.parse(transaction.config.newBytes);
528
+ nextConfig.config_generation = acceptedGeneration;
529
+ const nextManifest = transaction.manifest?.newBytes === null
530
+ ? null
531
+ : transaction.manifest
532
+ ? { ...JSON.parse(transaction.manifest.newBytes), config_generation: acceptedGeneration }
533
+ : undefined;
534
+ const files = [
535
+ ...transaction.tasks.map((task) => ({
536
+ path: taskFilePath(teamName, task.taskId, cwd),
537
+ oldBytes: task.oldBytes,
538
+ newBytes: task.newBytes,
539
+ })),
540
+ {
541
+ path: teamConfigPath(teamName, cwd),
542
+ oldBytes: transaction.config.oldBytes,
543
+ newBytes: JSON.stringify(nextConfig, null, 2),
544
+ },
545
+ ];
546
+ if (transaction.manifest) {
547
+ files.push({
548
+ path: teamManifestV2Path(teamName, cwd),
549
+ oldBytes: transaction.manifest.oldBytes,
550
+ newBytes: nextManifest === null ? null : JSON.stringify(nextManifest, null, 2),
551
+ });
552
+ }
553
+ const journalPath = membershipTransactionPath(teamName, cwd);
554
+ const journal = {
555
+ schemaVersion: 1,
556
+ // Membership rollback is itself a durable desired-state transition: an
557
+ // interruption must finish restoring the original membership, not revive
558
+ // the transient scaled-up generation.
559
+ phase: transaction.recoverToNewOnFailure ? 'committed' : 'prepared',
560
+ files,
561
+ };
562
+ await writeAtomic(journalPath, JSON.stringify(journal, null, 2));
563
+ try {
564
+ if (transaction.interruptAfterFirstTaskWrite && transaction.tasks.length > 0) {
565
+ await applyMembershipTransactionFiles(files.slice(0, 1), true);
566
+ throw new Error('injected_scale_down_interruption:after-first-task-write');
567
+ }
568
+ await applyMembershipTransactionFiles(files, true);
569
+ if (transaction.failRollbackPersistence || transaction.failRollbackPersistenceAfter) {
570
+ // Exercise the restore path after a complete new generation is visible.
571
+ // The catch below intentionally writes OLD bytes then leaves the durable
572
+ // journal in place so public entry recovery owns convergence.
573
+ throw new Error('injected_scale_down_failure:rollback-persistence-failure');
574
+ }
575
+ journal.phase = 'committed';
576
+ await writeAtomic(journalPath, JSON.stringify(journal, null, 2));
577
+ if (!transaction.retainJournalOnSuccess)
578
+ await removeDurableFile(journalPath);
579
+ }
580
+ catch (error) {
581
+ if (error instanceof Error && error.message === 'injected_scale_down_interruption:after-first-task-write')
582
+ throw error;
583
+ if (transaction.failRollbackPersistence || transaction.failRollbackPersistenceAfter) {
584
+ const target = transaction.failRollbackPersistenceAfter;
585
+ const targetIndex = target ? files.findIndex((file) => file.path === (target === 'config'
586
+ ? teamConfigPath(teamName, cwd)
587
+ : teamManifestV2Path(teamName, cwd))) : 0;
588
+ const partial = files.slice(0, Math.max(1, targetIndex + 1));
589
+ await applyMembershipTransactionFiles(partial, false);
590
+ throw error;
591
+ }
592
+ if (transaction.recoverToNewOnFailure) {
593
+ try {
594
+ await recoverTeamMembershipTaskTransaction(teamName, cwd);
595
+ }
596
+ catch {
597
+ // Keep the committed-direction journal as durable recovery authority.
598
+ }
599
+ throw error;
600
+ }
601
+ // Leave the prepared marker durable if restoring old bytes also fails. Entry
602
+ // recovery will retry until the state has converged to the old generation.
603
+ try {
604
+ await applyMembershipTransactionFiles(files, false);
605
+ await removeDurableFile(journalPath);
606
+ }
607
+ catch {
608
+ // The prepared journal is the durable recovery authority.
609
+ }
610
+ throw error;
611
+ }
612
+ }
353
613
  // Initialize team state directory + config.json
354
614
  // Creates: .omx/state/team/{name}/, workers/{worker-1}..{worker-N}/, tasks/
355
615
  // Throws if workerCount > maxWorkers (default 20)
@@ -401,12 +661,16 @@ export async function initTeamState(teamName, task, agentType, workerCount, cwd,
401
661
  workers,
402
662
  created_at: new Date().toISOString(),
403
663
  tmux_session: `omx-team-${teamName}`,
664
+ tmux_session_id: undefined,
665
+ tmux_session_created: undefined,
404
666
  next_task_id: 1,
405
667
  leader_cwd: workspace.leader_cwd,
406
668
  team_state_root: workspace.team_state_root,
407
669
  workspace_mode: workspace.workspace_mode,
408
670
  worktree_mode: workspace.worktree_mode,
409
671
  leader_pane_id: null,
672
+ leader_pane_pid: null,
673
+ hud_pane_pid: null,
410
674
  hud_pane_id: null,
411
675
  tmux_pane_owner_id: tmuxPaneOwnerId,
412
676
  resize_hook_name: null,
@@ -415,8 +679,11 @@ export async function initTeamState(teamName, task, agentType, workerCount, cwd,
415
679
  display_name: workspace.display_name,
416
680
  requested_name: workspace.requested_name,
417
681
  identity_source: workspace.identity_source,
682
+ config_generation: 0,
418
683
  };
419
- await writeAtomic(join(root, 'config.json'), JSON.stringify(config, null, 2));
684
+ await withTeamTaskBarrier(teamName, cwd, async () => {
685
+ await writeAtomic(join(root, 'config.json'), JSON.stringify(config, null, 2));
686
+ });
420
687
  await writeTeamPhase(teamName, {
421
688
  current_phase: 'team-exec',
422
689
  max_fix_attempts: 3,
@@ -438,6 +705,8 @@ export async function initTeamState(teamName, task, agentType, workerCount, cwd,
438
705
  lifecycle_profile: lifecycleProfile,
439
706
  permissions_snapshot: permissionsSnapshot,
440
707
  tmux_session: config.tmux_session,
708
+ tmux_session_id: config.tmux_session_id,
709
+ tmux_session_created: config.tmux_session_created,
441
710
  worker_count: workerCount,
442
711
  workers,
443
712
  next_task_id: 1,
@@ -447,11 +716,14 @@ export async function initTeamState(teamName, task, agentType, workerCount, cwd,
447
716
  workspace_mode: workspace.workspace_mode,
448
717
  worktree_mode: workspace.worktree_mode,
449
718
  leader_pane_id: null,
719
+ leader_pane_pid: null,
720
+ hud_pane_pid: null,
450
721
  hud_pane_id: null,
451
722
  tmux_pane_owner_id: tmuxPaneOwnerId,
452
723
  resize_hook_name: null,
453
724
  resize_hook_target: null,
454
725
  next_worker_index: workerCount + 1,
726
+ startup_cleanup_panes: undefined,
455
727
  display_name: workspace.display_name,
456
728
  requested_name: workspace.requested_name,
457
729
  identity_source: workspace.identity_source,
@@ -460,34 +732,64 @@ export async function initTeamState(teamName, task, agentType, workerCount, cwd,
460
732
  }
461
733
  async function writeConfig(cfg, cwd) {
462
734
  const normalized = normalizeTeamConfig(cfg);
463
- const p = teamConfigPath(normalized.name, cwd);
464
- await writeAtomic(p, JSON.stringify(normalized, null, 2));
735
+ const configPath = teamConfigPath(normalized.name, cwd);
736
+ const oldConfigBytes = await readFile(configPath, 'utf8');
465
737
  // Keep v2 manifest in sync when present. Don't create it implicitly here to preserve migration behavior.
466
- const existing = await readTeamManifestV2(normalized.name, cwd);
467
- if (existing) {
468
- const merged = {
469
- ...existing,
470
- task: normalized.task,
471
- tmux_session: normalized.tmux_session,
472
- worker_count: normalized.worker_count,
473
- workers: normalized.workers,
474
- lifecycle_profile: normalized.lifecycle_profile,
475
- next_task_id: normalizeNextTaskId(normalized.next_task_id),
476
- leader_cwd: normalized.leader_cwd,
477
- team_state_root: normalized.team_state_root,
478
- workspace_mode: normalized.workspace_mode,
479
- worktree_mode: normalized.worktree_mode,
480
- leader_pane_id: normalized.leader_pane_id,
481
- hud_pane_id: normalized.hud_pane_id,
482
- tmux_pane_owner_id: normalized.tmux_pane_owner_id,
483
- resize_hook_name: normalized.resize_hook_name,
484
- resize_hook_target: normalized.resize_hook_target,
485
- next_worker_index: normalized.next_worker_index ?? existing.next_worker_index,
486
- display_name: normalized.display_name ?? existing.display_name,
487
- requested_name: normalized.requested_name ?? existing.requested_name,
488
- identity_source: normalized.identity_source ?? existing.identity_source,
489
- };
490
- await writeTeamManifestV2(merged, cwd);
738
+ const existing = await readTeamManifestV2Raw(normalized.name, cwd);
739
+ if (!existing) {
740
+ await writeAtomic(configPath, JSON.stringify(normalized, null, 2));
741
+ return;
742
+ }
743
+ const merged = {
744
+ ...existing,
745
+ task: normalized.task,
746
+ tmux_session: normalized.tmux_session,
747
+ tmux_session_id: normalized.tmux_session_id,
748
+ tmux_session_created: normalized.tmux_session_created,
749
+ worker_count: normalized.worker_count,
750
+ workers: normalized.workers,
751
+ lifecycle_profile: normalized.lifecycle_profile,
752
+ next_task_id: normalizeNextTaskId(normalized.next_task_id),
753
+ leader_cwd: normalized.leader_cwd,
754
+ team_state_root: normalized.team_state_root,
755
+ workspace_mode: normalized.workspace_mode,
756
+ worktree_mode: normalized.worktree_mode,
757
+ leader_pane_id: normalized.leader_pane_id,
758
+ leader_pane_pid: normalized.leader_pane_pid,
759
+ hud_pane_pid: normalized.hud_pane_pid,
760
+ hud_pane_id: normalized.hud_pane_id,
761
+ tmux_pane_owner_id: normalized.tmux_pane_owner_id,
762
+ resize_hook_name: normalized.resize_hook_name,
763
+ resize_hook_target: normalized.resize_hook_target,
764
+ next_worker_index: normalized.next_worker_index ?? existing.next_worker_index,
765
+ startup_cleanup_panes: normalized.startup_cleanup_panes,
766
+ display_name: normalized.display_name ?? existing.display_name,
767
+ requested_name: normalized.requested_name ?? existing.requested_name,
768
+ identity_source: normalized.identity_source ?? existing.identity_source,
769
+ config_generation: normalized.config_generation,
770
+ };
771
+ const manifestPath = teamManifestV2Path(normalized.name, cwd);
772
+ const files = [
773
+ { path: configPath, oldBytes: oldConfigBytes, newBytes: JSON.stringify(normalized, null, 2) },
774
+ { path: manifestPath, oldBytes: await readFile(manifestPath, 'utf8'), newBytes: JSON.stringify(merged, null, 2) },
775
+ ];
776
+ const journalPath = membershipTransactionPath(normalized.name, cwd);
777
+ const journal = { schemaVersion: 1, phase: 'prepared', files };
778
+ await writeAtomic(journalPath, JSON.stringify(journal, null, 2));
779
+ try {
780
+ await applyMembershipTransactionFiles(files, true);
781
+ journal.phase = 'committed';
782
+ await writeAtomic(journalPath, JSON.stringify(journal, null, 2));
783
+ await removeDurableFile(journalPath);
784
+ }
785
+ catch (error) {
786
+ try {
787
+ await recoverTeamMembershipTaskTransaction(normalized.name, cwd);
788
+ }
789
+ catch {
790
+ // The prepared journal is the durable recovery authority.
791
+ }
792
+ throw error;
491
793
  }
492
794
  }
493
795
  function teamConfigFromManifest(manifest) {
@@ -507,34 +809,73 @@ function teamConfigFromManifest(manifest) {
507
809
  workers: manifest.workers,
508
810
  created_at: manifest.created_at,
509
811
  tmux_session: manifest.tmux_session,
812
+ tmux_session_id: manifest.tmux_session_id,
813
+ tmux_session_created: manifest.tmux_session_created,
510
814
  next_task_id: manifest.next_task_id,
511
815
  leader_cwd: manifest.leader_cwd,
512
816
  team_state_root: manifest.team_state_root,
513
817
  workspace_mode: manifest.workspace_mode,
514
818
  worktree_mode: manifest.worktree_mode,
515
819
  leader_pane_id: manifest.leader_pane_id,
820
+ leader_pane_pid: manifest.leader_pane_pid ?? null,
821
+ hud_pane_pid: manifest.hud_pane_pid ?? null,
516
822
  hud_pane_id: manifest.hud_pane_id,
517
- tmux_pane_owner_id: manifest.tmux_pane_owner_id ?? defaultTmuxPaneOwnerId(manifest.name),
823
+ tmux_pane_owner_id: typeof manifest.tmux_pane_owner_id === 'string' && manifest.tmux_pane_owner_id.trim() !== ''
824
+ ? manifest.tmux_pane_owner_id.trim()
825
+ : undefined,
518
826
  resize_hook_name: manifest.resize_hook_name,
519
827
  resize_hook_target: manifest.resize_hook_target,
520
828
  next_worker_index: manifest.next_worker_index,
829
+ startup_cleanup_panes: manifest.startup_cleanup_panes,
521
830
  display_name: manifest.display_name,
522
831
  requested_name: manifest.requested_name,
523
832
  identity_source: manifest.identity_source,
524
833
  };
525
834
  }
835
+ function normalizeStartupCleanupPanes(value) {
836
+ if (!Array.isArray(value))
837
+ return null;
838
+ const panes = new Map();
839
+ for (const raw of value) {
840
+ if (!raw || typeof raw !== 'object')
841
+ return null;
842
+ const paneId = raw.pane_id;
843
+ const pid = raw.pid;
844
+ if (typeof paneId !== 'string' || !/^%[0-9]+$/.test(paneId))
845
+ return null;
846
+ if (!(pid === null || (typeof pid === 'number' && Number.isSafeInteger(pid) && pid > 0)))
847
+ return null;
848
+ panes.set(paneId, { pane_id: paneId, pid });
849
+ }
850
+ return [...panes.values()];
851
+ }
526
852
  function normalizeTeamConfig(config) {
527
853
  const workerLaunchMode = config.worker_launch_mode === 'prompt' ? 'prompt' : 'interactive';
854
+ const configGeneration = typeof config.config_generation === 'number'
855
+ && Number.isSafeInteger(config.config_generation) && config.config_generation >= 0
856
+ ? config.config_generation
857
+ : 0;
858
+ const startupCleanupPanes = normalizeStartupCleanupPanes(config.startup_cleanup_panes ?? []);
528
859
  return {
529
860
  ...config,
861
+ config_generation: configGeneration,
530
862
  lifecycle_profile: 'default',
531
863
  leader_pane_id: config.leader_pane_id ?? null,
864
+ leader_pane_pid: typeof config.leader_pane_pid === 'number' && Number.isSafeInteger(config.leader_pane_pid) && config.leader_pane_pid > 0
865
+ ? config.leader_pane_pid
866
+ : null,
867
+ hud_pane_pid: typeof config.hud_pane_pid === 'number' && Number.isSafeInteger(config.hud_pane_pid) && config.hud_pane_pid > 0
868
+ ? config.hud_pane_pid
869
+ : null,
532
870
  hud_pane_id: config.hud_pane_id ?? null,
533
871
  tmux_pane_owner_id: typeof config.tmux_pane_owner_id === 'string' && config.tmux_pane_owner_id.trim() !== ''
534
872
  ? config.tmux_pane_owner_id.trim()
535
- : defaultTmuxPaneOwnerId(config.name),
873
+ : undefined,
536
874
  resize_hook_name: config.resize_hook_name ?? null,
537
875
  resize_hook_target: config.resize_hook_target ?? null,
876
+ startup_cleanup_panes: startupCleanupPanes && startupCleanupPanes.length > 0
877
+ ? startupCleanupPanes
878
+ : undefined,
538
879
  worker_launch_mode: workerLaunchMode,
539
880
  };
540
881
  }
@@ -556,6 +897,8 @@ function teamManifestFromConfig(config) {
556
897
  lifecycle_profile: normalized.lifecycle_profile,
557
898
  permissions_snapshot: defaultPermissionsSnapshot(),
558
899
  tmux_session: normalized.tmux_session,
900
+ tmux_session_id: normalized.tmux_session_id,
901
+ tmux_session_created: normalized.tmux_session_created,
559
902
  worker_count: normalized.worker_count,
560
903
  workers: normalized.workers,
561
904
  next_task_id: normalizeNextTaskId(normalized.next_task_id),
@@ -565,35 +908,41 @@ function teamManifestFromConfig(config) {
565
908
  workspace_mode: normalized.workspace_mode,
566
909
  worktree_mode: normalized.worktree_mode,
567
910
  leader_pane_id: normalized.leader_pane_id,
911
+ leader_pane_pid: normalized.leader_pane_pid,
912
+ hud_pane_pid: normalized.hud_pane_pid,
568
913
  hud_pane_id: normalized.hud_pane_id,
569
914
  tmux_pane_owner_id: normalized.tmux_pane_owner_id,
570
915
  resize_hook_name: normalized.resize_hook_name,
571
916
  resize_hook_target: normalized.resize_hook_target,
572
917
  next_worker_index: normalized.next_worker_index,
918
+ startup_cleanup_panes: normalized.startup_cleanup_panes,
573
919
  display_name: normalized.display_name,
574
920
  requested_name: normalized.requested_name,
575
921
  identity_source: normalized.identity_source,
922
+ config_generation: normalized.config_generation,
576
923
  };
577
924
  }
578
925
  export async function writeTeamManifestV2(manifest, cwd) {
579
- const normalizedPolicy = normalizeTeamPolicy(manifest.policy, {
580
- display_mode: manifest.policy?.display_mode === 'split_pane' ? 'split_pane' : 'auto',
581
- worker_launch_mode: manifest.policy?.worker_launch_mode === 'prompt' ? 'prompt' : 'interactive',
926
+ await withTeamTaskBarrier(manifest.name, cwd, async () => {
927
+ const normalizedPolicy = normalizeTeamPolicy(manifest.policy, {
928
+ display_mode: manifest.policy?.display_mode === 'split_pane' ? 'split_pane' : 'auto',
929
+ worker_launch_mode: manifest.policy?.worker_launch_mode === 'prompt' ? 'prompt' : 'interactive',
930
+ });
931
+ const normalizedGovernance = normalizeTeamGovernance(manifest.governance, manifest.policy);
932
+ const tmuxPaneOwnerId = typeof manifest.tmux_pane_owner_id === 'string' && manifest.tmux_pane_owner_id.trim() !== ''
933
+ ? manifest.tmux_pane_owner_id.trim()
934
+ : undefined;
935
+ const p = teamManifestV2Path(manifest.name, cwd);
936
+ await writeAtomic(p, JSON.stringify({
937
+ ...manifest,
938
+ tmux_pane_owner_id: tmuxPaneOwnerId,
939
+ policy: normalizedPolicy,
940
+ governance: normalizedGovernance,
941
+ lifecycle_profile: 'default',
942
+ }, null, 2));
582
943
  });
583
- const normalizedGovernance = normalizeTeamGovernance(manifest.governance, manifest.policy);
584
- const tmuxPaneOwnerId = typeof manifest.tmux_pane_owner_id === 'string' && manifest.tmux_pane_owner_id.trim() !== ''
585
- ? manifest.tmux_pane_owner_id.trim()
586
- : defaultTmuxPaneOwnerId(manifest.name);
587
- const p = teamManifestV2Path(manifest.name, cwd);
588
- await writeAtomic(p, JSON.stringify({
589
- ...manifest,
590
- tmux_pane_owner_id: tmuxPaneOwnerId,
591
- policy: normalizedPolicy,
592
- governance: normalizedGovernance,
593
- lifecycle_profile: 'default',
594
- }, null, 2));
595
944
  }
596
- export async function readTeamManifestV2(teamName, cwd) {
945
+ async function readTeamManifestV2Raw(teamName, cwd) {
597
946
  try {
598
947
  const p = teamManifestV2Path(teamName, cwd);
599
948
  if (!existsSync(p))
@@ -607,7 +956,7 @@ export async function readTeamManifestV2(teamName, cwd) {
607
956
  const legacyTeamDecomposition = legacyPolicy?.team_decomposition;
608
957
  const tmuxPaneOwnerId = typeof parsedManifest.tmux_pane_owner_id === 'string' && parsedManifest.tmux_pane_owner_id.trim() !== ''
609
958
  ? parsedManifest.tmux_pane_owner_id.trim()
610
- : defaultTmuxPaneOwnerId(parsedManifest.name);
959
+ : undefined;
611
960
  return {
612
961
  ...parsedManifest,
613
962
  tmux_pane_owner_id: tmuxPaneOwnerId,
@@ -627,6 +976,12 @@ export async function readTeamManifestV2(teamName, cwd) {
627
976
  return null;
628
977
  }
629
978
  }
979
+ export async function readTeamManifestV2(teamName, cwd) {
980
+ return await withTeamTaskBarrier(teamName, cwd, async () => {
981
+ await recoverTeamMembershipTaskTransaction(teamName, cwd);
982
+ return await readTeamManifestV2Raw(teamName, cwd);
983
+ });
984
+ }
630
985
  // Idempotent migration; keeps config.json untouched.
631
986
  export async function migrateV1ToV2(teamName, cwd) {
632
987
  const existing = await readTeamManifestV2(teamName, cwd);
@@ -683,11 +1038,23 @@ async function computeNextTaskIdFromDisk(teamName, cwd) {
683
1038
  }
684
1039
  return maxId + 1;
685
1040
  }
1041
+ async function readConfigGenerationRaw(teamName, cwd) {
1042
+ try {
1043
+ const raw = JSON.parse(await readFile(teamConfigPath(teamName, cwd), 'utf8'));
1044
+ return typeof raw.config_generation === 'number'
1045
+ && Number.isSafeInteger(raw.config_generation) && raw.config_generation >= 0
1046
+ ? raw.config_generation
1047
+ : 0;
1048
+ }
1049
+ catch {
1050
+ return null;
1051
+ }
1052
+ }
686
1053
  // Read team config
687
- export async function readTeamConfig(teamName, cwd) {
688
- const v2 = await readTeamManifestV2(teamName, cwd);
1054
+ async function readTeamConfigRaw(teamName, cwd) {
1055
+ const v2 = await readTeamManifestV2Raw(teamName, cwd);
689
1056
  if (v2)
690
- return teamConfigFromManifest(v2);
1057
+ return { ...teamConfigFromManifest(v2), config_generation: (await readConfigGenerationRaw(teamName, cwd)) ?? 0 };
691
1058
  // Attempt idempotent migration on first read.
692
1059
  const migrated = await migrateV1ToV2(teamName, cwd);
693
1060
  if (migrated)
@@ -706,6 +1073,12 @@ export async function readTeamConfig(teamName, cwd) {
706
1073
  return null;
707
1074
  }
708
1075
  }
1076
+ export async function readTeamConfig(teamName, cwd) {
1077
+ return await withTeamTaskBarrier(teamName, cwd, async () => {
1078
+ await recoverTeamMembershipTaskTransaction(teamName, cwd);
1079
+ return await readTeamConfigRaw(teamName, cwd);
1080
+ });
1081
+ }
709
1082
  // Write worker identity file
710
1083
  export async function writeWorkerIdentity(teamName, workerName, identity, cwd) {
711
1084
  const p = join(workerDir(teamName, workerName, cwd), 'identity.json');
@@ -753,7 +1126,8 @@ export async function writeWorkerStatus(teamName, workerName, status, cwd) {
753
1126
  const p = join(workerDir(teamName, workerName, cwd), 'status.json');
754
1127
  await writeAtomic(p, JSON.stringify(status, null, 2));
755
1128
  }
756
- // File-based scaling lock to prevent concurrent scale_up/scale_down operations
1129
+ // File-based scaling lock kept outside the deletable team root. Operations that
1130
+ // also mutate membership acquire this lock before the membership barrier.
757
1131
  export async function withScalingLock(teamName, cwd, fn) {
758
1132
  return await withScalingLockImpl(teamName, cwd, LOCK_STALE_MS, { teamDir, taskClaimLockDir, mailboxLockDir }, fn);
759
1133
  }
@@ -768,21 +1142,50 @@ function taskFilePath(teamName, taskId, cwd) {
768
1142
  assertPathWithinDir(p, resolveTeamStateRoot(cwd));
769
1143
  return p;
770
1144
  }
1145
+ const taskMembershipBarrierContext = new AsyncLocalStorage();
1146
+ function taskMembershipBarrierKey(teamName, cwd) {
1147
+ return `${resolve(cwd)}\0${teamName}`;
1148
+ }
771
1149
  async function withTeamLock(teamName, cwd, fn) {
772
1150
  return await withTeamLockImpl(teamName, cwd, LOCK_STALE_MS, { teamDir, taskClaimLockDir, mailboxLockDir }, fn);
773
1151
  }
1152
+ /**
1153
+ * Serializes membership snapshots with task creation and claims. The global
1154
+ * lock order is scaling, membership, then task claim locks. Operations that do
1155
+ * not scale acquire only this barrier (and then any task claim lock).
1156
+ */
1157
+ export async function withTeamTaskBarrier(teamName, cwd, fn) {
1158
+ const key = taskMembershipBarrierKey(teamName, cwd);
1159
+ if (taskMembershipBarrierContext.getStore()?.has(key))
1160
+ return await fn();
1161
+ return await withTeamLock(teamName, cwd, async () => {
1162
+ const held = new Set(taskMembershipBarrierContext.getStore() ?? []);
1163
+ held.add(key);
1164
+ return await taskMembershipBarrierContext.run(held, fn);
1165
+ });
1166
+ }
774
1167
  async function withTaskClaimLock(teamName, taskId, cwd, fn) {
775
1168
  return await withTaskClaimLockImpl(teamName, taskId, cwd, LOCK_STALE_MS, { teamDir, taskClaimLockDir, mailboxLockDir }, fn);
776
1169
  }
777
1170
  async function withMailboxLock(teamName, workerName, cwd, fn) {
778
1171
  return await withMailboxLockImpl(teamName, workerName, cwd, LOCK_STALE_MS, { teamDir, taskClaimLockDir, mailboxLockDir }, fn);
779
1172
  }
1173
+ export function teamContinuationRequiredDiagnostic(phase) {
1174
+ const epoch = phase.terminal_epoch ?? phase.updated_at;
1175
+ const reason = phase.terminal_reason ?? `terminal_phase_${phase.current_phase}`;
1176
+ return `team_continuation_required:terminal_epoch=${epoch}:reason=${reason}:action=reopen_or_start_continuation`;
1177
+ }
780
1178
  // Create a task (auto-increment ID)
781
1179
  export async function createTask(teamName, task, cwd) {
782
- return withTeamLock(teamName, cwd, async () => {
1180
+ return withTeamTaskBarrier(teamName, cwd, async () => {
1181
+ await recoverTeamMembershipTaskTransaction(teamName, cwd);
783
1182
  const cfg = await readTeamConfig(teamName, cwd);
784
1183
  if (!cfg)
785
1184
  throw new Error(`Team ${teamName} not found`);
1185
+ const phase = await readTeamPhase(teamName, cwd);
1186
+ if (phase?.terminal_epoch || (phase && isTerminalPhase(phase.current_phase))) {
1187
+ throw new Error(teamContinuationRequiredDiagnostic(phase));
1188
+ }
786
1189
  let nextNumeric = normalizeNextTaskId(cfg.next_task_id);
787
1190
  const nextNumericFromDisk = await computeNextTaskIdFromDisk(teamName, cwd);
788
1191
  if (!hasValidNextTaskId(cfg.next_task_id) || nextNumericFromDisk > nextNumeric) {
@@ -808,7 +1211,7 @@ export async function createTask(teamName, task, cwd) {
808
1211
  });
809
1212
  }
810
1213
  // Read a task (returns null on missing/malformed)
811
- export async function readTask(teamName, taskId, cwd) {
1214
+ async function readTaskRaw(teamName, taskId, cwd) {
812
1215
  try {
813
1216
  const p = taskFilePath(teamName, taskId, cwd);
814
1217
  if (!existsSync(p))
@@ -821,98 +1224,121 @@ export async function readTask(teamName, taskId, cwd) {
821
1224
  return null;
822
1225
  }
823
1226
  }
1227
+ export async function readTask(teamName, taskId, cwd) {
1228
+ return await withTeamTaskBarrier(teamName, cwd, async () => {
1229
+ await recoverTeamMembershipTaskTransaction(teamName, cwd);
1230
+ return await readTaskRaw(teamName, taskId, cwd);
1231
+ });
1232
+ }
824
1233
  // Update a task (merge updates, atomic write)
825
1234
  export async function updateTask(teamName, taskId, updates, cwd) {
826
- const lock = await withTaskClaimLock(teamName, taskId, cwd, async () => {
827
- const existing = await readTask(teamName, taskId, cwd);
828
- if (!existing)
829
- return null;
830
- if (updates.status !== undefined && !['pending', 'blocked', 'in_progress', 'completed', 'failed'].includes(updates.status)) {
831
- throw new Error(`Invalid task status: ${updates.status}`);
832
- }
833
- const rawDeps = updates.depends_on ?? updates.blocked_by ?? existing.depends_on ?? existing.blocked_by ?? [];
834
- const normalizedDeps = Array.isArray(rawDeps) ? rawDeps : [];
835
- const merged = normalizeTask({
836
- ...normalizeTask(existing),
837
- ...updates,
838
- id: existing.id,
839
- created_at: existing.created_at,
840
- depends_on: normalizedDeps,
841
- version: Math.max(1, existing.version ?? 1) + 1,
1235
+ return await withTeamTaskBarrier(teamName, cwd, async () => {
1236
+ await recoverTeamMembershipTaskTransaction(teamName, cwd);
1237
+ const lock = await withTaskClaimLock(teamName, taskId, cwd, async () => {
1238
+ const existing = await readTaskRaw(teamName, taskId, cwd);
1239
+ if (!existing)
1240
+ return null;
1241
+ if (updates.status !== undefined && !['pending', 'blocked', 'in_progress', 'completed', 'failed'].includes(updates.status)) {
1242
+ throw new Error(`Invalid task status: ${updates.status}`);
1243
+ }
1244
+ const rawDeps = updates.depends_on ?? updates.blocked_by ?? existing.depends_on ?? existing.blocked_by ?? [];
1245
+ const normalizedDeps = Array.isArray(rawDeps) ? rawDeps : [];
1246
+ const merged = normalizeTask({
1247
+ ...normalizeTask(existing),
1248
+ ...updates,
1249
+ id: existing.id,
1250
+ created_at: existing.created_at,
1251
+ depends_on: normalizedDeps,
1252
+ version: Math.max(1, existing.version ?? 1) + 1,
1253
+ });
1254
+ await writeAtomic(taskFilePath(teamName, taskId, cwd), JSON.stringify(merged, null, 2));
1255
+ return merged;
842
1256
  });
843
- await writeAtomic(taskFilePath(teamName, taskId, cwd), JSON.stringify(merged, null, 2));
844
- return merged;
1257
+ if (!lock.ok)
1258
+ throw new Error(`Timed out acquiring task claim lock for ${teamName}/${taskId}`);
1259
+ return lock.value;
845
1260
  });
846
- if (!lock.ok) {
847
- throw new Error(`Timed out acquiring task claim lock for ${teamName}/${taskId}`);
848
- }
849
- return lock.value;
850
1261
  }
851
1262
  // List all tasks sorted by numeric ID
852
1263
  export async function listTasks(teamName, cwd) {
853
- return await listTasksImpl(teamName, cwd, {
854
- teamDir,
855
- isTeamTask,
856
- normalizeTask,
1264
+ return await withTeamTaskBarrier(teamName, cwd, async () => {
1265
+ await recoverTeamMembershipTaskTransaction(teamName, cwd);
1266
+ return await listTasksImpl(teamName, cwd, {
1267
+ teamDir,
1268
+ isTeamTask,
1269
+ normalizeTask,
1270
+ });
857
1271
  });
858
1272
  }
859
1273
  export async function computeTaskReadiness(teamName, taskId, cwd) {
860
1274
  return await computeTaskReadinessImpl(teamName, taskId, cwd, { readTask });
861
1275
  }
862
1276
  export async function claimTask(teamName, taskId, workerName, expectedVersion, cwd) {
863
- return await claimTaskImpl(taskId, workerName, expectedVersion, {
864
- teamName,
865
- cwd,
866
- readTask,
867
- readTeamConfig,
868
- withTaskClaimLock,
869
- normalizeTask,
870
- isTerminalTaskStatus,
871
- taskFilePath,
872
- writeAtomic,
1277
+ return await withTeamTaskBarrier(teamName, cwd, async () => {
1278
+ await recoverTeamMembershipTaskTransaction(teamName, cwd);
1279
+ return await claimTaskImpl(taskId, workerName, expectedVersion, {
1280
+ teamName,
1281
+ cwd,
1282
+ readTask,
1283
+ readTeamConfig,
1284
+ withTaskClaimLock,
1285
+ normalizeTask,
1286
+ isTerminalTaskStatus,
1287
+ taskFilePath,
1288
+ writeAtomic,
1289
+ });
873
1290
  });
874
1291
  }
875
1292
  export async function transitionTaskStatus(teamName, taskId, from, to, claimToken, cwd, terminalData) {
876
- return await transitionTaskStatusImpl(taskId, from, to, claimToken, terminalData, {
877
- teamName,
878
- cwd,
879
- readTask,
880
- readTeamConfig,
881
- withTaskClaimLock,
882
- normalizeTask,
883
- isTerminalTaskStatus,
884
- canTransitionTaskStatus,
885
- taskFilePath,
886
- writeAtomic,
887
- appendTeamEvent,
888
- readMonitorSnapshot,
889
- writeMonitorSnapshot,
1293
+ return await withTeamTaskBarrier(teamName, cwd, async () => {
1294
+ await recoverTeamMembershipTaskTransaction(teamName, cwd);
1295
+ return await transitionTaskStatusImpl(taskId, from, to, claimToken, terminalData, {
1296
+ teamName,
1297
+ cwd,
1298
+ readTask,
1299
+ readTeamConfig,
1300
+ withTaskClaimLock,
1301
+ normalizeTask,
1302
+ isTerminalTaskStatus,
1303
+ canTransitionTaskStatus,
1304
+ taskFilePath,
1305
+ writeAtomic,
1306
+ appendTeamEvent,
1307
+ readMonitorSnapshot,
1308
+ writeMonitorSnapshot,
1309
+ });
890
1310
  });
891
1311
  }
892
1312
  export async function releaseTaskClaim(teamName, taskId, claimToken, workerName, cwd) {
893
- return await releaseTaskClaimImpl(taskId, claimToken, workerName, {
894
- teamName,
895
- cwd,
896
- readTask,
897
- readTeamConfig,
898
- withTaskClaimLock,
899
- normalizeTask,
900
- isTerminalTaskStatus,
901
- taskFilePath,
902
- writeAtomic,
1313
+ return await withTeamTaskBarrier(teamName, cwd, async () => {
1314
+ await recoverTeamMembershipTaskTransaction(teamName, cwd);
1315
+ return await releaseTaskClaimImpl(taskId, claimToken, workerName, {
1316
+ teamName,
1317
+ cwd,
1318
+ readTask,
1319
+ readTeamConfig,
1320
+ withTaskClaimLock,
1321
+ normalizeTask,
1322
+ isTerminalTaskStatus,
1323
+ taskFilePath,
1324
+ writeAtomic,
1325
+ });
903
1326
  });
904
1327
  }
905
1328
  export async function reclaimExpiredTaskClaim(teamName, taskId, cwd) {
906
- return await reclaimExpiredTaskClaimImpl(taskId, {
907
- teamName,
908
- cwd,
909
- readTask,
910
- readTeamConfig,
911
- withTaskClaimLock,
912
- normalizeTask,
913
- isTerminalTaskStatus,
914
- taskFilePath,
915
- writeAtomic,
1329
+ return await withTeamTaskBarrier(teamName, cwd, async () => {
1330
+ await recoverTeamMembershipTaskTransaction(teamName, cwd);
1331
+ return await reclaimExpiredTaskClaimImpl(taskId, {
1332
+ teamName,
1333
+ cwd,
1334
+ readTask,
1335
+ readTeamConfig,
1336
+ withTaskClaimLock,
1337
+ normalizeTask,
1338
+ isTerminalTaskStatus,
1339
+ taskFilePath,
1340
+ writeAtomic,
1341
+ });
916
1342
  });
917
1343
  }
918
1344
  export async function appendTeamEvent(teamName, event, cwd) {
@@ -1012,6 +1438,48 @@ async function readDispatchRequests(teamName, cwd) {
1012
1438
  return [];
1013
1439
  }
1014
1440
  }
1441
+ /** Read only strictly recognized target-team legacy request records for rollback scoping. */
1442
+ function isStrictLegacyDispatchRequestForRollback(value, teamName) {
1443
+ if (!value || typeof value !== 'object' || Array.isArray(value))
1444
+ return false;
1445
+ const request = value;
1446
+ const requiredFields = [
1447
+ 'request_id', 'kind', 'team_name', 'to_worker', 'trigger_message',
1448
+ 'transport_preference', 'fallback_allowed', 'status', 'attempt_count',
1449
+ 'created_at', 'updated_at',
1450
+ ];
1451
+ if (requiredFields.some((field) => !Object.prototype.hasOwnProperty.call(request, field)))
1452
+ return false;
1453
+ return typeof request.request_id === 'string'
1454
+ && request.request_id.length > 0
1455
+ && ['inbox', 'mailbox', 'nudge'].includes(String(request.kind))
1456
+ && request.team_name === teamName
1457
+ && typeof request.to_worker === 'string'
1458
+ && request.to_worker.length > 0
1459
+ && typeof request.trigger_message === 'string'
1460
+ && ['hook_preferred_with_fallback', 'transport_direct', 'prompt_stdin'].includes(String(request.transport_preference))
1461
+ && typeof request.fallback_allowed === 'boolean'
1462
+ && ['pending', 'notified', 'delivered', 'failed'].includes(String(request.status))
1463
+ && typeof request.attempt_count === 'number'
1464
+ && Number.isFinite(request.attempt_count)
1465
+ && typeof request.created_at === 'string'
1466
+ && typeof request.updated_at === 'string';
1467
+ }
1468
+ async function readLegacyDispatchRequestsForRollback(teamName, cwd) {
1469
+ const path = dispatchRequestsPath(teamName, cwd);
1470
+ try {
1471
+ const raw = JSON.parse(await readFile(path, 'utf8'));
1472
+ if (!Array.isArray(raw) || raw.some((entry) => !isStrictLegacyDispatchRequestForRollback(entry, teamName))) {
1473
+ throw new Error('legacy dispatch rollback evidence is malformed or unrecognized');
1474
+ }
1475
+ return raw;
1476
+ }
1477
+ catch (error) {
1478
+ if (error.code === 'ENOENT')
1479
+ return [];
1480
+ throw error;
1481
+ }
1482
+ }
1015
1483
  async function writeDispatchRequests(teamName, requests, cwd) {
1016
1484
  await writeAtomic(dispatchRequestsPath(teamName, cwd), JSON.stringify(requests, null, 2));
1017
1485
  await writeBridgeDispatchCompat(teamName, requests, cwd);
@@ -1065,6 +1533,61 @@ export function resolveDispatchLockTimeoutMs(env = process.env) {
1065
1533
  async function withDispatchLock(teamName, cwd, fn) {
1066
1534
  return await withDispatchLockImpl(teamName, cwd, teamDir, dispatchLockDir, fn);
1067
1535
  }
1536
+ /** Remove worker-targeted dispatch requests under the authoritative dispatch lock. */
1537
+ export async function removeDispatchRequestsForWorkers(teamName, workerNames, cwd) {
1538
+ const names = new Set(workerNames);
1539
+ await withDispatchLock(teamName, cwd, async () => {
1540
+ // Do not derive rollback IDs from bridge-normalized root records: unscoped
1541
+ // and other-team records can share a target worker name. This team's legacy
1542
+ // file is the canonical rollback scope.
1543
+ const requests = await readLegacyDispatchRequestsForRollback(teamName, cwd);
1544
+ const legacyRequestIds = requests
1545
+ .filter((request) => names.has(request.to_worker))
1546
+ .map((request) => request.request_id);
1547
+ let removedRequestIds = legacyRequestIds;
1548
+ if (isBridgeEnabled()) {
1549
+ const stateDir = resolveBridgeStateDir(cwd);
1550
+ const bridge = getDefaultBridge(stateDir);
1551
+ const snapshot = bridge.execCommand({ command: 'CaptureSnapshot' });
1552
+ if (snapshot.event !== 'SnapshotCaptured') {
1553
+ throw new Error(`authoritative_dispatch_rollback_discovery_failed:${[...names].join(',')}`);
1554
+ }
1555
+ const scopedAuthoritativeIds = bridge.readDispatchRecordsStrict()
1556
+ .filter((record) => {
1557
+ const metadataTeam = typeof record.metadata?.team_name === 'string' ? record.metadata.team_name : '';
1558
+ return metadataTeam === teamName && names.has(record.target);
1559
+ })
1560
+ .map((record) => record.request_id);
1561
+ removedRequestIds = [...new Set([...legacyRequestIds, ...scopedAuthoritativeIds])];
1562
+ if (removedRequestIds.length === 0) {
1563
+ await writeAtomic(dispatchRequestsPath(teamName, cwd), JSON.stringify(requests, null, 2));
1564
+ return;
1565
+ }
1566
+ const removal = bridge.removeDispatchRecords(removedRequestIds);
1567
+ if (removal.event !== 'DispatchRecordsRemoved'
1568
+ || removedRequestIds.some((requestId) => !removal.request_ids.includes(requestId))) {
1569
+ throw new Error(`authoritative_dispatch_rollback_command_failed:${[...names].join(',')}`);
1570
+ }
1571
+ // Force a separate runtime command after mutation. The removal event is
1572
+ // the authoritative acknowledgement; TS must not inspect or rewrite the
1573
+ // shared root dispatch.json as a substitute for runtime verification.
1574
+ const verificationSnapshot = bridge.execCommand({ command: 'CaptureSnapshot' });
1575
+ if (verificationSnapshot.event !== 'SnapshotCaptured') {
1576
+ throw new Error(`authoritative_dispatch_rollback_verification_failed:${[...names].join(',')}`);
1577
+ }
1578
+ const remainingRemovedRecord = bridge.readDispatchRecordsStrict()
1579
+ .some((record) => removedRequestIds.includes(record.request_id));
1580
+ if (remainingRemovedRecord) {
1581
+ throw new Error(`authoritative_dispatch_rollback_verification_failed:${[...names].join(',')}`);
1582
+ }
1583
+ }
1584
+ // The legacy per-team request file is compatibility output only. Update it
1585
+ // only after the authoritative runtime confirms removal; never regenerate
1586
+ // the shared bridge dispatch.json from a local snapshot during rollback.
1587
+ const retained = requests.filter((request) => !names.has(request.to_worker));
1588
+ await writeAtomic(dispatchRequestsPath(teamName, cwd), JSON.stringify(retained, null, 2));
1589
+ });
1590
+ }
1068
1591
  export async function enqueueDispatchRequest(teamName, requestInput, cwd) {
1069
1592
  return await enqueueDispatchRequestImpl(requestInput, {
1070
1593
  teamName,
@@ -1429,10 +1952,30 @@ export async function markOwnedTeamsLeaderStopObserved(cwd, leaderSessionId, now
1429
1952
  }
1430
1953
  // === Config persistence (public wrapper) ===
1431
1954
  export async function saveTeamConfig(config, cwd) {
1432
- await writeConfig(config, cwd);
1955
+ await withTeamTaskBarrier(config.name, cwd, async () => {
1956
+ // The caller's config is a full canonical replacement; recover any
1957
+ // interrupted membership generation while holding the same barrier before
1958
+ // deriving and writing its manifest companion.
1959
+ await recoverTeamMembershipTaskTransaction(config.name, cwd);
1960
+ const currentGeneration = await readConfigGenerationRaw(config.name, cwd);
1961
+ if (currentGeneration === null)
1962
+ throw new Error(`team_config_missing:${config.name}`);
1963
+ const expectedGeneration = normalizeTeamConfig(config).config_generation;
1964
+ if (expectedGeneration !== currentGeneration) {
1965
+ throw new Error(`team_config_stale_generation:${config.name}:${expectedGeneration}:${currentGeneration}`);
1966
+ }
1967
+ config.config_generation = currentGeneration + 1;
1968
+ await writeConfig(config, cwd);
1969
+ });
1433
1970
  }
1434
- // Delete team state directory
1971
+ // Delete team state only after excluding both scaling and membership mutations.
1972
+ // The scaling lock lives outside the deletable team root, so waiters cannot
1973
+ // recreate a deleted team merely by acquiring their lock.
1435
1974
  export async function cleanupTeamState(teamName, cwd) {
1436
- await rm(teamDir(teamName, cwd), { recursive: true, force: true });
1975
+ await withScalingLock(teamName, cwd, async () => {
1976
+ await withTeamTaskBarrier(teamName, cwd, async () => {
1977
+ await rm(teamDir(teamName, cwd), { recursive: true, force: true });
1978
+ });
1979
+ });
1437
1980
  }
1438
1981
  //# sourceMappingURL=state.js.map