oh-my-codex 0.18.13 → 0.18.15

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 (360) hide show
  1. package/Cargo.lock +6 -6
  2. package/Cargo.toml +1 -1
  3. package/README.md +41 -18
  4. package/dist/agents/__tests__/native-config.test.js +62 -0
  5. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  6. package/dist/agents/native-config.d.ts.map +1 -1
  7. package/dist/agents/native-config.js +15 -2
  8. package/dist/agents/native-config.js.map +1 -1
  9. package/dist/autopilot/__tests__/fsm.test.js +7 -0
  10. package/dist/autopilot/__tests__/fsm.test.js.map +1 -1
  11. package/dist/autopilot/__tests__/planner-routing.test.d.ts +2 -0
  12. package/dist/autopilot/__tests__/planner-routing.test.d.ts.map +1 -0
  13. package/dist/autopilot/__tests__/planner-routing.test.js +74 -0
  14. package/dist/autopilot/__tests__/planner-routing.test.js.map +1 -0
  15. package/dist/autopilot/__tests__/ralplan-gate.test.js +315 -0
  16. package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -1
  17. package/dist/autopilot/completion-gate.js +1 -1
  18. package/dist/autopilot/completion-gate.js.map +1 -1
  19. package/dist/autopilot/fsm.d.ts +2 -2
  20. package/dist/autopilot/fsm.d.ts.map +1 -1
  21. package/dist/autopilot/fsm.js +3 -0
  22. package/dist/autopilot/fsm.js.map +1 -1
  23. package/dist/autopilot/planner-routing.d.ts +21 -0
  24. package/dist/autopilot/planner-routing.d.ts.map +1 -0
  25. package/dist/autopilot/planner-routing.js +59 -0
  26. package/dist/autopilot/planner-routing.js.map +1 -0
  27. package/dist/autopilot/ralplan-gate.d.ts.map +1 -1
  28. package/dist/autopilot/ralplan-gate.js +30 -0
  29. package/dist/autopilot/ralplan-gate.js.map +1 -1
  30. package/dist/autoresearch/goal.d.ts.map +1 -1
  31. package/dist/autoresearch/goal.js +10 -1
  32. package/dist/autoresearch/goal.js.map +1 -1
  33. package/dist/cli/__tests__/autoresearch-goal.test.js +33 -0
  34. package/dist/cli/__tests__/autoresearch-goal.test.js.map +1 -1
  35. package/dist/cli/__tests__/autoresearch-guided.test.js +3 -0
  36. package/dist/cli/__tests__/autoresearch-guided.test.js.map +1 -1
  37. package/dist/cli/__tests__/codex-plugin-layout.test.js +30 -0
  38. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  39. package/dist/cli/__tests__/doctor-artifact-ownership.test.d.ts +2 -0
  40. package/dist/cli/__tests__/doctor-artifact-ownership.test.d.ts.map +1 -0
  41. package/dist/cli/__tests__/doctor-artifact-ownership.test.js +158 -0
  42. package/dist/cli/__tests__/doctor-artifact-ownership.test.js.map +1 -0
  43. package/dist/cli/__tests__/doctor-explore-deprecated.test.d.ts +2 -0
  44. package/dist/cli/__tests__/doctor-explore-deprecated.test.d.ts.map +1 -0
  45. package/dist/cli/__tests__/doctor-explore-deprecated.test.js +33 -0
  46. package/dist/cli/__tests__/doctor-explore-deprecated.test.js.map +1 -0
  47. package/dist/cli/__tests__/doctor-spark-routing.test.js +13 -0
  48. package/dist/cli/__tests__/doctor-spark-routing.test.js.map +1 -1
  49. package/dist/cli/__tests__/doctor-warning-copy.test.js +132 -2
  50. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  51. package/dist/cli/__tests__/index.test.js +5 -0
  52. package/dist/cli/__tests__/index.test.js.map +1 -1
  53. package/dist/cli/__tests__/mcp-parity.test.js +40 -0
  54. package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
  55. package/dist/cli/__tests__/nested-help-routing.test.js +4 -0
  56. package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
  57. package/dist/cli/__tests__/package-bin-contract.test.js +7 -1
  58. package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
  59. package/dist/cli/__tests__/performance-goal.test.js +22 -0
  60. package/dist/cli/__tests__/performance-goal.test.js.map +1 -1
  61. package/dist/cli/__tests__/plugin-marketplace-idempotent.test.d.ts +2 -0
  62. package/dist/cli/__tests__/plugin-marketplace-idempotent.test.d.ts.map +1 -0
  63. package/dist/cli/__tests__/plugin-marketplace-idempotent.test.js +64 -0
  64. package/dist/cli/__tests__/plugin-marketplace-idempotent.test.js.map +1 -0
  65. package/dist/cli/__tests__/resume.test.js +96 -0
  66. package/dist/cli/__tests__/resume.test.js.map +1 -1
  67. package/dist/cli/__tests__/session-scoped-runtime.test.js +162 -0
  68. package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -1
  69. package/dist/cli/__tests__/session-search.test.js +36 -0
  70. package/dist/cli/__tests__/session-search.test.js.map +1 -1
  71. package/dist/cli/__tests__/setup-agents-overwrite.test.js +70 -1
  72. package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
  73. package/dist/cli/__tests__/setup-install-mode.test.js +33 -0
  74. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  75. package/dist/cli/__tests__/team.test.js +17 -3
  76. package/dist/cli/__tests__/team.test.js.map +1 -1
  77. package/dist/cli/__tests__/ultragoal.test.js +37 -0
  78. package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
  79. package/dist/cli/__tests__/update.test.js +81 -2
  80. package/dist/cli/__tests__/update.test.js.map +1 -1
  81. package/dist/cli/__tests__/url.test.d.ts +2 -0
  82. package/dist/cli/__tests__/url.test.d.ts.map +1 -0
  83. package/dist/cli/__tests__/url.test.js +82 -0
  84. package/dist/cli/__tests__/url.test.js.map +1 -0
  85. package/dist/cli/autoresearch-goal.d.ts.map +1 -1
  86. package/dist/cli/autoresearch-goal.js +2 -1
  87. package/dist/cli/autoresearch-goal.js.map +1 -1
  88. package/dist/cli/autoresearch-intake.d.ts.map +1 -1
  89. package/dist/cli/autoresearch-intake.js +2 -0
  90. package/dist/cli/autoresearch-intake.js.map +1 -1
  91. package/dist/cli/doctor.d.ts +39 -1
  92. package/dist/cli/doctor.d.ts.map +1 -1
  93. package/dist/cli/doctor.js +460 -40
  94. package/dist/cli/doctor.js.map +1 -1
  95. package/dist/cli/index.d.ts +2 -2
  96. package/dist/cli/index.d.ts.map +1 -1
  97. package/dist/cli/index.js +71 -4
  98. package/dist/cli/index.js.map +1 -1
  99. package/dist/cli/performance-goal.d.ts.map +1 -1
  100. package/dist/cli/performance-goal.js +4 -2
  101. package/dist/cli/performance-goal.js.map +1 -1
  102. package/dist/cli/plugin-marketplace.d.ts +1 -0
  103. package/dist/cli/plugin-marketplace.d.ts.map +1 -1
  104. package/dist/cli/plugin-marketplace.js +88 -67
  105. package/dist/cli/plugin-marketplace.js.map +1 -1
  106. package/dist/cli/project-runtime-codex-homes.d.ts +2 -0
  107. package/dist/cli/project-runtime-codex-homes.d.ts.map +1 -1
  108. package/dist/cli/project-runtime-codex-homes.js +112 -5
  109. package/dist/cli/project-runtime-codex-homes.js.map +1 -1
  110. package/dist/cli/setup.d.ts.map +1 -1
  111. package/dist/cli/setup.js +15 -6
  112. package/dist/cli/setup.js.map +1 -1
  113. package/dist/cli/ultragoal.d.ts.map +1 -1
  114. package/dist/cli/ultragoal.js +5 -1
  115. package/dist/cli/ultragoal.js.map +1 -1
  116. package/dist/cli/update.d.ts.map +1 -1
  117. package/dist/cli/update.js +23 -4
  118. package/dist/cli/update.js.map +1 -1
  119. package/dist/cli/url.d.ts +8 -0
  120. package/dist/cli/url.d.ts.map +1 -0
  121. package/dist/cli/url.js +69 -0
  122. package/dist/cli/url.js.map +1 -0
  123. package/dist/config/__tests__/codex-hooks.test.js +20 -4
  124. package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
  125. package/dist/config/__tests__/models.test.js +21 -1
  126. package/dist/config/__tests__/models.test.js.map +1 -1
  127. package/dist/config/codex-hooks.d.ts.map +1 -1
  128. package/dist/config/codex-hooks.js +1 -4
  129. package/dist/config/codex-hooks.js.map +1 -1
  130. package/dist/config/models.d.ts +5 -0
  131. package/dist/config/models.d.ts.map +1 -1
  132. package/dist/config/models.js +23 -0
  133. package/dist/config/models.js.map +1 -1
  134. package/dist/goal-workflows/codex-goal-snapshot.d.ts +2 -0
  135. package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -1
  136. package/dist/goal-workflows/codex-goal-snapshot.js +10 -0
  137. package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -1
  138. package/dist/hooks/__tests__/autopilot-skill-contract.test.js +7 -0
  139. package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
  140. package/dist/hooks/__tests__/keyword-detector.test.js +46 -0
  141. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  142. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +100 -0
  143. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  144. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +75 -0
  145. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  146. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +225 -0
  147. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  148. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +75 -0
  149. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  150. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +563 -0
  151. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  152. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +187 -12
  153. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  154. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +225 -0
  155. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  156. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +0 -0
  157. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -1
  158. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +75 -0
  159. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  160. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  161. package/dist/hooks/keyword-detector.js +4 -0
  162. package/dist/hooks/keyword-detector.js.map +1 -1
  163. package/dist/hud/__tests__/reconcile.test.js +137 -2
  164. package/dist/hud/__tests__/reconcile.test.js.map +1 -1
  165. package/dist/hud/__tests__/state.test.js +107 -0
  166. package/dist/hud/__tests__/state.test.js.map +1 -1
  167. package/dist/hud/__tests__/tmux.test.js +17 -0
  168. package/dist/hud/__tests__/tmux.test.js.map +1 -1
  169. package/dist/hud/reconcile.d.ts.map +1 -1
  170. package/dist/hud/reconcile.js +21 -7
  171. package/dist/hud/reconcile.js.map +1 -1
  172. package/dist/hud/render.d.ts.map +1 -1
  173. package/dist/hud/render.js +9 -0
  174. package/dist/hud/render.js.map +1 -1
  175. package/dist/hud/state.d.ts.map +1 -1
  176. package/dist/hud/state.js +43 -5
  177. package/dist/hud/state.js.map +1 -1
  178. package/dist/hud/types.d.ts +6 -0
  179. package/dist/hud/types.d.ts.map +1 -1
  180. package/dist/hud/types.js.map +1 -1
  181. package/dist/index.d.ts +1 -0
  182. package/dist/index.d.ts.map +1 -1
  183. package/dist/index.js +1 -0
  184. package/dist/index.js.map +1 -1
  185. package/dist/mcp/__tests__/bootstrap.test.js +24 -1
  186. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  187. package/dist/mcp/__tests__/state-paths.test.js +53 -0
  188. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  189. package/dist/mcp/bootstrap.d.ts +2 -0
  190. package/dist/mcp/bootstrap.d.ts.map +1 -1
  191. package/dist/mcp/bootstrap.js +32 -6
  192. package/dist/mcp/bootstrap.js.map +1 -1
  193. package/dist/mcp/state-paths.d.ts.map +1 -1
  194. package/dist/mcp/state-paths.js +11 -5
  195. package/dist/mcp/state-paths.js.map +1 -1
  196. package/dist/modes/__tests__/base-autopilot-gates.test.js +48 -0
  197. package/dist/modes/__tests__/base-autopilot-gates.test.js.map +1 -1
  198. package/dist/modes/base.d.ts.map +1 -1
  199. package/dist/modes/base.js +1 -0
  200. package/dist/modes/base.js.map +1 -1
  201. package/dist/notifications/__tests__/http-client.test.js +9 -0
  202. package/dist/notifications/__tests__/http-client.test.js.map +1 -1
  203. package/dist/notifications/http-client.js +1 -1
  204. package/dist/notifications/http-client.js.map +1 -1
  205. package/dist/performance-goal/artifacts.d.ts.map +1 -1
  206. package/dist/performance-goal/artifacts.js +10 -1
  207. package/dist/performance-goal/artifacts.js.map +1 -1
  208. package/dist/ralplan/__tests__/consensus-gate.test.js +112 -0
  209. package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
  210. package/dist/ralplan/consensus-gate.d.ts +23 -0
  211. package/dist/ralplan/consensus-gate.d.ts.map +1 -1
  212. package/dist/ralplan/consensus-gate.js +133 -21
  213. package/dist/ralplan/consensus-gate.js.map +1 -1
  214. package/dist/scripts/__tests__/codex-native-hook.test.js +1251 -13
  215. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  216. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  217. package/dist/scripts/codex-native-hook.js +601 -24
  218. package/dist/scripts/codex-native-hook.js.map +1 -1
  219. package/dist/scripts/notify-hook/team-leader-nudge.d.ts +1 -0
  220. package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
  221. package/dist/scripts/notify-hook/team-leader-nudge.js +279 -86
  222. package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
  223. package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
  224. package/dist/scripts/notify-hook/team-tmux-guard.js +87 -8
  225. package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
  226. package/dist/scripts/notify-hook/tmux-injection.js +1 -1
  227. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  228. package/dist/scripts/run-compiled-ci.d.ts +2 -0
  229. package/dist/scripts/run-compiled-ci.d.ts.map +1 -0
  230. package/dist/scripts/run-compiled-ci.js +77 -0
  231. package/dist/scripts/run-compiled-ci.js.map +1 -0
  232. package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
  233. package/dist/scripts/sync-plugin-mirror.js +1 -0
  234. package/dist/scripts/sync-plugin-mirror.js.map +1 -1
  235. package/dist/session-history/search.d.ts.map +1 -1
  236. package/dist/session-history/search.js +24 -9
  237. package/dist/session-history/search.js.map +1 -1
  238. package/dist/sidecar/__tests__/args.test.d.ts +2 -0
  239. package/dist/sidecar/__tests__/args.test.d.ts.map +1 -0
  240. package/dist/sidecar/__tests__/args.test.js +18 -0
  241. package/dist/sidecar/__tests__/args.test.js.map +1 -0
  242. package/dist/sidecar/index.d.ts.map +1 -1
  243. package/dist/sidecar/index.js +12 -4
  244. package/dist/sidecar/index.js.map +1 -1
  245. package/dist/state/__tests__/operations.test.js +107 -3
  246. package/dist/state/__tests__/operations.test.js.map +1 -1
  247. package/dist/state/operations.d.ts.map +1 -1
  248. package/dist/state/operations.js +57 -2
  249. package/dist/state/operations.js.map +1 -1
  250. package/dist/team/__tests__/delivery-e2e-smoke.test.js +22 -1
  251. package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
  252. package/dist/team/__tests__/model-contract.test.js +57 -1
  253. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  254. package/dist/team/__tests__/runtime.test.js +1468 -110
  255. package/dist/team/__tests__/runtime.test.js.map +1 -1
  256. package/dist/team/__tests__/scaling.test.js +63 -0
  257. package/dist/team/__tests__/scaling.test.js.map +1 -1
  258. package/dist/team/__tests__/state.test.js +24 -1
  259. package/dist/team/__tests__/state.test.js.map +1 -1
  260. package/dist/team/__tests__/tmux-session.test.js +512 -0
  261. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  262. package/dist/team/__tests__/worker-bootstrap.test.js +42 -9
  263. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  264. package/dist/team/model-contract.d.ts +16 -0
  265. package/dist/team/model-contract.d.ts.map +1 -1
  266. package/dist/team/model-contract.js +41 -1
  267. package/dist/team/model-contract.js.map +1 -1
  268. package/dist/team/runtime.d.ts.map +1 -1
  269. package/dist/team/runtime.js +116 -30
  270. package/dist/team/runtime.js.map +1 -1
  271. package/dist/team/scaling.d.ts.map +1 -1
  272. package/dist/team/scaling.js +9 -1
  273. package/dist/team/scaling.js.map +1 -1
  274. package/dist/team/state/types.d.ts +2 -0
  275. package/dist/team/state/types.d.ts.map +1 -1
  276. package/dist/team/state/types.js.map +1 -1
  277. package/dist/team/state.d.ts +3 -0
  278. package/dist/team/state.d.ts.map +1 -1
  279. package/dist/team/state.js +20 -0
  280. package/dist/team/state.js.map +1 -1
  281. package/dist/team/tmux-session.d.ts +38 -3
  282. package/dist/team/tmux-session.d.ts.map +1 -1
  283. package/dist/team/tmux-session.js +275 -36
  284. package/dist/team/tmux-session.js.map +1 -1
  285. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  286. package/dist/team/worker-bootstrap.js +26 -1
  287. package/dist/team/worker-bootstrap.js.map +1 -1
  288. package/dist/ultragoal/__tests__/artifacts.test.js +388 -0
  289. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  290. package/dist/ultragoal/__tests__/docs-contract.test.js +3 -0
  291. package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
  292. package/dist/ultragoal/artifacts.d.ts +23 -0
  293. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  294. package/dist/ultragoal/artifacts.js +275 -12
  295. package/dist/ultragoal/artifacts.js.map +1 -1
  296. package/dist/url-reader/__tests__/url-reader.test.d.ts +2 -0
  297. package/dist/url-reader/__tests__/url-reader.test.d.ts.map +1 -0
  298. package/dist/url-reader/__tests__/url-reader.test.js +433 -0
  299. package/dist/url-reader/__tests__/url-reader.test.js.map +1 -0
  300. package/dist/url-reader/index.d.ts +4 -0
  301. package/dist/url-reader/index.d.ts.map +1 -0
  302. package/dist/url-reader/index.js +522 -0
  303. package/dist/url-reader/index.js.map +1 -0
  304. package/dist/url-reader/types.d.ts +41 -0
  305. package/dist/url-reader/types.d.ts.map +1 -0
  306. package/dist/url-reader/types.js +2 -0
  307. package/dist/url-reader/types.js.map +1 -0
  308. package/dist/utils/__tests__/agents-md.test.js +39 -1
  309. package/dist/utils/__tests__/agents-md.test.js.map +1 -1
  310. package/dist/utils/__tests__/agents-model-table.test.js +28 -0
  311. package/dist/utils/__tests__/agents-model-table.test.js.map +1 -1
  312. package/dist/utils/agents-md.d.ts +4 -0
  313. package/dist/utils/agents-md.d.ts.map +1 -1
  314. package/dist/utils/agents-md.js +28 -0
  315. package/dist/utils/agents-md.js.map +1 -1
  316. package/dist/utils/agents-model-table.d.ts +7 -3
  317. package/dist/utils/agents-model-table.d.ts.map +1 -1
  318. package/dist/utils/agents-model-table.js +16 -8
  319. package/dist/utils/agents-model-table.js.map +1 -1
  320. package/dist/utils/platform-command.d.ts +7 -1
  321. package/dist/utils/platform-command.d.ts.map +1 -1
  322. package/dist/utils/platform-command.js +12 -1
  323. package/dist/utils/platform-command.js.map +1 -1
  324. package/dist/verification/__tests__/ci-rust-gates.test.js +4 -0
  325. package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
  326. package/dist/vscode/__tests__/index.test.d.ts +2 -0
  327. package/dist/vscode/__tests__/index.test.d.ts.map +1 -0
  328. package/dist/vscode/__tests__/index.test.js +236 -0
  329. package/dist/vscode/__tests__/index.test.js.map +1 -0
  330. package/dist/vscode/index.d.ts +76 -0
  331. package/dist/vscode/index.d.ts.map +1 -0
  332. package/dist/vscode/index.js +196 -0
  333. package/dist/vscode/index.js.map +1 -0
  334. package/package.json +3 -3
  335. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  336. package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +59 -8
  337. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +9 -5
  338. package/plugins/oh-my-codex/skills/autoresearch-goal/SKILL.md +3 -0
  339. package/plugins/oh-my-codex/skills/performance-goal/SKILL.md +3 -0
  340. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +1 -1
  341. package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +22 -4
  342. package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +2 -2
  343. package/plugins/oh-my-codex/skills/ultrawork/references/agent-tiers.md +61 -0
  344. package/skills/autopilot/SKILL.md +9 -5
  345. package/skills/autoresearch-goal/SKILL.md +3 -0
  346. package/skills/ecomode/SKILL.md +1 -1
  347. package/skills/ecomode/references/agent-tiers.md +61 -0
  348. package/skills/performance-goal/SKILL.md +3 -0
  349. package/skills/ralplan/SKILL.md +1 -1
  350. package/skills/ultragoal/SKILL.md +22 -4
  351. package/skills/ultrawork/SKILL.md +2 -2
  352. package/skills/ultrawork/references/agent-tiers.md +61 -0
  353. package/src/scripts/__tests__/codex-native-hook.test.ts +1560 -181
  354. package/src/scripts/codex-native-hook.ts +663 -24
  355. package/src/scripts/notify-hook/team-leader-nudge.ts +298 -91
  356. package/src/scripts/notify-hook/team-tmux-guard.ts +92 -8
  357. package/src/scripts/notify-hook/tmux-injection.ts +1 -1
  358. package/src/scripts/run-compiled-ci.ts +85 -0
  359. package/src/scripts/sync-plugin-mirror.ts +1 -0
  360. package/templates/AGENTS.md +6 -0
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Team leader nudge: remind the leader to check teammate/mailbox state.
3
3
  */
4
+ export declare function setLeaderNudgeTestHooksForTests(hooks?: {}): void;
4
5
  export declare function resolveLeaderNudgeIntervalMs(): number;
5
6
  export declare function resolveLeaderAllIdleNudgeCooldownMs(): number;
6
7
  export declare function resolveLeaderStalenessThresholdMs(): number;
@@ -1 +1 @@
1
- {"version":3,"file":"team-leader-nudge.d.ts","sourceRoot":"","sources":["../../../src/scripts/notify-hook/team-leader-nudge.ts"],"names":[],"mappings":"AACA;;GAEG;AAmDH,wBAAgB,4BAA4B,WAM3C;AAED,wBAAgB,mCAAmC,WAMlD;AAED,wBAAgB,iCAAiC,WAMhD;AAgED,wBAAsB,qBAAqB,CAAC,UAAU,KAAA,EAAE,aAAa,UAAK;;;GAoBzE;AAED,wBAAsB,aAAa,CAAC,QAAQ,KAAA,EAAE,WAAW,KAAA,EAAE,KAAK,KAAA,oBAE/D;AA6UD,wBAAsB,kBAAkB,CAAC,GAAG,KAAA,EAAE,QAAQ,KAAA,EAAE,MAAM,KAAA,EAAE,mBAAmB,KAAA,EAAE,MAAM,KAAA,iBAkB1F;AA4BD,wBAAsB,oBAAoB,CAAC,EACzC,GAAG,EACH,QAAQ,EACR,OAAO,EACP,sBAAsB,EACtB,uBAA8B,EAC9B,MAAsB,GACvB;;;;;;;CAAA,iBAqgBA"}
1
+ {"version":3,"file":"team-leader-nudge.d.ts","sourceRoot":"","sources":["../../../src/scripts/notify-hook/team-leader-nudge.ts"],"names":[],"mappings":"AACA;;GAEG;AA+CH,wBAAgB,+BAA+B,CAAC,KAAK,KAAK,QAazD;AA8FD,wBAAgB,4BAA4B,WAM3C;AAED,wBAAgB,mCAAmC,WAMlD;AAED,wBAAgB,iCAAiC,WAMhD;AAgED,wBAAsB,qBAAqB,CAAC,UAAU,KAAA,EAAE,aAAa,UAAK;;;GAoBzE;AAED,wBAAsB,aAAa,CAAC,QAAQ,KAAA,EAAE,WAAW,KAAA,EAAE,KAAK,KAAA,oBAE/D;AA6UD,wBAAsB,kBAAkB,CAAC,GAAG,KAAA,EAAE,QAAQ,KAAA,EAAE,MAAM,KAAA,EAAE,mBAAmB,KAAA,EAAE,MAAM,KAAA,iBAkB1F;AA4BD,wBAAsB,oBAAoB,CAAC,EACzC,GAAG,EACH,QAAQ,EACR,OAAO,EACP,sBAAsB,EACtB,uBAA8B,EAC9B,MAAsB,GACvB;;;;;;;CAAA,iBA6mBA"}
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * Team leader nudge: remind the leader to check teammate/mailbox state.
4
4
  */
5
- import { readFile, writeFile, mkdir, appendFile, readdir } from 'fs/promises';
5
+ import { readFile, writeFile, mkdir, appendFile, readdir, rename, unlink } from 'fs/promises';
6
6
  import { existsSync } from 'fs';
7
7
  import { join, resolve } from 'path';
8
8
  import { readUsableSessionState } from '../../hooks/session.js';
@@ -17,13 +17,13 @@ import { classifyLeaderActionState, resolveLeaderNudgeIntent, } from './orchestr
17
17
  import { DEFAULT_MARKER, paneHasActiveTask } from '../tmux-hook-engine.js';
18
18
  import { isLeaderRuntimeStale } from '../../team/leader-activity.js';
19
19
  import { appendTeamDeliveryLog } from '../../team/delivery-log.js';
20
- import { writeTeamLeaderAttention } from '../../team/state.js';
21
20
  import { readLatestTeamProgressEvidenceMs } from '../../team/progress-evidence.js';
22
21
  import { validateSessionId } from '../../mcp/state-paths.js';
23
22
  import { TEAM_NAME_SAFE_PATTERN } from '../../team/contracts.js';
24
23
  import { isDeepInterviewStateActive } from './auto-nudge.js';
25
24
  const LEADER_PANE_MISSING_NO_INJECTION_REASON = 'leader_pane_missing_no_injection';
26
25
  const LEADER_PANE_SHELL_NO_INJECTION_REASON = 'leader_pane_shell_no_injection';
26
+ const TEAM_SHUTDOWN_NO_INJECTION_REASON = 'team_state_gone_or_shutdown';
27
27
  const LEADER_PANE_SAME_CLASSIFIED_STATE_SUPPRESSED_REASON = 'pane_already_shows_same_classified_state';
28
28
  const LEADER_NOTIFICATION_DEFERRED_TYPE = 'leader_notification_deferred';
29
29
  const ACK_WITHOUT_START_EVIDENCE_REASON = 'ack_without_start_evidence';
@@ -32,6 +32,99 @@ const ACK_LIKE_PATTERNS = [
32
32
  /^(?:ok|okay|k|roger|copy|received|got it|understood|sounds good)[.!]*$/i,
33
33
  /^(?:on it|will do|i(?:'|')ll do it|working on it)[.!]*$/i,
34
34
  ];
35
+ let atomicJsonWriteCounter = 0;
36
+ // Synchronous test-only callbacks let regression tests emulate filesystem races
37
+ // without shipping env-gated destructive fault injection in the notify hook.
38
+ const leaderNudgeTestHooks = {
39
+ beforeLeaderAttentionRename: null,
40
+ afterLeaderAttentionRename: null,
41
+ beforeGlobalNudgeStateRename: null,
42
+ afterGlobalNudgeStateRename: null,
43
+ };
44
+ export function setLeaderNudgeTestHooksForTests(hooks = {}) {
45
+ leaderNudgeTestHooks.beforeLeaderAttentionRename = typeof hooks.beforeLeaderAttentionRename === 'function'
46
+ ? hooks.beforeLeaderAttentionRename
47
+ : null;
48
+ leaderNudgeTestHooks.afterLeaderAttentionRename = typeof hooks.afterLeaderAttentionRename === 'function'
49
+ ? hooks.afterLeaderAttentionRename
50
+ : null;
51
+ leaderNudgeTestHooks.beforeGlobalNudgeStateRename = typeof hooks.beforeGlobalNudgeStateRename === 'function'
52
+ ? hooks.beforeGlobalNudgeStateRename
53
+ : null;
54
+ leaderNudgeTestHooks.afterGlobalNudgeStateRename = typeof hooks.afterGlobalNudgeStateRename === 'function'
55
+ ? hooks.afterGlobalNudgeStateRename
56
+ : null;
57
+ }
58
+ async function atomicWriteJsonNoParentCreate(path, value, { beforeRename = null, afterRename = null } = {}) {
59
+ const tempPath = `${path}.${process.pid}.${Date.now()}.${++atomicJsonWriteCounter}.tmp`;
60
+ try {
61
+ await writeFile(tempPath, JSON.stringify(value, null, 2));
62
+ if (beforeRename)
63
+ await beforeRename(tempPath);
64
+ await rename(tempPath, path);
65
+ if (afterRename)
66
+ await afterRename(path);
67
+ }
68
+ catch (error) {
69
+ await unlink(tempPath).catch(() => { });
70
+ throw error;
71
+ }
72
+ }
73
+ function cloneLeaderNudgeState(state) {
74
+ return {
75
+ ...(state && typeof state === 'object' ? state : {}),
76
+ last_nudged_by_team: { ...(state?.last_nudged_by_team || {}) },
77
+ last_idle_nudged_by_team: { ...(state?.last_idle_nudged_by_team || {}) },
78
+ progress_by_team: { ...(state?.progress_by_team || {}) },
79
+ };
80
+ }
81
+ function removeTeamFromLeaderNudgeState(state, teamName) {
82
+ if (state?.progress_by_team && typeof state.progress_by_team === 'object') {
83
+ delete state.progress_by_team[teamName];
84
+ }
85
+ if (state?.last_nudged_by_team && typeof state.last_nudged_by_team === 'object') {
86
+ delete state.last_nudged_by_team[teamName];
87
+ }
88
+ if (state?.last_idle_nudged_by_team && typeof state.last_idle_nudged_by_team === 'object') {
89
+ delete state.last_idle_nudged_by_team[teamName];
90
+ }
91
+ }
92
+ async function teamStateAllowsLeaderNudge(stateDir, teamName) {
93
+ const teamDir = join(stateDir, 'team', teamName);
94
+ if (!existsSync(teamDir))
95
+ return false;
96
+ if (existsSync(join(teamDir, 'shutdown.json')))
97
+ return false;
98
+ const phase = await readJsonIfExists(join(teamDir, 'phase.json'), null);
99
+ const currentPhase = safeString(phase?.current_phase || phase?.phase || '').trim();
100
+ if (currentPhase && isTerminalPhase(currentPhase))
101
+ return false;
102
+ return true;
103
+ }
104
+ async function recordSuppressedLeaderNudge({ logsDir, source, teamName, reason, orchestrationIntent = null, }) {
105
+ const nowIso = new Date().toISOString();
106
+ await logTmuxHookEvent(logsDir, {
107
+ timestamp: nowIso,
108
+ type: 'team_leader_nudge_suppressed',
109
+ team: teamName,
110
+ worker: 'leader-fixed',
111
+ to_worker: 'leader-fixed',
112
+ reason,
113
+ orchestration_intent: orchestrationIntent,
114
+ tmux_injection_attempted: false,
115
+ source_type: 'leader_nudge',
116
+ }).catch(() => { });
117
+ await appendTeamDeliveryLog(logsDir, {
118
+ event: 'nudge_triggered',
119
+ source,
120
+ team: teamName,
121
+ to_worker: 'leader-fixed',
122
+ transport: 'none',
123
+ result: 'suppressed',
124
+ reason,
125
+ orchestration_intent: orchestrationIntent,
126
+ }).catch(() => { });
127
+ }
35
128
  function normalizeValidSessionId(value) {
36
129
  const trimmed = safeString(value).trim();
37
130
  if (!trimmed)
@@ -579,6 +672,15 @@ export async function maybeNudgeTeamLeader({ cwd, stateDir, logsDir, preComputed
579
672
  // Use pre-computed staleness (captured before HUD state was updated this turn)
580
673
  const leaderStale = typeof preComputedLeaderStale === 'boolean' ? preComputedLeaderStale : false;
581
674
  for (const teamName of candidateTeamNames) {
675
+ if (!(await teamStateAllowsLeaderNudge(stateDir, teamName))) {
676
+ await recordSuppressedLeaderNudge({
677
+ logsDir,
678
+ source,
679
+ teamName,
680
+ reason: TEAM_SHUTDOWN_NO_INJECTION_REASON,
681
+ });
682
+ continue;
683
+ }
582
684
  let tmuxSession = '';
583
685
  let leaderPaneId = '';
584
686
  let ownerSessionId = '';
@@ -736,58 +838,158 @@ export async function maybeNudgeTeamLeader({ cwd, stateDir, logsDir, preComputed
736
838
  text = `Team ${teamName}: ${messages.length} msg(s) for leader. ${buildMailboxCheckReminder(teamName)}`;
737
839
  }
738
840
  const unreadLeaderMessageCount = messages.filter((message) => !safeString(message?.delivered_at).trim()).length;
739
- nudgeState.progress_by_team[teamName] = {
740
- signature: progressSnapshot.signature,
741
- last_progress_at: effectiveProgressAtIso,
742
- observed_at: nowIso,
743
- missing_signal_workers: progressSnapshot.missingSignalWorkers,
744
- work_remaining: progressSnapshot.workRemaining,
745
- leader_action_state: leaderActionState,
746
- leader_attention_pending: !!nudgeReason,
747
- leader_attention_reason: nudgeReason || null,
748
- leader_stale: leaderStale,
749
- all_workers_idle: allWorkersIdle,
750
- pending_task_count: (progressSnapshot.taskCounts.pending || 0)
751
- + (progressSnapshot.taskCounts.blocked || 0)
752
- + (progressSnapshot.taskCounts.in_progress || 0),
753
- unread_leader_message_count: unreadLeaderMessageCount,
754
- stalled_for_ms: null,
755
- source: source === 'notify_fallback_watcher' ? 'notify_hook' : source,
841
+ const recordShutdownSuppression = async (orchestrationIntent = null) => {
842
+ await recordSuppressedLeaderNudge({
843
+ logsDir,
844
+ source,
845
+ teamName,
846
+ reason: TEAM_SHUTDOWN_NO_INJECTION_REASON,
847
+ orchestrationIntent,
848
+ });
756
849
  };
757
- await writeTeamLeaderAttention(teamName, {
758
- team_name: teamName,
759
- updated_at: nowIso,
760
- source: 'notify_hook',
761
- leader_decision_state: leaderActionState,
762
- leader_attention_pending: !!nudgeReason,
763
- leader_attention_reason: nudgeReason || null,
764
- attention_reasons: nudgeReason ? [nudgeReason] : [],
765
- leader_stale: leaderStale,
766
- leader_session_active: true,
767
- leader_session_id: currentSessionId || ownerSessionId || null,
768
- leader_session_stopped_at: null,
769
- unread_leader_message_count: unreadLeaderMessageCount,
770
- work_remaining: progressSnapshot.workRemaining,
771
- stalled_for_ms: null,
772
- }, cwd).catch(() => { });
773
- if (!nudgeReason)
850
+ const cleanupTeamPersistence = async () => {
851
+ await unlink(join(stateDir, 'team', teamName, 'leader-attention.json')).catch(() => { });
852
+ const latestState = await readJsonIfExists(nudgeStatePath, nudgeState);
853
+ const cleanedState = cloneLeaderNudgeState(latestState);
854
+ removeTeamFromLeaderNudgeState(cleanedState, teamName);
855
+ nudgeState = cleanedState;
856
+ await atomicWriteJsonNoParentCreate(nudgeStatePath, cleanedState).catch(() => { });
857
+ };
858
+ const persistLeaderNudgeBookkeeping = async ({ orchestrationIntent = null, recordLastNudged = false } = {}) => {
859
+ if (!(await teamStateAllowsLeaderNudge(stateDir, teamName))) {
860
+ await recordShutdownSuppression(orchestrationIntent);
861
+ return false;
862
+ }
863
+ const leaderAttention = {
864
+ team_name: teamName,
865
+ updated_at: nowIso,
866
+ source: 'notify_hook',
867
+ leader_decision_state: leaderActionState,
868
+ leader_attention_pending: !!nudgeReason,
869
+ leader_attention_reason: nudgeReason || null,
870
+ attention_reasons: nudgeReason ? [nudgeReason] : [],
871
+ leader_stale: leaderStale,
872
+ leader_session_active: true,
873
+ leader_session_id: currentSessionId || ownerSessionId || null,
874
+ leader_session_stopped_at: null,
875
+ unread_leader_message_count: unreadLeaderMessageCount,
876
+ work_remaining: progressSnapshot.workRemaining,
877
+ stalled_for_ms: null,
878
+ };
879
+ const leaderAttentionPath = join(stateDir, 'team', teamName, 'leader-attention.json');
880
+ try {
881
+ await atomicWriteJsonNoParentCreate(leaderAttentionPath, leaderAttention, {
882
+ beforeRename: async (tempPath) => {
883
+ if (leaderNudgeTestHooks.beforeLeaderAttentionRename) {
884
+ await leaderNudgeTestHooks.beforeLeaderAttentionRename({ stateDir, teamName, tempPath });
885
+ }
886
+ if (!(await teamStateAllowsLeaderNudge(stateDir, teamName))) {
887
+ throw new Error('team_state_gone_or_shutdown_before_leader_attention_rename');
888
+ }
889
+ },
890
+ afterRename: async () => {
891
+ if (leaderNudgeTestHooks.afterLeaderAttentionRename) {
892
+ await leaderNudgeTestHooks.afterLeaderAttentionRename({ stateDir, teamName, path: leaderAttentionPath });
893
+ }
894
+ },
895
+ });
896
+ }
897
+ catch {
898
+ await unlink(leaderAttentionPath).catch(() => { });
899
+ await recordShutdownSuppression(orchestrationIntent);
900
+ return false;
901
+ }
902
+ if (!(await teamStateAllowsLeaderNudge(stateDir, teamName))) {
903
+ await cleanupTeamPersistence();
904
+ await recordShutdownSuppression(orchestrationIntent);
905
+ return false;
906
+ }
907
+ const nextNudgeState = cloneLeaderNudgeState(nudgeState);
908
+ nextNudgeState.progress_by_team[teamName] = {
909
+ signature: progressSnapshot.signature,
910
+ last_progress_at: effectiveProgressAtIso,
911
+ observed_at: nowIso,
912
+ missing_signal_workers: progressSnapshot.missingSignalWorkers,
913
+ work_remaining: progressSnapshot.workRemaining,
914
+ leader_action_state: leaderActionState,
915
+ leader_attention_pending: !!nudgeReason,
916
+ leader_attention_reason: nudgeReason || null,
917
+ leader_stale: leaderStale,
918
+ all_workers_idle: allWorkersIdle,
919
+ pending_task_count: (progressSnapshot.taskCounts.pending || 0)
920
+ + (progressSnapshot.taskCounts.blocked || 0)
921
+ + (progressSnapshot.taskCounts.in_progress || 0),
922
+ unread_leader_message_count: unreadLeaderMessageCount,
923
+ stalled_for_ms: null,
924
+ source: source === 'notify_fallback_watcher' ? 'notify_hook' : source,
925
+ };
926
+ if (recordLastNudged) {
927
+ nextNudgeState.last_nudged_by_team[teamName] = {
928
+ at: nowIso,
929
+ last_message_id: newestId || prevMsgId || '',
930
+ reason: nudgeReason,
931
+ orchestration_intent: orchestrationIntent,
932
+ };
933
+ if (shouldSendAllIdleNudge) {
934
+ nextNudgeState.last_idle_nudged_by_team[teamName] = {
935
+ at: nowIso,
936
+ worker_count: workerNames.length,
937
+ orchestration_intent: orchestrationIntent,
938
+ };
939
+ }
940
+ }
941
+ try {
942
+ await atomicWriteJsonNoParentCreate(nudgeStatePath, nextNudgeState, {
943
+ beforeRename: async (tempPath) => {
944
+ if (leaderNudgeTestHooks.beforeGlobalNudgeStateRename) {
945
+ await leaderNudgeTestHooks.beforeGlobalNudgeStateRename({ stateDir, teamName, tempPath });
946
+ }
947
+ if (!(await teamStateAllowsLeaderNudge(stateDir, teamName))) {
948
+ throw new Error('team_state_gone_or_shutdown_before_nudge_state_rename');
949
+ }
950
+ },
951
+ afterRename: async () => {
952
+ if (leaderNudgeTestHooks.afterGlobalNudgeStateRename) {
953
+ await leaderNudgeTestHooks.afterGlobalNudgeStateRename({ stateDir, teamName, path: nudgeStatePath });
954
+ }
955
+ },
956
+ });
957
+ }
958
+ catch {
959
+ await cleanupTeamPersistence();
960
+ await recordShutdownSuppression(orchestrationIntent);
961
+ return false;
962
+ }
963
+ if (!(await teamStateAllowsLeaderNudge(stateDir, teamName))) {
964
+ await cleanupTeamPersistence();
965
+ await recordShutdownSuppression(orchestrationIntent);
966
+ return false;
967
+ }
968
+ nudgeState = nextNudgeState;
969
+ return true;
970
+ };
971
+ if (!nudgeReason) {
972
+ if (!(await teamStateAllowsLeaderNudge(stateDir, teamName))) {
973
+ await recordShutdownSuppression();
974
+ continue;
975
+ }
976
+ await persistLeaderNudgeBookkeeping();
774
977
  continue;
978
+ }
775
979
  const orchestrationIntent = resolveLeaderNudgeIntent({ nudgeReason, leaderActionState });
980
+ if (!(await teamStateAllowsLeaderNudge(stateDir, teamName))) {
981
+ await recordShutdownSuppression(orchestrationIntent);
982
+ continue;
983
+ }
776
984
  const capped = text.length > 180 ? `${text.slice(0, 177)}...` : text;
777
985
  const markedText = `${capped} ${DEFAULT_MARKER}`;
778
986
  if (!tmuxTarget) {
779
- nudgeState.last_nudged_by_team[teamName] = {
780
- at: nowIso,
781
- last_message_id: newestId || prevMsgId || '',
782
- reason: nudgeReason,
783
- orchestration_intent: orchestrationIntent,
784
- };
785
- if (shouldSendAllIdleNudge) {
786
- nudgeState.last_idle_nudged_by_team[teamName] = {
787
- at: nowIso,
788
- worker_count: workerNames.length,
789
- orchestration_intent: orchestrationIntent,
790
- };
987
+ if (!(await teamStateAllowsLeaderNudge(stateDir, teamName))) {
988
+ await recordShutdownSuppression(orchestrationIntent);
989
+ continue;
990
+ }
991
+ if (!(await persistLeaderNudgeBookkeeping({ orchestrationIntent, recordLastNudged: true }))) {
992
+ continue;
791
993
  }
792
994
  await emitLeaderNudgeDeferredEvent(cwd, teamName, LEADER_PANE_MISSING_NO_INJECTION_REASON, orchestrationIntent, nowIso, {
793
995
  tmuxSession,
@@ -834,18 +1036,12 @@ export async function maybeNudgeTeamLeader({ cwd, stateDir, logsDir, preComputed
834
1036
  const deferredReason = paneGuard.reason === 'pane_running_shell'
835
1037
  ? LEADER_PANE_SHELL_NO_INJECTION_REASON
836
1038
  : paneGuard.reason;
837
- nudgeState.last_nudged_by_team[teamName] = {
838
- at: nowIso,
839
- last_message_id: newestId || prevMsgId || '',
840
- reason: nudgeReason,
841
- orchestration_intent: orchestrationIntent,
842
- };
843
- if (shouldSendAllIdleNudge) {
844
- nudgeState.last_idle_nudged_by_team[teamName] = {
845
- at: nowIso,
846
- worker_count: workerNames.length,
847
- orchestration_intent: orchestrationIntent,
848
- };
1039
+ if (!(await teamStateAllowsLeaderNudge(stateDir, teamName))) {
1040
+ await recordShutdownSuppression(orchestrationIntent);
1041
+ continue;
1042
+ }
1043
+ if (!(await persistLeaderNudgeBookkeeping({ orchestrationIntent, recordLastNudged: true }))) {
1044
+ continue;
849
1045
  }
850
1046
  await emitLeaderNudgeDeferredEvent(cwd, teamName, deferredReason, orchestrationIntent, nowIso, {
851
1047
  tmuxSession,
@@ -886,18 +1082,12 @@ export async function maybeNudgeTeamLeader({ cwd, stateDir, logsDir, preComputed
886
1082
  continue;
887
1083
  }
888
1084
  if (paneAlreadyShowsVisibleLeaderState(paneGuard.paneCapture, capped)) {
889
- nudgeState.last_nudged_by_team[teamName] = {
890
- at: nowIso,
891
- last_message_id: newestId || prevMsgId || '',
892
- reason: nudgeReason,
893
- orchestration_intent: orchestrationIntent,
894
- };
895
- if (shouldSendAllIdleNudge) {
896
- nudgeState.last_idle_nudged_by_team[teamName] = {
897
- at: nowIso,
898
- worker_count: workerNames.length,
899
- orchestration_intent: orchestrationIntent,
900
- };
1085
+ if (!(await teamStateAllowsLeaderNudge(stateDir, teamName))) {
1086
+ await recordShutdownSuppression(orchestrationIntent);
1087
+ continue;
1088
+ }
1089
+ if (!(await persistLeaderNudgeBookkeeping({ orchestrationIntent, recordLastNudged: true }))) {
1090
+ continue;
901
1091
  }
902
1092
  await emitTeamNudgeEvent(cwd, teamName, nudgeReason, orchestrationIntent, nowIso);
903
1093
  try {
@@ -932,6 +1122,10 @@ export async function maybeNudgeTeamLeader({ cwd, stateDir, logsDir, preComputed
932
1122
  }).catch(() => { });
933
1123
  continue;
934
1124
  }
1125
+ if (!(await teamStateAllowsLeaderNudge(stateDir, teamName))) {
1126
+ await recordShutdownSuppression(orchestrationIntent);
1127
+ continue;
1128
+ }
935
1129
  try {
936
1130
  const leaderHasActiveTask = paneHasActiveTask(paneGuard.paneCapture);
937
1131
  let deliveryMode = 'sent';
@@ -956,20 +1150,16 @@ export async function maybeNudgeTeamLeader({ cwd, stateDir, logsDir, preComputed
956
1150
  throw new Error(sendResult.error || sendResult.reason);
957
1151
  }
958
1152
  }
959
- nudgeState.last_nudged_by_team[teamName] = {
960
- at: nowIso,
961
- last_message_id: newestId || prevMsgId || '',
962
- reason: nudgeReason,
963
- orchestration_intent: orchestrationIntent,
964
- };
965
- if (shouldSendAllIdleNudge) {
966
- nudgeState.last_idle_nudged_by_team[teamName] = {
967
- at: nowIso,
968
- worker_count: workerNames.length,
969
- orchestration_intent: orchestrationIntent,
970
- };
1153
+ if (await teamStateAllowsLeaderNudge(stateDir, teamName)) {
1154
+ if (!(await persistLeaderNudgeBookkeeping({ orchestrationIntent, recordLastNudged: true }))) {
1155
+ continue;
1156
+ }
1157
+ await emitTeamNudgeEvent(cwd, teamName, nudgeReason, orchestrationIntent, nowIso);
1158
+ }
1159
+ else {
1160
+ await recordShutdownSuppression(orchestrationIntent);
1161
+ continue;
971
1162
  }
972
- await emitTeamNudgeEvent(cwd, teamName, nudgeReason, orchestrationIntent, nowIso);
973
1163
  try {
974
1164
  await logTmuxHookEvent(logsDir, {
975
1165
  timestamp: nowIso,
@@ -999,6 +1189,10 @@ export async function maybeNudgeTeamLeader({ cwd, stateDir, logsDir, preComputed
999
1189
  }).catch(() => { });
1000
1190
  }
1001
1191
  catch (err) {
1192
+ if (!(await teamStateAllowsLeaderNudge(stateDir, teamName))) {
1193
+ await recordShutdownSuppression(orchestrationIntent);
1194
+ continue;
1195
+ }
1002
1196
  try {
1003
1197
  await logTmuxHookEvent(logsDir, {
1004
1198
  timestamp: nowIso,
@@ -1024,6 +1218,5 @@ export async function maybeNudgeTeamLeader({ cwd, stateDir, logsDir, preComputed
1024
1218
  }).catch(() => { });
1025
1219
  }
1026
1220
  }
1027
- await writeFile(nudgeStatePath, JSON.stringify(nudgeState, null, 2)).catch(() => { });
1028
1221
  }
1029
1222
  //# sourceMappingURL=team-leader-nudge.js.map