oh-my-codex 0.15.2 → 0.16.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 (524) hide show
  1. package/Cargo.lock +10 -7
  2. package/Cargo.toml +1 -1
  3. package/README.md +3 -0
  4. package/crates/omx-explore/Cargo.toml +3 -0
  5. package/crates/omx-explore/src/main.rs +517 -16
  6. package/dist/agents/__tests__/native-config.test.js +33 -0
  7. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  8. package/dist/autoresearch/goal.d.ts +90 -0
  9. package/dist/autoresearch/goal.d.ts.map +1 -0
  10. package/dist/autoresearch/goal.js +237 -0
  11. package/dist/autoresearch/goal.js.map +1 -0
  12. package/dist/autoresearch/skill-validation.d.ts +1 -0
  13. package/dist/autoresearch/skill-validation.d.ts.map +1 -1
  14. package/dist/autoresearch/skill-validation.js +10 -3
  15. package/dist/autoresearch/skill-validation.js.map +1 -1
  16. package/dist/catalog/__tests__/generator.test.js +9 -4
  17. package/dist/catalog/__tests__/generator.test.js.map +1 -1
  18. package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +29 -2
  19. package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -1
  20. package/dist/catalog/__tests__/schema.test.js +14 -3
  21. package/dist/catalog/__tests__/schema.test.js.map +1 -1
  22. package/dist/catalog/schema.js +1 -1
  23. package/dist/catalog/schema.js.map +1 -1
  24. package/dist/cli/__tests__/autoresearch-goal.test.d.ts +2 -0
  25. package/dist/cli/__tests__/autoresearch-goal.test.d.ts.map +1 -0
  26. package/dist/cli/__tests__/autoresearch-goal.test.js +194 -0
  27. package/dist/cli/__tests__/autoresearch-goal.test.js.map +1 -0
  28. package/dist/cli/__tests__/cleanup.test.js +82 -1
  29. package/dist/cli/__tests__/cleanup.test.js.map +1 -1
  30. package/dist/cli/__tests__/codex-plugin-layout.test.js +7 -4
  31. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  32. package/dist/cli/__tests__/doctor-context-window-warning.test.d.ts +2 -0
  33. package/dist/cli/__tests__/doctor-context-window-warning.test.d.ts.map +1 -0
  34. package/dist/cli/__tests__/doctor-context-window-warning.test.js +122 -0
  35. package/dist/cli/__tests__/doctor-context-window-warning.test.js.map +1 -0
  36. package/dist/cli/__tests__/doctor-warning-copy.test.js +25 -2
  37. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  38. package/dist/cli/__tests__/exec.test.js +1 -0
  39. package/dist/cli/__tests__/exec.test.js.map +1 -1
  40. package/dist/cli/__tests__/explore.test.js +48 -18
  41. package/dist/cli/__tests__/explore.test.js.map +1 -1
  42. package/dist/cli/__tests__/index.test.js +222 -10
  43. package/dist/cli/__tests__/index.test.js.map +1 -1
  44. package/dist/cli/__tests__/launch-fallback.test.js +58 -0
  45. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  46. package/dist/cli/__tests__/mcp-serve.test.js +27 -1
  47. package/dist/cli/__tests__/mcp-serve.test.js.map +1 -1
  48. package/dist/cli/__tests__/native-assets.test.js +26 -1
  49. package/dist/cli/__tests__/native-assets.test.js.map +1 -1
  50. package/dist/cli/__tests__/package-bin-contract.test.js +2 -2
  51. package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
  52. package/dist/cli/__tests__/performance-goal.test.d.ts +2 -0
  53. package/dist/cli/__tests__/performance-goal.test.d.ts.map +1 -0
  54. package/dist/cli/__tests__/performance-goal.test.js +144 -0
  55. package/dist/cli/__tests__/performance-goal.test.js.map +1 -0
  56. package/dist/cli/__tests__/question.test.js +8 -0
  57. package/dist/cli/__tests__/question.test.js.map +1 -1
  58. package/dist/cli/__tests__/ralph-goal-mode-contract.test.d.ts +2 -0
  59. package/dist/cli/__tests__/ralph-goal-mode-contract.test.d.ts.map +1 -0
  60. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +31 -0
  61. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -0
  62. package/dist/cli/__tests__/ralph-prd-deep-interview.test.js +5 -4
  63. package/dist/cli/__tests__/ralph-prd-deep-interview.test.js.map +1 -1
  64. package/dist/cli/__tests__/ralph-prd-smoke.test.js +7 -0
  65. package/dist/cli/__tests__/ralph-prd-smoke.test.js.map +1 -1
  66. package/dist/cli/__tests__/ralph.test.js +59 -1
  67. package/dist/cli/__tests__/ralph.test.js.map +1 -1
  68. package/dist/cli/__tests__/setup-install-mode.test.js +57 -21
  69. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  70. package/dist/cli/__tests__/setup-refresh.test.js +27 -8
  71. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  72. package/dist/cli/__tests__/setup-scope.test.js +20 -10
  73. package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
  74. package/dist/cli/__tests__/setup-skill-validation.test.js +11 -11
  75. package/dist/cli/__tests__/setup-skill-validation.test.js.map +1 -1
  76. package/dist/cli/__tests__/setup-skills-overwrite.test.js +12 -12
  77. package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
  78. package/dist/cli/__tests__/team.test.js +242 -10
  79. package/dist/cli/__tests__/team.test.js.map +1 -1
  80. package/dist/cli/__tests__/ultragoal.test.d.ts +2 -0
  81. package/dist/cli/__tests__/ultragoal.test.d.ts.map +1 -0
  82. package/dist/cli/__tests__/ultragoal.test.js +106 -0
  83. package/dist/cli/__tests__/ultragoal.test.js.map +1 -0
  84. package/dist/cli/__tests__/uninstall.test.js +11 -0
  85. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  86. package/dist/cli/autoresearch-goal.d.ts +3 -0
  87. package/dist/cli/autoresearch-goal.d.ts.map +1 -0
  88. package/dist/cli/autoresearch-goal.js +175 -0
  89. package/dist/cli/autoresearch-goal.js.map +1 -0
  90. package/dist/cli/cleanup.d.ts +3 -1
  91. package/dist/cli/cleanup.d.ts.map +1 -1
  92. package/dist/cli/cleanup.js +42 -2
  93. package/dist/cli/cleanup.js.map +1 -1
  94. package/dist/cli/doctor.d.ts.map +1 -1
  95. package/dist/cli/doctor.js +95 -3
  96. package/dist/cli/doctor.js.map +1 -1
  97. package/dist/cli/explore.d.ts.map +1 -1
  98. package/dist/cli/explore.js +10 -2
  99. package/dist/cli/explore.js.map +1 -1
  100. package/dist/cli/index.d.ts +21 -2
  101. package/dist/cli/index.d.ts.map +1 -1
  102. package/dist/cli/index.js +268 -30
  103. package/dist/cli/index.js.map +1 -1
  104. package/dist/cli/mcp-serve.d.ts +1 -0
  105. package/dist/cli/mcp-serve.d.ts.map +1 -1
  106. package/dist/cli/mcp-serve.js +8 -0
  107. package/dist/cli/mcp-serve.js.map +1 -1
  108. package/dist/cli/native-assets.js +1 -1
  109. package/dist/cli/native-assets.js.map +1 -1
  110. package/dist/cli/performance-goal.d.ts +3 -0
  111. package/dist/cli/performance-goal.d.ts.map +1 -0
  112. package/dist/cli/performance-goal.js +186 -0
  113. package/dist/cli/performance-goal.js.map +1 -0
  114. package/dist/cli/ralph.d.ts +2 -0
  115. package/dist/cli/ralph.d.ts.map +1 -1
  116. package/dist/cli/ralph.js +25 -1
  117. package/dist/cli/ralph.js.map +1 -1
  118. package/dist/cli/setup.d.ts.map +1 -1
  119. package/dist/cli/setup.js +13 -6
  120. package/dist/cli/setup.js.map +1 -1
  121. package/dist/cli/team.d.ts +6 -0
  122. package/dist/cli/team.d.ts.map +1 -1
  123. package/dist/cli/team.js +113 -33
  124. package/dist/cli/team.js.map +1 -1
  125. package/dist/cli/tmux-hook.d.ts.map +1 -1
  126. package/dist/cli/tmux-hook.js +2 -1
  127. package/dist/cli/tmux-hook.js.map +1 -1
  128. package/dist/cli/ultragoal.d.ts +3 -0
  129. package/dist/cli/ultragoal.d.ts.map +1 -0
  130. package/dist/cli/ultragoal.js +191 -0
  131. package/dist/cli/ultragoal.js.map +1 -0
  132. package/dist/cli/uninstall.d.ts.map +1 -1
  133. package/dist/cli/uninstall.js +4 -2
  134. package/dist/cli/uninstall.js.map +1 -1
  135. package/dist/config/__tests__/generator-idempotent.test.js +39 -6
  136. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  137. package/dist/config/__tests__/generator-notify.test.js +5 -0
  138. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  139. package/dist/config/commit-lore-guard.d.ts +3 -0
  140. package/dist/config/commit-lore-guard.d.ts.map +1 -0
  141. package/dist/config/commit-lore-guard.js +9 -0
  142. package/dist/config/commit-lore-guard.js.map +1 -0
  143. package/dist/config/generator.d.ts +14 -4
  144. package/dist/config/generator.d.ts.map +1 -1
  145. package/dist/config/generator.js +166 -66
  146. package/dist/config/generator.js.map +1 -1
  147. package/dist/config/omx-first-party-mcp.d.ts +1 -0
  148. package/dist/config/omx-first-party-mcp.d.ts.map +1 -1
  149. package/dist/config/omx-first-party-mcp.js +4 -1
  150. package/dist/config/omx-first-party-mcp.js.map +1 -1
  151. package/dist/goal-workflows/__tests__/artifacts.test.d.ts +2 -0
  152. package/dist/goal-workflows/__tests__/artifacts.test.d.ts.map +1 -0
  153. package/dist/goal-workflows/__tests__/artifacts.test.js +96 -0
  154. package/dist/goal-workflows/__tests__/artifacts.test.js.map +1 -0
  155. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.d.ts +2 -0
  156. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.d.ts.map +1 -0
  157. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js +54 -0
  158. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js.map +1 -0
  159. package/dist/goal-workflows/artifacts.d.ts +62 -0
  160. package/dist/goal-workflows/artifacts.d.ts.map +1 -0
  161. package/dist/goal-workflows/artifacts.js +132 -0
  162. package/dist/goal-workflows/artifacts.js.map +1 -0
  163. package/dist/goal-workflows/codex-goal-snapshot.d.ts +28 -0
  164. package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -0
  165. package/dist/goal-workflows/codex-goal-snapshot.js +110 -0
  166. package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -0
  167. package/dist/goal-workflows/handoff.d.ts +10 -0
  168. package/dist/goal-workflows/handoff.d.ts.map +1 -0
  169. package/dist/goal-workflows/handoff.js +31 -0
  170. package/dist/goal-workflows/handoff.js.map +1 -0
  171. package/dist/goal-workflows/validation.d.ts +13 -0
  172. package/dist/goal-workflows/validation.d.ts.map +1 -0
  173. package/dist/goal-workflows/validation.js +36 -0
  174. package/dist/goal-workflows/validation.js.map +1 -0
  175. package/dist/hooks/__tests__/agents-overlay.test.js +59 -0
  176. package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
  177. package/dist/hooks/__tests__/anti-slop-workflow.test.js +109 -18
  178. package/dist/hooks/__tests__/anti-slop-workflow.test.js.map +1 -1
  179. package/dist/hooks/__tests__/keyword-detector.test.js +45 -32
  180. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  181. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +3 -3
  182. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  183. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +2 -1
  184. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  185. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +17 -24
  186. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  187. package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +3 -3
  188. package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +1 -1
  189. package/dist/hooks/__tests__/task-size-detector.test.js +1 -1
  190. package/dist/hooks/__tests__/task-size-detector.test.js.map +1 -1
  191. package/dist/hooks/__tests__/visual-ralph-skill.test.js +3 -3
  192. package/dist/hooks/__tests__/visual-ralph-skill.test.js.map +1 -1
  193. package/dist/hooks/__tests__/visual-verdict-loop.test.js +7 -11
  194. package/dist/hooks/__tests__/visual-verdict-loop.test.js.map +1 -1
  195. package/dist/hooks/agents-overlay.d.ts.map +1 -1
  196. package/dist/hooks/agents-overlay.js +23 -2
  197. package/dist/hooks/agents-overlay.js.map +1 -1
  198. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  199. package/dist/hooks/keyword-detector.js +12 -13
  200. package/dist/hooks/keyword-detector.js.map +1 -1
  201. package/dist/hooks/keyword-registry.d.ts.map +1 -1
  202. package/dist/hooks/keyword-registry.js +2 -10
  203. package/dist/hooks/keyword-registry.js.map +1 -1
  204. package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
  205. package/dist/hooks/prompt-guidance-contract.js +0 -4
  206. package/dist/hooks/prompt-guidance-contract.js.map +1 -1
  207. package/dist/hooks/session.js +2 -2
  208. package/dist/hooks/session.js.map +1 -1
  209. package/dist/hooks/task-size-detector.d.ts.map +1 -1
  210. package/dist/hooks/task-size-detector.js +1 -0
  211. package/dist/hooks/task-size-detector.js.map +1 -1
  212. package/dist/hud/__tests__/index.test.js +30 -14
  213. package/dist/hud/__tests__/index.test.js.map +1 -1
  214. package/dist/hud/__tests__/reconcile.test.js +29 -7
  215. package/dist/hud/__tests__/reconcile.test.js.map +1 -1
  216. package/dist/hud/reconcile.d.ts +2 -1
  217. package/dist/hud/reconcile.d.ts.map +1 -1
  218. package/dist/hud/reconcile.js +12 -0
  219. package/dist/hud/reconcile.js.map +1 -1
  220. package/dist/mcp/__tests__/bootstrap.test.js +15 -2
  221. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  222. package/dist/mcp/__tests__/state-paths.test.js +54 -0
  223. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  224. package/dist/mcp/__tests__/state-server.test.js +36 -0
  225. package/dist/mcp/__tests__/state-server.test.js.map +1 -1
  226. package/dist/mcp/bootstrap.d.ts +1 -1
  227. package/dist/mcp/bootstrap.d.ts.map +1 -1
  228. package/dist/mcp/bootstrap.js +9 -7
  229. package/dist/mcp/bootstrap.js.map +1 -1
  230. package/dist/mcp/state-paths.d.ts +17 -0
  231. package/dist/mcp/state-paths.d.ts.map +1 -1
  232. package/dist/mcp/state-paths.js +36 -2
  233. package/dist/mcp/state-paths.js.map +1 -1
  234. package/dist/modes/__tests__/base-session-scope.test.js +26 -0
  235. package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
  236. package/dist/modes/base.d.ts +1 -0
  237. package/dist/modes/base.d.ts.map +1 -1
  238. package/dist/modes/base.js +35 -5
  239. package/dist/modes/base.js.map +1 -1
  240. package/dist/notifications/__tests__/http-client.test.d.ts +2 -0
  241. package/dist/notifications/__tests__/http-client.test.d.ts.map +1 -0
  242. package/dist/notifications/__tests__/http-client.test.js +90 -0
  243. package/dist/notifications/__tests__/http-client.test.js.map +1 -0
  244. package/dist/notifications/__tests__/notifier.test.js +22 -60
  245. package/dist/notifications/__tests__/notifier.test.js.map +1 -1
  246. package/dist/notifications/dispatcher.d.ts.map +1 -1
  247. package/dist/notifications/dispatcher.js +35 -60
  248. package/dist/notifications/dispatcher.js.map +1 -1
  249. package/dist/notifications/http-client.d.ts +22 -0
  250. package/dist/notifications/http-client.d.ts.map +1 -0
  251. package/dist/notifications/http-client.js +298 -0
  252. package/dist/notifications/http-client.js.map +1 -0
  253. package/dist/notifications/notifier.d.ts +3 -2
  254. package/dist/notifications/notifier.d.ts.map +1 -1
  255. package/dist/notifications/notifier.js +17 -22
  256. package/dist/notifications/notifier.js.map +1 -1
  257. package/dist/openclaw/__tests__/dispatcher.test.js +63 -2
  258. package/dist/openclaw/__tests__/dispatcher.test.js.map +1 -1
  259. package/dist/openclaw/dispatcher.d.ts.map +1 -1
  260. package/dist/openclaw/dispatcher.js +3 -2
  261. package/dist/openclaw/dispatcher.js.map +1 -1
  262. package/dist/performance-goal/artifacts.d.ts +76 -0
  263. package/dist/performance-goal/artifacts.d.ts.map +1 -0
  264. package/dist/performance-goal/artifacts.js +221 -0
  265. package/dist/performance-goal/artifacts.js.map +1 -0
  266. package/dist/pipeline/__tests__/stages.test.js +423 -14
  267. package/dist/pipeline/__tests__/stages.test.js.map +1 -1
  268. package/dist/pipeline/stages/team-exec.d.ts +8 -4
  269. package/dist/pipeline/stages/team-exec.d.ts.map +1 -1
  270. package/dist/pipeline/stages/team-exec.js +181 -13
  271. package/dist/pipeline/stages/team-exec.js.map +1 -1
  272. package/dist/planning/__tests__/artifacts.test.js +261 -1
  273. package/dist/planning/__tests__/artifacts.test.js.map +1 -1
  274. package/dist/planning/artifact-names.d.ts +13 -0
  275. package/dist/planning/artifact-names.d.ts.map +1 -0
  276. package/dist/planning/artifact-names.js +108 -0
  277. package/dist/planning/artifact-names.js.map +1 -0
  278. package/dist/planning/artifacts.d.ts +23 -1
  279. package/dist/planning/artifacts.d.ts.map +1 -1
  280. package/dist/planning/artifacts.js +171 -59
  281. package/dist/planning/artifacts.js.map +1 -1
  282. package/dist/ralph/__tests__/persistence.test.js +21 -1
  283. package/dist/ralph/__tests__/persistence.test.js.map +1 -1
  284. package/dist/ralph/persistence.d.ts.map +1 -1
  285. package/dist/ralph/persistence.js +6 -4
  286. package/dist/ralph/persistence.js.map +1 -1
  287. package/dist/ralplan/__tests__/runtime.test.js +2 -0
  288. package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
  289. package/dist/ralplan/runtime.d.ts.map +1 -1
  290. package/dist/ralplan/runtime.js +6 -0
  291. package/dist/ralplan/runtime.js.map +1 -1
  292. package/dist/scripts/__tests__/codex-native-hook.test.js +1749 -88
  293. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  294. package/dist/scripts/__tests__/hook-derived-watcher.test.js +33 -1
  295. package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +1 -1
  296. package/dist/scripts/__tests__/run-test-files.test.js +36 -0
  297. package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
  298. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  299. package/dist/scripts/codex-native-hook.js +570 -45
  300. package/dist/scripts/codex-native-hook.js.map +1 -1
  301. package/dist/scripts/codex-native-pre-post.d.ts +7 -0
  302. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
  303. package/dist/scripts/codex-native-pre-post.js +341 -15
  304. package/dist/scripts/codex-native-pre-post.js.map +1 -1
  305. package/dist/scripts/hook-derived-watcher.js +2 -1
  306. package/dist/scripts/hook-derived-watcher.js.map +1 -1
  307. package/dist/scripts/notify-fallback-watcher.js +2 -1
  308. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  309. package/dist/scripts/notify-hook/orchestration-intent.d.ts +1 -2
  310. package/dist/scripts/notify-hook/orchestration-intent.d.ts.map +1 -1
  311. package/dist/scripts/notify-hook/orchestration-intent.js +2 -3
  312. package/dist/scripts/notify-hook/orchestration-intent.js.map +1 -1
  313. package/dist/scripts/notify-hook/team-leader-nudge.d.ts +0 -2
  314. package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
  315. package/dist/scripts/notify-hook/team-leader-nudge.js +8 -60
  316. package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
  317. package/dist/scripts/notify-hook/team-worker-posttooluse.js +1 -1
  318. package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -1
  319. package/dist/scripts/notify-hook/team-worker-stop.d.ts +15 -0
  320. package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -0
  321. package/dist/scripts/notify-hook/team-worker-stop.js +224 -0
  322. package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -0
  323. package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
  324. package/dist/scripts/notify-hook/team-worker.js +26 -18
  325. package/dist/scripts/notify-hook/team-worker.js.map +1 -1
  326. package/dist/scripts/notify-hook.js +1 -1
  327. package/dist/scripts/notify-hook.js.map +1 -1
  328. package/dist/scripts/run-test-files.js +17 -1
  329. package/dist/scripts/run-test-files.js.map +1 -1
  330. package/dist/scripts/sync-plugin-mirror.d.ts +1 -0
  331. package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
  332. package/dist/scripts/sync-plugin-mirror.js +10 -4
  333. package/dist/scripts/sync-plugin-mirror.js.map +1 -1
  334. package/dist/state/__tests__/operations.test.js +26 -0
  335. package/dist/state/__tests__/operations.test.js.map +1 -1
  336. package/dist/state/__tests__/skill-active.test.js +76 -0
  337. package/dist/state/__tests__/skill-active.test.js.map +1 -1
  338. package/dist/state/operations.d.ts +3 -1
  339. package/dist/state/operations.d.ts.map +1 -1
  340. package/dist/state/operations.js +8 -4
  341. package/dist/state/operations.js.map +1 -1
  342. package/dist/state/skill-active.d.ts +1 -0
  343. package/dist/state/skill-active.d.ts.map +1 -1
  344. package/dist/state/skill-active.js +54 -13
  345. package/dist/state/skill-active.js.map +1 -1
  346. package/dist/team/__tests__/api-interop.test.js +279 -0
  347. package/dist/team/__tests__/api-interop.test.js.map +1 -1
  348. package/dist/team/__tests__/approved-execution.test.d.ts +2 -0
  349. package/dist/team/__tests__/approved-execution.test.d.ts.map +1 -0
  350. package/dist/team/__tests__/approved-execution.test.js +124 -0
  351. package/dist/team/__tests__/approved-execution.test.js.map +1 -0
  352. package/dist/team/__tests__/delivery-e2e-smoke.test.js +2 -4
  353. package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
  354. package/dist/team/__tests__/delivery-log.test.d.ts +2 -0
  355. package/dist/team/__tests__/delivery-log.test.d.ts.map +1 -0
  356. package/dist/team/__tests__/delivery-log.test.js +44 -0
  357. package/dist/team/__tests__/delivery-log.test.js.map +1 -0
  358. package/dist/team/__tests__/model-contract.test.js +40 -9
  359. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  360. package/dist/team/__tests__/repo-aware-decomposition.test.js +41 -0
  361. package/dist/team/__tests__/repo-aware-decomposition.test.js.map +1 -1
  362. package/dist/team/__tests__/role-router.test.js +4 -4
  363. package/dist/team/__tests__/role-router.test.js.map +1 -1
  364. package/dist/team/__tests__/runtime-boxed-state.test.d.ts +2 -0
  365. package/dist/team/__tests__/runtime-boxed-state.test.d.ts.map +1 -0
  366. package/dist/team/__tests__/runtime-boxed-state.test.js +39 -0
  367. package/dist/team/__tests__/runtime-boxed-state.test.js.map +1 -0
  368. package/dist/team/__tests__/runtime-cli.test.js +24 -0
  369. package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
  370. package/dist/team/__tests__/runtime.test.js +563 -72
  371. package/dist/team/__tests__/runtime.test.js.map +1 -1
  372. package/dist/team/__tests__/state-root.test.js +13 -0
  373. package/dist/team/__tests__/state-root.test.js.map +1 -1
  374. package/dist/team/__tests__/state.test.js +13 -0
  375. package/dist/team/__tests__/state.test.js.map +1 -1
  376. package/dist/team/__tests__/team-identity.test.d.ts +2 -0
  377. package/dist/team/__tests__/team-identity.test.d.ts.map +1 -0
  378. package/dist/team/__tests__/team-identity.test.js +166 -0
  379. package/dist/team/__tests__/team-identity.test.js.map +1 -0
  380. package/dist/team/__tests__/tmux-session.test.js +58 -1
  381. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  382. package/dist/team/__tests__/worker-bootstrap.test.js +62 -0
  383. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  384. package/dist/team/api-interop.d.ts +1 -0
  385. package/dist/team/api-interop.d.ts.map +1 -1
  386. package/dist/team/api-interop.js +163 -132
  387. package/dist/team/api-interop.js.map +1 -1
  388. package/dist/team/approved-execution.d.ts +37 -0
  389. package/dist/team/approved-execution.d.ts.map +1 -0
  390. package/dist/team/approved-execution.js +136 -0
  391. package/dist/team/approved-execution.js.map +1 -0
  392. package/dist/team/delivery-log.d.ts +1 -1
  393. package/dist/team/delivery-log.d.ts.map +1 -1
  394. package/dist/team/delivery-log.js +2 -1
  395. package/dist/team/delivery-log.js.map +1 -1
  396. package/dist/team/followup-planner.js +2 -2
  397. package/dist/team/followup-planner.js.map +1 -1
  398. package/dist/team/goal-workflow.d.ts +20 -0
  399. package/dist/team/goal-workflow.d.ts.map +1 -0
  400. package/dist/team/goal-workflow.js +57 -0
  401. package/dist/team/goal-workflow.js.map +1 -0
  402. package/dist/team/orchestrator.js +2 -2
  403. package/dist/team/orchestrator.js.map +1 -1
  404. package/dist/team/repo-aware-decomposition.d.ts +3 -0
  405. package/dist/team/repo-aware-decomposition.d.ts.map +1 -1
  406. package/dist/team/repo-aware-decomposition.js +2 -0
  407. package/dist/team/repo-aware-decomposition.js.map +1 -1
  408. package/dist/team/role-router.js +5 -5
  409. package/dist/team/role-router.js.map +1 -1
  410. package/dist/team/runtime-cli.d.ts +32 -2
  411. package/dist/team/runtime-cli.d.ts.map +1 -1
  412. package/dist/team/runtime-cli.js +78 -26
  413. package/dist/team/runtime-cli.js.map +1 -1
  414. package/dist/team/runtime.d.ts +7 -1
  415. package/dist/team/runtime.d.ts.map +1 -1
  416. package/dist/team/runtime.js +383 -40
  417. package/dist/team/runtime.js.map +1 -1
  418. package/dist/team/scaling.d.ts.map +1 -1
  419. package/dist/team/scaling.js +2 -0
  420. package/dist/team/scaling.js.map +1 -1
  421. package/dist/team/state.d.ts +9 -0
  422. package/dist/team/state.d.ts.map +1 -1
  423. package/dist/team/state.js +21 -0
  424. package/dist/team/state.js.map +1 -1
  425. package/dist/team/team-identity.d.ts +26 -0
  426. package/dist/team/team-identity.d.ts.map +1 -0
  427. package/dist/team/team-identity.js +169 -0
  428. package/dist/team/team-identity.js.map +1 -0
  429. package/dist/team/tmux-session.d.ts +18 -0
  430. package/dist/team/tmux-session.d.ts.map +1 -1
  431. package/dist/team/tmux-session.js +65 -3
  432. package/dist/team/tmux-session.js.map +1 -1
  433. package/dist/team/worker-bootstrap.d.ts +4 -0
  434. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  435. package/dist/team/worker-bootstrap.js +28 -2
  436. package/dist/team/worker-bootstrap.js.map +1 -1
  437. package/dist/ultragoal/__tests__/artifacts.test.d.ts +2 -0
  438. package/dist/ultragoal/__tests__/artifacts.test.d.ts.map +1 -0
  439. package/dist/ultragoal/__tests__/artifacts.test.js +93 -0
  440. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -0
  441. package/dist/ultragoal/artifacts.d.ts +89 -0
  442. package/dist/ultragoal/artifacts.d.ts.map +1 -0
  443. package/dist/ultragoal/artifacts.js +233 -0
  444. package/dist/ultragoal/artifacts.js.map +1 -0
  445. package/dist/utils/__tests__/agents-model-table.test.js +3 -1
  446. package/dist/utils/__tests__/agents-model-table.test.js.map +1 -1
  447. package/dist/utils/__tests__/paths.test.js +31 -1
  448. package/dist/utils/__tests__/paths.test.js.map +1 -1
  449. package/dist/utils/agents-model-table.d.ts.map +1 -1
  450. package/dist/utils/agents-model-table.js +12 -1
  451. package/dist/utils/agents-model-table.js.map +1 -1
  452. package/dist/utils/paths.d.ts +2 -0
  453. package/dist/utils/paths.d.ts.map +1 -1
  454. package/dist/utils/paths.js +23 -7
  455. package/dist/utils/paths.js.map +1 -1
  456. package/dist/verification/__tests__/ci-rust-gates.test.js +30 -19
  457. package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
  458. package/package.json +5 -5
  459. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  460. package/plugins/oh-my-codex/skills/ai-slop-cleaner/SKILL.md +30 -5
  461. package/plugins/oh-my-codex/skills/ask/SKILL.md +58 -0
  462. package/plugins/oh-my-codex/skills/autoresearch-goal/SKILL.md +36 -0
  463. package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +2 -2
  464. package/plugins/oh-my-codex/skills/performance-goal/SKILL.md +65 -0
  465. package/plugins/oh-my-codex/skills/plan/SKILL.md +1 -1
  466. package/plugins/oh-my-codex/skills/ralph/SKILL.md +22 -3
  467. package/plugins/oh-my-codex/skills/team/SKILL.md +6 -2
  468. package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +49 -0
  469. package/plugins/oh-my-codex/skills/visual-ralph/SKILL.md +9 -9
  470. package/prompts/api-reviewer.md +1 -1
  471. package/prompts/code-reviewer.md +2 -0
  472. package/prompts/performance-reviewer.md +1 -1
  473. package/prompts/quality-reviewer.md +1 -1
  474. package/prompts/quality-strategist.md +2 -2
  475. package/prompts/style-reviewer.md +1 -1
  476. package/prompts/test-engineer.md +1 -1
  477. package/skills/ai-slop-cleaner/SKILL.md +30 -5
  478. package/skills/ask/SKILL.md +58 -0
  479. package/skills/ask-claude/SKILL.md +3 -54
  480. package/skills/ask-gemini/SKILL.md +3 -54
  481. package/skills/autoresearch-goal/SKILL.md +36 -0
  482. package/skills/build-fix/SKILL.md +4 -139
  483. package/skills/deepsearch/SKILL.md +4 -32
  484. package/skills/ecomode/SKILL.md +4 -108
  485. package/skills/help/SKILL.md +4 -196
  486. package/skills/note/SKILL.md +4 -56
  487. package/skills/omx-setup/SKILL.md +2 -2
  488. package/skills/performance-goal/SKILL.md +65 -0
  489. package/skills/plan/SKILL.md +1 -1
  490. package/skills/ralph/SKILL.md +22 -3
  491. package/skills/ralph-init/SKILL.md +4 -40
  492. package/skills/review/SKILL.md +4 -32
  493. package/skills/security-review/SKILL.md +4 -294
  494. package/skills/swarm/SKILL.md +4 -19
  495. package/skills/tdd/SKILL.md +4 -100
  496. package/skills/team/SKILL.md +6 -2
  497. package/skills/trace/SKILL.md +4 -27
  498. package/skills/ultragoal/SKILL.md +49 -0
  499. package/skills/visual-ralph/SKILL.md +9 -9
  500. package/skills/visual-verdict/SKILL.md +4 -70
  501. package/skills/web-clone/SKILL.md +4 -18
  502. package/src/scripts/__tests__/codex-native-hook.test.ts +2923 -1030
  503. package/src/scripts/__tests__/hook-derived-watcher.test.ts +45 -1
  504. package/src/scripts/__tests__/run-test-files.test.ts +46 -0
  505. package/src/scripts/codex-native-hook.ts +696 -46
  506. package/src/scripts/codex-native-pre-post.ts +369 -16
  507. package/src/scripts/hook-derived-watcher.ts +2 -1
  508. package/src/scripts/notify-fallback-watcher.ts +2 -1
  509. package/src/scripts/notify-hook/orchestration-intent.ts +1 -3
  510. package/src/scripts/notify-hook/team-leader-nudge.ts +7 -63
  511. package/src/scripts/notify-hook/team-worker-posttooluse.ts +1 -1
  512. package/src/scripts/notify-hook/team-worker-stop.ts +246 -0
  513. package/src/scripts/notify-hook/team-worker.ts +23 -14
  514. package/src/scripts/notify-hook.ts +1 -1
  515. package/src/scripts/run-test-files.ts +20 -1
  516. package/src/scripts/sync-plugin-mirror.ts +13 -4
  517. package/templates/catalog-manifest.json +45 -27
  518. package/plugins/oh-my-codex/skills/ask-claude/SKILL.md +0 -61
  519. package/plugins/oh-my-codex/skills/ask-gemini/SKILL.md +0 -61
  520. package/plugins/oh-my-codex/skills/help/SKILL.md +0 -202
  521. package/plugins/oh-my-codex/skills/note/SKILL.md +0 -62
  522. package/plugins/oh-my-codex/skills/security-review/SKILL.md +0 -300
  523. package/plugins/oh-my-codex/skills/trace/SKILL.md +0 -33
  524. package/plugins/oh-my-codex/skills/visual-verdict/SKILL.md +0 -76
@@ -3,25 +3,28 @@ import { existsSync, appendFileSync, mkdirSync } from 'fs';
3
3
  import { mkdir, readdir, readFile, writeFile } from 'fs/promises';
4
4
  import { performance } from 'perf_hooks';
5
5
  import { spawn, spawnSync } from 'child_process';
6
- import { sanitizeTeamName, isTmuxAvailable, hasCurrentTmuxClientContext, createTeamSession, buildWorkerProcessLaunchSpec, resolveTeamWorkerCli, resolveTeamWorkerCliPlan, resolveTeamWorkerLaunchMode, waitForWorkerReady, waitForWorkerReadyAsync, dismissTrustPromptIfPresent, sendToWorker, sendToWorkerStdin, isWorkerAlive, isWorkerPaneOpen, getWorkerPanePid, killWorkerByPaneIdAsync, restoreStandaloneHudPane, teardownWorkerPanes, unregisterResizeHook, destroyTeamSession, listPaneIds, listTeamSessions, resolveSharedSessionShutdownTopology, } from './tmux-session.js';
7
- import { teamInit as initTeamState, DEFAULT_MAX_WORKERS, teamReadConfig as readTeamConfig, teamWriteWorkerIdentity as writeWorkerIdentity, teamReadWorkerHeartbeat as readWorkerHeartbeat, teamReadWorkerStatus as readWorkerStatus, teamWriteWorkerInbox as writeWorkerInbox, teamCreateTask as createStateTask, teamReadTask as readTask, teamListTasks as listTasks, teamUpdateTask as updateTask, teamReadManifest as readTeamManifestV2, teamNormalizeGovernance as normalizeTeamGovernance, teamNormalizePolicy as normalizeTeamPolicy, teamClaimTask as claimTask, teamReleaseTaskClaim as releaseTaskClaim, teamReclaimExpiredTaskClaim as reclaimExpiredTaskClaim, teamAppendEvent as appendTeamEvent, teamReadTaskApproval as readTaskApproval, teamListMailbox as listMailboxMessages, teamMarkMessageDelivered as markMessageDelivered, teamMarkMessageNotified as markMessageNotified, teamEnqueueDispatchRequest as enqueueDispatchRequest, teamMarkDispatchRequestNotified as markDispatchRequestNotified, teamTransitionDispatchRequest as transitionDispatchRequest, teamReadDispatchRequest as readDispatchRequest, teamCleanup as cleanupTeamState, teamSaveConfig as saveTeamConfig, teamWriteShutdownRequest as writeShutdownRequest, teamReadShutdownAck as readShutdownAck, teamReadMonitorSnapshot as readMonitorSnapshot, teamWriteMonitorSnapshot as writeMonitorSnapshot, teamReadPhase as readTeamPhaseState, teamWritePhase as writeTeamPhaseState, teamWriteWorkerStatus as writeWorkerStatus, } from './team-ops.js';
6
+ import { sanitizeTeamName, isTmuxAvailable, hasCurrentTmuxClientContext, createTeamSession, buildWorkerProcessLaunchSpec, resolveTeamWorkerCli, resolveTeamWorkerCliPlan, resolveTeamWorkerLaunchMode, waitForWorkerReady, waitForWorkerReadyAsync, dismissTrustPromptIfPresent, evaluateStartupDirectTriggerSafety, sendToWorker, sendToWorkerStdin, isWorkerAlive, isWorkerPaneOpen, getWorkerPanePid, killWorkerByPaneIdAsync, restoreStandaloneHudPane, teardownWorkerPanes, unregisterResizeHook, destroyTeamSession, listPaneIds, listTeamSessions, resolveSharedSessionShutdownTopology, } from './tmux-session.js';
7
+ import { teamInit as initTeamState, DEFAULT_MAX_WORKERS, teamReadConfig as readTeamConfig, teamWriteWorkerIdentity as writeWorkerIdentity, teamReadWorkerHeartbeat as readWorkerHeartbeat, teamReadWorkerStatus as readWorkerStatus, teamWriteWorkerInbox as writeWorkerInbox, teamCreateTask as createStateTask, teamReadTask as readTask, teamListTasks as listTasks, teamUpdateTask as updateTask, teamReadManifest as readTeamManifestV2, teamNormalizeGovernance as normalizeTeamGovernance, teamNormalizePolicy as normalizeTeamPolicy, teamClaimTask as claimTask, teamReleaseTaskClaim as releaseTaskClaim, teamReclaimExpiredTaskClaim as reclaimExpiredTaskClaim, teamAppendEvent as appendTeamEvent, teamReadTaskApproval as readTaskApproval, teamListMailbox as listMailboxMessages, teamMarkMessageDelivered as markMessageDelivered, teamMarkMessageNotified as markMessageNotified, teamEnqueueDispatchRequest as enqueueDispatchRequest, teamMarkDispatchRequestNotified as markDispatchRequestNotified, teamTransitionDispatchRequest as transitionDispatchRequest, teamReadDispatchRequest as readDispatchRequest, teamCleanup as cleanupTeamState, teamSaveConfig as saveTeamConfig, teamWriteShutdownRequest as writeShutdownRequest, teamReadShutdownAck as readShutdownAck, teamReadMonitorSnapshot as readMonitorSnapshot, teamWriteMonitorSnapshot as writeMonitorSnapshot, teamReadPhase as readTeamPhaseState, teamWritePhase as writeTeamPhaseState, teamWriteWorkerStatus as writeWorkerStatus, writeAtomic, } from './team-ops.js';
8
8
  import { queueInboxInstruction, queueDirectMailboxMessage, queueBroadcastMailboxMessage, waitForDispatchReceipt, } from './mcp-comm.js';
9
9
  import { appendTeamDeliveryLogForCwd } from './delivery-log.js';
10
10
  import { remapRepoAwareDecompositionMetadataToCreatedTasks, } from './repo-aware-decomposition.js';
11
11
  import { generateWorkerOverlay, writeTeamWorkerInstructionsFile, removeTeamWorkerInstructionsFile, writeWorkerWorktreeRootAgentsFile, removeWorkerWorktreeRootAgentsFile, generateInitialInbox, generateTaskAssignmentInbox, generateShutdownInbox, buildTriggerDirective, buildMailboxTriggerDirective, buildLeaderMailboxTriggerDirective, writeWorkerRoleInstructionsFile, } from './worker-bootstrap.js';
12
+ import { buildTeamWorkerGoalInstruction } from './goal-workflow.js';
12
13
  import { synthesizeDelegationPlan } from './delegation-policy.js';
13
14
  import { loadRolePrompt } from './role-router.js';
14
15
  import { composeRoleInstructionsForRole } from '../agents/native-config.js';
15
- import { codexPromptsDir } from '../utils/paths.js';
16
+ import { codexPromptsDir, omxStateDir } from '../utils/paths.js';
16
17
  import { isTerminalPhase } from './orchestrator.js';
17
18
  import { resolveTeamWorkerLaunchArgs, TEAM_LOW_COMPLEXITY_DEFAULT_MODEL, parseTeamWorkerLaunchArgs, splitWorkerLaunchArgs, resolveAgentDefaultModel, resolveAgentReasoningEffort, } from './model-contract.js';
18
19
  import { resolveCanonicalTeamStateRoot } from './state-root.js';
20
+ import { buildInternalTeamName, resolveTeamIdentityScope, resolveTeamNameForCurrentContext } from './team-identity.js';
19
21
  import { inferPhaseTargetFromTaskCounts, reconcilePhaseStateForMonitor } from './phase-controller.js';
20
22
  import { getTeamTmuxSessions } from '../notifications/tmux.js';
21
23
  import { hasStructuredVerificationEvidence } from '../verification/verifier.js';
22
24
  import { buildRebalanceDecisions } from './rebalance-policy.js';
23
25
  import { getStatePath } from '../mcp/state-paths.js';
24
26
  import { readModeState, updateModeState } from '../modes/base.js';
27
+ import { buildApprovedTeamExecutionBinding, normalizeApprovedTeamExecutionBinding, readApprovedTeamExecutionHintFromBinding, resolvePersistedApprovedTeamExecutionContinuityState, writePersistedApprovedTeamExecutionBinding, } from './approved-execution.js';
25
28
  import { appendTeamCommitHygieneEntries, buildTeamCommitHygieneContext, resolveTeamCommitHygieneArtifactCwd, writeTeamCommitHygieneContext, } from './commit-hygiene.js';
26
29
  import { assertCleanLeaderWorkspaceForWorkerWorktrees, ensureWorktree, isGitRepository, isWorktreeDirty, planWorktreeTarget, removeWorktreeForce, rollbackProvisionedWorktrees, } from './worktree.js';
27
30
  import { cleanupOmxMcpProcesses, findLaunchSafeCleanupCandidates, } from '../cli/cleanup.js';
@@ -188,6 +191,21 @@ async function logRuntimeDispatchOutcome(params) {
188
191
  reason: outcome.reason,
189
192
  });
190
193
  }
194
+ async function logStartupTiming(params) {
195
+ const { cwd, teamName, workerName, event, paneId, elapsedMs, reason, requestId, transport } = params;
196
+ await appendTeamDeliveryLogForCwd(cwd, {
197
+ event: 'startup_timing',
198
+ source: 'team.runtime',
199
+ team: teamName,
200
+ to_worker: workerName,
201
+ startup_event: event,
202
+ pane_id: paneId,
203
+ elapsed_ms: typeof elapsedMs === 'number' ? Math.round(elapsedMs) : undefined,
204
+ reason,
205
+ request_id: requestId,
206
+ transport,
207
+ });
208
+ }
191
209
  function collectProvisionedShutdownWorktrees(config) {
192
210
  const seenWorktreePaths = new Set();
193
211
  const worktrees = [];
@@ -932,6 +950,52 @@ const WORKTREE_TRIGGER_STATE_ROOT = '$OMX_TEAM_STATE_ROOT';
932
950
  const STARTUP_EVIDENCE_TIMEOUT_MS = 15_000;
933
951
  const STARTUP_EVIDENCE_POLL_MS = 100;
934
952
  const STARTUP_EVIDENCE_LAUNCH_TIMEOUT_MS = 45_000;
953
+ const STARTUP_TIMING_LOG_VERSION = 1;
954
+ export function teamStartupTimingPath(teamName, cwd) {
955
+ return join(resolveCanonicalTeamStateRoot(cwd), 'team', teamName, 'startup-timing.json');
956
+ }
957
+ export function teamRuntimeTeamsRoot(cwd) {
958
+ return join(resolveCanonicalTeamStateRoot(cwd), 'team');
959
+ }
960
+ export function teamRuntimeTeamRoot(teamName, cwd) {
961
+ return join(teamRuntimeTeamsRoot(cwd), teamName);
962
+ }
963
+ export function teamRuntimeSessionPath(cwd) {
964
+ return join(omxStateDir(cwd), 'session.json');
965
+ }
966
+ function createStartupTimingRecorder(teamName, cwd) {
967
+ const startedAt = performance.now();
968
+ const events = [];
969
+ return {
970
+ mark: (phase, details = {}) => {
971
+ events.push({
972
+ phase,
973
+ at: new Date().toISOString(),
974
+ elapsed_ms: Math.round((performance.now() - startedAt) * 1000) / 1000,
975
+ ...details,
976
+ });
977
+ },
978
+ flush: async () => {
979
+ const timingPath = teamStartupTimingPath(teamName, cwd);
980
+ await writeAtomic(timingPath, JSON.stringify({ schema_version: STARTUP_TIMING_LOG_VERSION, team_name: teamName, events }, null, 2)).catch(() => { });
981
+ for (const event of events) {
982
+ await appendTeamDeliveryLogForCwd(cwd, {
983
+ event: 'dispatch_result',
984
+ source: 'team.runtime.startup-timing',
985
+ team: teamName,
986
+ result: event.ok === false ? 'failed' : 'ok',
987
+ phase: event.phase,
988
+ elapsed_ms: event.elapsed_ms,
989
+ to_worker: event.worker,
990
+ pane_id: event.pane_id,
991
+ reason: event.reason,
992
+ transport: event.transport,
993
+ request_id: event.request_id,
994
+ });
995
+ }
996
+ },
997
+ };
998
+ }
935
999
  const promptWorkerRegistry = new Map();
936
1000
  const previousModelInstructionsFileByTeam = new Map();
937
1001
  const PROMPT_WORKER_SIGTERM_WAIT_MS = 3_000;
@@ -1000,7 +1064,7 @@ function resolveGovernancePolicy(governance, legacyPolicy) {
1000
1064
  return normalizeTeamGovernance(governance, legacyPolicy);
1001
1065
  }
1002
1066
  async function assertNestedTeamAllowed(cwd) {
1003
- const workerContext = parseTeamWorkerContext(process.env.OMX_TEAM_WORKER);
1067
+ const workerContext = parseTeamWorkerContext(process.env.OMX_TEAM_INTERNAL_WORKER || process.env.OMX_TEAM_WORKER);
1004
1068
  if (!workerContext)
1005
1069
  return;
1006
1070
  for (const candidateCwd of resolveManifestLookupCwds(cwd)) {
@@ -1077,6 +1141,22 @@ async function recordRecoverableStartupIssue(params) {
1077
1141
  reason,
1078
1142
  }, cwd).catch(() => { });
1079
1143
  }
1144
+ async function recordPromptStartupWorkerStopped(params) {
1145
+ const { teamName, workerName, taskIds, reason, cwd } = params;
1146
+ const updatedAt = new Date().toISOString();
1147
+ await writeWorkerStatus(teamName, workerName, {
1148
+ state: 'failed',
1149
+ current_task_id: taskIds[0],
1150
+ reason,
1151
+ updated_at: updatedAt,
1152
+ }, cwd).catch(() => { });
1153
+ await appendTeamEvent(teamName, {
1154
+ type: 'worker_stopped',
1155
+ worker: workerName,
1156
+ task_id: taskIds[0],
1157
+ reason,
1158
+ }, cwd).catch(() => { });
1159
+ }
1080
1160
  function setTeamModelInstructionsFile(teamName, filePath) {
1081
1161
  if (!previousModelInstructionsFileByTeam.has(teamName)) {
1082
1162
  previousModelInstructionsFileByTeam.set(teamName, process.env[MODEL_INSTRUCTIONS_FILE_ENV]);
@@ -1383,10 +1463,16 @@ export { TEAM_LOW_COMPLEXITY_DEFAULT_MODEL };
1383
1463
  export { resolveCanonicalTeamStateRoot };
1384
1464
  function spawnPromptWorker(teamName, workerName, workerIndex, workerCwd, launchArgs, workerEnv, workerCli, initialPrompt, workerRole) {
1385
1465
  const processSpec = buildWorkerProcessLaunchSpec(teamName, workerIndex, launchArgs, workerCwd, workerEnv, workerCli, initialPrompt, workerRole);
1466
+ const childEnv = { ...process.env, ...processSpec.env };
1467
+ // Prompt workers are external CLI processes, not in-process runtime code.
1468
+ // Keeping c8's NODE_V8_COVERAGE in their environment makes coverage runs
1469
+ // track long-lived fake worker descendants and can keep node --test alive
1470
+ // after the runtime test itself has completed.
1471
+ delete childEnv.NODE_V8_COVERAGE;
1386
1472
  const child = spawn(processSpec.command, processSpec.args, {
1387
1473
  cwd: workerCwd,
1388
1474
  detached: process.platform !== 'win32',
1389
- env: { ...process.env, ...processSpec.env },
1475
+ env: childEnv,
1390
1476
  stdio: ['pipe', 'ignore', 'ignore'],
1391
1477
  });
1392
1478
  registerPromptWorkerHandle(teamName, workerName, child);
@@ -1481,11 +1567,28 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1481
1567
  const leaderCwd = resolve(cwd);
1482
1568
  await assertNestedTeamAllowed(leaderCwd);
1483
1569
  const effectiveWorktreeMode = resolveEffectiveTeamWorktreeMode(leaderCwd, options.worktreeMode);
1484
- const sanitized = sanitizeTeamName(teamName);
1485
- const leaderSessionId = await resolveLeaderSessionId(leaderCwd);
1486
- await assertTeamStartupIsNonDestructive(sanitized, leaderCwd, leaderSessionId);
1570
+ const displayName = sanitizeTeamName(teamName);
1487
1571
  const workerLaunchMode = resolveTeamWorkerLaunchMode(process.env);
1488
1572
  const displayMode = workerLaunchMode === 'interactive' ? 'split_pane' : 'auto';
1573
+ const rawIdentityScope = resolveTeamIdentityScope(process.env);
1574
+ const resolvedLeaderSessionId = await resolveLeaderSessionId(leaderCwd);
1575
+ const identityScope = rawIdentityScope.source === 'run-id'
1576
+ ? (resolvedLeaderSessionId
1577
+ ? { ...rawIdentityScope, sessionId: resolvedLeaderSessionId, runId: '' }
1578
+ : {
1579
+ ...rawIdentityScope,
1580
+ // Prompt-mode starts can run outside tmux/native session metadata. A fresh
1581
+ // random run id would give every start a new leader identity and bypass
1582
+ // one-active-team protection, so scope that fallback to the leader cwd.
1583
+ runId: `cwd:${leaderCwd}`,
1584
+ })
1585
+ : rawIdentityScope;
1586
+ const sanitized = buildInternalTeamName(displayName, identityScope);
1587
+ const leaderSessionId = identityScope.sessionId || identityScope.paneId || identityScope.tmuxTarget || identityScope.runId;
1588
+ await assertTeamStartupIsNonDestructive(sanitized, leaderCwd, leaderSessionId);
1589
+ if (displayName !== sanitized) {
1590
+ await assertTeamStartupIsNonDestructive(displayName, leaderCwd, leaderSessionId);
1591
+ }
1489
1592
  if (workerLaunchMode === 'interactive') {
1490
1593
  if (!isTmuxAvailable()) {
1491
1594
  throw new Error('Team mode requires tmux. Install with: apt install tmux / brew install tmux');
@@ -1495,6 +1598,16 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1495
1598
  }
1496
1599
  }
1497
1600
  const teamStateRoot = resolveCanonicalTeamStateRoot(leaderCwd);
1601
+ const requestedApprovedExecution = normalizeApprovedTeamExecutionBinding(options.approvedExecution);
1602
+ const selectedApprovedExecutionHint = requestedApprovedExecution
1603
+ ? readApprovedTeamExecutionHintFromBinding(leaderCwd, requestedApprovedExecution)
1604
+ : null;
1605
+ if (requestedApprovedExecution && !selectedApprovedExecutionHint) {
1606
+ throw new Error(`approved_execution_binding_stale:${requestedApprovedExecution.prd_path}:${requestedApprovedExecution.task}`);
1607
+ }
1608
+ const approvedExecution = selectedApprovedExecutionHint
1609
+ ? buildApprovedTeamExecutionBinding(selectedApprovedExecutionHint)
1610
+ : null;
1498
1611
  const activeWorktreeMode = effectiveWorktreeMode.enabled
1499
1612
  ? (effectiveWorktreeMode.detached ? 'detached' : 'named')
1500
1613
  : null;
@@ -1553,10 +1666,18 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1553
1666
  const skipWorkerReadyWait = shouldSkipWorkerReadyWait(process.env);
1554
1667
  try {
1555
1668
  // 3. Init state directory + config
1556
- config = await initTeamState(sanitized, task, agentType, workerCount, leaderCwd, DEFAULT_MAX_WORKERS, { ...process.env, OMX_TEAM_DISPLAY_MODE: displayMode, OMX_TEAM_WORKER_LAUNCH_MODE: workerLaunchMode }, {
1669
+ config = await initTeamState(sanitized, task, agentType, workerCount, leaderCwd, DEFAULT_MAX_WORKERS, {
1670
+ ...process.env,
1671
+ OMX_SESSION_ID: leaderSessionId,
1672
+ OMX_TEAM_DISPLAY_MODE: displayMode,
1673
+ OMX_TEAM_WORKER_LAUNCH_MODE: workerLaunchMode,
1674
+ }, {
1557
1675
  leader_cwd: leaderCwd,
1558
1676
  team_state_root: teamStateRoot,
1559
1677
  workspace_mode: workspaceMode,
1678
+ display_name: displayName,
1679
+ requested_name: displayName,
1680
+ identity_source: identityScope.source,
1560
1681
  worktree_mode: effectiveWorktreeMode,
1561
1682
  }, 'default');
1562
1683
  if (!config) {
@@ -1565,7 +1686,11 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1565
1686
  config.leader_cwd = leaderCwd;
1566
1687
  config.team_state_root = teamStateRoot;
1567
1688
  config.workspace_mode = workspaceMode;
1689
+ config.display_name = displayName;
1690
+ config.requested_name = displayName;
1691
+ config.identity_source = identityScope.source;
1568
1692
  config.worktree_mode = effectiveWorktreeMode;
1693
+ await writePersistedApprovedTeamExecutionBinding(sanitized, leaderCwd, approvedExecution, teamStateRoot);
1569
1694
  // 4. Create tasks. Repo-aware DAG dependencies are symbolic until the
1570
1695
  // state layer returns concrete task IDs, so create those tasks dependency
1571
1696
  // free and patch runtime dependency fields after ID assignment.
@@ -1661,6 +1786,8 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1661
1786
  rolePromptContent: rawRolePromptContent ?? undefined,
1662
1787
  worktreeRootAgentsCanonical: Boolean(workerWorkspace.worktreePath),
1663
1788
  taskHints: effectiveDecompositionMetadata?.task_hints,
1789
+ approvedContextSummary: effectiveDecompositionMetadata?.approved_context_summary,
1790
+ workerGoalInstruction: buildTeamWorkerGoalInstruction(sanitized, workerName, workerTasks, { teamStateRoot }),
1664
1791
  });
1665
1792
  const triggerDirective = buildTriggerDirective(workerName, sanitized, resolveInstructionStateRoot(workerWorkspace.worktreePath));
1666
1793
  const trigger = triggerDirective.text;
@@ -1688,6 +1815,7 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1688
1815
  [TEAM_STATE_ROOT_ENV]: teamStateRoot,
1689
1816
  [TEAM_LEADER_CWD_ENV]: leaderCwd,
1690
1817
  [MODEL_INSTRUCTIONS_FILE_ENV]: plan.instructionsFilePath,
1818
+ OMX_TEAM_DISPLAY_NAME: displayName,
1691
1819
  };
1692
1820
  if (plan.workerWorkspace.worktreePath) {
1693
1821
  env.OMX_TEAM_WORKTREE_PATH = plan.workerWorkspace.worktreePath;
@@ -1756,6 +1884,7 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1756
1884
  cleanup: options.cleanupLaunchOrphanedMcpProcesses,
1757
1885
  writeWarning: options.writeCleanupWarning,
1758
1886
  });
1887
+ const startupTiming = createStartupTimingRecorder(sanitized, leaderCwd);
1759
1888
  if (workerLaunchMode === 'interactive') {
1760
1889
  const createdSession = createTeamSession(sanitized, workerCount, leaderCwd, sharedWorkerLaunchArgs, workerStartups);
1761
1890
  sessionName = createdSession.name;
@@ -1763,6 +1892,9 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1763
1892
  createdWorkerPaneIds.push(...createdSession.workerPaneIds);
1764
1893
  createdLeaderPaneId = createdSession.leaderPaneId;
1765
1894
  applyCreatedInteractiveSessionToConfig(config, createdSession, workerPaneIds);
1895
+ for (const [index, paneId] of createdSession.workerPaneIds.entries()) {
1896
+ startupTiming.mark('split_returned', { worker: `worker-${index + 1}`, pane_id: paneId });
1897
+ }
1766
1898
  }
1767
1899
  else {
1768
1900
  config.tmux_session = `prompt-${sanitized}`;
@@ -1787,6 +1919,7 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1787
1919
  throw new Error(`missing bootstrap plan for worker-${i}`);
1788
1920
  }
1789
1921
  await materializeWorkerStartupState(bootstrapPlan, i, workerPaneIds[i - 1]);
1922
+ startupTiming.mark('identity_inbox_written', { worker: bootstrapPlan.workerName, pane_id: workerPaneIds[i - 1] });
1790
1923
  }
1791
1924
  await saveTeamConfig(config, leaderCwd);
1792
1925
  // 7. Start all safe per-worker readiness/dispatch attempts concurrently.
@@ -1812,6 +1945,7 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1812
1945
  const trigger = bootstrapPlan.trigger;
1813
1946
  const triggerIntent = bootstrapPlan.triggerIntent;
1814
1947
  const initialPrompt = bootstrapPlan.initialPrompt;
1948
+ const startupStartedAt = performance.now();
1815
1949
  const taskRoles = workerTasks
1816
1950
  .map((task) => task.role)
1817
1951
  .filter((role) => Boolean(role));
@@ -1819,8 +1953,26 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1819
1953
  if (uniqueTaskRoles.length > 1) {
1820
1954
  console.log(`[omx:team] ${workerName}: mixed task roles [${uniqueTaskRoles.join(', ')}], falling back to ${agentType}`);
1821
1955
  }
1822
- if (workerLaunchMode === 'interactive' && !skipWorkerReadyWait && !initialPrompt) {
1956
+ const startupDirectOutcome = workerLaunchMode === 'interactive' && !initialPrompt
1957
+ ? await attemptStartupDirectTrigger({
1958
+ teamName: sanitized,
1959
+ config: config,
1960
+ workerName,
1961
+ workerIndex,
1962
+ paneId,
1963
+ workerCli: workerCliPlan[workerIndex - 1],
1964
+ inbox,
1965
+ triggerMessage: trigger,
1966
+ intent: triggerIntent,
1967
+ taskIds: workerTasks.map((task) => task.id),
1968
+ cwd: leaderCwd,
1969
+ timing: startupTiming,
1970
+ })
1971
+ : null;
1972
+ if (workerLaunchMode === 'interactive' && !skipWorkerReadyWait && !initialPrompt && !startupDirectOutcome?.ok) {
1973
+ startupTiming.mark('ready_wait_start', { worker: workerName, pane_id: paneId });
1823
1974
  const ready = await waitForWorkerReadyAsync(sessionName, workerIndex, workerReadyTimeoutMs, paneId);
1975
+ startupTiming.mark('ready_wait_end', { worker: workerName, pane_id: paneId, ok: ready });
1824
1976
  if (!ready) {
1825
1977
  const workerAlive = isWorkerPaneOpen(sessionName, workerIndex, paneId);
1826
1978
  if (workerAlive) {
@@ -1841,10 +1993,11 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1841
1993
  };
1842
1994
  }
1843
1995
  }
1996
+ const startupReadyPromptObserved = workerLaunchMode === 'interactive' && !skipWorkerReadyWait && !initialPrompt;
1844
1997
  let dispatchOutcome = initialPrompt
1845
1998
  ? { ok: true, transport: 'none', reason: 'startup_prompt_delivered_at_launch' }
1846
- : { ok: false, transport: 'none', reason: 'not_attempted' };
1847
- if (!initialPrompt) {
1999
+ : (startupDirectOutcome ?? { ok: false, transport: 'none', reason: 'not_attempted' });
2000
+ if (!initialPrompt && !startupDirectOutcome?.ok) {
1848
2001
  for (let attempt = 1; attempt <= startupDispatchRetries; attempt++) {
1849
2002
  dispatchOutcome = await dispatchCriticalInboxInstruction({
1850
2003
  teamName: sanitized,
@@ -1861,7 +2014,20 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1861
2014
  inboxCorrelationKey: `startup:${workerName}`,
1862
2015
  requireWorkerStartupEvidence: true,
1863
2016
  startupEvidenceTimeoutMs: workerStartupEvidenceTimeoutMs,
2017
+ startupReadyPromptObserved,
2018
+ startupTiming,
1864
2019
  });
2020
+ await logStartupTiming({
2021
+ cwd: leaderCwd,
2022
+ teamName: sanitized,
2023
+ workerName,
2024
+ event: dispatchOutcome.ok ? 'startup_evidence' : 'startup_attempt_failed',
2025
+ paneId,
2026
+ elapsedMs: performance.now() - startupStartedAt,
2027
+ reason: dispatchOutcome.reason,
2028
+ requestId: dispatchOutcome.request_id,
2029
+ transport: dispatchOutcome.transport,
2030
+ }).catch(() => { });
1865
2031
  if (dispatchOutcome.ok)
1866
2032
  break;
1867
2033
  if (attempt < startupDispatchRetries) {
@@ -1895,6 +2061,16 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1895
2061
  });
1896
2062
  return { ok: true, workerIndex, workerName };
1897
2063
  }
2064
+ if (workerLaunchMode === 'prompt' && !workerAlive) {
2065
+ await recordPromptStartupWorkerStopped({
2066
+ teamName: sanitized,
2067
+ workerName,
2068
+ taskIds: workerTasks.map((task) => task.id),
2069
+ reason: dispatchOutcome.reason,
2070
+ cwd: leaderCwd,
2071
+ });
2072
+ return { ok: true, workerIndex, workerName };
2073
+ }
1898
2074
  return {
1899
2075
  ok: false,
1900
2076
  workerIndex,
@@ -1921,6 +2097,7 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
1921
2097
  throw firstStartupError.error;
1922
2098
  }
1923
2099
  await saveTeamConfig(config, leaderCwd);
2100
+ await startupTiming.flush();
1924
2101
  return {
1925
2102
  teamName: sanitized,
1926
2103
  sanitizedName: sanitized,
@@ -2046,7 +2223,7 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
2046
2223
  */
2047
2224
  export async function monitorTeam(teamName, cwd) {
2048
2225
  const monitorStartMs = performance.now();
2049
- const sanitized = sanitizeTeamName(teamName);
2226
+ const sanitized = resolveTeamNameForCurrentContext(teamName, cwd);
2050
2227
  const config = await readTeamConfig(sanitized, cwd);
2051
2228
  if (!config)
2052
2229
  return null;
@@ -2361,6 +2538,25 @@ export async function assignTask(teamName, workerName, taskId, cwd) {
2361
2538
  export async function reassignTask(teamName, taskId, _fromWorker, toWorker, cwd) {
2362
2539
  await assignTask(teamName, toWorker, taskId, cwd);
2363
2540
  }
2541
+ function resolveCommitHygieneArtifactTeamNames(config, internalTeamName) {
2542
+ const names = [];
2543
+ for (const value of [config.requested_name, config.display_name, internalTeamName]) {
2544
+ if (typeof value !== 'string' || value.trim() === '')
2545
+ continue;
2546
+ try {
2547
+ const sanitized = sanitizeTeamName(value);
2548
+ if (!names.includes(sanitized))
2549
+ names.push(sanitized);
2550
+ }
2551
+ catch {
2552
+ // Persisted display/request names are best-effort aliases. If an older
2553
+ // state file contains an invalid value, fall back to the internal name.
2554
+ }
2555
+ }
2556
+ if (!names.includes(internalTeamName))
2557
+ names.push(internalTeamName);
2558
+ return names;
2559
+ }
2364
2560
  /**
2365
2561
  * Graceful shutdown: send shutdown inbox to all workers, wait, force kill, cleanup.
2366
2562
  */
@@ -2368,7 +2564,7 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
2368
2564
  const force = options.force === true;
2369
2565
  const confirmIssues = options.confirmIssues === true;
2370
2566
  let skipWorkerAcks = false;
2371
- const sanitized = sanitizeTeamName(teamName);
2567
+ const sanitized = resolveTeamNameForCurrentContext(teamName, cwd);
2372
2568
  const config = await readTeamConfig(sanitized, cwd);
2373
2569
  if (!config) {
2374
2570
  // No config -- just try to kill tmux session and clean up
@@ -2616,14 +2812,22 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
2616
2812
  }
2617
2813
  }
2618
2814
  const artifactCwd = resolveTeamCommitHygieneArtifactCwd(config, cwd);
2619
- const ledger = await appendTeamCommitHygieneEntries(sanitized, commitHygieneEntries, artifactCwd);
2620
2815
  const taskView = await listTasks(sanitized, cwd).catch(() => []);
2621
- const commitHygieneContext = buildTeamCommitHygieneContext({
2622
- teamName: sanitized,
2623
- tasks: taskView,
2624
- ledger,
2625
- });
2626
- const commitHygieneArtifacts = await writeTeamCommitHygieneContext(sanitized, commitHygieneContext, artifactCwd);
2816
+ const internalLedger = await appendTeamCommitHygieneEntries(sanitized, commitHygieneEntries, artifactCwd);
2817
+ const commitHygieneArtifactTeamNames = resolveCommitHygieneArtifactTeamNames(config, sanitized);
2818
+ let commitHygieneArtifacts = null;
2819
+ for (const artifactTeamName of commitHygieneArtifactTeamNames) {
2820
+ const ledger = artifactTeamName === sanitized
2821
+ ? internalLedger
2822
+ : await appendTeamCommitHygieneEntries(artifactTeamName, internalLedger.entries, artifactCwd);
2823
+ const commitHygieneContext = buildTeamCommitHygieneContext({
2824
+ teamName: artifactTeamName,
2825
+ tasks: taskView,
2826
+ ledger,
2827
+ });
2828
+ const writtenArtifacts = await writeTeamCommitHygieneContext(artifactTeamName, commitHygieneContext, artifactCwd);
2829
+ commitHygieneArtifacts ??= writtenArtifacts;
2830
+ }
2627
2831
  // 5. Remove worker worktree-root instructions and team-scoped fallback instructions.
2628
2832
  for (const worker of config.workers) {
2629
2833
  if (!worker.worktree_path || !worker.team_state_root)
@@ -2675,11 +2879,19 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
2675
2879
  * Resume monitoring an existing team.
2676
2880
  */
2677
2881
  export async function resumeTeam(teamName, cwd) {
2678
- const sanitized = sanitizeTeamName(teamName);
2882
+ const sanitized = resolveTeamNameForCurrentContext(teamName, cwd);
2679
2883
  const config = await readTeamConfig(sanitized, cwd);
2680
2884
  if (!config)
2681
2885
  return null;
2682
2886
  config.lifecycle_profile = 'default';
2887
+ const leaderCwd = config.leader_cwd ?? cwd;
2888
+ const approvedExecutionState = await resolvePersistedApprovedTeamExecutionContinuityState(sanitized, leaderCwd, config.team_state_root ?? resolveCanonicalTeamStateRoot(leaderCwd));
2889
+ if (approvedExecutionState.status === 'malformed') {
2890
+ throw new Error(`approved_execution_binding_malformed:${sanitized}`);
2891
+ }
2892
+ if (approvedExecutionState.status === 'stale') {
2893
+ throw new Error(`approved_execution_binding_stale:${approvedExecutionState.binding.prd_path}:${approvedExecutionState.binding.task}`);
2894
+ }
2683
2895
  if (config.worker_launch_mode === 'prompt') {
2684
2896
  const handleTeamConfig = { ...config, name: sanitized };
2685
2897
  const hasLivePromptWorker = config.workers.some((worker) => isPromptWorkerAlive(handleTeamConfig, worker));
@@ -2718,7 +2930,7 @@ export async function resumeTeam(teamName, cwd) {
2718
2930
  };
2719
2931
  }
2720
2932
  async function findActiveTeams(cwd, leaderSessionId) {
2721
- const root = join(cwd, '.omx', 'state', 'team');
2933
+ const root = teamRuntimeTeamsRoot(cwd);
2722
2934
  if (!existsSync(root))
2723
2935
  return [];
2724
2936
  const sessions = new Set(listTeamSessions());
@@ -2754,7 +2966,7 @@ async function findActiveTeams(cwd, leaderSessionId) {
2754
2966
  return active;
2755
2967
  }
2756
2968
  async function detectAndCleanStaleTeam(teamName, leaderCwd, workerCount, confirmFn) {
2757
- const stateDir = join(leaderCwd, '.omx', 'state', 'team', teamName);
2969
+ const stateDir = teamRuntimeTeamRoot(teamName, leaderCwd);
2758
2970
  if (!existsSync(stateDir))
2759
2971
  return;
2760
2972
  const sessions = new Set(listTeamSessions());
@@ -2803,7 +3015,7 @@ async function resolveLeaderSessionId(cwd) {
2803
3015
  const fromEnv = process.env.OMX_SESSION_ID || process.env.CODEX_SESSION_ID || process.env.SESSION_ID;
2804
3016
  if (fromEnv && fromEnv.trim() !== '')
2805
3017
  return fromEnv.trim();
2806
- const p = join(cwd, '.omx', 'state', 'session.json');
3018
+ const p = teamRuntimeSessionPath(cwd);
2807
3019
  if (!existsSync(p))
2808
3020
  return '';
2809
3021
  try {
@@ -2951,8 +3163,89 @@ async function markDispatchRequestLeaderPaneMissingDeferred(params) {
2951
3163
  last_reason: 'leader_pane_missing_deferred',
2952
3164
  }, cwd).catch(() => { });
2953
3165
  }
3166
+ async function attemptStartupDirectTrigger(params) {
3167
+ const { teamName, config, workerName, workerIndex, paneId, workerCli, inbox, triggerMessage, intent, taskIds, cwd, timing, } = params;
3168
+ const safety = await evaluateStartupDirectTriggerSafety(config.tmux_session, workerIndex, paneId, workerCli);
3169
+ if (!safety.safe) {
3170
+ timing.mark('startup_direct_bypass', {
3171
+ worker: workerName,
3172
+ pane_id: paneId,
3173
+ ok: false,
3174
+ reason: `startup_direct_unsafe:${safety.reason}`,
3175
+ });
3176
+ return null;
3177
+ }
3178
+ const queued = await queueInboxInstruction({
3179
+ teamName,
3180
+ workerName,
3181
+ workerIndex,
3182
+ paneId,
3183
+ inbox,
3184
+ triggerMessage,
3185
+ intent,
3186
+ cwd,
3187
+ transportPreference: 'transport_direct',
3188
+ fallbackAllowed: false,
3189
+ inboxCorrelationKey: `startup-direct:${workerName}`,
3190
+ notify: (_target, message) => notifyWorkerOutcome(config, workerIndex, message, paneId),
3191
+ });
3192
+ timing.mark('dispatch_queued', {
3193
+ worker: workerName,
3194
+ pane_id: paneId,
3195
+ ok: queued.ok,
3196
+ reason: queued.reason,
3197
+ transport: queued.transport,
3198
+ request_id: queued.request_id,
3199
+ });
3200
+ timing.mark('direct_fallback', {
3201
+ worker: workerName,
3202
+ pane_id: paneId,
3203
+ ok: queued.ok,
3204
+ reason: queued.ok ? `startup_direct_trigger_sent:${safety.reason}` : queued.reason,
3205
+ transport: queued.transport,
3206
+ request_id: queued.request_id,
3207
+ });
3208
+ if (!queued.ok)
3209
+ return queued;
3210
+ const effectiveWorkerCli = workerCli ?? 'codex';
3211
+ const workerStartupEvidence = await waitForWorkerStartupEvidence({
3212
+ teamName,
3213
+ workerName,
3214
+ workerCli: effectiveWorkerCli,
3215
+ cwd,
3216
+ timeoutMs: 0,
3217
+ pollMs: STARTUP_EVIDENCE_POLL_MS,
3218
+ });
3219
+ timing.mark('startup_evidence', {
3220
+ worker: workerName,
3221
+ pane_id: paneId,
3222
+ ok: workerStartupEvidence !== 'none',
3223
+ reason: workerStartupEvidence,
3224
+ transport: queued.transport,
3225
+ request_id: queued.request_id,
3226
+ });
3227
+ const reason = workerStartupEvidence === 'none'
3228
+ ? `${effectiveWorkerCli}_startup_direct_no_evidence:${safety.reason}`
3229
+ : `startup_direct_trigger_sent:${safety.reason}`;
3230
+ if ((effectiveWorkerCli === 'codex' || effectiveWorkerCli === 'claude') && workerStartupEvidence === 'none') {
3231
+ await recordRecoverableStartupIssue({
3232
+ teamName,
3233
+ workerName,
3234
+ taskIds,
3235
+ reason,
3236
+ cwd,
3237
+ });
3238
+ }
3239
+ return {
3240
+ ...queued,
3241
+ reason,
3242
+ };
3243
+ }
2954
3244
  async function dispatchCriticalInboxInstruction(params) {
2955
- const { teamName, config, workerName, workerIndex, paneId, workerCli, inbox, triggerMessage, intent, cwd, dispatchPolicy, inboxCorrelationKey, requireWorkerStartupEvidence, startupEvidenceTimeoutMs, } = params;
3245
+ const { teamName, config, workerName, workerIndex, paneId, workerCli, inbox, triggerMessage, intent, cwd, dispatchPolicy, inboxCorrelationKey, requireWorkerStartupEvidence, startupEvidenceTimeoutMs, startupReadyPromptObserved = false, startupTiming, } = params;
3246
+ const noteTiming = (phase, details) => {
3247
+ startupTiming?.mark(phase, { worker: workerName, pane_id: paneId, ...details });
3248
+ };
2956
3249
  if (config.worker_launch_mode === 'prompt') {
2957
3250
  return await queueInboxInstruction({
2958
3251
  teamName,
@@ -2999,12 +3292,26 @@ async function dispatchCriticalInboxInstruction(params) {
2999
3292
  inboxCorrelationKey,
3000
3293
  notify: () => ({ ok: true, transport: 'hook', reason: 'queued_for_hook_dispatch' }),
3001
3294
  });
3295
+ noteTiming('dispatch_queued', {
3296
+ ok: queued.ok,
3297
+ reason: queued.reason,
3298
+ transport: queued.transport,
3299
+ request_id: queued.request_id,
3300
+ });
3002
3301
  if (!queued.request_id)
3003
3302
  return { ...queued, ok: false, reason: 'dispatch_request_missing_id' };
3004
3303
  const receipt = await waitForDispatchReceipt(teamName, queued.request_id, cwd, {
3005
3304
  timeoutMs: dispatchPolicy.dispatch_ack_timeout_ms,
3006
3305
  pollMs: 50,
3007
3306
  });
3307
+ if (receipt) {
3308
+ noteTiming('hook_receipt', {
3309
+ ok: receipt.status === 'delivered' || receipt.status === 'notified',
3310
+ reason: receipt.status,
3311
+ transport: 'hook',
3312
+ request_id: queued.request_id,
3313
+ });
3314
+ }
3008
3315
  if (receipt?.status === 'delivered') {
3009
3316
  return { ok: true, transport: 'hook', reason: 'hook_receipt_delivered', request_id: queued.request_id };
3010
3317
  }
@@ -3015,6 +3322,14 @@ async function dispatchCriticalInboxInstruction(params) {
3015
3322
  if (!requiresObservedStartupEvidence) {
3016
3323
  return { ok: true, transport: 'hook', reason: 'hook_receipt_notified', request_id: queued.request_id };
3017
3324
  }
3325
+ if (startupReadyPromptObserved) {
3326
+ return {
3327
+ ok: true,
3328
+ transport: 'hook',
3329
+ reason: 'hook_receipt_notified_with_ready_prompt',
3330
+ request_id: queued.request_id,
3331
+ };
3332
+ }
3018
3333
  startupEvidence = await waitForWorkerStartupEvidence({
3019
3334
  teamName,
3020
3335
  workerName,
@@ -3022,6 +3337,12 @@ async function dispatchCriticalInboxInstruction(params) {
3022
3337
  cwd,
3023
3338
  timeoutMs: startupEvidenceTimeoutMs,
3024
3339
  });
3340
+ noteTiming('startup_evidence', {
3341
+ ok: startupEvidence !== 'none',
3342
+ reason: startupEvidence,
3343
+ transport: 'hook',
3344
+ request_id: queued.request_id,
3345
+ });
3025
3346
  if (startupEvidence !== 'none') {
3026
3347
  return {
3027
3348
  ok: true,
@@ -3034,13 +3355,21 @@ async function dispatchCriticalInboxInstruction(params) {
3034
3355
  if (receipt?.status === 'failed') {
3035
3356
  const fallback = await notifyWorkerOutcome(config, workerIndex, triggerMessage, paneId);
3036
3357
  if (fallback.ok) {
3037
- const fallbackStartupEvidence = await waitForRequiredStartupEvidenceAfterDirectFallback({
3038
- requireWorkerStartupEvidence,
3039
- workerCli,
3040
- teamName,
3041
- workerName,
3042
- cwd,
3043
- timeoutMs: startupEvidenceTimeoutMs,
3358
+ const fallbackStartupEvidence = startupReadyPromptObserved
3359
+ ? 'ready_prompt'
3360
+ : await waitForRequiredStartupEvidenceAfterDirectFallback({
3361
+ requireWorkerStartupEvidence,
3362
+ workerCli,
3363
+ teamName,
3364
+ workerName,
3365
+ cwd,
3366
+ timeoutMs: startupEvidenceTimeoutMs,
3367
+ });
3368
+ noteTiming('startup_evidence', {
3369
+ ok: fallbackStartupEvidence !== 'none',
3370
+ reason: fallbackStartupEvidence,
3371
+ transport: fallback.transport,
3372
+ request_id: queued.request_id,
3044
3373
  });
3045
3374
  if (requiresObservedStartupEvidence && fallbackStartupEvidence === 'none') {
3046
3375
  await transitionDispatchRequest(teamName, queued.request_id, 'failed', 'failed', { last_reason: `${workerCli}_startup_no_evidence_after_fallback:${fallback.reason}` }, cwd).catch(() => { });
@@ -3071,6 +3400,12 @@ async function dispatchCriticalInboxInstruction(params) {
3071
3400
  };
3072
3401
  }
3073
3402
  const fallback = await notifyWorkerOutcome(config, workerIndex, triggerMessage, paneId);
3403
+ noteTiming('direct_fallback', {
3404
+ ok: fallback.ok,
3405
+ reason: fallback.reason,
3406
+ transport: fallback.transport,
3407
+ request_id: queued.request_id,
3408
+ });
3074
3409
  const startupFallbackLabel = receipt?.status === 'notified' && requiresObservedStartupEvidence
3075
3410
  ? `${workerCli}_startup_no_evidence`
3076
3411
  : null;
@@ -3078,13 +3413,21 @@ async function dispatchCriticalInboxInstruction(params) {
3078
3413
  ? `${startupFallbackLabel}_fallback_failed:${fallback.reason}`
3079
3414
  : `fallback_attempted_but_unconfirmed:${fallback.reason}`;
3080
3415
  if (fallback.ok) {
3081
- const fallbackStartupEvidence = await waitForRequiredStartupEvidenceAfterDirectFallback({
3082
- requireWorkerStartupEvidence,
3083
- workerCli,
3084
- teamName,
3085
- workerName,
3086
- cwd,
3087
- timeoutMs: startupEvidenceTimeoutMs,
3416
+ const fallbackStartupEvidence = startupReadyPromptObserved
3417
+ ? 'ready_prompt'
3418
+ : await waitForRequiredStartupEvidenceAfterDirectFallback({
3419
+ requireWorkerStartupEvidence,
3420
+ workerCli,
3421
+ teamName,
3422
+ workerName,
3423
+ cwd,
3424
+ timeoutMs: startupEvidenceTimeoutMs,
3425
+ });
3426
+ noteTiming('startup_evidence', {
3427
+ ok: fallbackStartupEvidence !== 'none',
3428
+ reason: fallbackStartupEvidence,
3429
+ transport: fallback.transport,
3430
+ request_id: queued.request_id,
3088
3431
  });
3089
3432
  if (requiresObservedStartupEvidence && fallbackStartupEvidence === 'none') {
3090
3433
  const current = await readDispatchRequest(teamName, queued.request_id, cwd);