oh-my-codex 0.11.13 → 0.12.1

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 (377) hide show
  1. package/Cargo.lock +5 -5
  2. package/Cargo.toml +1 -1
  3. package/README.md +34 -17
  4. package/crates/omx-runtime/src/main.rs +6 -2
  5. package/dist/agents/native-config.js +1 -1
  6. package/dist/agents/native-config.js.map +1 -1
  7. package/dist/cli/__tests__/autoresearch-guided.test.js +74 -2
  8. package/dist/cli/__tests__/autoresearch-guided.test.js.map +1 -1
  9. package/dist/cli/__tests__/cleanup.test.js +37 -30
  10. package/dist/cli/__tests__/cleanup.test.js.map +1 -1
  11. package/dist/cli/__tests__/error-handling-warnings.test.js +3 -1
  12. package/dist/cli/__tests__/error-handling-warnings.test.js.map +1 -1
  13. package/dist/cli/__tests__/index.test.js +276 -5
  14. package/dist/cli/__tests__/index.test.js.map +1 -1
  15. package/dist/cli/__tests__/launch-fallback.test.js +95 -1
  16. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  17. package/dist/cli/__tests__/setup-refresh.test.js +49 -9
  18. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  19. package/dist/cli/__tests__/setup-scope.test.js +9 -0
  20. package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
  21. package/dist/cli/__tests__/team.test.js +136 -11
  22. package/dist/cli/__tests__/team.test.js.map +1 -1
  23. package/dist/cli/__tests__/uninstall.test.js +10 -0
  24. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  25. package/dist/cli/__tests__/windows-popup-loop-contract.test.js +1 -0
  26. package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
  27. package/dist/cli/autoresearch-guided.d.ts.map +1 -1
  28. package/dist/cli/autoresearch-guided.js +2 -1
  29. package/dist/cli/autoresearch-guided.js.map +1 -1
  30. package/dist/cli/autoresearch.d.ts.map +1 -1
  31. package/dist/cli/autoresearch.js +2 -1
  32. package/dist/cli/autoresearch.js.map +1 -1
  33. package/dist/cli/cleanup.d.ts.map +1 -1
  34. package/dist/cli/cleanup.js +10 -5
  35. package/dist/cli/cleanup.js.map +1 -1
  36. package/dist/cli/index.d.ts +21 -1
  37. package/dist/cli/index.d.ts.map +1 -1
  38. package/dist/cli/index.js +298 -36
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/cli/omx.js +2 -0
  41. package/dist/cli/omx.js.map +1 -1
  42. package/dist/cli/setup.d.ts +1 -0
  43. package/dist/cli/setup.d.ts.map +1 -1
  44. package/dist/cli/setup.js +41 -7
  45. package/dist/cli/setup.js.map +1 -1
  46. package/dist/cli/team.d.ts.map +1 -1
  47. package/dist/cli/team.js +16 -557
  48. package/dist/cli/team.js.map +1 -1
  49. package/dist/cli/uninstall.d.ts.map +1 -1
  50. package/dist/cli/uninstall.js +34 -9
  51. package/dist/cli/uninstall.js.map +1 -1
  52. package/dist/config/__tests__/generator-idempotent.test.js +79 -2
  53. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  54. package/dist/config/__tests__/generator-notify.test.js +2 -0
  55. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  56. package/dist/config/codex-hooks.d.ts +11 -0
  57. package/dist/config/codex-hooks.d.ts.map +1 -0
  58. package/dist/config/codex-hooks.js +50 -0
  59. package/dist/config/codex-hooks.js.map +1 -0
  60. package/dist/config/generator.d.ts +5 -3
  61. package/dist/config/generator.d.ts.map +1 -1
  62. package/dist/config/generator.js +24 -14
  63. package/dist/config/generator.js.map +1 -1
  64. package/dist/hooks/__tests__/debugger-log-recency-contract.test.d.ts +2 -0
  65. package/dist/hooks/__tests__/debugger-log-recency-contract.test.d.ts.map +1 -0
  66. package/dist/hooks/__tests__/debugger-log-recency-contract.test.js +20 -0
  67. package/dist/hooks/__tests__/debugger-log-recency-contract.test.js.map +1 -0
  68. package/dist/hooks/__tests__/keyword-detector.test.js +132 -0
  69. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  70. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +292 -4
  71. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  72. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +86 -0
  73. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  74. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +40 -0
  75. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  76. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.d.ts +2 -0
  77. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.d.ts.map +1 -0
  78. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +54 -0
  79. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -0
  80. package/dist/hooks/__tests__/notify-hook-modules.test.js +31 -0
  81. package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -1
  82. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +51 -0
  83. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -1
  84. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.d.ts +2 -0
  85. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.d.ts.map +1 -0
  86. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js +136 -0
  87. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js.map +1 -0
  88. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +120 -0
  89. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  90. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +145 -20
  91. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  92. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +116 -0
  93. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  94. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +86 -0
  95. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  96. package/dist/hooks/__tests__/pre-context-gate-skills.test.js +1 -0
  97. package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -1
  98. package/dist/hooks/extensibility/__tests__/runtime.test.js +49 -0
  99. package/dist/hooks/extensibility/__tests__/runtime.test.js.map +1 -1
  100. package/dist/hooks/extensibility/runtime.d.ts.map +1 -1
  101. package/dist/hooks/extensibility/runtime.js +10 -0
  102. package/dist/hooks/extensibility/runtime.js.map +1 -1
  103. package/dist/hooks/extensibility/types.d.ts +1 -1
  104. package/dist/hooks/extensibility/types.d.ts.map +1 -1
  105. package/dist/hooks/keyword-detector.d.ts +2 -0
  106. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  107. package/dist/hooks/keyword-detector.js +76 -4
  108. package/dist/hooks/keyword-detector.js.map +1 -1
  109. package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
  110. package/dist/hooks/prompt-guidance-contract.js +12 -8
  111. package/dist/hooks/prompt-guidance-contract.js.map +1 -1
  112. package/dist/hooks/session.d.ts +5 -1
  113. package/dist/hooks/session.d.ts.map +1 -1
  114. package/dist/hooks/session.js +10 -6
  115. package/dist/hooks/session.js.map +1 -1
  116. package/dist/hud/index.d.ts.map +1 -1
  117. package/dist/hud/index.js +6 -1
  118. package/dist/hud/index.js.map +1 -1
  119. package/dist/mcp/__tests__/bootstrap.test.js +0 -3
  120. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  121. package/dist/mcp/__tests__/code-intel-server.test.js +27 -1
  122. package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -1
  123. package/dist/mcp/__tests__/server-lifecycle.test.js +0 -5
  124. package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
  125. package/dist/mcp/bootstrap.d.ts +1 -1
  126. package/dist/mcp/bootstrap.d.ts.map +1 -1
  127. package/dist/mcp/bootstrap.js +0 -1
  128. package/dist/mcp/bootstrap.js.map +1 -1
  129. package/dist/mcp/code-intel-server.d.ts +20 -0
  130. package/dist/mcp/code-intel-server.d.ts.map +1 -1
  131. package/dist/mcp/code-intel-server.js +6 -5
  132. package/dist/mcp/code-intel-server.js.map +1 -1
  133. package/dist/notifications/__tests__/idle-cooldown.test.js +24 -1
  134. package/dist/notifications/__tests__/idle-cooldown.test.js.map +1 -1
  135. package/dist/notifications/__tests__/reply-listener.test.js +20 -1
  136. package/dist/notifications/__tests__/reply-listener.test.js.map +1 -1
  137. package/dist/notifications/__tests__/tmux.test.js +41 -0
  138. package/dist/notifications/__tests__/tmux.test.js.map +1 -1
  139. package/dist/notifications/idle-cooldown.d.ts +13 -0
  140. package/dist/notifications/idle-cooldown.d.ts.map +1 -1
  141. package/dist/notifications/idle-cooldown.js +50 -16
  142. package/dist/notifications/idle-cooldown.js.map +1 -1
  143. package/dist/notifications/reply-listener.d.ts.map +1 -1
  144. package/dist/notifications/reply-listener.js +2 -0
  145. package/dist/notifications/reply-listener.js.map +1 -1
  146. package/dist/notifications/tmux.d.ts.map +1 -1
  147. package/dist/notifications/tmux.js +4 -0
  148. package/dist/notifications/tmux.js.map +1 -1
  149. package/dist/scripts/__tests__/codex-native-hook.test.d.ts +2 -0
  150. package/dist/scripts/__tests__/codex-native-hook.test.d.ts.map +1 -0
  151. package/dist/scripts/__tests__/codex-native-hook.test.js +1050 -0
  152. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -0
  153. package/dist/scripts/codex-native-hook.d.ts +22 -0
  154. package/dist/scripts/codex-native-hook.d.ts.map +1 -0
  155. package/dist/scripts/codex-native-hook.js +792 -0
  156. package/dist/scripts/codex-native-hook.js.map +1 -0
  157. package/dist/scripts/codex-native-pre-post.d.ts +26 -0
  158. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -0
  159. package/dist/scripts/codex-native-pre-post.js +118 -0
  160. package/dist/scripts/codex-native-pre-post.js.map +1 -0
  161. package/dist/scripts/notify-fallback-watcher.js +322 -21
  162. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  163. package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
  164. package/dist/scripts/notify-hook/auto-nudge.js +5 -6
  165. package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
  166. package/dist/scripts/notify-hook/log.d.ts +2 -2
  167. package/dist/scripts/notify-hook/log.d.ts.map +1 -1
  168. package/dist/scripts/notify-hook/log.js +10 -2
  169. package/dist/scripts/notify-hook/log.js.map +1 -1
  170. package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
  171. package/dist/scripts/notify-hook/managed-tmux.js +2 -0
  172. package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
  173. package/dist/scripts/notify-hook/orchestration-intent.d.ts +18 -0
  174. package/dist/scripts/notify-hook/orchestration-intent.d.ts.map +1 -0
  175. package/dist/scripts/notify-hook/orchestration-intent.js +72 -0
  176. package/dist/scripts/notify-hook/orchestration-intent.js.map +1 -0
  177. package/dist/scripts/notify-hook/process-runner.js.map +1 -1
  178. package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
  179. package/dist/scripts/notify-hook/ralph-session-resume.js +7 -0
  180. package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
  181. package/dist/scripts/notify-hook/team-dispatch.d.ts +15 -6
  182. package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
  183. package/dist/scripts/notify-hook/team-dispatch.js +125 -6
  184. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  185. package/dist/scripts/notify-hook/team-leader-nudge.d.ts +3 -2
  186. package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
  187. package/dist/scripts/notify-hook/team-leader-nudge.js +165 -37
  188. package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
  189. package/dist/scripts/notify-hook/team-tmux-guard.d.ts +4 -1
  190. package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
  191. package/dist/scripts/notify-hook/team-tmux-guard.js +33 -44
  192. package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
  193. package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
  194. package/dist/scripts/notify-hook/team-worker.js +68 -5
  195. package/dist/scripts/notify-hook/team-worker.js.map +1 -1
  196. package/dist/scripts/notify-hook/utils.d.ts +1 -1
  197. package/dist/scripts/notify-hook/utils.d.ts.map +1 -1
  198. package/dist/scripts/notify-hook/utils.js.map +1 -1
  199. package/dist/scripts/notify-hook.js +55 -32
  200. package/dist/scripts/notify-hook.js.map +1 -1
  201. package/dist/team/__tests__/api-interop.test.js +344 -18
  202. package/dist/team/__tests__/api-interop.test.js.map +1 -1
  203. package/dist/team/__tests__/delivery-e2e-smoke.test.d.ts +2 -0
  204. package/dist/team/__tests__/delivery-e2e-smoke.test.d.ts.map +1 -0
  205. package/dist/team/__tests__/delivery-e2e-smoke.test.js +671 -0
  206. package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -0
  207. package/dist/team/__tests__/mcp-comm.test.js +5 -0
  208. package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
  209. package/dist/team/__tests__/runtime.test.js +543 -15
  210. package/dist/team/__tests__/runtime.test.js.map +1 -1
  211. package/dist/team/__tests__/state.test.js +133 -8
  212. package/dist/team/__tests__/state.test.js.map +1 -1
  213. package/dist/team/__tests__/team-ops-contract.test.js +4 -0
  214. package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
  215. package/dist/team/__tests__/tmux-session.test.js +160 -0
  216. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  217. package/dist/team/__tests__/worker-bootstrap.test.js +19 -1
  218. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  219. package/dist/team/api-interop.d.ts.map +1 -1
  220. package/dist/team/api-interop.js +95 -23
  221. package/dist/team/api-interop.js.map +1 -1
  222. package/dist/team/contracts.d.ts +11 -1
  223. package/dist/team/contracts.d.ts.map +1 -1
  224. package/dist/team/contracts.js +29 -0
  225. package/dist/team/contracts.js.map +1 -1
  226. package/dist/team/delivery-log.d.ts +14 -0
  227. package/dist/team/delivery-log.d.ts.map +1 -0
  228. package/dist/team/delivery-log.js +35 -0
  229. package/dist/team/delivery-log.js.map +1 -0
  230. package/dist/team/idle-nudge.d.ts +2 -2
  231. package/dist/team/idle-nudge.js +2 -2
  232. package/dist/team/mcp-comm.d.ts +4 -0
  233. package/dist/team/mcp-comm.d.ts.map +1 -1
  234. package/dist/team/mcp-comm.js +84 -1
  235. package/dist/team/mcp-comm.js.map +1 -1
  236. package/dist/team/pane-status.d.ts +149 -0
  237. package/dist/team/pane-status.d.ts.map +1 -0
  238. package/dist/team/pane-status.js +558 -0
  239. package/dist/team/pane-status.js.map +1 -0
  240. package/dist/team/reminder-intents.d.ts +11 -0
  241. package/dist/team/reminder-intents.d.ts.map +1 -0
  242. package/dist/team/reminder-intents.js +40 -0
  243. package/dist/team/reminder-intents.js.map +1 -0
  244. package/dist/team/runtime-cli.d.ts +1 -1
  245. package/dist/team/runtime-cli.js +2 -2
  246. package/dist/team/runtime-cli.js.map +1 -1
  247. package/dist/team/runtime.d.ts +2 -1
  248. package/dist/team/runtime.d.ts.map +1 -1
  249. package/dist/team/runtime.js +409 -191
  250. package/dist/team/runtime.js.map +1 -1
  251. package/dist/team/scaling.d.ts.map +1 -1
  252. package/dist/team/scaling.js +6 -5
  253. package/dist/team/scaling.js.map +1 -1
  254. package/dist/team/state/dispatch.d.ts +4 -1
  255. package/dist/team/state/dispatch.d.ts.map +1 -1
  256. package/dist/team/state/dispatch.js +59 -18
  257. package/dist/team/state/dispatch.js.map +1 -1
  258. package/dist/team/state/mailbox.d.ts.map +1 -1
  259. package/dist/team/state/mailbox.js +45 -2
  260. package/dist/team/state/mailbox.js.map +1 -1
  261. package/dist/team/state/monitor.d.ts +2 -1
  262. package/dist/team/state/monitor.d.ts.map +1 -1
  263. package/dist/team/state/monitor.js +30 -1
  264. package/dist/team/state/monitor.js.map +1 -1
  265. package/dist/team/state/types.d.ts +5 -2
  266. package/dist/team/state/types.d.ts.map +1 -1
  267. package/dist/team/state/types.js.map +1 -1
  268. package/dist/team/state.d.ts +30 -3
  269. package/dist/team/state.d.ts.map +1 -1
  270. package/dist/team/state.js +170 -2
  271. package/dist/team/state.js.map +1 -1
  272. package/dist/team/team-ops.d.ts +5 -1
  273. package/dist/team/team-ops.d.ts.map +1 -1
  274. package/dist/team/team-ops.js +4 -0
  275. package/dist/team/team-ops.js.map +1 -1
  276. package/dist/team/tmux-session.d.ts +2 -0
  277. package/dist/team/tmux-session.d.ts.map +1 -1
  278. package/dist/team/tmux-session.js +19 -3
  279. package/dist/team/tmux-session.js.map +1 -1
  280. package/dist/team/worker-bootstrap.d.ts +4 -0
  281. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  282. package/dist/team/worker-bootstrap.js +33 -6
  283. package/dist/team/worker-bootstrap.js.map +1 -1
  284. package/dist/utils/__tests__/paths.test.js +63 -1
  285. package/dist/utils/__tests__/paths.test.js.map +1 -1
  286. package/dist/utils/__tests__/platform-command.test.js +50 -4
  287. package/dist/utils/__tests__/platform-command.test.js.map +1 -1
  288. package/dist/utils/paths.d.ts +12 -0
  289. package/dist/utils/paths.d.ts.map +1 -1
  290. package/dist/utils/paths.js +44 -2
  291. package/dist/utils/paths.js.map +1 -1
  292. package/dist/utils/platform-command.d.ts.map +1 -1
  293. package/dist/utils/platform-command.js +13 -5
  294. package/dist/utils/platform-command.js.map +1 -1
  295. package/dist/utils/sleep.d.ts.map +1 -1
  296. package/dist/utils/sleep.js +10 -1
  297. package/dist/utils/sleep.js.map +1 -1
  298. package/package.json +1 -1
  299. package/prompts/analyst.md +2 -2
  300. package/prompts/api-reviewer.md +2 -2
  301. package/prompts/architect.md +2 -2
  302. package/prompts/build-fixer.md +2 -2
  303. package/prompts/code-reviewer.md +2 -2
  304. package/prompts/code-simplifier.md +1 -1
  305. package/prompts/critic.md +2 -2
  306. package/prompts/debugger.md +3 -2
  307. package/prompts/dependency-expert.md +2 -2
  308. package/prompts/designer.md +2 -2
  309. package/prompts/executor.md +3 -2
  310. package/prompts/explore.md +2 -2
  311. package/prompts/git-master.md +2 -2
  312. package/prompts/information-architect.md +15 -102
  313. package/prompts/performance-reviewer.md +2 -2
  314. package/prompts/planner.md +3 -2
  315. package/prompts/product-analyst.md +2 -2
  316. package/prompts/product-manager.md +2 -2
  317. package/prompts/qa-tester.md +2 -2
  318. package/prompts/quality-reviewer.md +2 -2
  319. package/prompts/quality-strategist.md +2 -2
  320. package/prompts/researcher.md +2 -2
  321. package/prompts/security-reviewer.md +2 -2
  322. package/prompts/sisyphus-lite.md +2 -2
  323. package/prompts/style-reviewer.md +2 -2
  324. package/prompts/team-executor.md +2 -2
  325. package/prompts/test-engineer.md +2 -2
  326. package/prompts/ux-researcher.md +2 -2
  327. package/prompts/verifier.md +3 -2
  328. package/prompts/vision.md +2 -2
  329. package/prompts/writer.md +2 -2
  330. package/skills/team/SKILL.md +18 -33
  331. package/src/scripts/__tests__/codex-native-hook.test.ts +1346 -0
  332. package/src/scripts/codex-native-hook.ts +983 -0
  333. package/src/scripts/codex-native-pre-post.ts +161 -0
  334. package/src/scripts/notify-fallback-watcher.ts +378 -29
  335. package/src/scripts/notify-hook/auto-nudge.ts +5 -10
  336. package/src/scripts/notify-hook/log.ts +18 -4
  337. package/src/scripts/notify-hook/managed-tmux.ts +1 -0
  338. package/src/scripts/notify-hook/orchestration-intent.ts +82 -0
  339. package/src/scripts/notify-hook/process-runner.ts +4 -4
  340. package/src/scripts/notify-hook/ralph-session-resume.ts +9 -0
  341. package/src/scripts/notify-hook/team-dispatch.ts +134 -6
  342. package/src/scripts/notify-hook/team-leader-nudge.ts +183 -37
  343. package/src/scripts/notify-hook/team-tmux-guard.ts +35 -43
  344. package/src/scripts/notify-hook/team-worker.ts +73 -4
  345. package/src/scripts/notify-hook/utils.ts +1 -1
  346. package/src/scripts/notify-hook.ts +64 -32
  347. package/templates/AGENTS.md +21 -11
  348. package/README.de.md +0 -263
  349. package/README.el.md +0 -223
  350. package/README.es.md +0 -263
  351. package/README.fr.md +0 -263
  352. package/README.it.md +0 -263
  353. package/README.ja.md +0 -264
  354. package/README.ko.md +0 -264
  355. package/README.pl.md +0 -216
  356. package/README.pt.md +0 -263
  357. package/README.ru.md +0 -263
  358. package/README.tr.md +0 -263
  359. package/README.vi.md +0 -223
  360. package/README.zh-TW.md +0 -293
  361. package/README.zh.md +0 -264
  362. package/dist/mcp/__tests__/team-server-cleanup.test.d.ts +0 -2
  363. package/dist/mcp/__tests__/team-server-cleanup.test.d.ts.map +0 -1
  364. package/dist/mcp/__tests__/team-server-cleanup.test.js +0 -219
  365. package/dist/mcp/__tests__/team-server-cleanup.test.js.map +0 -1
  366. package/dist/mcp/__tests__/team-server-runtime-deps.test.d.ts +0 -2
  367. package/dist/mcp/__tests__/team-server-runtime-deps.test.d.ts.map +0 -1
  368. package/dist/mcp/__tests__/team-server-runtime-deps.test.js +0 -13
  369. package/dist/mcp/__tests__/team-server-runtime-deps.test.js.map +0 -1
  370. package/dist/mcp/__tests__/team-server-wait.test.d.ts +0 -2
  371. package/dist/mcp/__tests__/team-server-wait.test.d.ts.map +0 -1
  372. package/dist/mcp/__tests__/team-server-wait.test.js +0 -155
  373. package/dist/mcp/__tests__/team-server-wait.test.js.map +0 -1
  374. package/dist/mcp/team-server.d.ts +0 -24
  375. package/dist/mcp/team-server.d.ts.map +0 -1
  376. package/dist/mcp/team-server.js +0 -482
  377. package/dist/mcp/team-server.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { existsSync } from 'fs';
4
- import { appendFile, mkdir, open, readFile, readdir, rename, stat, unlink, writeFile } from 'fs/promises';
4
+ import { appendFile, mkdir, open, readFile, readdir, rename, rm, stat, unlink, writeFile } from 'fs/promises';
5
5
  import { spawnSync } from 'child_process';
6
6
  import { dirname, join, resolve } from 'path';
7
7
  import { homedir } from 'os';
@@ -25,6 +25,10 @@ import {
25
25
  import { DEFAULT_MARKER } from './tmux-hook-engine.js';
26
26
  import { isTerminalPhase } from './notify-hook/utils.js';
27
27
  import { isSessionStale, readSessionState } from '../hooks/session.js';
28
+ import {
29
+ DEFAULT_SUBAGENT_ACTIVE_WINDOW_MS,
30
+ readSubagentSessionSummary,
31
+ } from '../subagents/tracker.js';
28
32
 
29
33
  function argValue(name: string, fallback = ''): string {
30
34
  const idx = process.argv.indexOf(name);
@@ -82,6 +86,10 @@ const authorityOnly = process.argv.includes('--authority-only');
82
86
  // ack budget so leaderless team dispatch + stale-alert recovery do not feel
83
87
  // laggy between native notify-hook turns.
84
88
  const pollMs = Math.max(50, asNumber(argValue('--poll-ms', '250'), 250));
89
+ const idleMaxPollMs = Math.max(
90
+ pollMs,
91
+ asNumber(argValue('--idle-max-poll-ms', process.env.OMX_NOTIFY_FALLBACK_IDLE_MAX_POLL_MS || '1000'), 1000),
92
+ );
85
93
  const parentPid = Math.trunc(asNumber(argValue('--parent-pid', String(process.ppid || 0)), process.ppid || 0));
86
94
  const startedAt = Date.now();
87
95
  const fileWindowMs = runOnce ? 15000 : 30000;
@@ -102,6 +110,13 @@ const stateDir = join(omxDir, 'state');
102
110
  const statePath = join(stateDir, 'notify-fallback-state.json');
103
111
  const pidFilePath = resolve(argValue('--pid-file', join(stateDir, 'notify-fallback.pid')));
104
112
  const logPath = join(logsDir, `notify-fallback-${new Date().toISOString().split('T')[0]}.jsonl`);
113
+ const logRotatePath = `${logPath}.1`;
114
+ const logLockPath = `${logPath}.lock`;
115
+ const defaultMaxLogBytes = 10 * 1024 * 1024;
116
+ const maxLogBytes = Math.max(
117
+ 0,
118
+ asNumber(argValue('--log-max-bytes', process.env.OMX_NOTIFY_FALLBACK_LOG_MAX_BYTES || String(defaultMaxLogBytes)), defaultMaxLogBytes),
119
+ );
105
120
  const ralphSteerTimestampPath = join(stateDir, 'ralph-last-steer-at');
106
121
  const ralphSteerLockPath = join(stateDir, 'ralph-continue-steer.lock');
107
122
  const watcherOwnerToken = `${process.pid}-${startedAt}-${Math.random().toString(36).slice(2, 10)}`;
@@ -109,6 +124,7 @@ const RALPH_CONTINUE_TEXT = 'Ralph loop active continue';
109
124
  const RALPH_CONTINUE_CADENCE_MS = 60_000;
110
125
  const RALPH_STEER_LOCK_STALE_MS = 30_000;
111
126
  const RALPH_TERMINAL_PHASES = new Set(['complete', 'failed', 'cancelled']);
127
+ const QUIET_ONCE_EVENT_TYPES = new Set(['watcher_start', 'watcher_once_complete']);
112
128
 
113
129
  interface WatcherFileMeta {
114
130
  threadId: string;
@@ -131,6 +147,8 @@ interface RalphContinueSteerState {
131
147
  pane_id: string;
132
148
  pane_current_command: string;
133
149
  current_phase: string;
150
+ subagent_session_id: string;
151
+ active_subagent_thread_ids: string[];
134
152
  shared_timestamp_path: string;
135
153
  shared_last_sent_at: string;
136
154
  singleton_lock_path: string;
@@ -174,6 +192,15 @@ interface ParentGuardState {
174
192
  pane_count?: number;
175
193
  }
176
194
 
195
+ interface AuthorityBackoffState {
196
+ active: boolean;
197
+ reason: string;
198
+ primary_pid: number | null;
199
+ primary_last_tick_at: string;
200
+ freshness_ms: number | null;
201
+ threshold_ms: number | null;
202
+ }
203
+
177
204
  interface ActiveTeamResult {
178
205
  active: boolean;
179
206
  reason: string;
@@ -196,6 +223,22 @@ interface FallbackAutoNudgeState {
196
223
  last_nudged_at: string;
197
224
  }
198
225
 
226
+ interface AdaptivePollState {
227
+ enabled: boolean;
228
+ base_ms: number;
229
+ max_ms: number;
230
+ current_ms: number;
231
+ idle_streak: number;
232
+ last_tick_at: string | null;
233
+ last_activity_at: string | null;
234
+ last_activity_reason: string;
235
+ }
236
+
237
+ interface CycleActivitySummary {
238
+ active: boolean;
239
+ reason: string;
240
+ }
241
+
199
242
  const fileState = new Map<string, WatcherFileMeta>();
200
243
  const seenTurnKeys = new Set<string>();
201
244
  let stopping = false;
@@ -231,6 +274,8 @@ let lastRalphContinueSteer: RalphContinueSteerState = {
231
274
  pane_id: '',
232
275
  pane_current_command: '',
233
276
  current_phase: '',
277
+ subagent_session_id: '',
278
+ active_subagent_thread_ids: [],
234
279
  shared_timestamp_path: ralphSteerTimestampPath,
235
280
  shared_last_sent_at: '',
236
281
  singleton_lock_path: ralphSteerLockPath,
@@ -240,6 +285,14 @@ let lastParentGuard: ParentGuardState = {
240
285
  state_path: '',
241
286
  current_phase: '',
242
287
  };
288
+ let lastAuthorityBackoff: AuthorityBackoffState = {
289
+ active: false,
290
+ reason: '',
291
+ primary_pid: null,
292
+ primary_last_tick_at: '',
293
+ freshness_ms: null,
294
+ threshold_ms: null,
295
+ };
243
296
  const AUTO_NUDGE_STALL_MS = Math.max(
244
297
  pollMs,
245
298
  asNumber(process.env.OMX_NOTIFY_FALLBACK_AUTO_NUDGE_STALL_MS || '5000', 5000),
@@ -256,14 +309,108 @@ let lastFallbackAutoNudge: FallbackAutoNudgeState = {
256
309
  last_nudged_signature: '',
257
310
  last_nudged_at: '',
258
311
  };
259
- function eventLog(event: Record<string, unknown>): Promise<void> {
260
- return appendFile(logPath, `${JSON.stringify({ timestamp: new Date().toISOString(), ...event })}\n`).catch(() => {});
312
+ let adaptivePollState: AdaptivePollState = {
313
+ enabled: true,
314
+ base_ms: pollMs,
315
+ max_ms: idleMaxPollMs,
316
+ current_ms: pollMs,
317
+ idle_streak: 0,
318
+ last_tick_at: null,
319
+ last_activity_at: null,
320
+ last_activity_reason: 'init',
321
+ };
322
+
323
+ function shouldSuppressEventLog(event: Record<string, unknown>): boolean {
324
+ const eventType = safeString(event.type).trim();
325
+ return runOnce && QUIET_ONCE_EVENT_TYPES.has(eventType);
326
+ }
327
+
328
+ async function acquireLogLock(timeoutMs = 1000): Promise<boolean> {
329
+ const deadline = Date.now() + timeoutMs;
330
+ while (Date.now() < deadline) {
331
+ try {
332
+ await mkdir(logLockPath, { recursive: false });
333
+ return true;
334
+ } catch (error) {
335
+ if ((error as NodeJS.ErrnoException | null)?.code !== 'EEXIST') return false;
336
+ const lockStat = await stat(logLockPath).catch(() => null);
337
+ if (lockStat && Date.now() - lockStat.mtimeMs > 5000) {
338
+ await rm(logLockPath, { recursive: true, force: true }).catch(() => {});
339
+ continue;
340
+ }
341
+ await sleep(10);
342
+ }
343
+ }
344
+ return false;
345
+ }
346
+
347
+ async function releaseLogLock(): Promise<void> {
348
+ await rm(logLockPath, { recursive: true, force: true }).catch(() => {});
349
+ }
350
+
351
+ async function rotateLogIfNeeded(nextEntryBytes: number): Promise<void> {
352
+ if (maxLogBytes <= 0) return;
353
+ const currentStat = await stat(logPath).catch(() => null);
354
+ if (!currentStat || currentStat.size + nextEntryBytes <= maxLogBytes) return;
355
+ await unlink(logRotatePath).catch(() => {});
356
+ await rename(logPath, logRotatePath).catch(() => {});
357
+ }
358
+
359
+ async function eventLog(event: Record<string, unknown>): Promise<void> {
360
+ if (shouldSuppressEventLog(event)) return;
361
+ const line = `${JSON.stringify({ timestamp: new Date().toISOString(), ...event })}\n`;
362
+ await mkdir(dirname(logPath), { recursive: true }).catch(() => {});
363
+ const locked = await acquireLogLock();
364
+ if (!locked) return;
365
+ try {
366
+ await rotateLogIfNeeded(Buffer.byteLength(line));
367
+ await appendFile(logPath, line);
368
+ } catch {
369
+ // best effort only
370
+ } finally {
371
+ await releaseLogLock();
372
+ }
261
373
  }
262
374
 
263
375
  function shouldLogLeaderNudgeTick(reason: string): boolean {
264
376
  return reason === 'leader_nudge_checked' || reason === 'leader_nudge_failed';
265
377
  }
266
378
 
379
+ function nextIdlePollMs(currentMs: number): number {
380
+ return Math.min(idleMaxPollMs, Math.max(pollMs, currentMs * 2));
381
+ }
382
+
383
+ function updateAdaptivePollState(summary: CycleActivitySummary): number {
384
+ const nowIso = new Date().toISOString();
385
+ if (summary.active) {
386
+ adaptivePollState = {
387
+ ...adaptivePollState,
388
+ enabled: true,
389
+ base_ms: pollMs,
390
+ max_ms: idleMaxPollMs,
391
+ current_ms: pollMs,
392
+ idle_streak: 0,
393
+ last_tick_at: nowIso,
394
+ last_activity_at: nowIso,
395
+ last_activity_reason: summary.reason,
396
+ };
397
+ return adaptivePollState.current_ms;
398
+ }
399
+
400
+ const nextMs = nextIdlePollMs(adaptivePollState.current_ms);
401
+ adaptivePollState = {
402
+ ...adaptivePollState,
403
+ enabled: true,
404
+ base_ms: pollMs,
405
+ max_ms: idleMaxPollMs,
406
+ current_ms: nextMs,
407
+ idle_streak: adaptivePollState.idle_streak + 1,
408
+ last_tick_at: nowIso,
409
+ last_activity_reason: summary.reason,
410
+ };
411
+ return adaptivePollState.current_ms;
412
+ }
413
+
267
414
  function shouldLogDispatchDrainTick(result: unknown): boolean {
268
415
  if (!result || typeof result !== 'object') return false;
269
416
  const record = result as Record<string, unknown>;
@@ -291,6 +438,10 @@ function normalizeRalphContinueSteerState(raw: Record<string, unknown> | null |
291
438
  pane_id: safeString(raw.pane_id),
292
439
  pane_current_command: safeString(raw.pane_current_command),
293
440
  current_phase: safeString(raw.current_phase),
441
+ subagent_session_id: safeString(raw.subagent_session_id),
442
+ active_subagent_thread_ids: Array.isArray(raw.active_subagent_thread_ids)
443
+ ? raw.active_subagent_thread_ids.map((value) => safeString(value).trim()).filter(Boolean)
444
+ : [],
294
445
  shared_timestamp_path: safeString(raw.shared_timestamp_path) || ralphSteerTimestampPath,
295
446
  shared_last_sent_at: safeString(raw.shared_last_sent_at),
296
447
  singleton_lock_path: safeString(raw.singleton_lock_path) || ralphSteerLockPath,
@@ -328,6 +479,19 @@ async function loadPersistedWatcherState(): Promise<void> {
328
479
  last_nudged_at: safeString(persistedAutoNudge.last_nudged_at),
329
480
  };
330
481
  }
482
+ const persistedAdaptivePoll = persisted?.adaptive_poll as Record<string, unknown> | null | undefined;
483
+ if (persistedAdaptivePoll && typeof persistedAdaptivePoll === 'object') {
484
+ adaptivePollState = {
485
+ enabled: persistedAdaptivePoll.enabled !== false,
486
+ base_ms: pollMs,
487
+ max_ms: idleMaxPollMs,
488
+ current_ms: Math.min(idleMaxPollMs, Math.max(pollMs, asNumber(persistedAdaptivePoll.current_ms as string | number | undefined, pollMs))),
489
+ idle_streak: Math.max(0, Math.trunc(asNumber(persistedAdaptivePoll.idle_streak as string | number | undefined, 0))),
490
+ last_tick_at: safeString(persistedAdaptivePoll.last_tick_at) || null,
491
+ last_activity_at: safeString(persistedAdaptivePoll.last_activity_at) || null,
492
+ last_activity_reason: safeString(persistedAdaptivePoll.last_activity_reason) || 'init',
493
+ };
494
+ }
331
495
  }
332
496
 
333
497
  interface ActiveModeResult {
@@ -534,7 +698,8 @@ async function withRalphSteerLock<T>(task: () => Promise<T>): Promise<T | null>
534
698
  if (code !== 'EEXIST') throw error;
535
699
  const existing = await readRalphSteerLock(ralphSteerLockPath);
536
700
  const lockAgeMs = parseIsoMillis(existing?.acquired_at) ?? 0;
537
- const stale = !existing || !isPidAlive(existing.pid) || (lockAgeMs > 0 && Date.now() - lockAgeMs > RALPH_STEER_LOCK_STALE_MS);
701
+ const stale = existing !== null
702
+ && (!isPidAlive(existing.pid) || (lockAgeMs > 0 && Date.now() - lockAgeMs > RALPH_STEER_LOCK_STALE_MS));
538
703
  if (stale) {
539
704
  await unlink(ralphSteerLockPath).catch(() => {});
540
705
  continue;
@@ -560,29 +725,51 @@ interface RalphProgressGateResult {
560
725
  allow: boolean;
561
726
  reason: string;
562
727
  progress_at: string;
563
- }
728
+ subagent_session_id?: string;
729
+ active_subagent_thread_ids?: string[];
730
+ }
731
+
732
+ async function readRalphProgressGate(
733
+ activeRalphState: Record<string, unknown> | null,
734
+ now: number,
735
+ ): Promise<RalphProgressGateResult> {
736
+ const subagentSessionId = safeString(activeRalphState?.owner_codex_session_id).trim();
737
+ if (subagentSessionId) {
738
+ const summary = await readSubagentSessionSummary(cwd, subagentSessionId, {
739
+ now: new Date(now),
740
+ activeWindowMs: DEFAULT_SUBAGENT_ACTIVE_WINDOW_MS,
741
+ });
742
+ if ((summary?.activeSubagentThreadIds.length ?? 0) > 0) {
743
+ return {
744
+ allow: false,
745
+ reason: 'subagents_active',
746
+ progress_at: '',
747
+ subagent_session_id: subagentSessionId,
748
+ active_subagent_thread_ids: summary?.activeSubagentThreadIds ?? [],
749
+ };
750
+ }
751
+ }
564
752
 
565
- async function readRalphProgressGate(now: number): Promise<RalphProgressGateResult> {
566
753
  const hudState = await readJsonObject(join(stateDir, 'hud-state.json'));
567
754
  if (!hudState || typeof hudState !== 'object') {
568
- return { allow: false, reason: 'progress_missing', progress_at: '' };
755
+ return { allow: false, reason: 'progress_missing', progress_at: '', subagent_session_id: subagentSessionId };
569
756
  }
570
757
 
571
758
  const progressAt = safeString(hudState.last_progress_at).trim();
572
759
  if (!progressAt) {
573
- return { allow: false, reason: 'progress_missing', progress_at: '' };
760
+ return { allow: false, reason: 'progress_missing', progress_at: '', subagent_session_id: subagentSessionId };
574
761
  }
575
762
 
576
763
  const progressMs = parseIsoMillis(progressAt);
577
764
  if (progressMs === null) {
578
- return { allow: false, reason: 'progress_invalid', progress_at: progressAt };
765
+ return { allow: false, reason: 'progress_invalid', progress_at: progressAt, subagent_session_id: subagentSessionId };
579
766
  }
580
767
 
581
768
  if (now - progressMs < RALPH_CONTINUE_CADENCE_MS) {
582
- return { allow: false, reason: 'progress_fresh', progress_at: progressAt };
769
+ return { allow: false, reason: 'progress_fresh', progress_at: progressAt, subagent_session_id: subagentSessionId };
583
770
  }
584
771
 
585
- return { allow: true, reason: 'progress_stale', progress_at: progressAt };
772
+ return { allow: true, reason: 'progress_stale', progress_at: progressAt, subagent_session_id: subagentSessionId };
586
773
  }
587
774
 
588
775
  function shouldSkipRalphContinue(now: number, candidateIso: string, startupIso: string): { skip: boolean; reason: string; anchorMs: number; anchorIso: string } {
@@ -625,6 +812,108 @@ async function readPidFileRecord(path: string): Promise<PidFileRecord | null> {
625
812
  }
626
813
  }
627
814
 
815
+ function createAuthorityBackoffState(
816
+ reason: string,
817
+ overrides: Partial<AuthorityBackoffState> = {},
818
+ ): AuthorityBackoffState {
819
+ return {
820
+ active: false,
821
+ reason,
822
+ primary_pid: null,
823
+ primary_last_tick_at: '',
824
+ freshness_ms: null,
825
+ threshold_ms: null,
826
+ ...overrides,
827
+ };
828
+ }
829
+
830
+ function latestWatcherTickIso(state: Record<string, unknown> | null): string {
831
+ if (!state || typeof state !== 'object') return '';
832
+ const candidates = [
833
+ safeString((state.dispatch_drain as Record<string, unknown> | undefined)?.last_tick_at),
834
+ safeString((state.leader_nudge as Record<string, unknown> | undefined)?.last_tick_at),
835
+ safeString((state.fallback_auto_nudge as Record<string, unknown> | undefined)?.last_tick_at),
836
+ safeString((state.ralph_continue_steer as Record<string, unknown> | undefined)?.last_state_check_at),
837
+ ]
838
+ .map((value) => value.trim())
839
+ .filter(Boolean);
840
+ let latestIso = '';
841
+ let latestMs = -1;
842
+ for (const candidate of candidates) {
843
+ const parsed = parseIsoMillis(candidate);
844
+ if (parsed === null || parsed <= latestMs) continue;
845
+ latestMs = parsed;
846
+ latestIso = candidate;
847
+ }
848
+ return latestIso;
849
+ }
850
+
851
+ async function resolveAuthorityPrimaryWatcherHealth(now = Date.now()): Promise<AuthorityBackoffState> {
852
+ if (!authorityOnly) return createAuthorityBackoffState('not_authority');
853
+
854
+ const existingRecord = await readPidFileRecord(pidFilePath).catch(() => null);
855
+ if (!existingRecord) return createAuthorityBackoffState('pid_missing');
856
+ if (existingRecord.cwd && resolve(existingRecord.cwd) !== cwd) return createAuthorityBackoffState('cwd_mismatch');
857
+ if (!isPidAlive(existingRecord.pid)) {
858
+ return createAuthorityBackoffState('pid_stale', {
859
+ primary_pid: existingRecord.pid,
860
+ });
861
+ }
862
+
863
+ const persistedState = await readJsonObject(statePath);
864
+ if (!persistedState) {
865
+ return createAuthorityBackoffState('state_missing', {
866
+ primary_pid: existingRecord.pid,
867
+ });
868
+ }
869
+
870
+ const persistedPid = Math.trunc(asNumber(persistedState.pid as string | number | undefined, 0));
871
+ if (persistedPid > 0 && persistedPid !== existingRecord.pid) {
872
+ return createAuthorityBackoffState('state_pid_mismatch', {
873
+ primary_pid: existingRecord.pid,
874
+ });
875
+ }
876
+
877
+ const lastTickAt = latestWatcherTickIso(persistedState);
878
+ if (!lastTickAt) {
879
+ return createAuthorityBackoffState('tick_missing', {
880
+ primary_pid: existingRecord.pid,
881
+ });
882
+ }
883
+
884
+ const lastTickMs = parseIsoMillis(lastTickAt);
885
+ const primaryPollMs = Math.max(50, asNumber(persistedState.poll_ms as string | number | undefined, 250));
886
+ const thresholdMs = Math.max(1_000, primaryPollMs * 4);
887
+ if (lastTickMs === null) {
888
+ return createAuthorityBackoffState('tick_invalid', {
889
+ primary_pid: existingRecord.pid,
890
+ primary_last_tick_at: lastTickAt,
891
+ threshold_ms: thresholdMs,
892
+ });
893
+ }
894
+
895
+ const freshnessMs = now - lastTickMs;
896
+ if (freshnessMs > thresholdMs) {
897
+ return {
898
+ active: false,
899
+ reason: 'tick_stale',
900
+ primary_pid: existingRecord.pid,
901
+ primary_last_tick_at: lastTickAt,
902
+ freshness_ms: freshnessMs,
903
+ threshold_ms: thresholdMs,
904
+ };
905
+ }
906
+
907
+ return {
908
+ active: true,
909
+ reason: 'primary_watcher_healthy',
910
+ primary_pid: existingRecord.pid,
911
+ primary_last_tick_at: lastTickAt,
912
+ freshness_ms: freshnessMs,
913
+ threshold_ms: thresholdMs,
914
+ };
915
+ }
916
+
628
917
  async function writePidFileRecord(): Promise<void> {
629
918
  const nextRecord: PidFileRecord = {
630
919
  pid: process.pid,
@@ -653,6 +942,8 @@ async function runRalphContinueSteerTick(): Promise<void> {
653
942
  state_path: activeRalph.path,
654
943
  pane_id: activePaneId,
655
944
  pane_current_command: '',
945
+ subagent_session_id: safeString(activeRalph.state?.owner_codex_session_id).trim(),
946
+ active_subagent_thread_ids: [],
656
947
  shared_timestamp_path: ralphSteerTimestampPath,
657
948
  singleton_lock_path: ralphSteerLockPath,
658
949
  };
@@ -686,9 +977,11 @@ async function runRalphContinueSteerTick(): Promise<void> {
686
977
  return { sent: false, skipped: true };
687
978
  }
688
979
 
689
- const progressGate = await readRalphProgressGate(Date.now());
980
+ const progressGate = await readRalphProgressGate(activeRalph.state, Date.now());
690
981
  if (!progressGate.allow) {
691
982
  lastRalphContinueSteer.last_reason = progressGate.reason;
983
+ lastRalphContinueSteer.subagent_session_id = progressGate.subagent_session_id ?? lastRalphContinueSteer.subagent_session_id;
984
+ lastRalphContinueSteer.active_subagent_thread_ids = progressGate.active_subagent_thread_ids ?? [];
692
985
  return { sent: false, skipped: true };
693
986
  }
694
987
 
@@ -811,6 +1104,8 @@ async function writeState(extra: Record<string, unknown> = {}): Promise<void> {
811
1104
  notify_script: notifyScript,
812
1105
  authority_only: authorityOnly,
813
1106
  poll_ms: pollMs,
1107
+ effective_poll_ms: adaptivePollState.current_ms,
1108
+ idle_max_poll_ms: idleMaxPollMs,
814
1109
  pid_file: runOnce ? null : pidFilePath,
815
1110
  max_lifetime_ms: maxLifetimeMs,
816
1111
  tracked_files: fileState.size,
@@ -837,11 +1132,27 @@ async function writeState(extra: Record<string, unknown> = {}): Promise<void> {
837
1132
  enabled: true,
838
1133
  stall_ms: AUTO_NUDGE_STALL_MS,
839
1134
  },
1135
+ authority_backoff: lastAuthorityBackoff,
1136
+ adaptive_poll: {
1137
+ ...adaptivePollState,
1138
+ enabled: true,
1139
+ base_ms: pollMs,
1140
+ max_ms: idleMaxPollMs,
1141
+ },
840
1142
  ...extra,
841
1143
  };
842
1144
  await writeFile(statePath, JSON.stringify(state, null, 2)).catch(() => {});
843
1145
  }
844
1146
 
1147
+ async function writeAuthorityBackoffState(): Promise<void> {
1148
+ await mkdir(stateDir, { recursive: true }).catch(() => {});
1149
+ const existing = await readJsonObject(statePath);
1150
+ const state = existing && typeof existing === 'object'
1151
+ ? { ...existing, authority_backoff: lastAuthorityBackoff }
1152
+ : { authority_backoff: lastAuthorityBackoff };
1153
+ await writeFile(statePath, JSON.stringify(state, null, 2)).catch(() => {});
1154
+ }
1155
+
845
1156
  async function readJsonObject(path: string): Promise<Record<string, unknown> | null> {
846
1157
  return readFile(path, 'utf-8')
847
1158
  .then((content) => JSON.parse(content) as Record<string, unknown>)
@@ -1195,7 +1506,8 @@ function splitBufferedLines(partial: string, delta: string): { lines: string[];
1195
1506
  };
1196
1507
  }
1197
1508
 
1198
- async function pollFiles(): Promise<void> {
1509
+ async function pollFiles(): Promise<number> {
1510
+ let processedCount = 0;
1199
1511
  for (const [path, meta] of fileState.entries()) {
1200
1512
  const currentSize = (await stat(path).catch(() => ({ size: 0 }))).size || 0;
1201
1513
  if (currentSize <= meta.offset) continue;
@@ -1209,11 +1521,13 @@ async function pollFiles(): Promise<void> {
1209
1521
  for (const line of lines) {
1210
1522
  if (!line.trim()) continue;
1211
1523
  await processLine(meta, line, path);
1524
+ processedCount += 1;
1212
1525
  }
1213
1526
  }
1527
+ return processedCount;
1214
1528
  }
1215
1529
 
1216
- async function runLeaderNudgeTick(): Promise<void> {
1530
+ async function runLeaderNudgeTick(): Promise<boolean> {
1217
1531
  const startedIso = new Date().toISOString();
1218
1532
  const leaderOnly = safeString(process.env.OMX_TEAM_WORKER || '').trim() === '';
1219
1533
  const staleThresholdMs = resolveLeaderStalenessThresholdMs();
@@ -1228,7 +1542,7 @@ async function runLeaderNudgeTick(): Promise<void> {
1228
1542
  last_tick_at: startedIso,
1229
1543
  last_error: 'worker_context',
1230
1544
  };
1231
- return;
1545
+ return false;
1232
1546
  }
1233
1547
 
1234
1548
  try {
@@ -1239,6 +1553,7 @@ async function runLeaderNudgeTick(): Promise<void> {
1239
1553
  logsDir,
1240
1554
  preComputedLeaderStale,
1241
1555
  allowFreshMailboxNudges: false,
1556
+ source: 'notify_fallback_watcher',
1242
1557
  });
1243
1558
  leaderNudgeRuns += 1;
1244
1559
  lastLeaderNudge = {
@@ -1260,6 +1575,7 @@ async function runLeaderNudgeTick(): Promise<void> {
1260
1575
  reason,
1261
1576
  });
1262
1577
  }
1578
+ return preComputedLeaderStale;
1263
1579
  } catch (err) {
1264
1580
  leaderNudgeRuns += 1;
1265
1581
  lastLeaderNudge = {
@@ -1278,10 +1594,11 @@ async function runLeaderNudgeTick(): Promise<void> {
1278
1594
  reason: 'leader_nudge_failed',
1279
1595
  error: lastLeaderNudge.last_error,
1280
1596
  });
1597
+ return true;
1281
1598
  }
1282
1599
  }
1283
1600
 
1284
- async function runDispatchDrainTick(): Promise<void> {
1601
+ async function runDispatchDrainTick(): Promise<boolean> {
1285
1602
  const startedIso = new Date().toISOString();
1286
1603
  try {
1287
1604
  const result = await drainPendingTeamDispatch({ cwd, stateDir, logsDir, maxPerTick: dispatchTickMax } as any);
@@ -1301,6 +1618,7 @@ async function runDispatchDrainTick(): Promise<void> {
1301
1618
  ...(result && typeof result === 'object' ? result as Record<string, unknown> : {}),
1302
1619
  });
1303
1620
  }
1621
+ return shouldLogDispatchDrainTick(result);
1304
1622
  } catch (err) {
1305
1623
  dispatchDrainRuns += 1;
1306
1624
  lastDispatchDrain = {
@@ -1317,6 +1635,7 @@ async function runDispatchDrainTick(): Promise<void> {
1317
1635
  reason: 'dispatch_drain_failed',
1318
1636
  error: lastDispatchDrain.last_error,
1319
1637
  });
1638
+ return true;
1320
1639
  }
1321
1640
  }
1322
1641
 
@@ -1328,34 +1647,62 @@ async function shouldSuppressInteractiveFallbackTicks(): Promise<boolean> {
1328
1647
  return deepInterviewStateActive || deepInterviewInputLockActive;
1329
1648
  }
1330
1649
 
1331
- async function pumpTeamControlPlaneTick(): Promise<void> {
1332
- await runDispatchDrainTick();
1333
- if (await shouldSuppressInteractiveFallbackTicks()) return;
1334
- await runLeaderNudgeTick();
1650
+ async function pumpTeamControlPlaneTick(): Promise<CycleActivitySummary> {
1651
+ const dispatchActive = await runDispatchDrainTick();
1652
+ if (await shouldSuppressInteractiveFallbackTicks()) {
1653
+ return { active: dispatchActive, reason: dispatchActive ? 'dispatch_drain' : 'deep_interview_locked' };
1654
+ }
1655
+ const leaderActive = await runLeaderNudgeTick();
1335
1656
  await runFallbackAutoNudgeTick();
1336
- }
1337
-
1338
-
1339
- async function runWatcherCycle(): Promise<void> {
1657
+ const autoNudgeActive = lastFallbackAutoNudge.last_reason === 'sent';
1658
+ if (dispatchActive) return { active: true, reason: 'dispatch_drain' };
1659
+ if (leaderActive) return { active: true, reason: 'leader_nudge' };
1660
+ if (autoNudgeActive) return { active: true, reason: 'fallback_auto_nudge' };
1661
+ return { active: false, reason: lastFallbackAutoNudge.last_reason || 'control_plane_idle' };
1662
+ }
1663
+
1664
+
1665
+ async function runWatcherCycle(): Promise<number> {
1666
+ let processedRolloutCount = 0;
1667
+ if (authorityOnly) {
1668
+ const authorityBackoff = await resolveAuthorityPrimaryWatcherHealth();
1669
+ lastAuthorityBackoff = authorityBackoff;
1670
+ if (authorityBackoff.active) {
1671
+ await writeAuthorityBackoffState();
1672
+ return processedRolloutCount;
1673
+ }
1674
+ } else {
1675
+ lastAuthorityBackoff = createAuthorityBackoffState('');
1676
+ }
1340
1677
  if (!authorityOnly) {
1341
1678
  await ensureTrackedFiles();
1342
- await pollFiles();
1679
+ processedRolloutCount = await pollFiles();
1343
1680
  }
1344
- await pumpTeamControlPlaneTick();
1681
+ const controlPlaneSummary = await pumpTeamControlPlaneTick();
1345
1682
  if (!authorityOnly && !(await shouldSuppressInteractiveFallbackTicks())) {
1346
1683
  await runRalphWatcherBehaviorTick();
1347
1684
  }
1348
- await writeState();
1685
+ const ralphActive = lastRalphContinueSteer.last_reason === 'sent';
1686
+ const summary: CycleActivitySummary = processedRolloutCount > 0
1687
+ ? { active: true, reason: 'rollout_event' }
1688
+ : controlPlaneSummary.active
1689
+ ? controlPlaneSummary
1690
+ : ralphActive
1691
+ ? { active: true, reason: 'ralph_continue_steer' }
1692
+ : { active: false, reason: controlPlaneSummary.reason || lastRalphContinueSteer.last_reason || 'idle' };
1693
+ const nextDelayMs = updateAdaptivePollState(summary);
1694
+ await writeState({ last_cycle_activity: summary.reason });
1695
+ return nextDelayMs;
1349
1696
  }
1350
1697
 
1351
1698
  async function tick(): Promise<void> {
1352
1699
  if (stopping) return;
1353
1700
  if (await enforceLifecycleGuards()) return;
1354
- await runWatcherCycle();
1701
+ const nextDelayMs = await runWatcherCycle();
1355
1702
  if (await enforceLifecycleGuards()) return;
1356
1703
  setTimeout(() => {
1357
1704
  void tick();
1358
- }, pollMs);
1705
+ }, nextDelayMs);
1359
1706
  }
1360
1707
 
1361
1708
  function shutdown(signal: string): void {
@@ -1379,6 +1726,8 @@ async function main(): Promise<void> {
1379
1726
  notify_script: notifyScript,
1380
1727
  authority_only: authorityOnly,
1381
1728
  poll_ms: pollMs,
1729
+ effective_poll_ms: adaptivePollState.current_ms,
1730
+ idle_max_poll_ms: idleMaxPollMs,
1382
1731
  once: runOnce,
1383
1732
  parent_pid: parentPid,
1384
1733
  pid_file: runOnce ? null : pidFilePath,
@@ -12,6 +12,7 @@ import { readJsonIfExists, getScopedStateDirsForCurrentSession, readdir } from '
12
12
  import { runProcess } from './process-runner.js';
13
13
  import { logTmuxHookEvent } from './log.js';
14
14
  import { evaluatePaneInjectionReadiness, mapPaneInjectionReadinessReason, sendPaneInput } from './team-tmux-guard.js';
15
+ import { stripOrchestrationIntentTags } from './orchestration-intent.js';
15
16
  import { buildCapturePaneArgv, DEFAULT_MARKER, tmuxHookExplicitlyDisablesInjection } from '../tmux-hook-engine.js';
16
17
  import {
17
18
  isManagedOmxSession,
@@ -72,18 +73,12 @@ function buildBlockedAutoApprovalMatcher(blockedInputs) {
72
73
  export function isBlockedAutoApprovalInput(text, blockedInputs = DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS) {
73
74
  const normalized = normalizeBlockedAutoApprovalInput(text);
74
75
  if (!normalized) return false;
75
- const normalizedBlockedInputs = blockedInputs.map((entry) => normalizeBlockedAutoApprovalInput(entry)).filter(Boolean);
76
- if (normalizedBlockedInputs.includes(normalized)) return true;
77
-
78
- const blockedPrefixes = normalizedBlockedInputs.filter((entry) => DEEP_INTERVIEW_BLOCKED_APPROVAL_PREFIXES.has(entry));
79
- if (blockedPrefixes.some((prefix) => normalized.startsWith(`${prefix} `))) return true;
76
+ const { exactMatches, prefixedMatches, blockedTokenSet } = buildBlockedAutoApprovalMatcher(blockedInputs);
77
+ if (exactMatches.has(normalized)) return true;
78
+ if (prefixedMatches.some((prefix) => normalized.startsWith(`${prefix} `))) return true;
80
79
 
81
80
  const tokens = normalized.split(/\s+/).filter(Boolean);
82
81
  if (tokens.length === 0) return false;
83
-
84
- const blockedTokenSet = new Set(
85
- normalizedBlockedInputs.flatMap((entry) => entry.split(/\s+/).filter(Boolean)),
86
- );
87
82
  return tokens.every((token) => blockedTokenSet.has(token));
88
83
  }
89
84
 
@@ -288,7 +283,7 @@ const SEMANTIC_STALL_PROMPT_PATTERNS = [
288
283
  ];
289
284
 
290
285
  function normalizeStallDetectionText(text) {
291
- return safeString(text)
286
+ return stripOrchestrationIntentTags(safeString(text))
292
287
  .replace(/\r\n?/g, '\n')
293
288
  .split('\n')
294
289
  .filter((line) => !line.includes(DEFAULT_MARKER))