oh-my-codex 0.11.13 → 0.12.0

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 (369) hide show
  1. package/Cargo.lock +5 -5
  2. package/Cargo.toml +1 -1
  3. package/README.md +27 -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 +22 -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 +217 -4
  14. package/dist/cli/__tests__/index.test.js.map +1 -1
  15. package/dist/cli/__tests__/setup-refresh.test.js +49 -9
  16. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  17. package/dist/cli/__tests__/setup-scope.test.js +9 -0
  18. package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
  19. package/dist/cli/__tests__/team.test.js +136 -11
  20. package/dist/cli/__tests__/team.test.js.map +1 -1
  21. package/dist/cli/__tests__/uninstall.test.js +10 -0
  22. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  23. package/dist/cli/__tests__/windows-popup-loop-contract.test.js +1 -0
  24. package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
  25. package/dist/cli/autoresearch-guided.d.ts.map +1 -1
  26. package/dist/cli/autoresearch-guided.js +2 -1
  27. package/dist/cli/autoresearch-guided.js.map +1 -1
  28. package/dist/cli/autoresearch.d.ts.map +1 -1
  29. package/dist/cli/autoresearch.js +2 -1
  30. package/dist/cli/autoresearch.js.map +1 -1
  31. package/dist/cli/cleanup.d.ts.map +1 -1
  32. package/dist/cli/cleanup.js +4 -2
  33. package/dist/cli/cleanup.js.map +1 -1
  34. package/dist/cli/index.d.ts +12 -0
  35. package/dist/cli/index.d.ts.map +1 -1
  36. package/dist/cli/index.js +238 -30
  37. package/dist/cli/index.js.map +1 -1
  38. package/dist/cli/omx.js +2 -0
  39. package/dist/cli/omx.js.map +1 -1
  40. package/dist/cli/setup.d.ts +1 -0
  41. package/dist/cli/setup.d.ts.map +1 -1
  42. package/dist/cli/setup.js +41 -7
  43. package/dist/cli/setup.js.map +1 -1
  44. package/dist/cli/team.d.ts.map +1 -1
  45. package/dist/cli/team.js +16 -557
  46. package/dist/cli/team.js.map +1 -1
  47. package/dist/cli/uninstall.d.ts.map +1 -1
  48. package/dist/cli/uninstall.js +34 -9
  49. package/dist/cli/uninstall.js.map +1 -1
  50. package/dist/config/__tests__/generator-idempotent.test.js +79 -2
  51. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  52. package/dist/config/__tests__/generator-notify.test.js +2 -0
  53. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  54. package/dist/config/codex-hooks.d.ts +11 -0
  55. package/dist/config/codex-hooks.d.ts.map +1 -0
  56. package/dist/config/codex-hooks.js +50 -0
  57. package/dist/config/codex-hooks.js.map +1 -0
  58. package/dist/config/generator.d.ts +5 -3
  59. package/dist/config/generator.d.ts.map +1 -1
  60. package/dist/config/generator.js +24 -14
  61. package/dist/config/generator.js.map +1 -1
  62. package/dist/hooks/__tests__/debugger-log-recency-contract.test.d.ts +2 -0
  63. package/dist/hooks/__tests__/debugger-log-recency-contract.test.d.ts.map +1 -0
  64. package/dist/hooks/__tests__/debugger-log-recency-contract.test.js +20 -0
  65. package/dist/hooks/__tests__/debugger-log-recency-contract.test.js.map +1 -0
  66. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +236 -2
  67. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  68. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +86 -0
  69. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  70. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +40 -0
  71. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  72. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.d.ts +2 -0
  73. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.d.ts.map +1 -0
  74. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +54 -0
  75. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -0
  76. package/dist/hooks/__tests__/notify-hook-modules.test.js +31 -0
  77. package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -1
  78. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +51 -0
  79. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -1
  80. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.d.ts +2 -0
  81. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.d.ts.map +1 -0
  82. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js +136 -0
  83. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js.map +1 -0
  84. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +120 -0
  85. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  86. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +145 -20
  87. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  88. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +116 -0
  89. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  90. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +86 -0
  91. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  92. package/dist/hooks/__tests__/pre-context-gate-skills.test.js +1 -0
  93. package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -1
  94. package/dist/hooks/extensibility/__tests__/runtime.test.js +49 -0
  95. package/dist/hooks/extensibility/__tests__/runtime.test.js.map +1 -1
  96. package/dist/hooks/extensibility/runtime.d.ts.map +1 -1
  97. package/dist/hooks/extensibility/runtime.js +10 -0
  98. package/dist/hooks/extensibility/runtime.js.map +1 -1
  99. package/dist/hooks/extensibility/types.d.ts +1 -1
  100. package/dist/hooks/extensibility/types.d.ts.map +1 -1
  101. package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
  102. package/dist/hooks/prompt-guidance-contract.js +12 -8
  103. package/dist/hooks/prompt-guidance-contract.js.map +1 -1
  104. package/dist/hooks/session.d.ts +5 -1
  105. package/dist/hooks/session.d.ts.map +1 -1
  106. package/dist/hooks/session.js +10 -6
  107. package/dist/hooks/session.js.map +1 -1
  108. package/dist/hud/index.d.ts.map +1 -1
  109. package/dist/hud/index.js +6 -1
  110. package/dist/hud/index.js.map +1 -1
  111. package/dist/mcp/__tests__/bootstrap.test.js +0 -3
  112. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  113. package/dist/mcp/__tests__/code-intel-server.test.js +27 -1
  114. package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -1
  115. package/dist/mcp/__tests__/server-lifecycle.test.js +0 -5
  116. package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
  117. package/dist/mcp/bootstrap.d.ts +1 -1
  118. package/dist/mcp/bootstrap.d.ts.map +1 -1
  119. package/dist/mcp/bootstrap.js +0 -1
  120. package/dist/mcp/bootstrap.js.map +1 -1
  121. package/dist/mcp/code-intel-server.d.ts +20 -0
  122. package/dist/mcp/code-intel-server.d.ts.map +1 -1
  123. package/dist/mcp/code-intel-server.js +6 -5
  124. package/dist/mcp/code-intel-server.js.map +1 -1
  125. package/dist/notifications/__tests__/idle-cooldown.test.js +24 -1
  126. package/dist/notifications/__tests__/idle-cooldown.test.js.map +1 -1
  127. package/dist/notifications/__tests__/reply-listener.test.js +20 -1
  128. package/dist/notifications/__tests__/reply-listener.test.js.map +1 -1
  129. package/dist/notifications/__tests__/tmux.test.js +41 -0
  130. package/dist/notifications/__tests__/tmux.test.js.map +1 -1
  131. package/dist/notifications/idle-cooldown.d.ts +13 -0
  132. package/dist/notifications/idle-cooldown.d.ts.map +1 -1
  133. package/dist/notifications/idle-cooldown.js +50 -16
  134. package/dist/notifications/idle-cooldown.js.map +1 -1
  135. package/dist/notifications/reply-listener.d.ts.map +1 -1
  136. package/dist/notifications/reply-listener.js +2 -0
  137. package/dist/notifications/reply-listener.js.map +1 -1
  138. package/dist/notifications/tmux.d.ts.map +1 -1
  139. package/dist/notifications/tmux.js +4 -0
  140. package/dist/notifications/tmux.js.map +1 -1
  141. package/dist/scripts/__tests__/codex-native-hook.test.d.ts +2 -0
  142. package/dist/scripts/__tests__/codex-native-hook.test.d.ts.map +1 -0
  143. package/dist/scripts/__tests__/codex-native-hook.test.js +720 -0
  144. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -0
  145. package/dist/scripts/codex-native-hook.d.ts +22 -0
  146. package/dist/scripts/codex-native-hook.d.ts.map +1 -0
  147. package/dist/scripts/codex-native-hook.js +594 -0
  148. package/dist/scripts/codex-native-hook.js.map +1 -0
  149. package/dist/scripts/codex-native-pre-post.d.ts +26 -0
  150. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -0
  151. package/dist/scripts/codex-native-pre-post.js +118 -0
  152. package/dist/scripts/codex-native-pre-post.js.map +1 -0
  153. package/dist/scripts/notify-fallback-watcher.js +262 -18
  154. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  155. package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
  156. package/dist/scripts/notify-hook/auto-nudge.js +5 -6
  157. package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
  158. package/dist/scripts/notify-hook/log.d.ts +2 -2
  159. package/dist/scripts/notify-hook/log.d.ts.map +1 -1
  160. package/dist/scripts/notify-hook/log.js +10 -2
  161. package/dist/scripts/notify-hook/log.js.map +1 -1
  162. package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
  163. package/dist/scripts/notify-hook/managed-tmux.js +2 -0
  164. package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
  165. package/dist/scripts/notify-hook/orchestration-intent.d.ts +18 -0
  166. package/dist/scripts/notify-hook/orchestration-intent.d.ts.map +1 -0
  167. package/dist/scripts/notify-hook/orchestration-intent.js +72 -0
  168. package/dist/scripts/notify-hook/orchestration-intent.js.map +1 -0
  169. package/dist/scripts/notify-hook/process-runner.js.map +1 -1
  170. package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
  171. package/dist/scripts/notify-hook/ralph-session-resume.js +7 -0
  172. package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
  173. package/dist/scripts/notify-hook/team-dispatch.d.ts +15 -6
  174. package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
  175. package/dist/scripts/notify-hook/team-dispatch.js +125 -6
  176. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  177. package/dist/scripts/notify-hook/team-leader-nudge.d.ts +3 -2
  178. package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
  179. package/dist/scripts/notify-hook/team-leader-nudge.js +165 -37
  180. package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
  181. package/dist/scripts/notify-hook/team-tmux-guard.d.ts +4 -1
  182. package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
  183. package/dist/scripts/notify-hook/team-tmux-guard.js +33 -44
  184. package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
  185. package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
  186. package/dist/scripts/notify-hook/team-worker.js +68 -5
  187. package/dist/scripts/notify-hook/team-worker.js.map +1 -1
  188. package/dist/scripts/notify-hook/utils.d.ts +1 -1
  189. package/dist/scripts/notify-hook/utils.d.ts.map +1 -1
  190. package/dist/scripts/notify-hook/utils.js.map +1 -1
  191. package/dist/scripts/notify-hook.js +55 -32
  192. package/dist/scripts/notify-hook.js.map +1 -1
  193. package/dist/team/__tests__/api-interop.test.js +344 -18
  194. package/dist/team/__tests__/api-interop.test.js.map +1 -1
  195. package/dist/team/__tests__/delivery-e2e-smoke.test.d.ts +2 -0
  196. package/dist/team/__tests__/delivery-e2e-smoke.test.d.ts.map +1 -0
  197. package/dist/team/__tests__/delivery-e2e-smoke.test.js +671 -0
  198. package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -0
  199. package/dist/team/__tests__/mcp-comm.test.js +5 -0
  200. package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
  201. package/dist/team/__tests__/runtime.test.js +422 -12
  202. package/dist/team/__tests__/runtime.test.js.map +1 -1
  203. package/dist/team/__tests__/state.test.js +126 -8
  204. package/dist/team/__tests__/state.test.js.map +1 -1
  205. package/dist/team/__tests__/team-ops-contract.test.js +4 -0
  206. package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
  207. package/dist/team/__tests__/tmux-session.test.js +160 -0
  208. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  209. package/dist/team/__tests__/worker-bootstrap.test.js +19 -1
  210. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  211. package/dist/team/api-interop.d.ts.map +1 -1
  212. package/dist/team/api-interop.js +95 -23
  213. package/dist/team/api-interop.js.map +1 -1
  214. package/dist/team/contracts.d.ts +11 -1
  215. package/dist/team/contracts.d.ts.map +1 -1
  216. package/dist/team/contracts.js +29 -0
  217. package/dist/team/contracts.js.map +1 -1
  218. package/dist/team/delivery-log.d.ts +14 -0
  219. package/dist/team/delivery-log.d.ts.map +1 -0
  220. package/dist/team/delivery-log.js +35 -0
  221. package/dist/team/delivery-log.js.map +1 -0
  222. package/dist/team/idle-nudge.d.ts +2 -2
  223. package/dist/team/idle-nudge.js +2 -2
  224. package/dist/team/mcp-comm.d.ts +4 -0
  225. package/dist/team/mcp-comm.d.ts.map +1 -1
  226. package/dist/team/mcp-comm.js +84 -1
  227. package/dist/team/mcp-comm.js.map +1 -1
  228. package/dist/team/pane-status.d.ts +149 -0
  229. package/dist/team/pane-status.d.ts.map +1 -0
  230. package/dist/team/pane-status.js +558 -0
  231. package/dist/team/pane-status.js.map +1 -0
  232. package/dist/team/reminder-intents.d.ts +11 -0
  233. package/dist/team/reminder-intents.d.ts.map +1 -0
  234. package/dist/team/reminder-intents.js +40 -0
  235. package/dist/team/reminder-intents.js.map +1 -0
  236. package/dist/team/runtime-cli.d.ts +1 -1
  237. package/dist/team/runtime-cli.js +2 -2
  238. package/dist/team/runtime-cli.js.map +1 -1
  239. package/dist/team/runtime.d.ts +2 -1
  240. package/dist/team/runtime.d.ts.map +1 -1
  241. package/dist/team/runtime.js +407 -190
  242. package/dist/team/runtime.js.map +1 -1
  243. package/dist/team/scaling.d.ts.map +1 -1
  244. package/dist/team/scaling.js +6 -5
  245. package/dist/team/scaling.js.map +1 -1
  246. package/dist/team/state/dispatch.d.ts +4 -1
  247. package/dist/team/state/dispatch.d.ts.map +1 -1
  248. package/dist/team/state/dispatch.js +59 -18
  249. package/dist/team/state/dispatch.js.map +1 -1
  250. package/dist/team/state/mailbox.d.ts.map +1 -1
  251. package/dist/team/state/mailbox.js +39 -2
  252. package/dist/team/state/mailbox.js.map +1 -1
  253. package/dist/team/state/monitor.d.ts +2 -1
  254. package/dist/team/state/monitor.d.ts.map +1 -1
  255. package/dist/team/state/monitor.js +30 -1
  256. package/dist/team/state/monitor.js.map +1 -1
  257. package/dist/team/state/types.d.ts +5 -2
  258. package/dist/team/state/types.d.ts.map +1 -1
  259. package/dist/team/state/types.js.map +1 -1
  260. package/dist/team/state.d.ts +30 -3
  261. package/dist/team/state.d.ts.map +1 -1
  262. package/dist/team/state.js +170 -2
  263. package/dist/team/state.js.map +1 -1
  264. package/dist/team/team-ops.d.ts +5 -1
  265. package/dist/team/team-ops.d.ts.map +1 -1
  266. package/dist/team/team-ops.js +4 -0
  267. package/dist/team/team-ops.js.map +1 -1
  268. package/dist/team/tmux-session.d.ts +2 -0
  269. package/dist/team/tmux-session.d.ts.map +1 -1
  270. package/dist/team/tmux-session.js +19 -3
  271. package/dist/team/tmux-session.js.map +1 -1
  272. package/dist/team/worker-bootstrap.d.ts +4 -0
  273. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  274. package/dist/team/worker-bootstrap.js +33 -6
  275. package/dist/team/worker-bootstrap.js.map +1 -1
  276. package/dist/utils/__tests__/paths.test.js +63 -1
  277. package/dist/utils/__tests__/paths.test.js.map +1 -1
  278. package/dist/utils/__tests__/platform-command.test.js +50 -4
  279. package/dist/utils/__tests__/platform-command.test.js.map +1 -1
  280. package/dist/utils/paths.d.ts +12 -0
  281. package/dist/utils/paths.d.ts.map +1 -1
  282. package/dist/utils/paths.js +44 -2
  283. package/dist/utils/paths.js.map +1 -1
  284. package/dist/utils/platform-command.d.ts.map +1 -1
  285. package/dist/utils/platform-command.js +13 -5
  286. package/dist/utils/platform-command.js.map +1 -1
  287. package/dist/utils/sleep.d.ts.map +1 -1
  288. package/dist/utils/sleep.js +10 -1
  289. package/dist/utils/sleep.js.map +1 -1
  290. package/package.json +1 -1
  291. package/prompts/analyst.md +2 -2
  292. package/prompts/api-reviewer.md +2 -2
  293. package/prompts/architect.md +2 -2
  294. package/prompts/build-fixer.md +2 -2
  295. package/prompts/code-reviewer.md +2 -2
  296. package/prompts/code-simplifier.md +1 -1
  297. package/prompts/critic.md +2 -2
  298. package/prompts/debugger.md +3 -2
  299. package/prompts/dependency-expert.md +2 -2
  300. package/prompts/designer.md +2 -2
  301. package/prompts/executor.md +3 -2
  302. package/prompts/explore.md +2 -2
  303. package/prompts/git-master.md +2 -2
  304. package/prompts/information-architect.md +2 -2
  305. package/prompts/performance-reviewer.md +2 -2
  306. package/prompts/planner.md +3 -2
  307. package/prompts/product-analyst.md +2 -2
  308. package/prompts/product-manager.md +2 -2
  309. package/prompts/qa-tester.md +2 -2
  310. package/prompts/quality-reviewer.md +2 -2
  311. package/prompts/quality-strategist.md +2 -2
  312. package/prompts/researcher.md +2 -2
  313. package/prompts/security-reviewer.md +2 -2
  314. package/prompts/sisyphus-lite.md +2 -2
  315. package/prompts/style-reviewer.md +2 -2
  316. package/prompts/team-executor.md +2 -2
  317. package/prompts/test-engineer.md +2 -2
  318. package/prompts/ux-researcher.md +2 -2
  319. package/prompts/verifier.md +3 -2
  320. package/prompts/vision.md +2 -2
  321. package/prompts/writer.md +2 -2
  322. package/skills/team/SKILL.md +18 -33
  323. package/src/scripts/__tests__/codex-native-hook.test.ts +931 -0
  324. package/src/scripts/codex-native-hook.ts +721 -0
  325. package/src/scripts/codex-native-pre-post.ts +161 -0
  326. package/src/scripts/notify-fallback-watcher.ts +318 -26
  327. package/src/scripts/notify-hook/auto-nudge.ts +5 -10
  328. package/src/scripts/notify-hook/log.ts +18 -4
  329. package/src/scripts/notify-hook/managed-tmux.ts +1 -0
  330. package/src/scripts/notify-hook/orchestration-intent.ts +82 -0
  331. package/src/scripts/notify-hook/process-runner.ts +4 -4
  332. package/src/scripts/notify-hook/ralph-session-resume.ts +9 -0
  333. package/src/scripts/notify-hook/team-dispatch.ts +134 -6
  334. package/src/scripts/notify-hook/team-leader-nudge.ts +183 -37
  335. package/src/scripts/notify-hook/team-tmux-guard.ts +35 -43
  336. package/src/scripts/notify-hook/team-worker.ts +73 -4
  337. package/src/scripts/notify-hook/utils.ts +1 -1
  338. package/src/scripts/notify-hook.ts +64 -32
  339. package/templates/AGENTS.md +21 -11
  340. package/README.de.md +0 -263
  341. package/README.el.md +0 -223
  342. package/README.es.md +0 -263
  343. package/README.fr.md +0 -263
  344. package/README.it.md +0 -263
  345. package/README.ja.md +0 -264
  346. package/README.ko.md +0 -264
  347. package/README.pl.md +0 -216
  348. package/README.pt.md +0 -263
  349. package/README.ru.md +0 -263
  350. package/README.tr.md +0 -263
  351. package/README.vi.md +0 -223
  352. package/README.zh-TW.md +0 -293
  353. package/README.zh.md +0 -264
  354. package/dist/mcp/__tests__/team-server-cleanup.test.d.ts +0 -2
  355. package/dist/mcp/__tests__/team-server-cleanup.test.d.ts.map +0 -1
  356. package/dist/mcp/__tests__/team-server-cleanup.test.js +0 -219
  357. package/dist/mcp/__tests__/team-server-cleanup.test.js.map +0 -1
  358. package/dist/mcp/__tests__/team-server-runtime-deps.test.d.ts +0 -2
  359. package/dist/mcp/__tests__/team-server-runtime-deps.test.d.ts.map +0 -1
  360. package/dist/mcp/__tests__/team-server-runtime-deps.test.js +0 -13
  361. package/dist/mcp/__tests__/team-server-runtime-deps.test.js.map +0 -1
  362. package/dist/mcp/__tests__/team-server-wait.test.d.ts +0 -2
  363. package/dist/mcp/__tests__/team-server-wait.test.d.ts.map +0 -1
  364. package/dist/mcp/__tests__/team-server-wait.test.js +0 -155
  365. package/dist/mcp/__tests__/team-server-wait.test.js.map +0 -1
  366. package/dist/mcp/team-server.d.ts +0 -24
  367. package/dist/mcp/team-server.d.ts.map +0 -1
  368. package/dist/mcp/team-server.js +0 -482
  369. package/dist/mcp/team-server.js.map +0 -1
@@ -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;
@@ -131,6 +139,8 @@ interface RalphContinueSteerState {
131
139
  pane_id: string;
132
140
  pane_current_command: string;
133
141
  current_phase: string;
142
+ subagent_session_id: string;
143
+ active_subagent_thread_ids: string[];
134
144
  shared_timestamp_path: string;
135
145
  shared_last_sent_at: string;
136
146
  singleton_lock_path: string;
@@ -174,6 +184,15 @@ interface ParentGuardState {
174
184
  pane_count?: number;
175
185
  }
176
186
 
187
+ interface AuthorityBackoffState {
188
+ active: boolean;
189
+ reason: string;
190
+ primary_pid: number | null;
191
+ primary_last_tick_at: string;
192
+ freshness_ms: number | null;
193
+ threshold_ms: number | null;
194
+ }
195
+
177
196
  interface ActiveTeamResult {
178
197
  active: boolean;
179
198
  reason: string;
@@ -196,6 +215,22 @@ interface FallbackAutoNudgeState {
196
215
  last_nudged_at: string;
197
216
  }
198
217
 
218
+ interface AdaptivePollState {
219
+ enabled: boolean;
220
+ base_ms: number;
221
+ max_ms: number;
222
+ current_ms: number;
223
+ idle_streak: number;
224
+ last_tick_at: string | null;
225
+ last_activity_at: string | null;
226
+ last_activity_reason: string;
227
+ }
228
+
229
+ interface CycleActivitySummary {
230
+ active: boolean;
231
+ reason: string;
232
+ }
233
+
199
234
  const fileState = new Map<string, WatcherFileMeta>();
200
235
  const seenTurnKeys = new Set<string>();
201
236
  let stopping = false;
@@ -231,6 +266,8 @@ let lastRalphContinueSteer: RalphContinueSteerState = {
231
266
  pane_id: '',
232
267
  pane_current_command: '',
233
268
  current_phase: '',
269
+ subagent_session_id: '',
270
+ active_subagent_thread_ids: [],
234
271
  shared_timestamp_path: ralphSteerTimestampPath,
235
272
  shared_last_sent_at: '',
236
273
  singleton_lock_path: ralphSteerLockPath,
@@ -240,6 +277,14 @@ let lastParentGuard: ParentGuardState = {
240
277
  state_path: '',
241
278
  current_phase: '',
242
279
  };
280
+ let lastAuthorityBackoff: AuthorityBackoffState = {
281
+ active: false,
282
+ reason: '',
283
+ primary_pid: null,
284
+ primary_last_tick_at: '',
285
+ freshness_ms: null,
286
+ threshold_ms: null,
287
+ };
243
288
  const AUTO_NUDGE_STALL_MS = Math.max(
244
289
  pollMs,
245
290
  asNumber(process.env.OMX_NOTIFY_FALLBACK_AUTO_NUDGE_STALL_MS || '5000', 5000),
@@ -256,6 +301,16 @@ let lastFallbackAutoNudge: FallbackAutoNudgeState = {
256
301
  last_nudged_signature: '',
257
302
  last_nudged_at: '',
258
303
  };
304
+ let adaptivePollState: AdaptivePollState = {
305
+ enabled: true,
306
+ base_ms: pollMs,
307
+ max_ms: idleMaxPollMs,
308
+ current_ms: pollMs,
309
+ idle_streak: 0,
310
+ last_tick_at: null,
311
+ last_activity_at: null,
312
+ last_activity_reason: 'init',
313
+ };
259
314
  function eventLog(event: Record<string, unknown>): Promise<void> {
260
315
  return appendFile(logPath, `${JSON.stringify({ timestamp: new Date().toISOString(), ...event })}\n`).catch(() => {});
261
316
  }
@@ -264,6 +319,41 @@ function shouldLogLeaderNudgeTick(reason: string): boolean {
264
319
  return reason === 'leader_nudge_checked' || reason === 'leader_nudge_failed';
265
320
  }
266
321
 
322
+ function nextIdlePollMs(currentMs: number): number {
323
+ return Math.min(idleMaxPollMs, Math.max(pollMs, currentMs * 2));
324
+ }
325
+
326
+ function updateAdaptivePollState(summary: CycleActivitySummary): number {
327
+ const nowIso = new Date().toISOString();
328
+ if (summary.active) {
329
+ adaptivePollState = {
330
+ ...adaptivePollState,
331
+ enabled: true,
332
+ base_ms: pollMs,
333
+ max_ms: idleMaxPollMs,
334
+ current_ms: pollMs,
335
+ idle_streak: 0,
336
+ last_tick_at: nowIso,
337
+ last_activity_at: nowIso,
338
+ last_activity_reason: summary.reason,
339
+ };
340
+ return adaptivePollState.current_ms;
341
+ }
342
+
343
+ const nextMs = nextIdlePollMs(adaptivePollState.current_ms);
344
+ adaptivePollState = {
345
+ ...adaptivePollState,
346
+ enabled: true,
347
+ base_ms: pollMs,
348
+ max_ms: idleMaxPollMs,
349
+ current_ms: nextMs,
350
+ idle_streak: adaptivePollState.idle_streak + 1,
351
+ last_tick_at: nowIso,
352
+ last_activity_reason: summary.reason,
353
+ };
354
+ return adaptivePollState.current_ms;
355
+ }
356
+
267
357
  function shouldLogDispatchDrainTick(result: unknown): boolean {
268
358
  if (!result || typeof result !== 'object') return false;
269
359
  const record = result as Record<string, unknown>;
@@ -291,6 +381,10 @@ function normalizeRalphContinueSteerState(raw: Record<string, unknown> | null |
291
381
  pane_id: safeString(raw.pane_id),
292
382
  pane_current_command: safeString(raw.pane_current_command),
293
383
  current_phase: safeString(raw.current_phase),
384
+ subagent_session_id: safeString(raw.subagent_session_id),
385
+ active_subagent_thread_ids: Array.isArray(raw.active_subagent_thread_ids)
386
+ ? raw.active_subagent_thread_ids.map((value) => safeString(value).trim()).filter(Boolean)
387
+ : [],
294
388
  shared_timestamp_path: safeString(raw.shared_timestamp_path) || ralphSteerTimestampPath,
295
389
  shared_last_sent_at: safeString(raw.shared_last_sent_at),
296
390
  singleton_lock_path: safeString(raw.singleton_lock_path) || ralphSteerLockPath,
@@ -328,6 +422,19 @@ async function loadPersistedWatcherState(): Promise<void> {
328
422
  last_nudged_at: safeString(persistedAutoNudge.last_nudged_at),
329
423
  };
330
424
  }
425
+ const persistedAdaptivePoll = persisted?.adaptive_poll as Record<string, unknown> | null | undefined;
426
+ if (persistedAdaptivePoll && typeof persistedAdaptivePoll === 'object') {
427
+ adaptivePollState = {
428
+ enabled: persistedAdaptivePoll.enabled !== false,
429
+ base_ms: pollMs,
430
+ max_ms: idleMaxPollMs,
431
+ current_ms: Math.min(idleMaxPollMs, Math.max(pollMs, asNumber(persistedAdaptivePoll.current_ms as string | number | undefined, pollMs))),
432
+ idle_streak: Math.max(0, Math.trunc(asNumber(persistedAdaptivePoll.idle_streak as string | number | undefined, 0))),
433
+ last_tick_at: safeString(persistedAdaptivePoll.last_tick_at) || null,
434
+ last_activity_at: safeString(persistedAdaptivePoll.last_activity_at) || null,
435
+ last_activity_reason: safeString(persistedAdaptivePoll.last_activity_reason) || 'init',
436
+ };
437
+ }
331
438
  }
332
439
 
333
440
  interface ActiveModeResult {
@@ -534,7 +641,8 @@ async function withRalphSteerLock<T>(task: () => Promise<T>): Promise<T | null>
534
641
  if (code !== 'EEXIST') throw error;
535
642
  const existing = await readRalphSteerLock(ralphSteerLockPath);
536
643
  const lockAgeMs = parseIsoMillis(existing?.acquired_at) ?? 0;
537
- const stale = !existing || !isPidAlive(existing.pid) || (lockAgeMs > 0 && Date.now() - lockAgeMs > RALPH_STEER_LOCK_STALE_MS);
644
+ const stale = existing !== null
645
+ && (!isPidAlive(existing.pid) || (lockAgeMs > 0 && Date.now() - lockAgeMs > RALPH_STEER_LOCK_STALE_MS));
538
646
  if (stale) {
539
647
  await unlink(ralphSteerLockPath).catch(() => {});
540
648
  continue;
@@ -560,29 +668,51 @@ interface RalphProgressGateResult {
560
668
  allow: boolean;
561
669
  reason: string;
562
670
  progress_at: string;
563
- }
671
+ subagent_session_id?: string;
672
+ active_subagent_thread_ids?: string[];
673
+ }
674
+
675
+ async function readRalphProgressGate(
676
+ activeRalphState: Record<string, unknown> | null,
677
+ now: number,
678
+ ): Promise<RalphProgressGateResult> {
679
+ const subagentSessionId = safeString(activeRalphState?.owner_codex_session_id).trim();
680
+ if (subagentSessionId) {
681
+ const summary = await readSubagentSessionSummary(cwd, subagentSessionId, {
682
+ now: new Date(now),
683
+ activeWindowMs: DEFAULT_SUBAGENT_ACTIVE_WINDOW_MS,
684
+ });
685
+ if ((summary?.activeSubagentThreadIds.length ?? 0) > 0) {
686
+ return {
687
+ allow: false,
688
+ reason: 'subagents_active',
689
+ progress_at: '',
690
+ subagent_session_id: subagentSessionId,
691
+ active_subagent_thread_ids: summary?.activeSubagentThreadIds ?? [],
692
+ };
693
+ }
694
+ }
564
695
 
565
- async function readRalphProgressGate(now: number): Promise<RalphProgressGateResult> {
566
696
  const hudState = await readJsonObject(join(stateDir, 'hud-state.json'));
567
697
  if (!hudState || typeof hudState !== 'object') {
568
- return { allow: false, reason: 'progress_missing', progress_at: '' };
698
+ return { allow: false, reason: 'progress_missing', progress_at: '', subagent_session_id: subagentSessionId };
569
699
  }
570
700
 
571
701
  const progressAt = safeString(hudState.last_progress_at).trim();
572
702
  if (!progressAt) {
573
- return { allow: false, reason: 'progress_missing', progress_at: '' };
703
+ return { allow: false, reason: 'progress_missing', progress_at: '', subagent_session_id: subagentSessionId };
574
704
  }
575
705
 
576
706
  const progressMs = parseIsoMillis(progressAt);
577
707
  if (progressMs === null) {
578
- return { allow: false, reason: 'progress_invalid', progress_at: progressAt };
708
+ return { allow: false, reason: 'progress_invalid', progress_at: progressAt, subagent_session_id: subagentSessionId };
579
709
  }
580
710
 
581
711
  if (now - progressMs < RALPH_CONTINUE_CADENCE_MS) {
582
- return { allow: false, reason: 'progress_fresh', progress_at: progressAt };
712
+ return { allow: false, reason: 'progress_fresh', progress_at: progressAt, subagent_session_id: subagentSessionId };
583
713
  }
584
714
 
585
- return { allow: true, reason: 'progress_stale', progress_at: progressAt };
715
+ return { allow: true, reason: 'progress_stale', progress_at: progressAt, subagent_session_id: subagentSessionId };
586
716
  }
587
717
 
588
718
  function shouldSkipRalphContinue(now: number, candidateIso: string, startupIso: string): { skip: boolean; reason: string; anchorMs: number; anchorIso: string } {
@@ -625,6 +755,108 @@ async function readPidFileRecord(path: string): Promise<PidFileRecord | null> {
625
755
  }
626
756
  }
627
757
 
758
+ function createAuthorityBackoffState(
759
+ reason: string,
760
+ overrides: Partial<AuthorityBackoffState> = {},
761
+ ): AuthorityBackoffState {
762
+ return {
763
+ active: false,
764
+ reason,
765
+ primary_pid: null,
766
+ primary_last_tick_at: '',
767
+ freshness_ms: null,
768
+ threshold_ms: null,
769
+ ...overrides,
770
+ };
771
+ }
772
+
773
+ function latestWatcherTickIso(state: Record<string, unknown> | null): string {
774
+ if (!state || typeof state !== 'object') return '';
775
+ const candidates = [
776
+ safeString((state.dispatch_drain as Record<string, unknown> | undefined)?.last_tick_at),
777
+ safeString((state.leader_nudge as Record<string, unknown> | undefined)?.last_tick_at),
778
+ safeString((state.fallback_auto_nudge as Record<string, unknown> | undefined)?.last_tick_at),
779
+ safeString((state.ralph_continue_steer as Record<string, unknown> | undefined)?.last_state_check_at),
780
+ ]
781
+ .map((value) => value.trim())
782
+ .filter(Boolean);
783
+ let latestIso = '';
784
+ let latestMs = -1;
785
+ for (const candidate of candidates) {
786
+ const parsed = parseIsoMillis(candidate);
787
+ if (parsed === null || parsed <= latestMs) continue;
788
+ latestMs = parsed;
789
+ latestIso = candidate;
790
+ }
791
+ return latestIso;
792
+ }
793
+
794
+ async function resolveAuthorityPrimaryWatcherHealth(now = Date.now()): Promise<AuthorityBackoffState> {
795
+ if (!authorityOnly) return createAuthorityBackoffState('not_authority');
796
+
797
+ const existingRecord = await readPidFileRecord(pidFilePath).catch(() => null);
798
+ if (!existingRecord) return createAuthorityBackoffState('pid_missing');
799
+ if (existingRecord.cwd && resolve(existingRecord.cwd) !== cwd) return createAuthorityBackoffState('cwd_mismatch');
800
+ if (!isPidAlive(existingRecord.pid)) {
801
+ return createAuthorityBackoffState('pid_stale', {
802
+ primary_pid: existingRecord.pid,
803
+ });
804
+ }
805
+
806
+ const persistedState = await readJsonObject(statePath);
807
+ if (!persistedState) {
808
+ return createAuthorityBackoffState('state_missing', {
809
+ primary_pid: existingRecord.pid,
810
+ });
811
+ }
812
+
813
+ const persistedPid = Math.trunc(asNumber(persistedState.pid as string | number | undefined, 0));
814
+ if (persistedPid > 0 && persistedPid !== existingRecord.pid) {
815
+ return createAuthorityBackoffState('state_pid_mismatch', {
816
+ primary_pid: existingRecord.pid,
817
+ });
818
+ }
819
+
820
+ const lastTickAt = latestWatcherTickIso(persistedState);
821
+ if (!lastTickAt) {
822
+ return createAuthorityBackoffState('tick_missing', {
823
+ primary_pid: existingRecord.pid,
824
+ });
825
+ }
826
+
827
+ const lastTickMs = parseIsoMillis(lastTickAt);
828
+ const primaryPollMs = Math.max(50, asNumber(persistedState.poll_ms as string | number | undefined, 250));
829
+ const thresholdMs = Math.max(1_000, primaryPollMs * 4);
830
+ if (lastTickMs === null) {
831
+ return createAuthorityBackoffState('tick_invalid', {
832
+ primary_pid: existingRecord.pid,
833
+ primary_last_tick_at: lastTickAt,
834
+ threshold_ms: thresholdMs,
835
+ });
836
+ }
837
+
838
+ const freshnessMs = now - lastTickMs;
839
+ if (freshnessMs > thresholdMs) {
840
+ return {
841
+ active: false,
842
+ reason: 'tick_stale',
843
+ primary_pid: existingRecord.pid,
844
+ primary_last_tick_at: lastTickAt,
845
+ freshness_ms: freshnessMs,
846
+ threshold_ms: thresholdMs,
847
+ };
848
+ }
849
+
850
+ return {
851
+ active: true,
852
+ reason: 'primary_watcher_healthy',
853
+ primary_pid: existingRecord.pid,
854
+ primary_last_tick_at: lastTickAt,
855
+ freshness_ms: freshnessMs,
856
+ threshold_ms: thresholdMs,
857
+ };
858
+ }
859
+
628
860
  async function writePidFileRecord(): Promise<void> {
629
861
  const nextRecord: PidFileRecord = {
630
862
  pid: process.pid,
@@ -653,6 +885,8 @@ async function runRalphContinueSteerTick(): Promise<void> {
653
885
  state_path: activeRalph.path,
654
886
  pane_id: activePaneId,
655
887
  pane_current_command: '',
888
+ subagent_session_id: safeString(activeRalph.state?.owner_codex_session_id).trim(),
889
+ active_subagent_thread_ids: [],
656
890
  shared_timestamp_path: ralphSteerTimestampPath,
657
891
  singleton_lock_path: ralphSteerLockPath,
658
892
  };
@@ -686,9 +920,11 @@ async function runRalphContinueSteerTick(): Promise<void> {
686
920
  return { sent: false, skipped: true };
687
921
  }
688
922
 
689
- const progressGate = await readRalphProgressGate(Date.now());
923
+ const progressGate = await readRalphProgressGate(activeRalph.state, Date.now());
690
924
  if (!progressGate.allow) {
691
925
  lastRalphContinueSteer.last_reason = progressGate.reason;
926
+ lastRalphContinueSteer.subagent_session_id = progressGate.subagent_session_id ?? lastRalphContinueSteer.subagent_session_id;
927
+ lastRalphContinueSteer.active_subagent_thread_ids = progressGate.active_subagent_thread_ids ?? [];
692
928
  return { sent: false, skipped: true };
693
929
  }
694
930
 
@@ -811,6 +1047,8 @@ async function writeState(extra: Record<string, unknown> = {}): Promise<void> {
811
1047
  notify_script: notifyScript,
812
1048
  authority_only: authorityOnly,
813
1049
  poll_ms: pollMs,
1050
+ effective_poll_ms: adaptivePollState.current_ms,
1051
+ idle_max_poll_ms: idleMaxPollMs,
814
1052
  pid_file: runOnce ? null : pidFilePath,
815
1053
  max_lifetime_ms: maxLifetimeMs,
816
1054
  tracked_files: fileState.size,
@@ -837,11 +1075,27 @@ async function writeState(extra: Record<string, unknown> = {}): Promise<void> {
837
1075
  enabled: true,
838
1076
  stall_ms: AUTO_NUDGE_STALL_MS,
839
1077
  },
1078
+ authority_backoff: lastAuthorityBackoff,
1079
+ adaptive_poll: {
1080
+ ...adaptivePollState,
1081
+ enabled: true,
1082
+ base_ms: pollMs,
1083
+ max_ms: idleMaxPollMs,
1084
+ },
840
1085
  ...extra,
841
1086
  };
842
1087
  await writeFile(statePath, JSON.stringify(state, null, 2)).catch(() => {});
843
1088
  }
844
1089
 
1090
+ async function writeAuthorityBackoffState(): Promise<void> {
1091
+ await mkdir(stateDir, { recursive: true }).catch(() => {});
1092
+ const existing = await readJsonObject(statePath);
1093
+ const state = existing && typeof existing === 'object'
1094
+ ? { ...existing, authority_backoff: lastAuthorityBackoff }
1095
+ : { authority_backoff: lastAuthorityBackoff };
1096
+ await writeFile(statePath, JSON.stringify(state, null, 2)).catch(() => {});
1097
+ }
1098
+
845
1099
  async function readJsonObject(path: string): Promise<Record<string, unknown> | null> {
846
1100
  return readFile(path, 'utf-8')
847
1101
  .then((content) => JSON.parse(content) as Record<string, unknown>)
@@ -1195,7 +1449,8 @@ function splitBufferedLines(partial: string, delta: string): { lines: string[];
1195
1449
  };
1196
1450
  }
1197
1451
 
1198
- async function pollFiles(): Promise<void> {
1452
+ async function pollFiles(): Promise<number> {
1453
+ let processedCount = 0;
1199
1454
  for (const [path, meta] of fileState.entries()) {
1200
1455
  const currentSize = (await stat(path).catch(() => ({ size: 0 }))).size || 0;
1201
1456
  if (currentSize <= meta.offset) continue;
@@ -1209,11 +1464,13 @@ async function pollFiles(): Promise<void> {
1209
1464
  for (const line of lines) {
1210
1465
  if (!line.trim()) continue;
1211
1466
  await processLine(meta, line, path);
1467
+ processedCount += 1;
1212
1468
  }
1213
1469
  }
1470
+ return processedCount;
1214
1471
  }
1215
1472
 
1216
- async function runLeaderNudgeTick(): Promise<void> {
1473
+ async function runLeaderNudgeTick(): Promise<boolean> {
1217
1474
  const startedIso = new Date().toISOString();
1218
1475
  const leaderOnly = safeString(process.env.OMX_TEAM_WORKER || '').trim() === '';
1219
1476
  const staleThresholdMs = resolveLeaderStalenessThresholdMs();
@@ -1228,7 +1485,7 @@ async function runLeaderNudgeTick(): Promise<void> {
1228
1485
  last_tick_at: startedIso,
1229
1486
  last_error: 'worker_context',
1230
1487
  };
1231
- return;
1488
+ return false;
1232
1489
  }
1233
1490
 
1234
1491
  try {
@@ -1239,6 +1496,7 @@ async function runLeaderNudgeTick(): Promise<void> {
1239
1496
  logsDir,
1240
1497
  preComputedLeaderStale,
1241
1498
  allowFreshMailboxNudges: false,
1499
+ source: 'notify_fallback_watcher',
1242
1500
  });
1243
1501
  leaderNudgeRuns += 1;
1244
1502
  lastLeaderNudge = {
@@ -1260,6 +1518,7 @@ async function runLeaderNudgeTick(): Promise<void> {
1260
1518
  reason,
1261
1519
  });
1262
1520
  }
1521
+ return preComputedLeaderStale;
1263
1522
  } catch (err) {
1264
1523
  leaderNudgeRuns += 1;
1265
1524
  lastLeaderNudge = {
@@ -1278,10 +1537,11 @@ async function runLeaderNudgeTick(): Promise<void> {
1278
1537
  reason: 'leader_nudge_failed',
1279
1538
  error: lastLeaderNudge.last_error,
1280
1539
  });
1540
+ return true;
1281
1541
  }
1282
1542
  }
1283
1543
 
1284
- async function runDispatchDrainTick(): Promise<void> {
1544
+ async function runDispatchDrainTick(): Promise<boolean> {
1285
1545
  const startedIso = new Date().toISOString();
1286
1546
  try {
1287
1547
  const result = await drainPendingTeamDispatch({ cwd, stateDir, logsDir, maxPerTick: dispatchTickMax } as any);
@@ -1301,6 +1561,7 @@ async function runDispatchDrainTick(): Promise<void> {
1301
1561
  ...(result && typeof result === 'object' ? result as Record<string, unknown> : {}),
1302
1562
  });
1303
1563
  }
1564
+ return shouldLogDispatchDrainTick(result);
1304
1565
  } catch (err) {
1305
1566
  dispatchDrainRuns += 1;
1306
1567
  lastDispatchDrain = {
@@ -1317,6 +1578,7 @@ async function runDispatchDrainTick(): Promise<void> {
1317
1578
  reason: 'dispatch_drain_failed',
1318
1579
  error: lastDispatchDrain.last_error,
1319
1580
  });
1581
+ return true;
1320
1582
  }
1321
1583
  }
1322
1584
 
@@ -1328,34 +1590,62 @@ async function shouldSuppressInteractiveFallbackTicks(): Promise<boolean> {
1328
1590
  return deepInterviewStateActive || deepInterviewInputLockActive;
1329
1591
  }
1330
1592
 
1331
- async function pumpTeamControlPlaneTick(): Promise<void> {
1332
- await runDispatchDrainTick();
1333
- if (await shouldSuppressInteractiveFallbackTicks()) return;
1334
- await runLeaderNudgeTick();
1593
+ async function pumpTeamControlPlaneTick(): Promise<CycleActivitySummary> {
1594
+ const dispatchActive = await runDispatchDrainTick();
1595
+ if (await shouldSuppressInteractiveFallbackTicks()) {
1596
+ return { active: dispatchActive, reason: dispatchActive ? 'dispatch_drain' : 'deep_interview_locked' };
1597
+ }
1598
+ const leaderActive = await runLeaderNudgeTick();
1335
1599
  await runFallbackAutoNudgeTick();
1336
- }
1337
-
1338
-
1339
- async function runWatcherCycle(): Promise<void> {
1600
+ const autoNudgeActive = lastFallbackAutoNudge.last_reason === 'sent';
1601
+ if (dispatchActive) return { active: true, reason: 'dispatch_drain' };
1602
+ if (leaderActive) return { active: true, reason: 'leader_nudge' };
1603
+ if (autoNudgeActive) return { active: true, reason: 'fallback_auto_nudge' };
1604
+ return { active: false, reason: lastFallbackAutoNudge.last_reason || 'control_plane_idle' };
1605
+ }
1606
+
1607
+
1608
+ async function runWatcherCycle(): Promise<number> {
1609
+ let processedRolloutCount = 0;
1610
+ if (authorityOnly) {
1611
+ const authorityBackoff = await resolveAuthorityPrimaryWatcherHealth();
1612
+ lastAuthorityBackoff = authorityBackoff;
1613
+ if (authorityBackoff.active) {
1614
+ await writeAuthorityBackoffState();
1615
+ return processedRolloutCount;
1616
+ }
1617
+ } else {
1618
+ lastAuthorityBackoff = createAuthorityBackoffState('');
1619
+ }
1340
1620
  if (!authorityOnly) {
1341
1621
  await ensureTrackedFiles();
1342
- await pollFiles();
1622
+ processedRolloutCount = await pollFiles();
1343
1623
  }
1344
- await pumpTeamControlPlaneTick();
1624
+ const controlPlaneSummary = await pumpTeamControlPlaneTick();
1345
1625
  if (!authorityOnly && !(await shouldSuppressInteractiveFallbackTicks())) {
1346
1626
  await runRalphWatcherBehaviorTick();
1347
1627
  }
1348
- await writeState();
1628
+ const ralphActive = lastRalphContinueSteer.last_reason === 'sent';
1629
+ const summary: CycleActivitySummary = processedRolloutCount > 0
1630
+ ? { active: true, reason: 'rollout_event' }
1631
+ : controlPlaneSummary.active
1632
+ ? controlPlaneSummary
1633
+ : ralphActive
1634
+ ? { active: true, reason: 'ralph_continue_steer' }
1635
+ : { active: false, reason: controlPlaneSummary.reason || lastRalphContinueSteer.last_reason || 'idle' };
1636
+ const nextDelayMs = updateAdaptivePollState(summary);
1637
+ await writeState({ last_cycle_activity: summary.reason });
1638
+ return nextDelayMs;
1349
1639
  }
1350
1640
 
1351
1641
  async function tick(): Promise<void> {
1352
1642
  if (stopping) return;
1353
1643
  if (await enforceLifecycleGuards()) return;
1354
- await runWatcherCycle();
1644
+ const nextDelayMs = await runWatcherCycle();
1355
1645
  if (await enforceLifecycleGuards()) return;
1356
1646
  setTimeout(() => {
1357
1647
  void tick();
1358
- }, pollMs);
1648
+ }, nextDelayMs);
1359
1649
  }
1360
1650
 
1361
1651
  function shutdown(signal: string): void {
@@ -1379,6 +1669,8 @@ async function main(): Promise<void> {
1379
1669
  notify_script: notifyScript,
1380
1670
  authority_only: authorityOnly,
1381
1671
  poll_ms: pollMs,
1672
+ effective_poll_ms: adaptivePollState.current_ms,
1673
+ idle_max_poll_ms: idleMaxPollMs,
1382
1674
  once: runOnce,
1383
1675
  parent_pid: parentPid,
1384
1676
  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))
@@ -5,12 +5,26 @@
5
5
  import { appendFile } from 'fs/promises';
6
6
  import { join } from 'path';
7
7
 
8
- export async function logTmuxHookEvent(logsDir: any, event: any): Promise<void> {
8
+ async function safeAppend(file: string, line: string): Promise<void> {
9
+ try {
10
+ await appendFile(file, line);
11
+ } catch {
12
+ // Fall through — log writes should never crash the caller
13
+ }
14
+ }
15
+
16
+ export async function logTmuxHookEvent(
17
+ logsDir: string,
18
+ event: Record<string, unknown>,
19
+ ): Promise<void> {
9
20
  const file = join(logsDir, `tmux-hook-${new Date().toISOString().split('T')[0]}.jsonl`);
10
- await appendFile(file, JSON.stringify(event) + '\n').catch(() => {});
21
+ await safeAppend(file, JSON.stringify(event) + '\n');
11
22
  }
12
23
 
13
- export async function logNotifyHookEvent(logsDir: any, event: any): Promise<void> {
24
+ export async function logNotifyHookEvent(
25
+ logsDir: string,
26
+ event: Record<string, unknown>,
27
+ ): Promise<void> {
14
28
  const file = join(logsDir, `notify-hook-${new Date().toISOString().split('T')[0]}.jsonl`);
15
- await appendFile(file, JSON.stringify(event) + '\n').catch(() => {});
29
+ await safeAppend(file, JSON.stringify(event) + '\n');
16
30
  }
@@ -72,6 +72,7 @@ function readCurrentTmuxSessionName(): string {
72
72
  function readParentPid(pid: number): number | null {
73
73
  if (!Number.isInteger(pid) || pid <= 1) return null;
74
74
  try {
75
+ if (process.platform === 'win32') return null;
75
76
  if (process.platform === 'linux') {
76
77
  const stat = readFileSync(`/proc/${pid}/stat`, 'utf-8');
77
78
  const commandEnd = stat.lastIndexOf(')');