oh-my-codex 0.20.1 → 0.20.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (791) hide show
  1. package/Cargo.lock +7 -6
  2. package/Cargo.toml +1 -1
  3. package/README.md +36 -1
  4. package/crates/omx-runtime/Cargo.toml +1 -0
  5. package/crates/omx-runtime/src/main.rs +25 -2
  6. package/crates/omx-runtime/tests/execution.rs +219 -0
  7. package/crates/omx-runtime-core/src/dispatch.rs +96 -10
  8. package/crates/omx-runtime-core/src/engine.rs +839 -29
  9. package/crates/omx-runtime-core/src/lib.rs +8 -0
  10. package/dist/adapt/__tests__/hermes.test.js.map +1 -1
  11. package/dist/adapt/contracts.d.ts.map +1 -1
  12. package/dist/agents/__tests__/definitions.test.js +81 -0
  13. package/dist/agents/__tests__/definitions.test.js.map +1 -1
  14. package/dist/agents/__tests__/native-config.test.js +25 -0
  15. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  16. package/dist/agents/native-config.d.ts +2 -1
  17. package/dist/agents/native-config.d.ts.map +1 -1
  18. package/dist/agents/native-config.js.map +1 -1
  19. package/dist/auth/__tests__/hotswap.test.d.ts +2 -0
  20. package/dist/auth/__tests__/hotswap.test.d.ts.map +1 -0
  21. package/dist/auth/__tests__/hotswap.test.js +183 -0
  22. package/dist/auth/__tests__/hotswap.test.js.map +1 -0
  23. package/dist/auth/hotswap.d.ts +6 -0
  24. package/dist/auth/hotswap.d.ts.map +1 -1
  25. package/dist/auth/hotswap.js +102 -19
  26. package/dist/auth/hotswap.js.map +1 -1
  27. package/dist/auth/paths.js.map +1 -1
  28. package/dist/auth/storage.js.map +1 -1
  29. package/dist/autopilot/__tests__/ralplan-gate.test.js +5 -5
  30. package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -1
  31. package/dist/autopilot/completion-gate.js.map +1 -1
  32. package/dist/autopilot/fsm.d.ts +1 -1
  33. package/dist/autopilot/fsm.d.ts.map +1 -1
  34. package/dist/autoresearch/goal.js.map +1 -1
  35. package/dist/autoresearch/runtime.js.map +1 -1
  36. package/dist/capabilities/lockfile.js.map +1 -1
  37. package/dist/catalog/reader.js.map +1 -1
  38. package/dist/catalog/skill-mirror.js.map +1 -1
  39. package/dist/cli/__tests__/adapt-help.test.js.map +1 -1
  40. package/dist/cli/__tests__/agents-init.test.js.map +1 -1
  41. package/dist/cli/__tests__/agents.test.js.map +1 -1
  42. package/dist/cli/__tests__/api.test.js.map +1 -1
  43. package/dist/cli/__tests__/ask.test.js.map +1 -1
  44. package/dist/cli/__tests__/auth.test.js +60 -6
  45. package/dist/cli/__tests__/auth.test.js.map +1 -1
  46. package/dist/cli/__tests__/autoresearch-guided.test.js.map +1 -1
  47. package/dist/cli/__tests__/autoresearch.test.js.map +1 -1
  48. package/dist/cli/__tests__/capabilities.test.js.map +1 -1
  49. package/dist/cli/__tests__/codex-plugin-layout.test.js +80 -0
  50. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  51. package/dist/cli/__tests__/doctor-context-window-warning.test.js.map +1 -1
  52. package/dist/cli/__tests__/doctor-invalid-config.test.js +47 -4
  53. package/dist/cli/__tests__/doctor-invalid-config.test.js.map +1 -1
  54. package/dist/cli/__tests__/doctor-team.test.js.map +1 -1
  55. package/dist/cli/__tests__/doctor-warning-copy.test.js +752 -15
  56. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  57. package/dist/cli/__tests__/exec.test.js +136 -0
  58. package/dist/cli/__tests__/exec.test.js.map +1 -1
  59. package/dist/cli/__tests__/imagegen-continuation.test.js.map +1 -1
  60. package/dist/cli/__tests__/index.test.js +473 -14
  61. package/dist/cli/__tests__/index.test.js.map +1 -1
  62. package/dist/cli/__tests__/launch-fallback.test.js +336 -4
  63. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  64. package/dist/cli/__tests__/mcp-parity.test.js +87 -12
  65. package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
  66. package/dist/cli/__tests__/native-hook-claim-journal.test.d.ts +2 -0
  67. package/dist/cli/__tests__/native-hook-claim-journal.test.d.ts.map +1 -0
  68. package/dist/cli/__tests__/native-hook-claim-journal.test.js +206 -0
  69. package/dist/cli/__tests__/native-hook-claim-journal.test.js.map +1 -0
  70. package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
  71. package/dist/cli/__tests__/question.test.js.map +1 -1
  72. package/dist/cli/__tests__/ralph-deslop-contract.test.js.map +1 -1
  73. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +6 -0
  74. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
  75. package/dist/cli/__tests__/ralph-prd-deep-interview.test.js.map +1 -1
  76. package/dist/cli/__tests__/ralph-prd-smoke.test.js.map +1 -1
  77. package/dist/cli/__tests__/ralph.test.js +8 -3
  78. package/dist/cli/__tests__/ralph.test.js.map +1 -1
  79. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.d.ts +2 -0
  80. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.d.ts.map +1 -0
  81. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js +72 -0
  82. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js.map +1 -0
  83. package/dist/cli/__tests__/ralplan.test.d.ts +2 -0
  84. package/dist/cli/__tests__/ralplan.test.d.ts.map +1 -0
  85. package/dist/cli/__tests__/ralplan.test.js +55 -0
  86. package/dist/cli/__tests__/ralplan.test.js.map +1 -0
  87. package/dist/cli/__tests__/resume.test.js +17 -11
  88. package/dist/cli/__tests__/resume.test.js.map +1 -1
  89. package/dist/cli/__tests__/session-scoped-runtime.test.js +25 -0
  90. package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -1
  91. package/dist/cli/__tests__/session-search-help.test.js +25 -1
  92. package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
  93. package/dist/cli/__tests__/session-search.test.js.map +1 -1
  94. package/dist/cli/__tests__/setup-agents-overwrite.test.js +79 -0
  95. package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
  96. package/dist/cli/__tests__/setup-gh-star.test.js.map +1 -1
  97. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +77 -3
  98. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
  99. package/dist/cli/__tests__/setup-hooks-trust-e2e.test.d.ts +2 -0
  100. package/dist/cli/__tests__/setup-hooks-trust-e2e.test.d.ts.map +1 -0
  101. package/dist/cli/__tests__/setup-hooks-trust-e2e.test.js +285 -0
  102. package/dist/cli/__tests__/setup-hooks-trust-e2e.test.js.map +1 -0
  103. package/dist/cli/__tests__/setup-install-mode.test.js +2579 -294
  104. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  105. package/dist/cli/__tests__/setup-preferences.test.d.ts +2 -0
  106. package/dist/cli/__tests__/setup-preferences.test.d.ts.map +1 -0
  107. package/dist/cli/__tests__/setup-preferences.test.js +79 -0
  108. package/dist/cli/__tests__/setup-preferences.test.js.map +1 -0
  109. package/dist/cli/__tests__/setup-refresh.test.js +33 -2
  110. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  111. package/dist/cli/__tests__/setup-scope.test.js +46 -3
  112. package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
  113. package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -1
  114. package/dist/cli/__tests__/state.test.js +37 -0
  115. package/dist/cli/__tests__/state.test.js.map +1 -1
  116. package/dist/cli/__tests__/team.test.js +105 -7
  117. package/dist/cli/__tests__/team.test.js.map +1 -1
  118. package/dist/cli/__tests__/ultragoal.test.js +61 -1
  119. package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
  120. package/dist/cli/__tests__/uninstall.test.js +1817 -24
  121. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  122. package/dist/cli/__tests__/update.test.js +58 -0
  123. package/dist/cli/__tests__/update.test.js.map +1 -1
  124. package/dist/cli/__tests__/url.test.js.map +1 -1
  125. package/dist/cli/__tests__/windows-popup-loop-contract.test.js +2 -1
  126. package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
  127. package/dist/cli/adapt.js.map +1 -1
  128. package/dist/cli/agents-init.js.map +1 -1
  129. package/dist/cli/agents.js.map +1 -1
  130. package/dist/cli/api.js.map +1 -1
  131. package/dist/cli/ask.d.ts +1 -1
  132. package/dist/cli/ask.d.ts.map +1 -1
  133. package/dist/cli/ask.js.map +1 -1
  134. package/dist/cli/auth.js.map +1 -1
  135. package/dist/cli/autoresearch-guided.js.map +1 -1
  136. package/dist/cli/autoresearch-intake.js.map +1 -1
  137. package/dist/cli/capabilities.js.map +1 -1
  138. package/dist/cli/cleanup.js.map +1 -1
  139. package/dist/cli/codex-feature-probe.js.map +1 -1
  140. package/dist/cli/codex-home.js.map +1 -1
  141. package/dist/cli/doctor.d.ts +21 -0
  142. package/dist/cli/doctor.d.ts.map +1 -1
  143. package/dist/cli/doctor.js +607 -130
  144. package/dist/cli/doctor.js.map +1 -1
  145. package/dist/cli/explore.js.map +1 -1
  146. package/dist/cli/index.d.ts +14 -3
  147. package/dist/cli/index.d.ts.map +1 -1
  148. package/dist/cli/index.js +245 -57
  149. package/dist/cli/index.js.map +1 -1
  150. package/dist/cli/mcp-parity.js +2 -2
  151. package/dist/cli/mcp-parity.js.map +1 -1
  152. package/dist/cli/mcp-serve.js.map +1 -1
  153. package/dist/cli/mission.js.map +1 -1
  154. package/dist/cli/native-assets.js.map +1 -1
  155. package/dist/cli/native-hook-claim-journal.d.ts +29 -0
  156. package/dist/cli/native-hook-claim-journal.d.ts.map +1 -0
  157. package/dist/cli/native-hook-claim-journal.js +252 -0
  158. package/dist/cli/native-hook-claim-journal.js.map +1 -0
  159. package/dist/cli/omx.js.map +1 -1
  160. package/dist/cli/plugin-marketplace.js.map +1 -1
  161. package/dist/cli/project-runtime-codex-homes.js.map +1 -1
  162. package/dist/cli/question.js.map +1 -1
  163. package/dist/cli/ralph.d.ts.map +1 -1
  164. package/dist/cli/ralph.js +3 -2
  165. package/dist/cli/ralph.js.map +1 -1
  166. package/dist/cli/ralplan.d.ts +10 -0
  167. package/dist/cli/ralplan.d.ts.map +1 -0
  168. package/dist/cli/ralplan.js +110 -0
  169. package/dist/cli/ralplan.js.map +1 -0
  170. package/dist/cli/session-search.d.ts +5 -0
  171. package/dist/cli/session-search.d.ts.map +1 -1
  172. package/dist/cli/session-search.js +87 -0
  173. package/dist/cli/session-search.js.map +1 -1
  174. package/dist/cli/setup-preferences.d.ts +11 -0
  175. package/dist/cli/setup-preferences.d.ts.map +1 -1
  176. package/dist/cli/setup-preferences.js +32 -0
  177. package/dist/cli/setup-preferences.js.map +1 -1
  178. package/dist/cli/setup.d.ts +58 -0
  179. package/dist/cli/setup.d.ts.map +1 -1
  180. package/dist/cli/setup.js +1450 -398
  181. package/dist/cli/setup.js.map +1 -1
  182. package/dist/cli/sparkshell.js.map +1 -1
  183. package/dist/cli/star-prompt.js.map +1 -1
  184. package/dist/cli/state.d.ts.map +1 -1
  185. package/dist/cli/state.js +2 -1
  186. package/dist/cli/state.js.map +1 -1
  187. package/dist/cli/team.js.map +1 -1
  188. package/dist/cli/ultragoal.d.ts +5 -1
  189. package/dist/cli/ultragoal.d.ts.map +1 -1
  190. package/dist/cli/ultragoal.js +34 -2
  191. package/dist/cli/ultragoal.js.map +1 -1
  192. package/dist/cli/uninstall.d.ts +17 -0
  193. package/dist/cli/uninstall.d.ts.map +1 -1
  194. package/dist/cli/uninstall.js +986 -95
  195. package/dist/cli/uninstall.js.map +1 -1
  196. package/dist/cli/update.d.ts.map +1 -1
  197. package/dist/cli/update.js +8 -1
  198. package/dist/cli/update.js.map +1 -1
  199. package/dist/cli/url.js.map +1 -1
  200. package/dist/compat/__tests__/doctor-contract.test.js +5 -1
  201. package/dist/compat/__tests__/doctor-contract.test.js.map +1 -1
  202. package/dist/compat/__tests__/rust-runtime-compat.test.js +1 -1
  203. package/dist/compat/__tests__/rust-runtime-compat.test.js.map +1 -1
  204. package/dist/config/__tests__/codex-hooks.test.js +1287 -11
  205. package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
  206. package/dist/config/__tests__/generator-idempotent.test.js +1179 -32
  207. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  208. package/dist/config/__tests__/generator-notify.test.js +6 -1
  209. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  210. package/dist/config/__tests__/models.test.js +67 -3
  211. package/dist/config/__tests__/models.test.js.map +1 -1
  212. package/dist/config/codex-feature-flags.d.ts.map +1 -1
  213. package/dist/config/codex-feature-flags.js.map +1 -1
  214. package/dist/config/codex-hooks.d.ts +124 -1
  215. package/dist/config/codex-hooks.d.ts.map +1 -1
  216. package/dist/config/codex-hooks.js +2142 -265
  217. package/dist/config/codex-hooks.js.map +1 -1
  218. package/dist/config/commit-lore-guard.js.map +1 -1
  219. package/dist/config/generator.d.ts +23 -34
  220. package/dist/config/generator.d.ts.map +1 -1
  221. package/dist/config/generator.js +1480 -246
  222. package/dist/config/generator.js.map +1 -1
  223. package/dist/config/mcp-registry.js.map +1 -1
  224. package/dist/config/models.d.ts +14 -4
  225. package/dist/config/models.d.ts.map +1 -1
  226. package/dist/config/models.js +15 -1
  227. package/dist/config/models.js.map +1 -1
  228. package/dist/config/omx-first-party-mcp.js.map +1 -1
  229. package/dist/config/team-mode.d.ts.map +1 -1
  230. package/dist/document-refresh/__tests__/enforcer.test.js.map +1 -1
  231. package/dist/document-refresh/enforcer.js.map +1 -1
  232. package/dist/exec/followup.js.map +1 -1
  233. package/dist/goal-workflows/artifacts.js.map +1 -1
  234. package/dist/hooks/__tests__/agents-overlay.test.js +7 -4
  235. package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
  236. package/dist/hooks/__tests__/analyze-routing-contract.test.js.map +1 -1
  237. package/dist/hooks/__tests__/analyze-skill-contract.test.js.map +1 -1
  238. package/dist/hooks/__tests__/anti-slop-workflow.test.js.map +1 -1
  239. package/dist/hooks/__tests__/autopilot-skill-contract.test.js +9 -3
  240. package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
  241. package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +1 -1
  242. package/dist/hooks/__tests__/consensus-execution-handoff.test.js.map +1 -1
  243. package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
  244. package/dist/hooks/__tests__/design-skill.test.js.map +1 -1
  245. package/dist/hooks/__tests__/keyword-detector.test.js +1376 -6
  246. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  247. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +252 -543
  248. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  249. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +38 -4
  250. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  251. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +765 -10
  252. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  253. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +2 -0
  254. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
  255. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +142 -1
  256. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
  257. package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -1
  258. package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js +48 -2
  259. package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js.map +1 -1
  260. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +61 -44
  261. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -1
  262. package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
  263. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js +3 -2
  264. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js.map +1 -1
  265. package/dist/hooks/__tests__/notify-hook-session-scope.test.js +243 -4
  266. package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
  267. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +531 -12
  268. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  269. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +163 -24
  270. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  271. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +482 -32
  272. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  273. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +68 -1
  274. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  275. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +7 -1
  276. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -1
  277. package/dist/hooks/__tests__/notify-hook-visual-verdict.test.js.map +1 -1
  278. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +43 -4
  279. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  280. package/dist/hooks/__tests__/openclaw-setup-contract.test.js.map +1 -1
  281. package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -1
  282. package/dist/hooks/__tests__/prometheus-strict-contract.test.js.map +1 -1
  283. package/dist/hooks/__tests__/prompt-guidance-fragments.test.js.map +1 -1
  284. package/dist/hooks/__tests__/prompt-guidance-test-helpers.js.map +1 -1
  285. package/dist/hooks/__tests__/prompt-session-provenance.test.d.ts +2 -0
  286. package/dist/hooks/__tests__/prompt-session-provenance.test.d.ts.map +1 -0
  287. package/dist/hooks/__tests__/prompt-session-provenance.test.js +82 -0
  288. package/dist/hooks/__tests__/prompt-session-provenance.test.js.map +1 -0
  289. package/dist/hooks/__tests__/session.test.js +878 -11
  290. package/dist/hooks/__tests__/session.test.js.map +1 -1
  291. package/dist/hooks/__tests__/skill-catalog-hygiene.test.js.map +1 -1
  292. package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js.map +1 -1
  293. package/dist/hooks/__tests__/visual-ralph-skill.test.js.map +1 -1
  294. package/dist/hooks/__tests__/visual-verdict-loop.test.js.map +1 -1
  295. package/dist/hooks/agents-overlay.js +5 -5
  296. package/dist/hooks/agents-overlay.js.map +1 -1
  297. package/dist/hooks/code-simplifier/index.js.map +1 -1
  298. package/dist/hooks/explore-routing.js.map +1 -1
  299. package/dist/hooks/extensibility/dispatcher.js.map +1 -1
  300. package/dist/hooks/extensibility/events.js.map +1 -1
  301. package/dist/hooks/extensibility/loader.js.map +1 -1
  302. package/dist/hooks/extensibility/plugin-runner-stdin.js.map +1 -1
  303. package/dist/hooks/extensibility/sdk/logging.js.map +1 -1
  304. package/dist/hooks/keyword-detector.d.ts +33 -7
  305. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  306. package/dist/hooks/keyword-detector.js +2228 -119
  307. package/dist/hooks/keyword-detector.js.map +1 -1
  308. package/dist/hooks/keyword-registry.d.ts +12 -0
  309. package/dist/hooks/keyword-registry.d.ts.map +1 -1
  310. package/dist/hooks/keyword-registry.js +41 -0
  311. package/dist/hooks/keyword-registry.js.map +1 -1
  312. package/dist/hooks/prompt-session-provenance.d.ts +87 -0
  313. package/dist/hooks/prompt-session-provenance.d.ts.map +1 -0
  314. package/dist/hooks/prompt-session-provenance.js +180 -0
  315. package/dist/hooks/prompt-session-provenance.js.map +1 -0
  316. package/dist/hooks/session.d.ts +163 -34
  317. package/dist/hooks/session.d.ts.map +1 -1
  318. package/dist/hooks/session.js +1395 -317
  319. package/dist/hooks/session.js.map +1 -1
  320. package/dist/hooks/task-size-detector.js.map +1 -1
  321. package/dist/hud/__tests__/state.test.js.map +1 -1
  322. package/dist/hud/authority.js.map +1 -1
  323. package/dist/hud/constants.js.map +1 -1
  324. package/dist/hud/index.js.map +1 -1
  325. package/dist/hud/reconcile.js.map +1 -1
  326. package/dist/hud/render.js.map +1 -1
  327. package/dist/hud/state.js.map +1 -1
  328. package/dist/hud/tmux.js.map +1 -1
  329. package/dist/leader/__tests__/contract.test.js +153 -1
  330. package/dist/leader/__tests__/contract.test.js.map +1 -1
  331. package/dist/leader/contract.d.ts +42 -5
  332. package/dist/leader/contract.d.ts.map +1 -1
  333. package/dist/leader/contract.js +184 -3
  334. package/dist/leader/contract.js.map +1 -1
  335. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  336. package/dist/mcp/__tests__/code-intel-server.test.js +31 -3
  337. package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -1
  338. package/dist/mcp/__tests__/server-lifecycle.test.js +15 -2
  339. package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
  340. package/dist/mcp/__tests__/state-paths.test.js +98 -1
  341. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  342. package/dist/mcp/__tests__/wiki-server.test.js +18 -0
  343. package/dist/mcp/__tests__/wiki-server.test.js.map +1 -1
  344. package/dist/mcp/bootstrap.js.map +1 -1
  345. package/dist/mcp/code-intel-server.d.ts +58 -58
  346. package/dist/mcp/code-intel-server.d.ts.map +1 -1
  347. package/dist/mcp/code-intel-server.js +13 -3
  348. package/dist/mcp/code-intel-server.js.map +1 -1
  349. package/dist/mcp/hermes-bridge.js.map +1 -1
  350. package/dist/mcp/hermes-server.d.ts +70 -70
  351. package/dist/mcp/hermes-server.d.ts.map +1 -1
  352. package/dist/mcp/lifecycle-telemetry.js.map +1 -1
  353. package/dist/mcp/memory-server.d.ts +34 -34
  354. package/dist/mcp/memory-server.d.ts.map +1 -1
  355. package/dist/mcp/memory-server.js.map +1 -1
  356. package/dist/mcp/state-paths.d.ts +14 -0
  357. package/dist/mcp/state-paths.d.ts.map +1 -1
  358. package/dist/mcp/state-paths.js +96 -20
  359. package/dist/mcp/state-paths.js.map +1 -1
  360. package/dist/mcp/state-server.d.ts +47 -47
  361. package/dist/mcp/state-server.d.ts.map +1 -1
  362. package/dist/mcp/trace-server.d.ts +4 -4
  363. package/dist/mcp/trace-server.d.ts.map +1 -1
  364. package/dist/mcp/trace-server.js.map +1 -1
  365. package/dist/mcp/wiki-server.d.ts +34 -23
  366. package/dist/mcp/wiki-server.d.ts.map +1 -1
  367. package/dist/mcp/wiki-server.js +9 -2
  368. package/dist/mcp/wiki-server.js.map +1 -1
  369. package/dist/modes/__tests__/base-session-scope.test.js +53 -1
  370. package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
  371. package/dist/modes/__tests__/base-tmux-pane.test.js +4 -4
  372. package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
  373. package/dist/modes/base.d.ts.map +1 -1
  374. package/dist/modes/base.js +5 -5
  375. package/dist/modes/base.js.map +1 -1
  376. package/dist/notifications/__tests__/lifecycle-dedupe.test.js.map +1 -1
  377. package/dist/notifications/__tests__/reply-listener.test.js.map +1 -1
  378. package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js +177 -85
  379. package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js.map +1 -1
  380. package/dist/notifications/__tests__/session-registry.test.js.map +1 -1
  381. package/dist/notifications/__tests__/template-engine.test.js.map +1 -1
  382. package/dist/notifications/__tests__/verbosity.test.js.map +1 -1
  383. package/dist/notifications/http-client.js.map +1 -1
  384. package/dist/notifications/index.d.ts +4 -1
  385. package/dist/notifications/index.d.ts.map +1 -1
  386. package/dist/notifications/index.js +3 -9
  387. package/dist/notifications/index.js.map +1 -1
  388. package/dist/notifications/lifecycle-dedupe.js.map +1 -1
  389. package/dist/notifications/reply-listener.d.ts.map +1 -1
  390. package/dist/notifications/reply-listener.js.map +1 -1
  391. package/dist/notifications/session-registry.js.map +1 -1
  392. package/dist/notifications/session-status.js.map +1 -1
  393. package/dist/notifications/temp-contract.d.ts.map +1 -1
  394. package/dist/notifications/temp-contract.js +4 -0
  395. package/dist/notifications/temp-contract.js.map +1 -1
  396. package/dist/notifications/tmux-detector.js.map +1 -1
  397. package/dist/notifications/tmux.js.map +1 -1
  398. package/dist/openclaw/config.js.map +1 -1
  399. package/dist/openclaw/dispatcher.js.map +1 -1
  400. package/dist/pipeline/__tests__/orchestrator.test.js +4 -4
  401. package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
  402. package/dist/pipeline/__tests__/stages.test.js +16 -13
  403. package/dist/pipeline/__tests__/stages.test.js.map +1 -1
  404. package/dist/pipeline/stages/code-review.js.map +1 -1
  405. package/dist/pipeline/stages/ralph-verify.js.map +1 -1
  406. package/dist/pipeline/stages/ralplan.js.map +1 -1
  407. package/dist/pipeline/stages/team-exec.js.map +1 -1
  408. package/dist/pipeline/stages/ultragoal.js.map +1 -1
  409. package/dist/pipeline/stages/ultraqa.js.map +1 -1
  410. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js.map +1 -1
  411. package/dist/planning/artifact-names.js.map +1 -1
  412. package/dist/planning/artifacts.js.map +1 -1
  413. package/dist/question/__tests__/state.test.js.map +1 -1
  414. package/dist/question/__tests__/ui.test.js.map +1 -1
  415. package/dist/question/autopilot-wait.js.map +1 -1
  416. package/dist/question/client.d.ts.map +1 -1
  417. package/dist/question/client.js.map +1 -1
  418. package/dist/question/deep-interview.js.map +1 -1
  419. package/dist/question/events.js.map +1 -1
  420. package/dist/question/renderer.js.map +1 -1
  421. package/dist/question/state.d.ts.map +1 -1
  422. package/dist/question/state.js.map +1 -1
  423. package/dist/question/ui.js.map +1 -1
  424. package/dist/ralph/contract.d.ts +1 -1
  425. package/dist/ralph/contract.d.ts.map +1 -1
  426. package/dist/ralplan/__tests__/consensus-gate.test.js +527 -8
  427. package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
  428. package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts +2 -0
  429. package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts.map +1 -0
  430. package/dist/ralplan/__tests__/documented-leader-preflight.test.js +46 -0
  431. package/dist/ralplan/__tests__/documented-leader-preflight.test.js.map +1 -0
  432. package/dist/ralplan/__tests__/runtime.test.js +116 -14
  433. package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
  434. package/dist/ralplan/consensus-gate.d.ts +3 -3
  435. package/dist/ralplan/consensus-gate.d.ts.map +1 -1
  436. package/dist/ralplan/consensus-gate.js +173 -70
  437. package/dist/ralplan/consensus-gate.js.map +1 -1
  438. package/dist/ralplan/documented-leader-preflight.d.ts +34 -0
  439. package/dist/ralplan/documented-leader-preflight.d.ts.map +1 -0
  440. package/dist/ralplan/documented-leader-preflight.js +58 -0
  441. package/dist/ralplan/documented-leader-preflight.js.map +1 -0
  442. package/dist/ralplan/runtime.d.ts +3 -2
  443. package/dist/ralplan/runtime.d.ts.map +1 -1
  444. package/dist/ralplan/runtime.js +12 -9
  445. package/dist/ralplan/runtime.js.map +1 -1
  446. package/dist/runtime/__tests__/bridge.test.js +42 -1
  447. package/dist/runtime/__tests__/bridge.test.js.map +1 -1
  448. package/dist/runtime/bridge.d.ts +12 -0
  449. package/dist/runtime/bridge.d.ts.map +1 -1
  450. package/dist/runtime/bridge.js +52 -1
  451. package/dist/runtime/bridge.js.map +1 -1
  452. package/dist/runtime/process-tree.js.map +1 -1
  453. package/dist/runtime/run-loop.js.map +1 -1
  454. package/dist/runtime/run-outcome.d.ts +3 -3
  455. package/dist/runtime/run-outcome.d.ts.map +1 -1
  456. package/dist/runtime/run-outcome.js.map +1 -1
  457. package/dist/runtime/run-state.js.map +1 -1
  458. package/dist/scripts/__tests__/codex-native-hook.test.js +6657 -995
  459. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  460. package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.d.ts +2 -0
  461. package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.d.ts.map +1 -0
  462. package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.js +634 -0
  463. package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.js.map +1 -0
  464. package/dist/scripts/__tests__/generate-release-body.test.js.map +1 -1
  465. package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +1 -1
  466. package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -1
  467. package/dist/scripts/__tests__/notify-fallback-delivery.test.d.ts +2 -0
  468. package/dist/scripts/__tests__/notify-fallback-delivery.test.d.ts.map +1 -0
  469. package/dist/scripts/__tests__/notify-fallback-delivery.test.js +174 -0
  470. package/dist/scripts/__tests__/notify-fallback-delivery.test.js.map +1 -0
  471. package/dist/scripts/__tests__/notify-state-io.test.js +57 -1
  472. package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -1
  473. package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts +2 -0
  474. package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts.map +1 -0
  475. package/dist/scripts/__tests__/reasoning-artifact-contract.test.js +108 -0
  476. package/dist/scripts/__tests__/reasoning-artifact-contract.test.js.map +1 -0
  477. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.d.ts +2 -0
  478. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.d.ts.map +1 -0
  479. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js +78 -0
  480. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js.map +1 -0
  481. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.d.ts +2 -0
  482. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.d.ts.map +1 -0
  483. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js +55 -0
  484. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js.map +1 -0
  485. package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
  486. package/dist/scripts/__tests__/smoke-packed-install.test.js +1100 -4
  487. package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
  488. package/dist/scripts/__tests__/test-reply-listener-live.test.js.map +1 -1
  489. package/dist/scripts/build-api.js.map +1 -1
  490. package/dist/scripts/build-explore-harness.js.map +1 -1
  491. package/dist/scripts/build-sparkshell.js.map +1 -1
  492. package/dist/scripts/cleanup-explore-harness.js.map +1 -1
  493. package/dist/scripts/codex-execution-surface.js.map +1 -1
  494. package/dist/scripts/codex-native-hook.d.ts +4 -1
  495. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  496. package/dist/scripts/codex-native-hook.js +11577 -1184
  497. package/dist/scripts/codex-native-hook.js.map +1 -1
  498. package/dist/scripts/generate-native-release-manifest.js.map +1 -1
  499. package/dist/scripts/generate-release-body.js.map +1 -1
  500. package/dist/scripts/hook-payload-guard.d.ts.map +1 -1
  501. package/dist/scripts/hook-payload-guard.js.map +1 -1
  502. package/dist/scripts/notify-fallback-delivery.d.ts +48 -0
  503. package/dist/scripts/notify-fallback-delivery.d.ts.map +1 -0
  504. package/dist/scripts/notify-fallback-delivery.js +419 -0
  505. package/dist/scripts/notify-fallback-delivery.js.map +1 -0
  506. package/dist/scripts/notify-fallback-watcher.js +218 -138
  507. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  508. package/dist/scripts/notify-hook/auto-nudge.d.ts +18 -9
  509. package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
  510. package/dist/scripts/notify-hook/auto-nudge.js +112 -15
  511. package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
  512. package/dist/scripts/notify-hook/managed-tmux.d.ts +23 -0
  513. package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
  514. package/dist/scripts/notify-hook/managed-tmux.js +122 -12
  515. package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
  516. package/dist/scripts/notify-hook/orchestration-intent.d.ts +7 -7
  517. package/dist/scripts/notify-hook/orchestration-intent.d.ts.map +1 -1
  518. package/dist/scripts/notify-hook/ralph-session-resume.d.ts +5 -2
  519. package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
  520. package/dist/scripts/notify-hook/ralph-session-resume.js +33 -37
  521. package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
  522. package/dist/scripts/notify-hook/state-io.d.ts +17 -0
  523. package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
  524. package/dist/scripts/notify-hook/state-io.js +73 -11
  525. package/dist/scripts/notify-hook/state-io.js.map +1 -1
  526. package/dist/scripts/notify-hook/team-dispatch.d.ts +10 -1
  527. package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
  528. package/dist/scripts/notify-hook/team-dispatch.js +234 -79
  529. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  530. package/dist/scripts/notify-hook/team-leader-nudge.d.ts +2 -2
  531. package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
  532. package/dist/scripts/notify-hook/team-leader-nudge.js +39 -13
  533. package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
  534. package/dist/scripts/notify-hook/team-tmux-guard.d.ts +16 -8
  535. package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
  536. package/dist/scripts/notify-hook/team-tmux-guard.js +365 -44
  537. package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
  538. package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -1
  539. package/dist/scripts/notify-hook/team-worker-stop.d.ts +1 -1
  540. package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -1
  541. package/dist/scripts/notify-hook/team-worker-stop.js +19 -18
  542. package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -1
  543. package/dist/scripts/notify-hook/team-worker.d.ts +5 -2
  544. package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
  545. package/dist/scripts/notify-hook/team-worker.js +37 -28
  546. package/dist/scripts/notify-hook/team-worker.js.map +1 -1
  547. package/dist/scripts/notify-hook/tmux-injection.d.ts +8 -1
  548. package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
  549. package/dist/scripts/notify-hook/tmux-injection.js +53 -18
  550. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  551. package/dist/scripts/notify-hook/visual-verdict.d.ts +1 -1
  552. package/dist/scripts/notify-hook/visual-verdict.d.ts.map +1 -1
  553. package/dist/scripts/notify-hook/visual-verdict.js +15 -13
  554. package/dist/scripts/notify-hook/visual-verdict.js.map +1 -1
  555. package/dist/scripts/notify-hook.d.ts +24 -1
  556. package/dist/scripts/notify-hook.d.ts.map +1 -1
  557. package/dist/scripts/notify-hook.js +267 -90
  558. package/dist/scripts/notify-hook.js.map +1 -1
  559. package/dist/scripts/postinstall.js.map +1 -1
  560. package/dist/scripts/prompt-inventory.js.map +1 -1
  561. package/dist/scripts/smoke-packed-install.d.ts +927 -5
  562. package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
  563. package/dist/scripts/smoke-packed-install.js +4317 -13
  564. package/dist/scripts/smoke-packed-install.js.map +1 -1
  565. package/dist/scripts/sync-plugin-mirror.js.map +1 -1
  566. package/dist/scripts/test-reply-listener-live.js.map +1 -1
  567. package/dist/scripts/test-sparkshell.js.map +1 -1
  568. package/dist/scripts/verify-native-agents.js.map +1 -1
  569. package/dist/session-history/friction.js.map +1 -1
  570. package/dist/session-history/search.js.map +1 -1
  571. package/dist/sidecar/__tests__/boundary.test.js.map +1 -1
  572. package/dist/sidecar/collector.js.map +1 -1
  573. package/dist/sidecar/index.js.map +1 -1
  574. package/dist/sidecar/render.js.map +1 -1
  575. package/dist/sidecar/tmux.js.map +1 -1
  576. package/dist/state/__tests__/mode-state-context.test.js +54 -0
  577. package/dist/state/__tests__/mode-state-context.test.js.map +1 -1
  578. package/dist/state/__tests__/operations.test.js +66 -15
  579. package/dist/state/__tests__/operations.test.js.map +1 -1
  580. package/dist/state/__tests__/skill-active.test.js +19 -1
  581. package/dist/state/__tests__/skill-active.test.js.map +1 -1
  582. package/dist/state/__tests__/workflow-transition.test.js +61 -0
  583. package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
  584. package/dist/state/mode-state-context.d.ts +5 -0
  585. package/dist/state/mode-state-context.d.ts.map +1 -1
  586. package/dist/state/mode-state-context.js +59 -0
  587. package/dist/state/mode-state-context.js.map +1 -1
  588. package/dist/state/operations.d.ts +1 -1
  589. package/dist/state/operations.d.ts.map +1 -1
  590. package/dist/state/operations.js +49 -55
  591. package/dist/state/operations.js.map +1 -1
  592. package/dist/state/paths.d.ts +1 -1
  593. package/dist/state/paths.d.ts.map +1 -1
  594. package/dist/state/paths.js +1 -1
  595. package/dist/state/paths.js.map +1 -1
  596. package/dist/state/skill-active.d.ts +13 -1
  597. package/dist/state/skill-active.d.ts.map +1 -1
  598. package/dist/state/skill-active.js +43 -4
  599. package/dist/state/skill-active.js.map +1 -1
  600. package/dist/state/terminal-normalization.js.map +1 -1
  601. package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
  602. package/dist/state/workflow-transition-reconcile.js +20 -4
  603. package/dist/state/workflow-transition-reconcile.js.map +1 -1
  604. package/dist/state/workflow-transition.d.ts +1 -1
  605. package/dist/state/workflow-transition.d.ts.map +1 -1
  606. package/dist/state/workflow-transition.js.map +1 -1
  607. package/dist/subagents/__tests__/leader-bootstrap-3181.test.d.ts +2 -0
  608. package/dist/subagents/__tests__/leader-bootstrap-3181.test.d.ts.map +1 -0
  609. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js +52 -0
  610. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js.map +1 -0
  611. package/dist/subagents/__tests__/tracker.test.js +1550 -10
  612. package/dist/subagents/__tests__/tracker.test.js.map +1 -1
  613. package/dist/subagents/role-routing-marker.d.ts +10 -0
  614. package/dist/subagents/role-routing-marker.d.ts.map +1 -0
  615. package/dist/subagents/role-routing-marker.js +136 -0
  616. package/dist/subagents/role-routing-marker.js.map +1 -0
  617. package/dist/subagents/tracker.d.ts +91 -0
  618. package/dist/subagents/tracker.d.ts.map +1 -1
  619. package/dist/subagents/tracker.js +806 -62
  620. package/dist/subagents/tracker.js.map +1 -1
  621. package/dist/team/__tests__/api-interop.test.js +91 -1
  622. package/dist/team/__tests__/api-interop.test.js.map +1 -1
  623. package/dist/team/__tests__/approved-execution.test.js.map +1 -1
  624. package/dist/team/__tests__/delivery-e2e-smoke.test.js +52 -10
  625. package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
  626. package/dist/team/__tests__/idle-nudge.test.js +45 -15
  627. package/dist/team/__tests__/idle-nudge.test.js.map +1 -1
  628. package/dist/team/__tests__/mcp-comm.test.js +93 -27
  629. package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
  630. package/dist/team/__tests__/model-contract.test.js +341 -4
  631. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  632. package/dist/team/__tests__/role-router.test.js.map +1 -1
  633. package/dist/team/__tests__/runtime-cli.test.js +9 -0
  634. package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
  635. package/dist/team/__tests__/runtime.test.js +3624 -355
  636. package/dist/team/__tests__/runtime.test.js.map +1 -1
  637. package/dist/team/__tests__/scaling.test.js +2516 -118
  638. package/dist/team/__tests__/scaling.test.js.map +1 -1
  639. package/dist/team/__tests__/state-root.test.js.map +1 -1
  640. package/dist/team/__tests__/state.test.js +804 -36
  641. package/dist/team/__tests__/state.test.js.map +1 -1
  642. package/dist/team/__tests__/team-ops-contract.test.js +6 -0
  643. package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
  644. package/dist/team/__tests__/tmux-session.test.js +3664 -969
  645. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  646. package/dist/team/__tests__/tmux-test-fixture.js.map +1 -1
  647. package/dist/team/__tests__/worker-runtime-identity.test.js +38 -2
  648. package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
  649. package/dist/team/__tests__/worktree.test.js +6 -0
  650. package/dist/team/__tests__/worktree.test.js.map +1 -1
  651. package/dist/team/api-interop.d.ts +2 -2
  652. package/dist/team/api-interop.d.ts.map +1 -1
  653. package/dist/team/api-interop.js +15 -9
  654. package/dist/team/api-interop.js.map +1 -1
  655. package/dist/team/commit-hygiene.js.map +1 -1
  656. package/dist/team/contracts.d.ts +5 -5
  657. package/dist/team/contracts.d.ts.map +1 -1
  658. package/dist/team/delivery-log.js.map +1 -1
  659. package/dist/team/exact-pane.d.ts +23 -0
  660. package/dist/team/exact-pane.d.ts.map +1 -0
  661. package/dist/team/exact-pane.js +133 -0
  662. package/dist/team/exact-pane.js.map +1 -0
  663. package/dist/team/followup-planner.js.map +1 -1
  664. package/dist/team/goal-workflow.js.map +1 -1
  665. package/dist/team/idle-nudge.d.ts +12 -1
  666. package/dist/team/idle-nudge.d.ts.map +1 -1
  667. package/dist/team/idle-nudge.js +41 -14
  668. package/dist/team/idle-nudge.js.map +1 -1
  669. package/dist/team/model-contract.d.ts +18 -2
  670. package/dist/team/model-contract.d.ts.map +1 -1
  671. package/dist/team/model-contract.js +314 -35
  672. package/dist/team/model-contract.js.map +1 -1
  673. package/dist/team/orchestrator.js.map +1 -1
  674. package/dist/team/pane-status.js.map +1 -1
  675. package/dist/team/phase-controller.js.map +1 -1
  676. package/dist/team/reminder-intents.d.ts +1 -1
  677. package/dist/team/reminder-intents.d.ts.map +1 -1
  678. package/dist/team/reminder-intents.js.map +1 -1
  679. package/dist/team/runtime-cli.js.map +1 -1
  680. package/dist/team/runtime.d.ts +1 -0
  681. package/dist/team/runtime.d.ts.map +1 -1
  682. package/dist/team/runtime.js +1326 -231
  683. package/dist/team/runtime.js.map +1 -1
  684. package/dist/team/scaling.d.ts +22 -8
  685. package/dist/team/scaling.d.ts.map +1 -1
  686. package/dist/team/scaling.js +1463 -376
  687. package/dist/team/scaling.js.map +1 -1
  688. package/dist/team/state/dispatch-lock.js.map +1 -1
  689. package/dist/team/state/dispatch.d.ts.map +1 -1
  690. package/dist/team/state/dispatch.js +26 -8
  691. package/dist/team/state/dispatch.js.map +1 -1
  692. package/dist/team/state/events.js.map +1 -1
  693. package/dist/team/state/locks.d.ts.map +1 -1
  694. package/dist/team/state/locks.js +61 -13
  695. package/dist/team/state/locks.js.map +1 -1
  696. package/dist/team/state/tasks.d.ts.map +1 -1
  697. package/dist/team/state/tasks.js +4 -3
  698. package/dist/team/state/tasks.js.map +1 -1
  699. package/dist/team/state-root.js.map +1 -1
  700. package/dist/team/state.d.ts +67 -1
  701. package/dist/team/state.d.ts.map +1 -1
  702. package/dist/team/state.js +636 -129
  703. package/dist/team/state.js.map +1 -1
  704. package/dist/team/team-identity.d.ts.map +1 -1
  705. package/dist/team/team-identity.js.map +1 -1
  706. package/dist/team/team-ops.d.ts +5 -0
  707. package/dist/team/team-ops.d.ts.map +1 -1
  708. package/dist/team/team-ops.js +4 -0
  709. package/dist/team/team-ops.js.map +1 -1
  710. package/dist/team/tmux-session.d.ts +125 -23
  711. package/dist/team/tmux-session.d.ts.map +1 -1
  712. package/dist/team/tmux-session.js +1340 -333
  713. package/dist/team/tmux-session.js.map +1 -1
  714. package/dist/team/worker-bootstrap.js.map +1 -1
  715. package/dist/team/worktree.d.ts.map +1 -1
  716. package/dist/team/worktree.js +4 -0
  717. package/dist/team/worktree.js.map +1 -1
  718. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  719. package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
  720. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  721. package/dist/ultragoal/artifacts.js +4 -1
  722. package/dist/ultragoal/artifacts.js.map +1 -1
  723. package/dist/url-reader/index.js.map +1 -1
  724. package/dist/utils/__tests__/file-durability.test.d.ts +2 -0
  725. package/dist/utils/__tests__/file-durability.test.d.ts.map +1 -0
  726. package/dist/utils/__tests__/file-durability.test.js +57 -0
  727. package/dist/utils/__tests__/file-durability.test.js.map +1 -0
  728. package/dist/utils/agents-model-table.js.map +1 -1
  729. package/dist/utils/file-durability.d.ts +15 -0
  730. package/dist/utils/file-durability.d.ts.map +1 -0
  731. package/dist/utils/file-durability.js +37 -0
  732. package/dist/utils/file-durability.js.map +1 -0
  733. package/dist/utils/package.js.map +1 -1
  734. package/dist/utils/paths.js.map +1 -1
  735. package/dist/utils/platform-command.js.map +1 -1
  736. package/dist/utils/repo-deps.js.map +1 -1
  737. package/dist/utils/version.js.map +1 -1
  738. package/dist/verification/__tests__/ci-rust-gates.test.js +1 -1
  739. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +3 -0
  740. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -1
  741. package/dist/verification/verifier.js.map +1 -1
  742. package/dist/visual/constants.d.ts +1 -1
  743. package/dist/visual/constants.d.ts.map +1 -1
  744. package/dist/vscode/__tests__/index.test.js.map +1 -1
  745. package/dist/vscode/index.js.map +1 -1
  746. package/dist/wiki/__tests__/cjk-tokenize.test.js.map +1 -1
  747. package/dist/wiki/__tests__/lint.test.js.map +1 -1
  748. package/dist/wiki/__tests__/query.test.js.map +1 -1
  749. package/dist/wiki/__tests__/storage.test.js.map +1 -1
  750. package/dist/wiki/__tests__/test-helpers.d.ts.map +1 -1
  751. package/dist/wiki/lint.d.ts +4 -1
  752. package/dist/wiki/lint.d.ts.map +1 -1
  753. package/dist/wiki/lint.js +3 -2
  754. package/dist/wiki/lint.js.map +1 -1
  755. package/dist/wiki/query.js.map +1 -1
  756. package/dist/wiki/storage.js.map +1 -1
  757. package/package.json +2 -2
  758. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  759. package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +24 -0
  760. package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +10 -5
  761. package/plugins/oh-my-codex/skills/ralph/SKILL.md +6 -2
  762. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +6 -2
  763. package/plugins/oh-my-codex/skills/team/SKILL.md +13 -9
  764. package/skills/omx-setup/SKILL.md +10 -5
  765. package/skills/ralph/SKILL.md +6 -2
  766. package/skills/ralplan/SKILL.md +6 -2
  767. package/skills/team/SKILL.md +13 -9
  768. package/src/scripts/__tests__/codex-native-hook.test.ts +20048 -10827
  769. package/src/scripts/__tests__/fixtures/issue-3138-installed-smoke.ts +734 -0
  770. package/src/scripts/__tests__/notify-fallback-delivery.test.ts +177 -0
  771. package/src/scripts/__tests__/notify-state-io.test.ts +73 -0
  772. package/src/scripts/__tests__/reasoning-artifact-contract.test.ts +129 -0
  773. package/src/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.ts +78 -0
  774. package/src/scripts/__tests__/role-intent-durable-recovery-3181.test.ts +60 -0
  775. package/src/scripts/__tests__/smoke-packed-install.test.ts +1309 -4
  776. package/src/scripts/codex-native-hook.ts +11429 -1163
  777. package/src/scripts/notify-fallback-delivery.ts +416 -0
  778. package/src/scripts/notify-fallback-watcher.ts +216 -155
  779. package/src/scripts/notify-hook/auto-nudge.ts +113 -14
  780. package/src/scripts/notify-hook/managed-tmux.ts +149 -12
  781. package/src/scripts/notify-hook/ralph-session-resume.ts +37 -36
  782. package/src/scripts/notify-hook/state-io.ts +100 -13
  783. package/src/scripts/notify-hook/team-dispatch.ts +242 -75
  784. package/src/scripts/notify-hook/team-leader-nudge.ts +40 -18
  785. package/src/scripts/notify-hook/team-tmux-guard.ts +366 -39
  786. package/src/scripts/notify-hook/team-worker-stop.ts +20 -16
  787. package/src/scripts/notify-hook/team-worker.ts +39 -26
  788. package/src/scripts/notify-hook/tmux-injection.ts +66 -23
  789. package/src/scripts/notify-hook/visual-verdict.ts +22 -12
  790. package/src/scripts/notify-hook.ts +336 -90
  791. package/src/scripts/smoke-packed-install.ts +5154 -149
@@ -1,16 +1,47 @@
1
- import { existsSync } from 'node:fs';
2
- import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
- import { dirname, join } from 'node:path';
4
- import { getBaseStateDir } from '../state/paths.js';
1
+ import { randomUUID } from 'node:crypto';
2
+ import { closeSync, existsSync, ftruncateSync, linkSync, mkdirSync, openSync, readdirSync, readFileSync, renameSync, unlinkSync, writeFileSync, writeSync } from 'node:fs';
3
+ import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
4
+ import { hostname } from 'node:os';
5
+ import { basename, dirname, join } from 'node:path';
6
+ import { AGENT_DEFINITIONS } from '../agents/definitions.js';
7
+ import { getBaseStateDir, getBaseStateDirWithSource } from '../state/paths.js';
8
+ import { canonicalizeOriginCwd } from '../leader/contract.js';
9
+ import { codexAgentsDir, projectCodexAgentsDir } from '../utils/paths.js';
5
10
  export const SUBAGENT_TRACKING_SCHEMA_VERSION = 1;
6
11
  export const DEFAULT_SUBAGENT_ACTIVE_WINDOW_MS = 120_000;
12
+ export const OMX_ADAPTED_PROVENANCE = 'omx_adapted';
13
+ export const NATIVE_SUBAGENT_PROVENANCE = 'native_subagent';
14
+ const KNOWN_TYPED_AGENT_ROLES = new Set(Object.keys(AGENT_DEFINITIONS).map((role) => role.toLowerCase()));
7
15
  export function subagentTrackingPath(cwd) {
8
16
  return join(getBaseStateDir(cwd), 'subagent-tracking.json');
9
17
  }
18
+ export function resolveInstalledRoleName(role, codexHomeOverride, projectRootOverride) {
19
+ const normalizedRole = role.trim().toLowerCase();
20
+ if (!normalizedRole)
21
+ return null;
22
+ if (KNOWN_TYPED_AGENT_ROLES.has(normalizedRole))
23
+ return normalizedRole;
24
+ for (const agentsDir of [codexAgentsDir(codexHomeOverride), projectCodexAgentsDir(projectRootOverride)]) {
25
+ try {
26
+ for (const entry of readdirSync(agentsDir, { withFileTypes: true })) {
27
+ if (!entry.isFile() || !entry.name.endsWith('.toml'))
28
+ continue;
29
+ const installedRole = entry.name.slice(0, -'.toml'.length).trim().toLowerCase();
30
+ if (installedRole === normalizedRole)
31
+ return installedRole;
32
+ }
33
+ }
34
+ catch {
35
+ // Missing or unreadable agent directories do not invalidate built-in roles.
36
+ }
37
+ }
38
+ return null;
39
+ }
10
40
  export function createSubagentTrackingState() {
11
41
  return {
12
42
  schemaVersion: SUBAGENT_TRACKING_SCHEMA_VERSION,
13
43
  sessions: {},
44
+ pending_role_intents: [],
14
45
  };
15
46
  }
16
47
  function normalizeSubagentStatus(value) {
@@ -88,6 +119,40 @@ export function isTrustedSubagentThread(session, threadId) {
88
119
  return false;
89
120
  return session.threads[normalizedThreadId]?.kind === 'subagent';
90
121
  }
122
+ function normalizePendingRoleIntent(value) {
123
+ if (!value || typeof value !== 'object')
124
+ return null;
125
+ const candidate = value;
126
+ const role = readOptionalTrimmedString(candidate.role);
127
+ const sessionId = readOptionalTrimmedString(candidate.session_id);
128
+ const parentThreadId = readOptionalTrimmedString(candidate.parent_thread_id);
129
+ const createdAt = readOptionalTrimmedString(candidate.created_at);
130
+ const expiresAt = readOptionalTrimmedString(candidate.expires_at);
131
+ if (!role || !sessionId || !parentThreadId || !Object.hasOwn(candidate, 'correlation_token') || !createdAt || !expiresAt)
132
+ return null;
133
+ if (!Number.isFinite(Date.parse(createdAt)) || !Number.isFinite(Date.parse(expiresAt)))
134
+ return null;
135
+ const bindingState = candidate.binding_state === 'bound' ? 'bound' : undefined;
136
+ const boundAt = readOptionalTrimmedString(candidate.bound_at);
137
+ const hasValidBoundAt = Boolean(boundAt && Number.isFinite(Date.parse(boundAt)));
138
+ const originCwd = readOptionalTrimmedString(candidate.origin_cwd);
139
+ return {
140
+ role,
141
+ session_id: sessionId,
142
+ parent_thread_id: parentThreadId,
143
+ // Bound journals are durable security records. Retain malformed credentials verbatim so
144
+ // completion can reject them rather than silently converting them into claimant-less data.
145
+ correlation_token: candidate.correlation_token,
146
+ created_at: createdAt,
147
+ expires_at: expiresAt,
148
+ ...(bindingState ? { binding_state: bindingState } : {}),
149
+ ...(bindingState && Object.hasOwn(candidate, 'binding_claimant_token')
150
+ ? { binding_claimant_token: candidate.binding_claimant_token }
151
+ : {}),
152
+ ...(bindingState && hasValidBoundAt ? { bound_at: boundAt } : {}),
153
+ ...(originCwd ? { origin_cwd: originCwd } : {}),
154
+ };
155
+ }
91
156
  export function normalizeSubagentTrackingState(input) {
92
157
  const base = createSubagentTrackingState();
93
158
  if (!input || typeof input !== 'object')
@@ -102,9 +167,7 @@ export function normalizeSubagentTrackingState(input) {
102
167
  if (!rawThread || typeof rawThread !== 'object')
103
168
  continue;
104
169
  const candidate = rawThread;
105
- const normalizedThreadId = typeof candidate.thread_id === 'string' && candidate.thread_id.trim().length > 0
106
- ? candidate.thread_id.trim()
107
- : threadId.trim();
170
+ const normalizedThreadId = typeof candidate.thread_id === 'string' && candidate.thread_id.trim().length > 0 ? candidate.thread_id.trim() : threadId.trim();
108
171
  if (!normalizedThreadId)
109
172
  continue;
110
173
  const kind = candidate.kind === 'leader' ? 'leader' : 'subagent';
@@ -113,32 +176,31 @@ export function normalizeSubagentTrackingState(input) {
113
176
  : typeof candidate.last_seen_at === 'string' && candidate.last_seen_at.trim().length > 0
114
177
  ? candidate.last_seen_at
115
178
  : new Date(0).toISOString();
116
- const lastSeenAt = typeof candidate.last_seen_at === 'string' && candidate.last_seen_at.trim().length > 0
117
- ? candidate.last_seen_at
118
- : firstSeenAt;
179
+ const lastSeenAt = typeof candidate.last_seen_at === 'string' && candidate.last_seen_at.trim().length > 0 ? candidate.last_seen_at : firstSeenAt;
119
180
  threads[normalizedThreadId] = {
120
181
  thread_id: normalizedThreadId,
121
182
  kind,
122
183
  first_seen_at: firstSeenAt,
123
184
  last_seen_at: lastSeenAt,
124
- ...(typeof candidate.last_turn_id === 'string' && candidate.last_turn_id.trim().length > 0
125
- ? { last_turn_id: candidate.last_turn_id }
126
- : {}),
127
- ...(typeof candidate.completed_at === 'string' && candidate.completed_at.trim().length > 0
128
- ? { completed_at: candidate.completed_at }
129
- : {}),
185
+ ...(typeof candidate.last_turn_id === 'string' && candidate.last_turn_id.trim().length > 0 ? { last_turn_id: candidate.last_turn_id } : {}),
186
+ ...(typeof candidate.completed_at === 'string' && candidate.completed_at.trim().length > 0 ? { completed_at: candidate.completed_at } : {}),
130
187
  ...(typeof candidate.last_completed_turn_id === 'string' && candidate.last_completed_turn_id.trim().length > 0
131
188
  ? { last_completed_turn_id: candidate.last_completed_turn_id }
132
189
  : {}),
133
- turn_count: typeof candidate.turn_count === 'number' && Number.isFinite(candidate.turn_count) && candidate.turn_count > 0
134
- ? candidate.turn_count
135
- : 1,
190
+ turn_count: typeof candidate.turn_count === 'number' && Number.isFinite(candidate.turn_count) && candidate.turn_count > 0 ? candidate.turn_count : 1,
136
191
  ...(typeof candidate.mode === 'string' && candidate.mode.trim().length > 0 ? { mode: candidate.mode } : {}),
137
192
  ...(typeof candidate.role === 'string' && candidate.role.trim().length > 0 ? { role: candidate.role.trim() } : {}),
193
+ ...(typeof candidate.provenance_kind === 'string' && candidate.provenance_kind.trim().length > 0
194
+ ? { provenance_kind: candidate.provenance_kind.trim() }
195
+ : {}),
138
196
  ...(typeof candidate.lane_id === 'string' && candidate.lane_id.trim().length > 0 ? { lane_id: candidate.lane_id.trim() } : {}),
139
197
  ...(typeof candidate.scope === 'string' && candidate.scope.trim().length > 0 ? { scope: candidate.scope.trim() } : {}),
140
- ...(typeof candidate.agent_nickname === 'string' && candidate.agent_nickname.trim().length > 0 ? { agent_nickname: candidate.agent_nickname.trim() } : {}),
141
- ...(typeof candidate.completion_source === 'string' && candidate.completion_source.trim().length > 0 ? { completion_source: candidate.completion_source } : {}),
198
+ ...(typeof candidate.agent_nickname === 'string' && candidate.agent_nickname.trim().length > 0
199
+ ? { agent_nickname: candidate.agent_nickname.trim() }
200
+ : {}),
201
+ ...(typeof candidate.completion_source === 'string' && candidate.completion_source.trim().length > 0
202
+ ? { completion_source: candidate.completion_source }
203
+ : {}),
142
204
  ...(normalizeSubagentStatus(candidate.status) ? { status: normalizeSubagentStatus(candidate.status) } : {}),
143
205
  ...(typeof candidate.last_handoff_summary === 'string' && candidate.last_handoff_summary.trim().length > 0
144
206
  ? { last_handoff_summary: candidate.last_handoff_summary.trim() }
@@ -158,9 +220,7 @@ export function normalizeSubagentTrackingState(input) {
158
220
  };
159
221
  }
160
222
  const sessionCandidate = rawSession;
161
- const leaderThreadId = typeof sessionCandidate.leader_thread_id === 'string'
162
- ? sessionCandidate.leader_thread_id.trim() || undefined
163
- : undefined;
223
+ const leaderThreadId = typeof sessionCandidate.leader_thread_id === 'string' ? sessionCandidate.leader_thread_id.trim() || undefined : undefined;
164
224
  const updatedAt = typeof sessionCandidate.updated_at === 'string' && sessionCandidate.updated_at.trim().length > 0
165
225
  ? sessionCandidate.updated_at
166
226
  : new Date(0).toISOString();
@@ -171,11 +231,398 @@ export function normalizeSubagentTrackingState(input) {
171
231
  threads,
172
232
  };
173
233
  }
234
+ const pendingRoleIntents = Array.isArray(parsed.pending_role_intents)
235
+ ? parsed.pending_role_intents.map((intent) => normalizePendingRoleIntent(intent)).filter((intent) => intent !== null)
236
+ : [];
174
237
  return {
175
238
  schemaVersion: SUBAGENT_TRACKING_SCHEMA_VERSION,
176
239
  sessions,
240
+ pending_role_intents: pendingRoleIntents,
241
+ };
242
+ }
243
+ function atomicTrackingTempPath(path) {
244
+ return `${path}.${process.pid}.${randomUUID()}.tmp`;
245
+ }
246
+ export const DEFAULT_CROSS_PROCESS_LOCK_MAX_ATTEMPTS = 80;
247
+ export const DEFAULT_CROSS_PROCESS_LOCK_RETRY_MS = 2;
248
+ export const CROSS_PROCESS_LOCK_LEASE_MS = 60_000;
249
+ const crossProcessLockWaitArray = new Int32Array(new SharedArrayBuffer(4));
250
+ export class CrossProcessLockLostError extends Error {
251
+ constructor(lockPath) {
252
+ super(`Lost cross-process lock ownership at ${lockPath}`);
253
+ this.name = 'CrossProcessLockLostError';
254
+ }
255
+ }
256
+ export function crossProcessLockPath(resourcePath) {
257
+ return `${resourcePath}.lock`;
258
+ }
259
+ function sleepForCrossProcessLockSync(durationMs) {
260
+ Atomics.wait(crossProcessLockWaitArray, 0, 0, durationMs);
261
+ }
262
+ export function readProcessStartIdentity(pid) {
263
+ if (process.platform !== 'linux')
264
+ return undefined;
265
+ try {
266
+ const stat = readFileSync(`/proc/${pid}/stat`, 'utf-8');
267
+ const closingParenthesis = stat.lastIndexOf(')');
268
+ const fields = stat.slice(closingParenthesis + 1).trim().split(/\s+/);
269
+ const starttime = fields[19];
270
+ const bootId = readFileSync('/proc/sys/kernel/random/boot_id', 'utf-8').trim();
271
+ if (closingParenthesis < 0 || !starttime || !/^\d+$/.test(starttime) || !bootId)
272
+ return undefined;
273
+ return `${bootId}:${starttime}`;
274
+ }
275
+ catch {
276
+ return undefined;
277
+ }
278
+ }
279
+ function createCrossProcessLockClaim(token) {
280
+ const pidStartId = readProcessStartIdentity(process.pid);
281
+ return {
282
+ token,
283
+ pid: process.pid,
284
+ host: hostname(),
285
+ acquiredAtMs: Date.now(),
286
+ ...(pidStartId ? { pidStartId } : {}),
177
287
  };
178
288
  }
289
+ function serializeCrossProcessLockClaim(claim) {
290
+ return `${JSON.stringify({
291
+ token: claim.token,
292
+ pid: claim.pid,
293
+ host: claim.host,
294
+ acquired_at: new Date(claim.acquiredAtMs).toISOString(),
295
+ ...(claim.pidStartId ? { pid_start_id: claim.pidStartId } : {}),
296
+ })}\n`;
297
+ }
298
+ function readCrossProcessLockState(lockPath) {
299
+ try {
300
+ const parsed = JSON.parse(readFileSync(lockPath, 'utf-8'));
301
+ const token = typeof parsed.token === 'string' && parsed.token === parsed.token.trim() && parsed.token ? parsed.token : undefined;
302
+ const pid = typeof parsed.pid === 'number' && Number.isSafeInteger(parsed.pid) && parsed.pid > 0 ? parsed.pid : undefined;
303
+ const host = typeof parsed.host === 'string' && parsed.host.trim() ? parsed.host : undefined;
304
+ const acquiredAtMs = typeof parsed.acquired_at === 'string' ? Date.parse(parsed.acquired_at) : Number.NaN;
305
+ const pidStartId = parsed.pid_start_id === undefined
306
+ ? undefined
307
+ : typeof parsed.pid_start_id === 'string' && parsed.pid_start_id.trim()
308
+ ? parsed.pid_start_id
309
+ : null;
310
+ if (!token || !pid || !host || !Number.isFinite(acquiredAtMs) || pidStartId === null)
311
+ return { kind: 'malformed' };
312
+ return {
313
+ kind: 'claim',
314
+ claim: { token, pid, host, acquiredAtMs, ...(pidStartId ? { pidStartId } : {}) },
315
+ };
316
+ }
317
+ catch (error) {
318
+ if (error.code === 'ENOENT')
319
+ return { kind: 'missing' };
320
+ return { kind: 'malformed' };
321
+ }
322
+ }
323
+ function isCrossProcessLockOwnerDead(pid) {
324
+ try {
325
+ process.kill(pid, 0);
326
+ return false;
327
+ }
328
+ catch (error) {
329
+ return error.code === 'ESRCH';
330
+ }
331
+ }
332
+ function isCrossProcessLockOlderThanLease(acquiredAtMs, nowMs) {
333
+ return acquiredAtMs < nowMs - CROSS_PROCESS_LOCK_LEASE_MS;
334
+ }
335
+ function isCrossProcessLockReclaimable(claim) {
336
+ if (claim.host !== hostname())
337
+ return isCrossProcessLockOlderThanLease(claim.acquiredAtMs, Date.now());
338
+ if (isCrossProcessLockOwnerDead(claim.pid))
339
+ return true;
340
+ const currentPidStartId = readProcessStartIdentity(claim.pid);
341
+ if (claim.pidStartId && currentPidStartId)
342
+ return currentPidStartId !== claim.pidStartId;
343
+ return isCrossProcessLockOlderThanLease(claim.acquiredAtMs, Date.now());
344
+ }
345
+ function removeCrossProcessLockFile(path) {
346
+ try {
347
+ unlinkSync(path);
348
+ }
349
+ catch (error) {
350
+ if (error.code !== 'ENOENT')
351
+ throw error;
352
+ }
353
+ }
354
+ function tryAcquireCrossProcessFileLock(lockPath, token) {
355
+ const temporaryPath = `${lockPath}.${process.pid}.${randomUUID()}.tmp`;
356
+ let acquired = false;
357
+ try {
358
+ writeFileSync(temporaryPath, serializeCrossProcessLockClaim(createCrossProcessLockClaim(token)));
359
+ try {
360
+ linkSync(temporaryPath, lockPath);
361
+ acquired = true;
362
+ return true;
363
+ }
364
+ catch (error) {
365
+ if (error.code === 'EEXIST')
366
+ return false;
367
+ throw error;
368
+ }
369
+ }
370
+ finally {
371
+ try {
372
+ removeCrossProcessLockFile(temporaryPath);
373
+ }
374
+ catch (error) {
375
+ if (!acquired)
376
+ throw error;
377
+ }
378
+ }
379
+ }
380
+ function restoreQuarantinedCrossProcessLock(lockPath, quarantinedPath) {
381
+ try {
382
+ linkSync(quarantinedPath, lockPath);
383
+ }
384
+ catch (error) {
385
+ const code = error.code;
386
+ // EEXIST: a replacement claim already holds the lock; the displaced copy is redundant.
387
+ // ENOENT: the displaced artifact was already removed (e.g. by a concurrent bounded
388
+ // sweep) — a fenced clean terminal outcome, never a cleanup failure to throw on.
389
+ if (code === 'EEXIST') {
390
+ removeCrossProcessLockFile(quarantinedPath);
391
+ return;
392
+ }
393
+ if (code === 'ENOENT')
394
+ return;
395
+ throw error;
396
+ }
397
+ removeCrossProcessLockFile(quarantinedPath);
398
+ }
399
+ function recoverCrossProcessFileLock(lockPath, observed) {
400
+ if (observed.kind === 'missing')
401
+ return true;
402
+ if (observed.kind === 'claim' && !isCrossProcessLockReclaimable(observed.claim))
403
+ return false;
404
+ const quarantinedPath = `${lockPath}.${Date.now()}.${randomUUID()}.quarantine`;
405
+ try {
406
+ renameSync(lockPath, quarantinedPath);
407
+ }
408
+ catch (error) {
409
+ if (error.code === 'ENOENT')
410
+ return true;
411
+ throw error;
412
+ }
413
+ const barrier = crossProcessQuarantineBarrier;
414
+ crossProcessQuarantineBarrier = null;
415
+ barrier?.(lockPath, quarantinedPath);
416
+ const captured = readCrossProcessLockState(quarantinedPath);
417
+ const capturedExpectedClaim = observed.kind === 'claim'
418
+ && captured.kind === 'claim'
419
+ && captured.claim.token === observed.claim.token;
420
+ const capturedRecoverable = captured.kind === 'malformed'
421
+ || (capturedExpectedClaim && captured.kind === 'claim' && isCrossProcessLockReclaimable(captured.claim));
422
+ if (!capturedRecoverable) {
423
+ restoreQuarantinedCrossProcessLock(lockPath, quarantinedPath);
424
+ return true;
425
+ }
426
+ removeCrossProcessLockFile(quarantinedPath);
427
+ return true;
428
+ }
429
+ function assertCrossProcessFileLockOwnership(lockPath, token) {
430
+ const state = readCrossProcessLockState(lockPath);
431
+ if (state.kind === 'claim' && state.claim.token === token)
432
+ return;
433
+ throw new CrossProcessLockLostError(lockPath);
434
+ }
435
+ function releaseCrossProcessFileLock(lockPath, token) {
436
+ const observed = readCrossProcessLockState(lockPath);
437
+ if (observed.kind !== 'claim' || observed.claim.token !== token)
438
+ return;
439
+ const quarantinedPath = `${lockPath}.${Date.now()}.${randomUUID()}.release`;
440
+ try {
441
+ renameSync(lockPath, quarantinedPath);
442
+ }
443
+ catch (error) {
444
+ if (error.code === 'ENOENT')
445
+ return;
446
+ throw error;
447
+ }
448
+ const barrier = crossProcessQuarantineBarrier;
449
+ crossProcessQuarantineBarrier = null;
450
+ barrier?.(lockPath, quarantinedPath);
451
+ const captured = readCrossProcessLockState(quarantinedPath);
452
+ if (captured.kind === 'claim' && captured.claim.token === token) {
453
+ removeCrossProcessLockFile(quarantinedPath);
454
+ return;
455
+ }
456
+ restoreQuarantinedCrossProcessLock(lockPath, quarantinedPath);
457
+ }
458
+ function crossProcessLockStagePath(resourcePath, token) {
459
+ return `${resourcePath}.stage.${token}`;
460
+ }
461
+ function createCrossProcessLockStage(stagePath) {
462
+ const descriptor = openSync(stagePath, 'wx');
463
+ closeSync(descriptor);
464
+ }
465
+ function sweepForeignCrossProcessLockStages(resourcePath, token) {
466
+ const directory = dirname(resourcePath);
467
+ const stagePrefix = `${basename(resourcePath)}.stage.`;
468
+ for (const entry of readdirSync(directory)) {
469
+ if (!entry.startsWith(stagePrefix) || entry.slice(stagePrefix.length) === token)
470
+ continue;
471
+ removeCrossProcessLockFile(join(directory, entry));
472
+ }
473
+ }
474
+ export const CROSS_PROCESS_LOCK_ARTIFACT_SWEEP_CAP = 64;
475
+ function sweepAbandonedCrossProcessLockArtifacts(resourcePath) {
476
+ const directory = dirname(resourcePath);
477
+ const lockName = basename(crossProcessLockPath(resourcePath));
478
+ const escapedLockName = lockName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
479
+ const artifactPattern = new RegExp(`^${escapedLockName}\\.([^.]+)\\.[^.]+\\.(?:quarantine|release)$`);
480
+ const nowMs = Date.now();
481
+ const aged = [];
482
+ for (const entry of readdirSync(directory)) {
483
+ const match = artifactPattern.exec(entry);
484
+ if (!match)
485
+ continue;
486
+ const displacedAtMs = Number(match[1]);
487
+ // Only lease-aged, parseable-timestamp artifacts are eligible; fresh/live/malformed-ts
488
+ // artifacts are always preserved (never delete a live successor's in-flight evidence).
489
+ if (!Number.isFinite(displacedAtMs) || nowMs - displacedAtMs <= CROSS_PROCESS_LOCK_LEASE_MS)
490
+ continue;
491
+ aged.push({ displacedAtMs, entry });
492
+ }
493
+ // Bounded, deterministic cleanup: process oldest-first (tie-break by name) and remove at
494
+ // most CROSS_PROCESS_LOCK_ARTIFACT_SWEEP_CAP per acquisition, so a large backlog drains
495
+ // predictably across acquisitions instead of doing unbounded work in a single lock take.
496
+ aged.sort((a, b) => a.displacedAtMs - b.displacedAtMs || (a.entry < b.entry ? -1 : a.entry > b.entry ? 1 : 0));
497
+ for (const { entry } of aged.slice(0, CROSS_PROCESS_LOCK_ARTIFACT_SWEEP_CAP)) {
498
+ removeCrossProcessLockFile(join(directory, entry));
499
+ }
500
+ }
501
+ let crossProcessPublishBarrier = null;
502
+ let crossProcessQuarantineBarrier = null;
503
+ export function __setCrossProcessPublishBarrierForTest(barrier) {
504
+ crossProcessPublishBarrier = barrier;
505
+ }
506
+ export function __setCrossProcessQuarantineBarrierForTest(barrier) {
507
+ crossProcessQuarantineBarrier = barrier;
508
+ }
509
+ export function withCrossProcessFileLockSync(resourcePath, operation, options = {}) {
510
+ const lockPath = crossProcessLockPath(resourcePath);
511
+ const maxAttempts = typeof options.maxAttempts === 'number' && Number.isFinite(options.maxAttempts)
512
+ ? Math.max(1, Math.floor(options.maxAttempts))
513
+ : DEFAULT_CROSS_PROCESS_LOCK_MAX_ATTEMPTS;
514
+ const retryMs = typeof options.retryMs === 'number' && Number.isFinite(options.retryMs)
515
+ ? Math.max(1, Math.floor(options.retryMs))
516
+ : DEFAULT_CROSS_PROCESS_LOCK_RETRY_MS;
517
+ mkdirSync(dirname(lockPath), { recursive: true });
518
+ const token = randomUUID();
519
+ const stagePath = crossProcessLockStagePath(resourcePath, token);
520
+ let acquired = false;
521
+ for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
522
+ if (tryAcquireCrossProcessFileLock(lockPath, token)) {
523
+ acquired = true;
524
+ break;
525
+ }
526
+ const recovered = recoverCrossProcessFileLock(lockPath, readCrossProcessLockState(lockPath));
527
+ if (recovered && tryAcquireCrossProcessFileLock(lockPath, token)) {
528
+ acquired = true;
529
+ break;
530
+ }
531
+ if (attempt === maxAttempts - 1) {
532
+ throw new Error(`Timed out waiting for cross-process lock at ${lockPath}`);
533
+ }
534
+ sleepForCrossProcessLockSync(Math.min(25, retryMs * 2 ** Math.min(attempt, 4)));
535
+ }
536
+ if (!acquired) {
537
+ throw new Error(`Timed out waiting for cross-process lock at ${lockPath}`);
538
+ }
539
+ try {
540
+ sweepForeignCrossProcessLockStages(resourcePath, token);
541
+ sweepAbandonedCrossProcessLockArtifacts(resourcePath);
542
+ createCrossProcessLockStage(stagePath);
543
+ return operation({
544
+ assertOwnership: () => assertCrossProcessFileLockOwnership(lockPath, token),
545
+ publish: (contents) => {
546
+ let descriptor;
547
+ try {
548
+ descriptor = openSync(stagePath, 'r+');
549
+ }
550
+ catch (error) {
551
+ if (error.code === 'ENOENT')
552
+ throw new CrossProcessLockLostError(lockPath);
553
+ throw error;
554
+ }
555
+ try {
556
+ ftruncateSync(descriptor, 0);
557
+ writeSync(descriptor, contents);
558
+ }
559
+ finally {
560
+ closeSync(descriptor);
561
+ }
562
+ const barrier = crossProcessPublishBarrier;
563
+ crossProcessPublishBarrier = null;
564
+ barrier?.();
565
+ try {
566
+ renameSync(stagePath, resourcePath);
567
+ }
568
+ catch (error) {
569
+ if (error.code === 'ENOENT')
570
+ throw new CrossProcessLockLostError(lockPath);
571
+ throw error;
572
+ }
573
+ createCrossProcessLockStage(stagePath);
574
+ },
575
+ });
576
+ }
577
+ finally {
578
+ removeCrossProcessLockFile(stagePath);
579
+ releaseCrossProcessFileLock(lockPath, token);
580
+ }
581
+ }
582
+ function readSubagentTrackingStateSync(cwd) {
583
+ const path = subagentTrackingPath(cwd);
584
+ if (!existsSync(path))
585
+ return createSubagentTrackingState();
586
+ try {
587
+ return normalizeSubagentTrackingState(JSON.parse(readFileSync(path, 'utf-8')));
588
+ }
589
+ catch {
590
+ return createSubagentTrackingState();
591
+ }
592
+ }
593
+ // Strict reads preserve fail-closed behavior for security-sensitive tracker decisions.
594
+ export async function readSubagentTrackingStateStrict(cwd) {
595
+ const path = subagentTrackingPath(cwd);
596
+ let raw;
597
+ try {
598
+ raw = await readFile(path, 'utf-8');
599
+ }
600
+ catch (error) {
601
+ if (error?.code === 'ENOENT')
602
+ return { ok: true, state: createSubagentTrackingState() };
603
+ return { ok: false };
604
+ }
605
+ try {
606
+ return { ok: true, state: normalizeSubagentTrackingState(JSON.parse(raw)) };
607
+ }
608
+ catch {
609
+ return { ok: false };
610
+ }
611
+ }
612
+ function writeSubagentTrackingStateSync(cwd, state, publish) {
613
+ const normalized = normalizeSubagentTrackingState(state);
614
+ const path = subagentTrackingPath(cwd);
615
+ mkdirSync(dirname(path), { recursive: true });
616
+ const contents = `${JSON.stringify(normalized, null, 2)}\n`;
617
+ if (publish) {
618
+ publish(contents);
619
+ return path;
620
+ }
621
+ const temporaryPath = atomicTrackingTempPath(path);
622
+ writeFileSync(temporaryPath, contents);
623
+ renameSync(temporaryPath, path);
624
+ return path;
625
+ }
179
626
  export async function readSubagentTrackingState(cwd) {
180
627
  const path = subagentTrackingPath(cwd);
181
628
  if (!existsSync(path))
@@ -191,9 +638,299 @@ export async function writeSubagentTrackingState(cwd, state) {
191
638
  const normalized = normalizeSubagentTrackingState(state);
192
639
  const path = subagentTrackingPath(cwd);
193
640
  await mkdir(dirname(path), { recursive: true });
194
- await writeFile(path, `${JSON.stringify(normalized, null, 2)}\n`);
641
+ const temporaryPath = atomicTrackingTempPath(path);
642
+ await writeFile(temporaryPath, `${JSON.stringify(normalized, null, 2)}\n`);
643
+ await rename(temporaryPath, path);
195
644
  return path;
196
645
  }
646
+ function normalizeNowMs(nowMs) {
647
+ return typeof nowMs === 'number' && Number.isFinite(nowMs) ? nowMs : Date.now();
648
+ }
649
+ function isExpiredPendingRoleIntent(intent, nowMs) {
650
+ if (intent.binding_state === 'bound')
651
+ return false;
652
+ const expiresAtMs = Date.parse(intent.expires_at);
653
+ return !Number.isFinite(expiresAtMs) || expiresAtMs <= nowMs;
654
+ }
655
+ function pendingRoleIntentPredicates(cwd, canonicalOrigin, nowMs) {
656
+ const isCwdPartitionedStateRoot = getBaseStateDirWithSource(cwd).rootSource === 'cwd-default';
657
+ const isOwn = (intent) => (intent.origin_cwd
658
+ ? canonicalizeOriginCwd(intent.origin_cwd) === canonicalOrigin
659
+ : isCwdPartitionedStateRoot);
660
+ const shouldPruneExpired = (intent) => (isOwn(intent)
661
+ && intent.binding_state !== 'bound'
662
+ && isExpiredPendingRoleIntent(intent, nowMs));
663
+ return { isOwn, shouldPruneExpired };
664
+ }
665
+ export function isRoleIntentOwnedByCwd(cwd, intent) {
666
+ return pendingRoleIntentPredicates(cwd, canonicalizeOriginCwd(cwd), Date.now()).isOwn(intent);
667
+ }
668
+ function sameLogicalRoleIntent(intent, sessionId, parentThreadId, correlationToken) {
669
+ return (intent.session_id === sessionId
670
+ && intent.parent_thread_id === parentThreadId
671
+ && (correlationToken === undefined || intent.correlation_token === correlationToken));
672
+ }
673
+ export function isCanonicalCorrelationToken(value) {
674
+ return typeof value === 'string' && /^[0-9a-f]{32}$/.test(value);
675
+ }
676
+ export function isCanonicalClaimantToken(value) {
677
+ return typeof value === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(value);
678
+ }
679
+ function hasOwnBoundLogicalIntent(all, isOwn, sessionId, parentThreadId, correlationToken) {
680
+ return all.some((intent) => (isOwn(intent)
681
+ && intent.binding_state === 'bound'
682
+ && sameLogicalRoleIntent(intent, sessionId, parentThreadId, correlationToken)));
683
+ }
684
+ function selectDominantRoleIntent(candidates, canonicalOrigin) {
685
+ return [...candidates].sort((left, right) => {
686
+ const leftIsBound = left.binding_state === 'bound';
687
+ const rightIsBound = right.binding_state === 'bound';
688
+ if (leftIsBound !== rightIsBound)
689
+ return leftIsBound ? -1 : 1;
690
+ const leftIsExactOrigin = left.origin_cwd !== undefined
691
+ && canonicalizeOriginCwd(left.origin_cwd) === canonicalOrigin;
692
+ const rightIsExactOrigin = right.origin_cwd !== undefined
693
+ && canonicalizeOriginCwd(right.origin_cwd) === canonicalOrigin;
694
+ if (leftIsExactOrigin !== rightIsExactOrigin)
695
+ return leftIsExactOrigin ? -1 : 1;
696
+ const leftStableKey = [
697
+ left.role,
698
+ left.correlation_token,
699
+ left.created_at,
700
+ left.expires_at,
701
+ left.binding_state ?? '',
702
+ left.binding_claimant_token ?? '',
703
+ left.bound_at ?? '',
704
+ left.origin_cwd ?? '',
705
+ ].join('\u0000');
706
+ const rightStableKey = [
707
+ right.role,
708
+ right.correlation_token,
709
+ right.created_at,
710
+ right.expires_at,
711
+ right.binding_state ?? '',
712
+ right.binding_claimant_token ?? '',
713
+ right.bound_at ?? '',
714
+ right.origin_cwd ?? '',
715
+ ].join('\u0000');
716
+ return leftStableKey.localeCompare(rightStableKey);
717
+ })[0] ?? null;
718
+ }
719
+ export function recordPendingRoleIntent(cwd, input) {
720
+ const role = resolveInstalledRoleName(input.role);
721
+ if (!role)
722
+ return { ok: false, reason: 'unknown_role' };
723
+ const correlationToken = input.correlationToken;
724
+ if (!isCanonicalCorrelationToken(correlationToken)) {
725
+ return { ok: false, reason: 'invalid_correlation_token' };
726
+ }
727
+ const nowMs = normalizeNowMs(input.nowMs);
728
+ const sessionId = input.sessionId.trim();
729
+ const parentThreadId = input.parentThreadId.trim();
730
+ const canonicalOrigin = canonicalizeOriginCwd(cwd);
731
+ if (canonicalOrigin === null)
732
+ return { ok: false, reason: 'invalid_origin' };
733
+ const { isOwn, shouldPruneExpired } = pendingRoleIntentPredicates(cwd, canonicalOrigin, nowMs);
734
+ return withCrossProcessFileLockSync(subagentTrackingPath(cwd), (context) => {
735
+ const state = readSubagentTrackingStateSync(cwd);
736
+ const all = state.pending_role_intents;
737
+ if (all.some((intent) => (isOwn(intent)
738
+ && intent.session_id === sessionId
739
+ && intent.parent_thread_id === parentThreadId
740
+ && (intent.binding_state === 'bound' || !isExpiredPendingRoleIntent(intent, nowMs))))) {
741
+ return { ok: false, reason: 'single_flight_conflict' };
742
+ }
743
+ const ttlMs = typeof input.ttlMs === 'number' && Number.isFinite(input.ttlMs) ? input.ttlMs : 10 * 60_000;
744
+ const intent = {
745
+ role,
746
+ session_id: sessionId,
747
+ parent_thread_id: parentThreadId,
748
+ correlation_token: correlationToken,
749
+ created_at: new Date(nowMs).toISOString(),
750
+ expires_at: new Date(nowMs + ttlMs).toISOString(),
751
+ // Store the canonical origin workspace so it authenticates future bind/complete/recover.
752
+ ...(canonicalOrigin ? { origin_cwd: canonicalOrigin } : {}),
753
+ };
754
+ state.pending_role_intents = [...all.filter((candidate) => !shouldPruneExpired(candidate)), intent];
755
+ context.assertOwnership();
756
+ writeSubagentTrackingStateSync(cwd, state, context.publish);
757
+ return { ok: true, intent };
758
+ });
759
+ }
760
+ export function bindPendingRoleIntentUnderLock(cwd, input, bind) {
761
+ const nowMs = normalizeNowMs(input.nowMs);
762
+ const sessionId = input.sessionId.trim();
763
+ const parentThreadId = input.parentThreadId.trim();
764
+ const correlationToken = input.correlationToken;
765
+ if (!isCanonicalCorrelationToken(correlationToken))
766
+ return null;
767
+ // Fail-closed origin authentication: establish the caller's canonical origin workspace up
768
+ // front. A malformed/unavailable origin can never disclose role/claimant, run the bind
769
+ // callback, mutate pending->bound, or acquire the lock.
770
+ const canonicalOrigin = canonicalizeOriginCwd(cwd);
771
+ if (canonicalOrigin === null)
772
+ return null;
773
+ return withCrossProcessFileLockSync(subagentTrackingPath(cwd), (context) => {
774
+ const state = readSubagentTrackingStateSync(cwd);
775
+ const all = state.pending_role_intents;
776
+ const { isOwn, shouldPruneExpired } = pendingRoleIntentPredicates(cwd, canonicalOrigin, nowMs);
777
+ const matchedIntent = selectDominantRoleIntent(all.filter((intent) => (isOwn(intent)
778
+ && correlationToken !== undefined
779
+ && sameLogicalRoleIntent(intent, sessionId, parentThreadId, correlationToken)
780
+ && (intent.binding_state === 'bound' || !isExpiredPendingRoleIntent(intent, nowMs)))), canonicalOrigin);
781
+ if (!matchedIntent) {
782
+ const retained = all.filter((intent) => !shouldPruneExpired(intent));
783
+ if (retained.length !== all.length) {
784
+ state.pending_role_intents = retained;
785
+ context.assertOwnership();
786
+ writeSubagentTrackingStateSync(cwd, state, context.publish);
787
+ }
788
+ return null;
789
+ }
790
+ const adaptedIntent = {
791
+ role: matchedIntent.role,
792
+ provenanceKind: OMX_ADAPTED_PROVENANCE,
793
+ };
794
+ if (matchedIntent.binding_state === 'bound') {
795
+ const next = all
796
+ .filter((intent) => (intent.binding_state === 'bound'
797
+ || !(isOwn(intent) && sameLogicalRoleIntent(intent, sessionId, parentThreadId, correlationToken))))
798
+ .map((intent) => (intent === matchedIntent && !intent.origin_cwd
799
+ ? { ...intent, origin_cwd: canonicalOrigin }
800
+ : intent));
801
+ if (next.length !== all.length || !matchedIntent.origin_cwd) {
802
+ state.pending_role_intents = next;
803
+ context.assertOwnership();
804
+ writeSubagentTrackingStateSync(cwd, state, context.publish);
805
+ }
806
+ return {
807
+ ...adaptedIntent,
808
+ claimantToken: undefined,
809
+ alreadyBound: true,
810
+ };
811
+ }
812
+ const claimantToken = randomUUID();
813
+ const boundState = bind(state, adaptedIntent);
814
+ boundState.pending_role_intents = all
815
+ .filter((intent) => !shouldPruneExpired(intent))
816
+ .filter((intent) => (intent === matchedIntent
817
+ || !(isOwn(intent) && sameLogicalRoleIntent(intent, sessionId, parentThreadId, correlationToken))))
818
+ .map((intent) => (intent === matchedIntent
819
+ ? {
820
+ ...matchedIntent,
821
+ binding_state: 'bound',
822
+ binding_claimant_token: claimantToken,
823
+ bound_at: new Date(nowMs).toISOString(),
824
+ origin_cwd: matchedIntent.origin_cwd ?? canonicalOrigin,
825
+ }
826
+ : intent));
827
+ context.assertOwnership();
828
+ writeSubagentTrackingStateSync(cwd, boundState, context.publish);
829
+ return { ...adaptedIntent, claimantToken, alreadyBound: false };
830
+ });
831
+ }
832
+ export function consumePendingRoleIntent(cwd, input) {
833
+ const nowMs = normalizeNowMs(input.nowMs);
834
+ const sessionId = input.sessionId.trim();
835
+ const parentThreadId = input.parentThreadId.trim();
836
+ const correlationToken = input.correlationToken;
837
+ if (!isCanonicalCorrelationToken(correlationToken))
838
+ return null;
839
+ const canonicalOrigin = canonicalizeOriginCwd(cwd);
840
+ if (canonicalOrigin === null)
841
+ return null;
842
+ return withCrossProcessFileLockSync(subagentTrackingPath(cwd), (context) => {
843
+ const state = readSubagentTrackingStateSync(cwd);
844
+ const all = state.pending_role_intents;
845
+ const { isOwn, shouldPruneExpired } = pendingRoleIntentPredicates(cwd, canonicalOrigin, nowMs);
846
+ if (hasOwnBoundLogicalIntent(all, isOwn, sessionId, parentThreadId, correlationToken))
847
+ return null;
848
+ const consumed = selectDominantRoleIntent(all.filter((intent) => (isOwn(intent)
849
+ && intent.binding_state !== 'bound'
850
+ && !isExpiredPendingRoleIntent(intent, nowMs)
851
+ && correlationToken !== undefined
852
+ && sameLogicalRoleIntent(intent, sessionId, parentThreadId, correlationToken))), canonicalOrigin);
853
+ if (!consumed) {
854
+ const retained = all.filter((intent) => !shouldPruneExpired(intent));
855
+ if (retained.length !== all.length) {
856
+ state.pending_role_intents = retained;
857
+ context.assertOwnership();
858
+ writeSubagentTrackingStateSync(cwd, state, context.publish);
859
+ }
860
+ return null;
861
+ }
862
+ state.pending_role_intents = all
863
+ .filter((intent) => !shouldPruneExpired(intent))
864
+ .filter((intent) => (intent.binding_state === 'bound'
865
+ || !(isOwn(intent) && sameLogicalRoleIntent(intent, sessionId, parentThreadId, correlationToken))));
866
+ context.assertOwnership();
867
+ writeSubagentTrackingStateSync(cwd, state, context.publish);
868
+ return { role: consumed.role, provenanceKind: OMX_ADAPTED_PROVENANCE };
869
+ });
870
+ }
871
+ export function completeAdaptedRoleBinding(cwd, input) {
872
+ const nowMs = normalizeNowMs(input.nowMs);
873
+ const sessionId = input.sessionId.trim();
874
+ const parentThreadId = input.parentThreadId.trim();
875
+ const correlationToken = input.correlationToken;
876
+ const claimantToken = input.claimantToken;
877
+ const canonicalOrigin = canonicalizeOriginCwd(cwd);
878
+ if (canonicalOrigin === null)
879
+ return 'not_found';
880
+ return withCrossProcessFileLockSync(subagentTrackingPath(cwd), (context) => {
881
+ const state = readSubagentTrackingStateSync(cwd);
882
+ const all = state.pending_role_intents;
883
+ const { isOwn, shouldPruneExpired } = pendingRoleIntentPredicates(cwd, canonicalOrigin, nowMs);
884
+ // Select the owned bound scope before authenticating it. Credentials are not a lookup key:
885
+ // otherwise an invalid dominant duplicate could be bypassed by a lower valid duplicate.
886
+ const boundIntent = selectDominantRoleIntent(all.filter((intent) => (isOwn(intent)
887
+ && intent.binding_state === 'bound'
888
+ && sameLogicalRoleIntent(intent, sessionId, parentThreadId))), canonicalOrigin);
889
+ if (!boundIntent) {
890
+ const retained = all.filter((intent) => !shouldPruneExpired(intent));
891
+ if (retained.length !== all.length) {
892
+ state.pending_role_intents = retained;
893
+ context.assertOwnership();
894
+ writeSubagentTrackingStateSync(cwd, state, context.publish);
895
+ }
896
+ return 'not_found';
897
+ }
898
+ const hasClaimant = Object.hasOwn(boundIntent, 'binding_claimant_token');
899
+ if (!isCanonicalCorrelationToken(boundIntent.correlation_token)
900
+ || !isCanonicalCorrelationToken(correlationToken)
901
+ || boundIntent.correlation_token !== correlationToken
902
+ || (hasClaimant && (!isCanonicalClaimantToken(boundIntent.binding_claimant_token)
903
+ || !isCanonicalClaimantToken(claimantToken)
904
+ || boundIntent.binding_claimant_token !== claimantToken)))
905
+ return 'claimant_mismatch';
906
+ state.pending_role_intents = all
907
+ .filter((intent) => !shouldPruneExpired(intent))
908
+ .filter((intent) => !(isOwn(intent) && sameLogicalRoleIntent(intent, sessionId, parentThreadId, boundIntent.correlation_token)));
909
+ context.assertOwnership();
910
+ writeSubagentTrackingStateSync(cwd, state, context.publish);
911
+ return 'completed';
912
+ });
913
+ }
914
+ export function listBoundAdaptedRoleIntents(cwd, _nowMs, ownedDominant = false) {
915
+ const allBound = readSubagentTrackingStateSync(cwd).pending_role_intents.filter((intent) => intent.binding_state === 'bound');
916
+ if (!ownedDominant)
917
+ return allBound;
918
+ const canonicalOrigin = canonicalizeOriginCwd(cwd);
919
+ if (canonicalOrigin === null)
920
+ return [];
921
+ const { isOwn } = pendingRoleIntentPredicates(cwd, canonicalOrigin, Date.now());
922
+ const scopes = new Map();
923
+ for (const intent of allBound) {
924
+ if (!isOwn(intent))
925
+ continue;
926
+ const key = `${intent.session_id}\u0000${intent.parent_thread_id}`;
927
+ scopes.set(key, [...(scopes.get(key) ?? []), intent]);
928
+ }
929
+ return [...scopes.values()].flatMap((candidates) => {
930
+ const dominant = selectDominantRoleIntent(candidates, canonicalOrigin);
931
+ return dominant ? [dominant] : [];
932
+ });
933
+ }
197
934
  export function recordSubagentTurn(state, input) {
198
935
  const sessionId = input.sessionId.trim();
199
936
  const threadId = input.threadId.trim();
@@ -209,42 +946,29 @@ export function recordSubagentTurn(state, input) {
209
946
  const requestedKind = input.kind === 'leader' || input.kind === 'subagent' ? input.kind : undefined;
210
947
  const requestedLeaderThreadId = input.leaderThreadId?.trim();
211
948
  const existingThread = existingSession.threads[threadId];
212
- const existingKind = existingThread?.kind === 'leader' || existingThread?.kind === 'subagent'
213
- ? existingThread.kind
214
- : undefined;
949
+ const existingKind = existingThread?.kind === 'leader' || existingThread?.kind === 'subagent' ? existingThread.kind : undefined;
215
950
  const existingLeaderThreadId = existingSession.leader_thread_id?.trim();
216
951
  // `leader_thread_id` is the session's top-level leader boundary. A native
217
952
  // subagent can itself be the immediate parent of a nested native role, but
218
953
  // that must not reclassify known subagent evidence as the session leader.
219
- const requestedLeaderThread = requestedLeaderThreadId
220
- ? existingSession.threads[requestedLeaderThreadId]
221
- : undefined;
954
+ const requestedLeaderThread = requestedLeaderThreadId ? existingSession.threads[requestedLeaderThreadId] : undefined;
222
955
  const requestedLeaderWouldReclassifySubagent = requestedLeaderThread?.kind === 'subagent';
223
- const requestedSessionLeaderThreadId = requestedLeaderWouldReclassifySubagent
224
- ? undefined
225
- : requestedLeaderThreadId;
956
+ const requestedSessionLeaderThreadId = requestedLeaderWouldReclassifySubagent ? undefined : requestedLeaderThreadId;
226
957
  const preserveExistingSubagent = existingKind === 'subagent' && requestedKind !== 'subagent';
227
- const preserveKnownLeader = requestedKind === 'subagent'
228
- && (existingKind === 'leader' || existingLeaderThreadId === threadId);
958
+ const preserveKnownLeader = requestedKind === 'subagent' && (existingKind === 'leader' || existingLeaderThreadId === threadId);
229
959
  const leaderThreadId = preserveKnownLeader
230
960
  ? existingLeaderThreadId || threadId
231
- : existingLeaderThreadId
232
- || requestedSessionLeaderThreadId
233
- || (requestedKind === 'subagent' || preserveExistingSubagent ? undefined : threadId);
961
+ : existingLeaderThreadId || requestedSessionLeaderThreadId || (requestedKind === 'subagent' || preserveExistingSubagent ? undefined : threadId);
234
962
  const kind = preserveKnownLeader
235
963
  ? 'leader'
236
964
  : requestedKind === 'leader' && existingKind === 'subagent'
237
965
  ? 'subagent'
238
- : requestedKind ?? (threadId === leaderThreadId ? 'leader' : existingKind ?? 'subagent');
966
+ : (requestedKind ?? (threadId === leaderThreadId ? 'leader' : (existingKind ?? 'subagent')));
239
967
  const requestedStatus = normalizeSubagentStatus(input.status);
240
968
  const preservedStatus = normalizeSubagentStatus(existingThread?.status);
241
969
  const preserveCompletionEvidence = input.preserveCompletionEvidence === true;
242
- const clearsPriorCompletion = input.completed !== true
243
- && preserveCompletionEvidence !== true
244
- && Boolean(existingThread?.completed_at);
245
- const status = requestedStatus
246
- ?? (input.completed ? 'closed' : undefined)
247
- ?? (clearsPriorCompletion ? undefined : preservedStatus);
970
+ const clearsPriorCompletion = input.completed !== true && preserveCompletionEvidence !== true && Boolean(existingThread?.completed_at);
971
+ const status = requestedStatus ?? (input.completed ? 'closed' : undefined) ?? (clearsPriorCompletion ? undefined : preservedStatus);
248
972
  const preservedCompletion = preserveCompletionEvidence && existingThread?.completed_at
249
973
  ? {
250
974
  completed_at: existingThread.completed_at,
@@ -258,7 +982,11 @@ export function recordSubagentTurn(state, input) {
258
982
  first_seen_at: existingThread?.first_seen_at ?? timestamp,
259
983
  last_seen_at: timestamp,
260
984
  turn_count: (existingThread?.turn_count ?? 0) + 1,
261
- ...(input.turnId?.trim() ? { last_turn_id: input.turnId.trim() } : existingThread?.last_turn_id ? { last_turn_id: existingThread.last_turn_id } : {}),
985
+ ...(input.turnId?.trim()
986
+ ? { last_turn_id: input.turnId.trim() }
987
+ : existingThread?.last_turn_id
988
+ ? { last_turn_id: existingThread.last_turn_id }
989
+ : {}),
262
990
  ...(input.completed
263
991
  ? {
264
992
  completed_at: timestamp,
@@ -268,27 +996,44 @@ export function recordSubagentTurn(state, input) {
268
996
  : preservedCompletion),
269
997
  ...(input.mode?.trim() ? { mode: input.mode.trim() } : existingThread?.mode ? { mode: existingThread.mode } : {}),
270
998
  ...(input.role?.trim() ? { role: input.role.trim() } : existingThread?.role ? { role: existingThread.role } : {}),
999
+ ...(input.provenanceKind?.trim()
1000
+ ? { provenance_kind: input.provenanceKind.trim() }
1001
+ : existingThread?.provenance_kind
1002
+ ? { provenance_kind: existingThread.provenance_kind }
1003
+ : {}),
271
1004
  ...(input.laneId?.trim() ? { lane_id: input.laneId.trim() } : existingThread?.lane_id ? { lane_id: existingThread.lane_id } : {}),
272
1005
  ...(input.scope?.trim() ? { scope: input.scope.trim() } : existingThread?.scope ? { scope: existingThread.scope } : {}),
273
1006
  ...(input.agentNickname?.trim()
274
1007
  ? { agent_nickname: input.agentNickname.trim() }
275
- : existingThread?.agent_nickname ? { agent_nickname: existingThread.agent_nickname } : {}),
1008
+ : existingThread?.agent_nickname
1009
+ ? { agent_nickname: existingThread.agent_nickname }
1010
+ : {}),
276
1011
  ...(status ? { status } : {}),
277
1012
  ...(input.lastHandoffSummary?.trim()
278
1013
  ? { last_handoff_summary: input.lastHandoffSummary.trim() }
279
- : existingThread?.last_handoff_summary ? { last_handoff_summary: existingThread.last_handoff_summary } : {}),
1014
+ : existingThread?.last_handoff_summary
1015
+ ? { last_handoff_summary: existingThread.last_handoff_summary }
1016
+ : {}),
280
1017
  ...(input.resumeRequestedAt?.trim()
281
1018
  ? { resume_requested_at: input.resumeRequestedAt.trim() }
282
- : existingThread?.resume_requested_at ? { resume_requested_at: existingThread.resume_requested_at } : {}),
1019
+ : existingThread?.resume_requested_at
1020
+ ? { resume_requested_at: existingThread.resume_requested_at }
1021
+ : {}),
283
1022
  ...(input.resumeCompletedAt?.trim()
284
1023
  ? { resume_completed_at: input.resumeCompletedAt.trim() }
285
- : existingThread?.resume_completed_at ? { resume_completed_at: existingThread.resume_completed_at } : {}),
1024
+ : existingThread?.resume_completed_at
1025
+ ? { resume_completed_at: existingThread.resume_completed_at }
1026
+ : {}),
286
1027
  ...(input.resumeFailedAt?.trim()
287
1028
  ? { resume_failed_at: input.resumeFailedAt.trim() }
288
- : existingThread?.resume_failed_at ? { resume_failed_at: existingThread.resume_failed_at } : {}),
1029
+ : existingThread?.resume_failed_at
1030
+ ? { resume_failed_at: existingThread.resume_failed_at }
1031
+ : {}),
289
1032
  ...(input.resumeFailureReason?.trim()
290
1033
  ? { resume_failure_reason: input.resumeFailureReason.trim() }
291
- : existingThread?.resume_failure_reason ? { resume_failure_reason: existingThread.resume_failure_reason } : {}),
1034
+ : existingThread?.resume_failure_reason
1035
+ ? { resume_failure_reason: existingThread.resume_failure_reason }
1036
+ : {}),
292
1037
  };
293
1038
  const threads = {
294
1039
  ...existingSession.threads,
@@ -309,10 +1054,13 @@ export function recordSubagentTurn(state, input) {
309
1054
  return normalized;
310
1055
  }
311
1056
  export async function recordSubagentTurnForSession(cwd, input) {
312
- const current = await readSubagentTrackingState(cwd);
313
- const next = recordSubagentTurn(current, input);
314
- await writeSubagentTrackingState(cwd, next);
315
- return next;
1057
+ return withCrossProcessFileLockSync(subagentTrackingPath(cwd), (context) => {
1058
+ const current = readSubagentTrackingStateSync(cwd);
1059
+ const next = recordSubagentTurn(current, input);
1060
+ context.assertOwnership();
1061
+ writeSubagentTrackingStateSync(cwd, next, context.publish);
1062
+ return next;
1063
+ });
316
1064
  }
317
1065
  export function summarizeSubagentSession(state, sessionId, options = {}) {
318
1066
  const normalized = normalizeSubagentTrackingState(state);
@@ -320,11 +1068,7 @@ export function summarizeSubagentSession(state, sessionId, options = {}) {
320
1068
  if (!session)
321
1069
  return null;
322
1070
  const activeWindowMs = options.activeWindowMs ?? DEFAULT_SUBAGENT_ACTIVE_WINDOW_MS;
323
- const nowMs = typeof options.now === 'string'
324
- ? Date.parse(options.now)
325
- : options.now instanceof Date
326
- ? options.now.getTime()
327
- : Date.now();
1071
+ const nowMs = typeof options.now === 'string' ? Date.parse(options.now) : options.now instanceof Date ? options.now.getTime() : Date.now();
328
1072
  const allThreadIds = Object.keys(session.threads).sort();
329
1073
  const allSubagentThreadIds = allThreadIds.filter((threadId) => isTrustedSubagentThread(session, threadId));
330
1074
  const activeSubagentThreadIds = allSubagentThreadIds.filter((threadId) => {