oh-my-codex 0.14.4 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (614) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/Cargo.lock +6 -6
  3. package/Cargo.toml +2 -1
  4. package/README.md +40 -7
  5. package/crates/omx-explore/Cargo.toml +1 -0
  6. package/crates/omx-explore/src/main.rs +246 -24
  7. package/crates/omx-mux/Cargo.toml +1 -0
  8. package/crates/omx-runtime/Cargo.toml +1 -0
  9. package/crates/omx-runtime-core/Cargo.toml +1 -0
  10. package/crates/omx-runtime-core/src/dispatch.rs +2 -1
  11. package/crates/omx-runtime-core/src/engine.rs +2 -2
  12. package/crates/omx-runtime-core/src/mailbox.rs +2 -1
  13. package/crates/omx-sparkshell/Cargo.toml +1 -0
  14. package/crates/omx-sparkshell/src/codex_bridge.rs +1 -0
  15. package/crates/omx-sparkshell/src/prompt.rs +1 -0
  16. package/crates/omx-sparkshell/src/threshold.rs +1 -0
  17. package/dist/agents/__tests__/native-config.test.js +98 -4
  18. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  19. package/dist/agents/native-config.d.ts +4 -0
  20. package/dist/agents/native-config.d.ts.map +1 -1
  21. package/dist/agents/native-config.js +19 -3
  22. package/dist/agents/native-config.js.map +1 -1
  23. package/dist/agents/policy.d.ts +10 -0
  24. package/dist/agents/policy.d.ts.map +1 -0
  25. package/dist/agents/policy.js +61 -0
  26. package/dist/agents/policy.js.map +1 -0
  27. package/dist/catalog/__tests__/generator.test.js +2 -0
  28. package/dist/catalog/__tests__/generator.test.js.map +1 -1
  29. package/dist/catalog/__tests__/plugin-bundle-ssot.test.d.ts +2 -0
  30. package/dist/catalog/__tests__/plugin-bundle-ssot.test.d.ts.map +1 -0
  31. package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +72 -0
  32. package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -0
  33. package/dist/catalog/installable.d.ts +5 -0
  34. package/dist/catalog/installable.d.ts.map +1 -0
  35. package/dist/catalog/installable.js +13 -0
  36. package/dist/catalog/installable.js.map +1 -0
  37. package/dist/catalog/skill-mirror.d.ts +20 -0
  38. package/dist/catalog/skill-mirror.d.ts.map +1 -0
  39. package/dist/catalog/skill-mirror.js +104 -0
  40. package/dist/catalog/skill-mirror.js.map +1 -0
  41. package/dist/cli/__tests__/ask.test.js +4 -1
  42. package/dist/cli/__tests__/ask.test.js.map +1 -1
  43. package/dist/cli/__tests__/codex-plugin-layout.test.d.ts +2 -0
  44. package/dist/cli/__tests__/codex-plugin-layout.test.d.ts.map +1 -0
  45. package/dist/cli/__tests__/codex-plugin-layout.test.js +210 -0
  46. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -0
  47. package/dist/cli/__tests__/doctor-team.test.js +46 -1
  48. package/dist/cli/__tests__/doctor-team.test.js.map +1 -1
  49. package/dist/cli/__tests__/doctor-warning-copy.test.js +225 -111
  50. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  51. package/dist/cli/__tests__/exec.test.js +96 -1
  52. package/dist/cli/__tests__/exec.test.js.map +1 -1
  53. package/dist/cli/__tests__/explore.test.js +26 -9
  54. package/dist/cli/__tests__/explore.test.js.map +1 -1
  55. package/dist/cli/__tests__/index.test.js +301 -7
  56. package/dist/cli/__tests__/index.test.js.map +1 -1
  57. package/dist/cli/__tests__/launch-fallback.test.js +358 -4
  58. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  59. package/dist/cli/__tests__/list.test.d.ts +2 -0
  60. package/dist/cli/__tests__/list.test.d.ts.map +1 -0
  61. package/dist/cli/__tests__/list.test.js +38 -0
  62. package/dist/cli/__tests__/list.test.js.map +1 -0
  63. package/dist/cli/__tests__/mcp-parity.test.js +86 -0
  64. package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
  65. package/dist/cli/__tests__/mcp-serve.test.d.ts +2 -0
  66. package/dist/cli/__tests__/mcp-serve.test.d.ts.map +1 -0
  67. package/dist/cli/__tests__/mcp-serve.test.js +38 -0
  68. package/dist/cli/__tests__/mcp-serve.test.js.map +1 -0
  69. package/dist/cli/__tests__/nested-help-routing.test.js +1 -0
  70. package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
  71. package/dist/cli/__tests__/package-bin-contract.test.js +58 -3
  72. package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
  73. package/dist/cli/__tests__/question.test.js +209 -5
  74. package/dist/cli/__tests__/question.test.js.map +1 -1
  75. package/dist/cli/__tests__/setup-agents-overwrite.test.js +146 -3
  76. package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
  77. package/dist/cli/__tests__/setup-install-mode.test.d.ts +2 -0
  78. package/dist/cli/__tests__/setup-install-mode.test.d.ts.map +1 -0
  79. package/dist/cli/__tests__/setup-install-mode.test.js +873 -0
  80. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -0
  81. package/dist/cli/__tests__/setup-prompts-overwrite.test.js +83 -22
  82. package/dist/cli/__tests__/setup-prompts-overwrite.test.js.map +1 -1
  83. package/dist/cli/__tests__/setup-refresh.test.js +120 -2
  84. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  85. package/dist/cli/__tests__/setup-skills-overwrite.test.js +32 -13
  86. package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
  87. package/dist/cli/__tests__/sidecar.test.d.ts +2 -0
  88. package/dist/cli/__tests__/sidecar.test.d.ts.map +1 -0
  89. package/dist/cli/__tests__/sidecar.test.js +24 -0
  90. package/dist/cli/__tests__/sidecar.test.js.map +1 -0
  91. package/dist/cli/__tests__/team.test.js +90 -42
  92. package/dist/cli/__tests__/team.test.js.map +1 -1
  93. package/dist/cli/__tests__/version-sync-contract.test.js +11 -0
  94. package/dist/cli/__tests__/version-sync-contract.test.js.map +1 -1
  95. package/dist/cli/codex-home.d.ts +4 -5
  96. package/dist/cli/codex-home.d.ts.map +1 -1
  97. package/dist/cli/codex-home.js +9 -37
  98. package/dist/cli/codex-home.js.map +1 -1
  99. package/dist/cli/doctor.d.ts +1 -1
  100. package/dist/cli/doctor.d.ts.map +1 -1
  101. package/dist/cli/doctor.js +509 -278
  102. package/dist/cli/doctor.js.map +1 -1
  103. package/dist/cli/index.d.ts +13 -5
  104. package/dist/cli/index.d.ts.map +1 -1
  105. package/dist/cli/index.js +351 -60
  106. package/dist/cli/index.js.map +1 -1
  107. package/dist/cli/list.d.ts +2 -0
  108. package/dist/cli/list.d.ts.map +1 -0
  109. package/dist/cli/list.js +40 -0
  110. package/dist/cli/list.js.map +1 -0
  111. package/dist/cli/mcp-serve.d.ts +12 -0
  112. package/dist/cli/mcp-serve.d.ts.map +1 -0
  113. package/dist/cli/mcp-serve.js +63 -0
  114. package/dist/cli/mcp-serve.js.map +1 -0
  115. package/dist/cli/plugin-marketplace.d.ts +13 -0
  116. package/dist/cli/plugin-marketplace.d.ts.map +1 -0
  117. package/dist/cli/plugin-marketplace.js +77 -0
  118. package/dist/cli/plugin-marketplace.js.map +1 -0
  119. package/dist/cli/question.d.ts.map +1 -1
  120. package/dist/cli/question.js +27 -2
  121. package/dist/cli/question.js.map +1 -1
  122. package/dist/cli/setup-preferences.d.ts +20 -0
  123. package/dist/cli/setup-preferences.d.ts.map +1 -0
  124. package/dist/cli/setup-preferences.js +71 -0
  125. package/dist/cli/setup-preferences.js.map +1 -0
  126. package/dist/cli/setup.d.ts +12 -3
  127. package/dist/cli/setup.d.ts.map +1 -1
  128. package/dist/cli/setup.js +1080 -254
  129. package/dist/cli/setup.js.map +1 -1
  130. package/dist/cli/team.d.ts +1 -0
  131. package/dist/cli/team.d.ts.map +1 -1
  132. package/dist/cli/team.js +22 -3
  133. package/dist/cli/team.js.map +1 -1
  134. package/dist/cli/uninstall.d.ts.map +1 -1
  135. package/dist/cli/uninstall.js +2 -8
  136. package/dist/cli/uninstall.js.map +1 -1
  137. package/dist/config/__tests__/generator-idempotent.test.js +100 -3
  138. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  139. package/dist/config/__tests__/generator-notify.test.js +6 -5
  140. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  141. package/dist/config/__tests__/generator-status-line-presets.test.d.ts +2 -0
  142. package/dist/config/__tests__/generator-status-line-presets.test.d.ts.map +1 -0
  143. package/dist/config/__tests__/generator-status-line-presets.test.js +203 -0
  144. package/dist/config/__tests__/generator-status-line-presets.test.js.map +1 -0
  145. package/dist/config/__tests__/models.test.js +35 -2
  146. package/dist/config/__tests__/models.test.js.map +1 -1
  147. package/dist/config/codex-hooks.d.ts.map +1 -1
  148. package/dist/config/codex-hooks.js +2 -7
  149. package/dist/config/codex-hooks.js.map +1 -1
  150. package/dist/config/generator.d.ts +10 -0
  151. package/dist/config/generator.d.ts.map +1 -1
  152. package/dist/config/generator.js +259 -76
  153. package/dist/config/generator.js.map +1 -1
  154. package/dist/config/models.d.ts +13 -3
  155. package/dist/config/models.d.ts.map +1 -1
  156. package/dist/config/models.js +25 -5
  157. package/dist/config/models.js.map +1 -1
  158. package/dist/config/omx-first-party-mcp.d.ts +18 -0
  159. package/dist/config/omx-first-party-mcp.d.ts.map +1 -0
  160. package/dist/config/omx-first-party-mcp.js +76 -0
  161. package/dist/config/omx-first-party-mcp.js.map +1 -0
  162. package/dist/document-refresh/__tests__/enforcer.test.d.ts +2 -0
  163. package/dist/document-refresh/__tests__/enforcer.test.d.ts.map +1 -0
  164. package/dist/document-refresh/__tests__/enforcer.test.js +128 -0
  165. package/dist/document-refresh/__tests__/enforcer.test.js.map +1 -0
  166. package/dist/document-refresh/config.d.ts +9 -0
  167. package/dist/document-refresh/config.d.ts.map +1 -0
  168. package/dist/document-refresh/config.js +70 -0
  169. package/dist/document-refresh/config.js.map +1 -0
  170. package/dist/document-refresh/enforcer.d.ts +43 -0
  171. package/dist/document-refresh/enforcer.d.ts.map +1 -0
  172. package/dist/document-refresh/enforcer.js +329 -0
  173. package/dist/document-refresh/enforcer.js.map +1 -0
  174. package/dist/exec/followup.d.ts +44 -0
  175. package/dist/exec/followup.d.ts.map +1 -0
  176. package/dist/exec/followup.js +349 -0
  177. package/dist/exec/followup.js.map +1 -0
  178. package/dist/hooks/__tests__/codebase-map.test.js +63 -1
  179. package/dist/hooks/__tests__/codebase-map.test.js.map +1 -1
  180. package/dist/hooks/__tests__/deep-interview-contract.test.js +10 -7
  181. package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
  182. package/dist/hooks/__tests__/keyword-detector.test.js +89 -0
  183. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  184. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +84 -1
  185. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  186. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +23 -2
  187. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  188. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +43 -0
  189. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  190. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +17 -0
  191. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
  192. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +53 -0
  193. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
  194. package/dist/hooks/__tests__/notify-hook-regression-205.test.js +4 -4
  195. package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
  196. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +103 -0
  197. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  198. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +27 -13
  199. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  200. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.d.ts +2 -0
  201. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.d.ts.map +1 -0
  202. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js +35 -0
  203. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js.map +1 -0
  204. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +70 -3
  205. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  206. package/dist/hooks/__tests__/pre-context-gate-skills.test.js +5 -0
  207. package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -1
  208. package/dist/hooks/__tests__/prompt-guidance-fragments.test.js +3 -2
  209. package/dist/hooks/__tests__/prompt-guidance-fragments.test.js.map +1 -1
  210. package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts +2 -0
  211. package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts.map +1 -0
  212. package/dist/hooks/__tests__/prompt-refactor-contract.test.js +22 -0
  213. package/dist/hooks/__tests__/prompt-refactor-contract.test.js.map +1 -0
  214. package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.d.ts +2 -0
  215. package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.d.ts.map +1 -0
  216. package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js +28 -0
  217. package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js.map +1 -0
  218. package/dist/hooks/__tests__/triage-heuristic.test.js +59 -4
  219. package/dist/hooks/__tests__/triage-heuristic.test.js.map +1 -1
  220. package/dist/hooks/__tests__/visual-ralph-skill.test.d.ts +2 -0
  221. package/dist/hooks/__tests__/visual-ralph-skill.test.d.ts.map +1 -0
  222. package/dist/hooks/__tests__/visual-ralph-skill.test.js +44 -0
  223. package/dist/hooks/__tests__/visual-ralph-skill.test.js.map +1 -0
  224. package/dist/hooks/codebase-map.d.ts.map +1 -1
  225. package/dist/hooks/codebase-map.js +83 -6
  226. package/dist/hooks/codebase-map.js.map +1 -1
  227. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  228. package/dist/hooks/keyword-detector.js +19 -14
  229. package/dist/hooks/keyword-detector.js.map +1 -1
  230. package/dist/hooks/prompt-guidance-contract.d.ts +6 -0
  231. package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
  232. package/dist/hooks/prompt-guidance-contract.js +89 -0
  233. package/dist/hooks/prompt-guidance-contract.js.map +1 -1
  234. package/dist/hooks/session.d.ts +2 -0
  235. package/dist/hooks/session.d.ts.map +1 -1
  236. package/dist/hooks/session.js +6 -0
  237. package/dist/hooks/session.js.map +1 -1
  238. package/dist/hooks/triage-heuristic.d.ts +2 -2
  239. package/dist/hooks/triage-heuristic.d.ts.map +1 -1
  240. package/dist/hooks/triage-heuristic.js +97 -20
  241. package/dist/hooks/triage-heuristic.js.map +1 -1
  242. package/dist/hooks/triage-state.d.ts +1 -1
  243. package/dist/hooks/triage-state.d.ts.map +1 -1
  244. package/dist/hooks/triage-state.js +2 -1
  245. package/dist/hooks/triage-state.js.map +1 -1
  246. package/dist/hud/__tests__/index.test.js +4 -4
  247. package/dist/hud/__tests__/index.test.js.map +1 -1
  248. package/dist/hud/__tests__/state.test.js +4 -0
  249. package/dist/hud/__tests__/state.test.js.map +1 -1
  250. package/dist/hud/__tests__/types.test.js +27 -0
  251. package/dist/hud/__tests__/types.test.js.map +1 -1
  252. package/dist/hud/state.d.ts.map +1 -1
  253. package/dist/hud/state.js +8 -0
  254. package/dist/hud/state.js.map +1 -1
  255. package/dist/hud/types.d.ts +9 -0
  256. package/dist/hud/types.d.ts.map +1 -1
  257. package/dist/hud/types.js +3 -0
  258. package/dist/hud/types.js.map +1 -1
  259. package/dist/mcp/__tests__/bootstrap.test.js +45 -5
  260. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  261. package/dist/mcp/__tests__/server-lifecycle.test.js +50 -7
  262. package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
  263. package/dist/mcp/__tests__/state-server.test.js +67 -9
  264. package/dist/mcp/__tests__/state-server.test.js.map +1 -1
  265. package/dist/mcp/bootstrap.d.ts +12 -1
  266. package/dist/mcp/bootstrap.d.ts.map +1 -1
  267. package/dist/mcp/bootstrap.js +87 -29
  268. package/dist/mcp/bootstrap.js.map +1 -1
  269. package/dist/mcp/state-server.d.ts +5 -11
  270. package/dist/mcp/state-server.d.ts.map +1 -1
  271. package/dist/mcp/state-server.js +16 -432
  272. package/dist/mcp/state-server.js.map +1 -1
  273. package/dist/planning/__tests__/artifacts.test.js +152 -1
  274. package/dist/planning/__tests__/artifacts.test.js.map +1 -1
  275. package/dist/planning/artifacts.d.ts +9 -0
  276. package/dist/planning/artifacts.d.ts.map +1 -1
  277. package/dist/planning/artifacts.js +60 -1
  278. package/dist/planning/artifacts.js.map +1 -1
  279. package/dist/question/__tests__/deep-interview.test.js +1 -1
  280. package/dist/question/__tests__/deep-interview.test.js.map +1 -1
  281. package/dist/question/__tests__/renderer.test.js +70 -0
  282. package/dist/question/__tests__/renderer.test.js.map +1 -1
  283. package/dist/question/__tests__/ui.test.js +49 -0
  284. package/dist/question/__tests__/ui.test.js.map +1 -1
  285. package/dist/question/renderer.d.ts +14 -1
  286. package/dist/question/renderer.d.ts.map +1 -1
  287. package/dist/question/renderer.js +109 -10
  288. package/dist/question/renderer.js.map +1 -1
  289. package/dist/question/state.d.ts +2 -0
  290. package/dist/question/state.d.ts.map +1 -1
  291. package/dist/question/state.js +4 -0
  292. package/dist/question/state.js.map +1 -1
  293. package/dist/question/types.d.ts +2 -1
  294. package/dist/question/types.d.ts.map +1 -1
  295. package/dist/question/types.js.map +1 -1
  296. package/dist/question/ui.d.ts.map +1 -1
  297. package/dist/question/ui.js +28 -8
  298. package/dist/question/ui.js.map +1 -1
  299. package/dist/runtime/__tests__/bridge.test.js +143 -1
  300. package/dist/runtime/__tests__/bridge.test.js.map +1 -1
  301. package/dist/runtime/bridge.d.ts +21 -0
  302. package/dist/runtime/bridge.d.ts.map +1 -1
  303. package/dist/runtime/bridge.js +54 -4
  304. package/dist/runtime/bridge.js.map +1 -1
  305. package/dist/scripts/__tests__/codex-native-hook.test.js +1904 -230
  306. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  307. package/dist/scripts/__tests__/generate-release-body.test.js +90 -1
  308. package/dist/scripts/__tests__/generate-release-body.test.js.map +1 -1
  309. package/dist/scripts/__tests__/hook-derived-watcher.test.js +110 -2
  310. package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +1 -1
  311. package/dist/scripts/__tests__/postinstall.test.js +7 -93
  312. package/dist/scripts/__tests__/postinstall.test.js.map +1 -1
  313. package/dist/scripts/__tests__/prompt-inventory.test.d.ts +2 -0
  314. package/dist/scripts/__tests__/prompt-inventory.test.d.ts.map +1 -0
  315. package/dist/scripts/__tests__/prompt-inventory.test.js +56 -0
  316. package/dist/scripts/__tests__/prompt-inventory.test.js.map +1 -0
  317. package/dist/scripts/__tests__/run-test-files.test.d.ts +2 -0
  318. package/dist/scripts/__tests__/run-test-files.test.d.ts.map +1 -0
  319. package/dist/scripts/__tests__/run-test-files.test.js +62 -0
  320. package/dist/scripts/__tests__/run-test-files.test.js.map +1 -0
  321. package/dist/scripts/__tests__/smoke-packed-install.test.js +13 -1
  322. package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
  323. package/dist/scripts/__tests__/verify-native-agents.test.d.ts +2 -0
  324. package/dist/scripts/__tests__/verify-native-agents.test.d.ts.map +1 -0
  325. package/dist/scripts/__tests__/verify-native-agents.test.js +166 -0
  326. package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -0
  327. package/dist/scripts/codex-execution-surface.d.ts +16 -0
  328. package/dist/scripts/codex-execution-surface.d.ts.map +1 -0
  329. package/dist/scripts/codex-execution-surface.js +42 -0
  330. package/dist/scripts/codex-execution-surface.js.map +1 -0
  331. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  332. package/dist/scripts/codex-native-hook.js +418 -76
  333. package/dist/scripts/codex-native-hook.js.map +1 -1
  334. package/dist/scripts/codex-native-pre-post.d.ts +8 -0
  335. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
  336. package/dist/scripts/codex-native-pre-post.js +133 -19
  337. package/dist/scripts/codex-native-pre-post.js.map +1 -1
  338. package/dist/scripts/generate-release-body.d.ts +1 -0
  339. package/dist/scripts/generate-release-body.d.ts.map +1 -1
  340. package/dist/scripts/generate-release-body.js +32 -3
  341. package/dist/scripts/generate-release-body.js.map +1 -1
  342. package/dist/scripts/hook-derived-watcher.js +46 -7
  343. package/dist/scripts/hook-derived-watcher.js.map +1 -1
  344. package/dist/scripts/notify-fallback-watcher.js +59 -9
  345. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  346. package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts +2 -0
  347. package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts.map +1 -0
  348. package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js +153 -0
  349. package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js.map +1 -0
  350. package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
  351. package/dist/scripts/notify-hook/managed-tmux.js +18 -1
  352. package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
  353. package/dist/scripts/notify-hook/process-runner.d.ts.map +1 -1
  354. package/dist/scripts/notify-hook/process-runner.js +7 -3
  355. package/dist/scripts/notify-hook/process-runner.js.map +1 -1
  356. package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
  357. package/dist/scripts/notify-hook/team-dispatch.js +96 -11
  358. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  359. package/dist/scripts/notify-hook/team-tmux-guard.js +3 -3
  360. package/dist/scripts/notify-hook/team-worker-posttooluse.d.ts +34 -0
  361. package/dist/scripts/notify-hook/team-worker-posttooluse.d.ts.map +1 -0
  362. package/dist/scripts/notify-hook/team-worker-posttooluse.js +434 -0
  363. package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -0
  364. package/dist/scripts/notify-hook/team-worker.d.ts +1 -1
  365. package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
  366. package/dist/scripts/notify-hook/team-worker.js +3 -43
  367. package/dist/scripts/notify-hook/team-worker.js.map +1 -1
  368. package/dist/scripts/notify-hook.js +36 -5
  369. package/dist/scripts/notify-hook.js.map +1 -1
  370. package/dist/scripts/postinstall.d.ts +1 -5
  371. package/dist/scripts/postinstall.d.ts.map +1 -1
  372. package/dist/scripts/postinstall.js +3 -42
  373. package/dist/scripts/postinstall.js.map +1 -1
  374. package/dist/scripts/prompt-inventory.d.ts +29 -0
  375. package/dist/scripts/prompt-inventory.d.ts.map +1 -0
  376. package/dist/scripts/prompt-inventory.js +178 -0
  377. package/dist/scripts/prompt-inventory.js.map +1 -0
  378. package/dist/scripts/run-test-files.js +32 -2
  379. package/dist/scripts/run-test-files.js.map +1 -1
  380. package/dist/scripts/smoke-packed-install.d.ts +3 -0
  381. package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
  382. package/dist/scripts/smoke-packed-install.js +9 -1
  383. package/dist/scripts/smoke-packed-install.js.map +1 -1
  384. package/dist/scripts/sync-plugin-mirror.d.ts +13 -0
  385. package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -0
  386. package/dist/scripts/sync-plugin-mirror.js +242 -0
  387. package/dist/scripts/sync-plugin-mirror.js.map +1 -0
  388. package/dist/scripts/verify-native-agents.d.ts +16 -0
  389. package/dist/scripts/verify-native-agents.d.ts.map +1 -0
  390. package/dist/scripts/verify-native-agents.js +188 -0
  391. package/dist/scripts/verify-native-agents.js.map +1 -0
  392. package/dist/session-history/search.d.ts.map +1 -1
  393. package/dist/session-history/search.js +7 -2
  394. package/dist/session-history/search.js.map +1 -1
  395. package/dist/sidecar/__tests__/boundary.test.d.ts +2 -0
  396. package/dist/sidecar/__tests__/boundary.test.d.ts.map +1 -0
  397. package/dist/sidecar/__tests__/boundary.test.js +48 -0
  398. package/dist/sidecar/__tests__/boundary.test.js.map +1 -0
  399. package/dist/sidecar/__tests__/collector.test.d.ts +2 -0
  400. package/dist/sidecar/__tests__/collector.test.d.ts.map +1 -0
  401. package/dist/sidecar/__tests__/collector.test.js +162 -0
  402. package/dist/sidecar/__tests__/collector.test.js.map +1 -0
  403. package/dist/sidecar/__tests__/render.test.d.ts +2 -0
  404. package/dist/sidecar/__tests__/render.test.d.ts.map +1 -0
  405. package/dist/sidecar/__tests__/render.test.js +67 -0
  406. package/dist/sidecar/__tests__/render.test.js.map +1 -0
  407. package/dist/sidecar/__tests__/tmux.test.d.ts +2 -0
  408. package/dist/sidecar/__tests__/tmux.test.d.ts.map +1 -0
  409. package/dist/sidecar/__tests__/tmux.test.js +30 -0
  410. package/dist/sidecar/__tests__/tmux.test.js.map +1 -0
  411. package/dist/sidecar/__tests__/watch.test.d.ts +2 -0
  412. package/dist/sidecar/__tests__/watch.test.d.ts.map +1 -0
  413. package/dist/sidecar/__tests__/watch.test.js +42 -0
  414. package/dist/sidecar/__tests__/watch.test.js.map +1 -0
  415. package/dist/sidecar/collector.d.ts +4 -0
  416. package/dist/sidecar/collector.d.ts.map +1 -0
  417. package/dist/sidecar/collector.js +377 -0
  418. package/dist/sidecar/collector.js.map +1 -0
  419. package/dist/sidecar/index.d.ts +25 -0
  420. package/dist/sidecar/index.d.ts.map +1 -0
  421. package/dist/sidecar/index.js +165 -0
  422. package/dist/sidecar/index.js.map +1 -0
  423. package/dist/sidecar/render.d.ts +3 -0
  424. package/dist/sidecar/render.d.ts.map +1 -0
  425. package/dist/sidecar/render.js +72 -0
  426. package/dist/sidecar/render.js.map +1 -0
  427. package/dist/sidecar/tmux.d.ts +13 -0
  428. package/dist/sidecar/tmux.d.ts.map +1 -0
  429. package/dist/sidecar/tmux.js +44 -0
  430. package/dist/sidecar/tmux.js.map +1 -0
  431. package/dist/sidecar/types.d.ts +125 -0
  432. package/dist/sidecar/types.d.ts.map +1 -0
  433. package/dist/sidecar/types.js +2 -0
  434. package/dist/sidecar/types.js.map +1 -0
  435. package/dist/state/__tests__/operations.test.js +50 -22
  436. package/dist/state/__tests__/operations.test.js.map +1 -1
  437. package/dist/state/operations.d.ts +1 -1
  438. package/dist/state/operations.d.ts.map +1 -1
  439. package/dist/state/operations.js +19 -7
  440. package/dist/state/operations.js.map +1 -1
  441. package/dist/team/__tests__/commit-hygiene.test.d.ts +2 -0
  442. package/dist/team/__tests__/commit-hygiene.test.d.ts.map +1 -0
  443. package/dist/team/__tests__/commit-hygiene.test.js +93 -0
  444. package/dist/team/__tests__/commit-hygiene.test.js.map +1 -0
  445. package/dist/team/__tests__/delegation-policy.test.d.ts +2 -0
  446. package/dist/team/__tests__/delegation-policy.test.d.ts.map +1 -0
  447. package/dist/team/__tests__/delegation-policy.test.js +69 -0
  448. package/dist/team/__tests__/delegation-policy.test.js.map +1 -0
  449. package/dist/team/__tests__/events.test.js +54 -4
  450. package/dist/team/__tests__/events.test.js.map +1 -1
  451. package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts +2 -0
  452. package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts.map +1 -0
  453. package/dist/team/__tests__/hook-primary-e2e-contract.test.js +78 -0
  454. package/dist/team/__tests__/hook-primary-e2e-contract.test.js.map +1 -0
  455. package/dist/team/__tests__/model-contract.test.js +18 -2
  456. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  457. package/dist/team/__tests__/repo-aware-decomposition.test.d.ts +2 -0
  458. package/dist/team/__tests__/repo-aware-decomposition.test.d.ts.map +1 -0
  459. package/dist/team/__tests__/repo-aware-decomposition.test.js +95 -0
  460. package/dist/team/__tests__/repo-aware-decomposition.test.js.map +1 -0
  461. package/dist/team/__tests__/runtime.test.js +677 -17
  462. package/dist/team/__tests__/runtime.test.js.map +1 -1
  463. package/dist/team/__tests__/state-root.test.js +177 -1
  464. package/dist/team/__tests__/state-root.test.js.map +1 -1
  465. package/dist/team/__tests__/state.test.js +110 -0
  466. package/dist/team/__tests__/state.test.js.map +1 -1
  467. package/dist/team/__tests__/tmux-session.test.js +301 -2
  468. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  469. package/dist/team/__tests__/worker-bootstrap.test.js +94 -0
  470. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  471. package/dist/team/commit-hygiene.d.ts +22 -3
  472. package/dist/team/commit-hygiene.d.ts.map +1 -1
  473. package/dist/team/commit-hygiene.js +134 -2
  474. package/dist/team/commit-hygiene.js.map +1 -1
  475. package/dist/team/contracts.d.ts +1 -1
  476. package/dist/team/contracts.d.ts.map +1 -1
  477. package/dist/team/contracts.js +2 -0
  478. package/dist/team/contracts.js.map +1 -1
  479. package/dist/team/dag-schema.d.ts +38 -0
  480. package/dist/team/dag-schema.d.ts.map +1 -0
  481. package/dist/team/dag-schema.js +221 -0
  482. package/dist/team/dag-schema.js.map +1 -0
  483. package/dist/team/delegation-policy.d.ts +3 -0
  484. package/dist/team/delegation-policy.d.ts.map +1 -0
  485. package/dist/team/delegation-policy.js +82 -0
  486. package/dist/team/delegation-policy.js.map +1 -0
  487. package/dist/team/model-contract.d.ts +3 -1
  488. package/dist/team/model-contract.d.ts.map +1 -1
  489. package/dist/team/model-contract.js +44 -5
  490. package/dist/team/model-contract.js.map +1 -1
  491. package/dist/team/repo-aware-decomposition.d.ts +60 -0
  492. package/dist/team/repo-aware-decomposition.d.ts.map +1 -0
  493. package/dist/team/repo-aware-decomposition.js +229 -0
  494. package/dist/team/repo-aware-decomposition.js.map +1 -0
  495. package/dist/team/runtime.d.ts +34 -0
  496. package/dist/team/runtime.d.ts.map +1 -1
  497. package/dist/team/runtime.js +191 -50
  498. package/dist/team/runtime.js.map +1 -1
  499. package/dist/team/state/tasks.d.ts.map +1 -1
  500. package/dist/team/state/tasks.js +33 -0
  501. package/dist/team/state/tasks.js.map +1 -1
  502. package/dist/team/state/types.d.ts +23 -1
  503. package/dist/team/state/types.d.ts.map +1 -1
  504. package/dist/team/state/types.js.map +1 -1
  505. package/dist/team/state-root.d.ts +35 -0
  506. package/dist/team/state-root.d.ts.map +1 -1
  507. package/dist/team/state-root.js +281 -1
  508. package/dist/team/state-root.js.map +1 -1
  509. package/dist/team/state.d.ts +27 -1
  510. package/dist/team/state.d.ts.map +1 -1
  511. package/dist/team/state.js +6 -0
  512. package/dist/team/state.js.map +1 -1
  513. package/dist/team/tmux-session.d.ts +1 -0
  514. package/dist/team/tmux-session.d.ts.map +1 -1
  515. package/dist/team/tmux-session.js +83 -6
  516. package/dist/team/tmux-session.js.map +1 -1
  517. package/dist/team/worker-bootstrap.d.ts +3 -0
  518. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  519. package/dist/team/worker-bootstrap.js +77 -4
  520. package/dist/team/worker-bootstrap.js.map +1 -1
  521. package/dist/utils/__tests__/agents-model-table.test.js +8 -0
  522. package/dist/utils/__tests__/agents-model-table.test.js.map +1 -1
  523. package/dist/utils/__tests__/paths.test.js +42 -9
  524. package/dist/utils/__tests__/paths.test.js.map +1 -1
  525. package/dist/utils/agents-md.d.ts +3 -0
  526. package/dist/utils/agents-md.d.ts.map +1 -1
  527. package/dist/utils/agents-md.js +25 -0
  528. package/dist/utils/agents-md.js.map +1 -1
  529. package/dist/utils/agents-model-table.d.ts.map +1 -1
  530. package/dist/utils/agents-model-table.js +2 -3
  531. package/dist/utils/agents-model-table.js.map +1 -1
  532. package/package.json +14 -7
  533. package/plugins/oh-my-codex/.app.json +3 -0
  534. package/plugins/oh-my-codex/.codex-plugin/plugin.json +30 -0
  535. package/plugins/oh-my-codex/.mcp.json +44 -0
  536. package/plugins/oh-my-codex/skills/ai-slop-cleaner/SKILL.md +114 -0
  537. package/plugins/oh-my-codex/skills/analyze/SKILL.md +148 -0
  538. package/plugins/oh-my-codex/skills/ask-claude/SKILL.md +61 -0
  539. package/plugins/oh-my-codex/skills/ask-gemini/SKILL.md +61 -0
  540. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +231 -0
  541. package/plugins/oh-my-codex/skills/autoresearch/SKILL.md +68 -0
  542. package/plugins/oh-my-codex/skills/cancel/SKILL.md +399 -0
  543. package/plugins/oh-my-codex/skills/code-review/SKILL.md +290 -0
  544. package/plugins/oh-my-codex/skills/configure-notifications/SKILL.md +287 -0
  545. package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +464 -0
  546. package/plugins/oh-my-codex/skills/doctor/SKILL.md +239 -0
  547. package/plugins/oh-my-codex/skills/help/SKILL.md +202 -0
  548. package/plugins/oh-my-codex/skills/hud/SKILL.md +98 -0
  549. package/plugins/oh-my-codex/skills/note/SKILL.md +62 -0
  550. package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +135 -0
  551. package/plugins/oh-my-codex/skills/pipeline/SKILL.md +86 -0
  552. package/plugins/oh-my-codex/skills/plan/SKILL.md +276 -0
  553. package/plugins/oh-my-codex/skills/ralph/SKILL.md +269 -0
  554. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +162 -0
  555. package/plugins/oh-my-codex/skills/security-review/SKILL.md +300 -0
  556. package/plugins/oh-my-codex/skills/skill/SKILL.md +835 -0
  557. package/plugins/oh-my-codex/skills/team/SKILL.md +510 -0
  558. package/plugins/oh-my-codex/skills/trace/SKILL.md +33 -0
  559. package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +143 -0
  560. package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +175 -0
  561. package/plugins/oh-my-codex/skills/visual-ralph/SKILL.md +153 -0
  562. package/plugins/oh-my-codex/skills/visual-verdict/SKILL.md +76 -0
  563. package/plugins/oh-my-codex/skills/wiki/SKILL.md +57 -0
  564. package/plugins/oh-my-codex/skills/worker/SKILL.md +106 -0
  565. package/prompts/critic.md +35 -83
  566. package/prompts/executor.md +32 -109
  567. package/prompts/explore-harness.md +1 -1
  568. package/prompts/explore.md +37 -90
  569. package/prompts/planner.md +28 -58
  570. package/prompts/researcher.md +46 -78
  571. package/prompts/verifier.md +23 -31
  572. package/skills/autopilot/SKILL.md +1 -4
  573. package/skills/deep-interview/SKILL.md +8 -5
  574. package/skills/doctor/SKILL.md +45 -17
  575. package/skills/help/SKILL.md +2 -2
  576. package/skills/omx-setup/SKILL.md +52 -9
  577. package/skills/plan/SKILL.md +1 -4
  578. package/skills/ralph/SKILL.md +3 -5
  579. package/skills/ralplan/SKILL.md +2 -6
  580. package/skills/team/SKILL.md +2 -5
  581. package/skills/ultraqa/SKILL.md +1 -4
  582. package/skills/ultrawork/SKILL.md +2 -3
  583. package/skills/visual-ralph/SKILL.md +153 -0
  584. package/skills/web-clone/SKILL.md +12 -354
  585. package/src/scripts/__tests__/codex-native-hook.test.ts +2306 -224
  586. package/src/scripts/__tests__/generate-release-body.test.ts +109 -0
  587. package/src/scripts/__tests__/hook-derived-watcher.test.ts +132 -2
  588. package/src/scripts/__tests__/postinstall.test.ts +7 -104
  589. package/src/scripts/__tests__/prompt-inventory.test.ts +64 -0
  590. package/src/scripts/__tests__/run-test-files.test.ts +72 -0
  591. package/src/scripts/__tests__/smoke-packed-install.test.ts +15 -0
  592. package/src/scripts/__tests__/verify-native-agents.test.ts +204 -0
  593. package/src/scripts/codex-execution-surface.ts +73 -0
  594. package/src/scripts/codex-native-hook.ts +579 -82
  595. package/src/scripts/codex-native-pre-post.ts +157 -19
  596. package/src/scripts/generate-release-body.ts +34 -2
  597. package/src/scripts/hook-derived-watcher.ts +51 -8
  598. package/src/scripts/notify-fallback-watcher.ts +65 -9
  599. package/src/scripts/notify-hook/__tests__/team-worker-posttooluse.test.ts +180 -0
  600. package/src/scripts/notify-hook/managed-tmux.ts +22 -4
  601. package/src/scripts/notify-hook/process-runner.ts +7 -3
  602. package/src/scripts/notify-hook/team-dispatch.ts +103 -11
  603. package/src/scripts/notify-hook/team-tmux-guard.ts +3 -3
  604. package/src/scripts/notify-hook/team-worker-posttooluse.ts +536 -0
  605. package/src/scripts/notify-hook/team-worker.ts +4 -48
  606. package/src/scripts/notify-hook.ts +36 -5
  607. package/src/scripts/postinstall.ts +4 -58
  608. package/src/scripts/prompt-inventory.ts +218 -0
  609. package/src/scripts/run-test-files.ts +41 -2
  610. package/src/scripts/smoke-packed-install.ts +10 -1
  611. package/src/scripts/sync-plugin-mirror.ts +360 -0
  612. package/src/scripts/verify-native-agents.ts +245 -0
  613. package/templates/AGENTS.md +26 -91
  614. package/templates/catalog-manifest.json +16 -1
@@ -0,0 +1,536 @@
1
+ import { execFile } from 'child_process';
2
+ import { existsSync } from 'fs';
3
+ import { mkdir, readFile, writeFile } from 'fs/promises';
4
+ import { join, resolve } from 'path';
5
+ import { promisify } from 'util';
6
+ import { appendTeamCommitHygieneEntries, type TeamOperationalCommitEntry, type TeamOperationalCommitKind } from '../../team/commit-hygiene.js';
7
+ import { appendTeamEvent } from '../../team/state.js';
8
+ import { resolveWorkerTeamStateRoot } from '../../team/state-root.js';
9
+
10
+ const execFileAsync = promisify(execFile);
11
+
12
+ type PostToolUseStatus = 'applied' | 'noop' | 'conflict' | 'skipped';
13
+ type PostToolUseOperationKind = 'auto_checkpoint' | 'worker_clean_rebase' | 'leader_integration_attempt';
14
+
15
+ type JsonRecord = Record<string, unknown>;
16
+
17
+ export interface TeamWorkerPostToolUseResult {
18
+ handled: boolean;
19
+ status: PostToolUseStatus;
20
+ reason?: string;
21
+ teamName?: string;
22
+ workerName?: string;
23
+ stateRoot?: string;
24
+ worktreePath?: string;
25
+ workerHeadBefore?: string | null;
26
+ workerHeadAfter?: string | null;
27
+ checkpointCommit?: string | null;
28
+ leaderHeadObserved?: string | null;
29
+ operationKinds: PostToolUseOperationKind[];
30
+ dedupeKey?: string;
31
+ }
32
+
33
+ interface ParsedTeamWorkerEnv {
34
+ teamName: string;
35
+ workerName: string;
36
+ }
37
+
38
+ interface DedupeMarker {
39
+ version: 1;
40
+ updated_at: string;
41
+ latest_key?: string;
42
+ keys: string[];
43
+ entries: Array<{ dedupe_key: string; created_at: string; tool_use_id?: string; status: PostToolUseStatus }>;
44
+ }
45
+
46
+ const PROTECTED_PATH_PREFIXES = [
47
+ '.omx/state/',
48
+ '.omx/logs/',
49
+ '.omx/reports/',
50
+ ];
51
+ const PROTECTED_PATH_SUFFIXES = [
52
+ '.pid',
53
+ '.lock',
54
+ '.tmp',
55
+ ];
56
+ const PROTECTED_PATH_EXACT = new Set([
57
+ 'AGENTS.md',
58
+ ]);
59
+
60
+ function safeString(value: unknown): string {
61
+ return typeof value === 'string' ? value : '';
62
+ }
63
+
64
+ function safeRecord(value: unknown): JsonRecord {
65
+ return value && typeof value === 'object' && !Array.isArray(value) ? value as JsonRecord : {};
66
+ }
67
+
68
+ function parseTeamWorkerEnv(raw: unknown): ParsedTeamWorkerEnv | null {
69
+ const value = safeString(raw).trim();
70
+ const match = /^([a-z0-9][a-z0-9-]{0,29})\/(worker-\d+)$/.exec(value);
71
+ return match ? { teamName: match[1]!, workerName: match[2]! } : null;
72
+ }
73
+
74
+ function readHookEvent(payload: JsonRecord): string {
75
+ return safeString(payload.hook_event_name ?? payload.hookEventName ?? payload.event ?? payload.name).trim();
76
+ }
77
+
78
+ function readToolName(payload: JsonRecord): string {
79
+ return safeString(payload.tool_name ?? payload.toolName ?? payload.tool).trim();
80
+ }
81
+
82
+ function readExitCode(payload: JsonRecord): number | null {
83
+ const response = safeRecord(payload.tool_response ?? payload.toolResponse ?? payload.result);
84
+ for (const source of [payload, response]) {
85
+ for (const key of ['exit_code', 'exitCode', 'code', 'status']) {
86
+ const value = source[key];
87
+ if (typeof value === 'number' && Number.isInteger(value)) return value;
88
+ if (typeof value === 'string' && /^-?\d+$/.test(value.trim())) return Number.parseInt(value.trim(), 10);
89
+ }
90
+ }
91
+ return null;
92
+ }
93
+
94
+ function readToolUseId(payload: JsonRecord): string | undefined {
95
+ const value = safeString(payload.tool_use_id ?? payload.toolUseId ?? payload.id).trim();
96
+ return value || undefined;
97
+ }
98
+
99
+ async function readJsonIfExists(path: string): Promise<JsonRecord | null> {
100
+ try {
101
+ if (!existsSync(path)) return null;
102
+ const parsed = JSON.parse(await readFile(path, 'utf-8')) as unknown;
103
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed as JsonRecord : null;
104
+ } catch {
105
+ return null;
106
+ }
107
+ }
108
+
109
+ async function git(cwd: string, args: string[]): Promise<string> {
110
+ const { stdout } = await execFileAsync('git', args, { cwd, encoding: 'utf-8', maxBuffer: 1024 * 1024 });
111
+ return stdout.trim();
112
+ }
113
+
114
+ async function gitMaybe(cwd: string, args: string[]): Promise<{ ok: true; stdout: string } | { ok: false; stderr: string }> {
115
+ try {
116
+ return { ok: true, stdout: await git(cwd, args) };
117
+ } catch (error) {
118
+ const err = error as { stderr?: unknown; message?: string };
119
+ return { ok: false, stderr: safeString(err.stderr) || safeString(err.message) };
120
+ }
121
+ }
122
+
123
+ async function gitHead(cwd: string): Promise<string | null> {
124
+ const result = await gitMaybe(cwd, ['rev-parse', '--verify', 'HEAD']);
125
+ return result.ok ? result.stdout : null;
126
+ }
127
+
128
+ async function hasGitOperationInProgress(cwd: string): Promise<string | null> {
129
+ const gitDirResult = await gitMaybe(cwd, ['rev-parse', '--git-dir']);
130
+ if (!gitDirResult.ok) return 'not_git_repository';
131
+ const gitDir = resolve(cwd, gitDirResult.stdout);
132
+ const paths = [
133
+ 'MERGE_HEAD',
134
+ 'CHERRY_PICK_HEAD',
135
+ 'REVERT_HEAD',
136
+ 'BISECT_LOG',
137
+ 'rebase-merge',
138
+ 'rebase-apply',
139
+ ];
140
+ for (const path of paths) {
141
+ if (existsSync(join(gitDir, path))) return path;
142
+ }
143
+ return null;
144
+ }
145
+
146
+ function parsePorcelainPaths(status: string): string[] {
147
+ return status
148
+ .split('\n')
149
+ .map((line) => line.trimEnd())
150
+ .filter(Boolean)
151
+ .map((line) => {
152
+ const raw = line.slice(3).trim();
153
+ const renameTarget = raw.includes(' -> ') ? raw.split(' -> ').at(-1)! : raw;
154
+ return renameTarget.replace(/^"|"$/g, '');
155
+ })
156
+ .filter(Boolean);
157
+ }
158
+
159
+ function isProtectedCheckpointPath(path: string): boolean {
160
+ const normalized = path.replace(/\\/g, '/');
161
+ if (PROTECTED_PATH_EXACT.has(normalized)) return true;
162
+ if (normalized.includes('/posttooluse-dedupe.json') || normalized.endsWith('/posttooluse-dedupe.json')) return true;
163
+ if (PROTECTED_PATH_PREFIXES.some((prefix) => normalized.startsWith(prefix))) return true;
164
+ if (PROTECTED_PATH_SUFFIXES.some((suffix) => normalized.endsWith(suffix))) return true;
165
+ return false;
166
+ }
167
+
168
+ async function readTeamConfig(stateRoot: string, teamName: string): Promise<JsonRecord | null> {
169
+ return readJsonIfExists(join(stateRoot, 'team', teamName, 'config.json'));
170
+ }
171
+
172
+ function readLeaderArtifactCwd(config: JsonRecord | null, fallbackCwd: string): string {
173
+ const leaderCwd = safeString(config?.leader_cwd ?? config?.leaderCwd).trim();
174
+ return leaderCwd ? resolve(fallbackCwd, leaderCwd) : fallbackCwd;
175
+ }
176
+
177
+ async function readLeaderHeadObserved(config: JsonRecord | null, fallbackCwd: string): Promise<string | null> {
178
+ const leaderCwd = safeString(config?.leader_cwd ?? config?.leaderCwd).trim();
179
+ if (leaderCwd) {
180
+ const head = await gitMaybe(resolve(fallbackCwd, leaderCwd), ['rev-parse', '--verify', 'HEAD']);
181
+ if (head.ok && head.stdout) return head.stdout;
182
+ }
183
+ const value = safeString(config?.leader_head ?? config?.leaderHead ?? config?.leader_head_observed).trim();
184
+ return value || null;
185
+ }
186
+
187
+ async function readTeamPhaseTerminal(stateRoot: string, teamName: string): Promise<boolean> {
188
+ const phase = await readJsonIfExists(join(stateRoot, 'team', teamName, 'phase.json'));
189
+ const current = safeString(phase?.current_phase ?? phase?.phase).trim();
190
+ return current === 'complete' || current === 'failed' || current === 'cancelled';
191
+ }
192
+
193
+ async function writeHeartbeat(stateRoot: string, teamName: string, workerName: string, nowIso: string): Promise<void> {
194
+ const dir = join(stateRoot, 'team', teamName, 'workers', workerName);
195
+ await mkdir(dir, { recursive: true });
196
+ await writeFile(join(dir, 'heartbeat.json'), JSON.stringify({ last_turn_at: nowIso, source: 'posttooluse' }, null, 2));
197
+ }
198
+
199
+ async function readDedupeMarker(path: string): Promise<DedupeMarker> {
200
+ const parsed = await readJsonIfExists(path);
201
+ const keys = Array.isArray(parsed?.keys) ? parsed.keys.filter((key): key is string => typeof key === 'string') : [];
202
+ const entries = Array.isArray(parsed?.entries)
203
+ ? parsed.entries.filter((entry): entry is DedupeMarker['entries'][number] => !!entry && typeof entry === 'object' && typeof (entry as JsonRecord).dedupe_key === 'string')
204
+ : [];
205
+ return {
206
+ version: 1,
207
+ updated_at: safeString(parsed?.updated_at) || new Date(0).toISOString(),
208
+ latest_key: safeString(parsed?.latest_key) || undefined,
209
+ keys,
210
+ entries,
211
+ };
212
+ }
213
+
214
+ function buildDedupeKey(params: {
215
+ teamName: string;
216
+ workerName: string;
217
+ workerHeadAfter: string | null;
218
+ operationKind: PostToolUseOperationKind;
219
+ }): string {
220
+ return [
221
+ params.teamName,
222
+ params.workerName,
223
+ params.workerHeadAfter ?? '',
224
+ params.operationKind,
225
+ ].join('|');
226
+ }
227
+
228
+ async function appendLeaderSignal(params: {
229
+ teamName: string;
230
+ workerName: string;
231
+ workerHeadBefore: string | null;
232
+ workerHeadAfter: string | null;
233
+ checkpointCommit: string | null;
234
+ leaderHeadObserved: string | null;
235
+ outcomeStatus: PostToolUseStatus;
236
+ toolUseId?: string;
237
+ dedupeKey: string;
238
+ worktreePath: string;
239
+ leaderArtifactCwd: string;
240
+ }): Promise<void> {
241
+ await appendTeamEvent(params.teamName, {
242
+ type: 'worker_integration_attempt_requested',
243
+ worker: params.workerName,
244
+ metadata: {
245
+ worker_head_before: params.workerHeadBefore,
246
+ worker_head_after: params.workerHeadAfter,
247
+ checkpoint_commit: params.checkpointCommit,
248
+ leader_head_observed: params.leaderHeadObserved,
249
+ operation_kind: 'leader_integration_attempt',
250
+ outcome_status: params.outcomeStatus,
251
+ tool_use_id: params.toolUseId,
252
+ dedupe_key: params.dedupeKey,
253
+ worktree_path: params.worktreePath,
254
+ source: 'posttooluse',
255
+ },
256
+ }, params.leaderArtifactCwd);
257
+ }
258
+
259
+ async function appendLedger(params: {
260
+ teamName: string;
261
+ workerName: string;
262
+ cwd: string;
263
+ leaderArtifactCwd: string;
264
+ operation: TeamOperationalCommitKind;
265
+ status: PostToolUseStatus;
266
+ workerHeadBefore: string | null;
267
+ workerHeadAfter: string | null;
268
+ leaderHeadObserved: string | null;
269
+ operationalCommit?: string | null;
270
+ sourceCommit?: string | null;
271
+ detail?: string;
272
+ }): Promise<void> {
273
+ const entry: TeamOperationalCommitEntry = {
274
+ recorded_at: new Date().toISOString(),
275
+ operation: params.operation,
276
+ worker_name: params.workerName,
277
+ status: params.status,
278
+ operational_commit: params.operationalCommit ?? null,
279
+ source_commit: params.sourceCommit ?? null,
280
+ leader_head_before: params.leaderHeadObserved,
281
+ leader_head_after: params.leaderHeadObserved,
282
+ worker_head_before: params.workerHeadBefore,
283
+ worker_head_after: params.workerHeadAfter,
284
+ worktree_path: params.cwd,
285
+ detail: params.detail,
286
+ };
287
+ await appendTeamCommitHygieneEntries(params.teamName, [entry], params.leaderArtifactCwd);
288
+ }
289
+
290
+ async function writeDedupeMarker(path: string, params: {
291
+ dedupeKey: string;
292
+ createdAt: string;
293
+ toolUseId?: string;
294
+ status: PostToolUseStatus;
295
+ }): Promise<void> {
296
+ await mkdir(resolve(path, '..'), { recursive: true });
297
+ const marker = await readDedupeMarker(path);
298
+ const keys = marker.keys.includes(params.dedupeKey) ? marker.keys : [...marker.keys, params.dedupeKey].slice(-100);
299
+ const entries = [
300
+ ...marker.entries.filter((entry) => entry.dedupe_key !== params.dedupeKey),
301
+ {
302
+ dedupe_key: params.dedupeKey,
303
+ created_at: params.createdAt,
304
+ tool_use_id: params.toolUseId,
305
+ status: params.status,
306
+ },
307
+ ].slice(-100);
308
+ await writeFile(path, JSON.stringify({
309
+ version: 1,
310
+ updated_at: params.createdAt,
311
+ latest_key: params.dedupeKey,
312
+ keys,
313
+ entries,
314
+ }, null, 2));
315
+ }
316
+
317
+ async function classifyCleanScaffolding(cwd: string, leaderHeadObserved: string | null, workerHeadAfter: string | null): Promise<{ status: PostToolUseStatus; reason: string }> {
318
+ if (!leaderHeadObserved) return { status: 'skipped', reason: 'no_leader_head_observed' };
319
+ if (!workerHeadAfter) return { status: 'skipped', reason: 'no_worker_head' };
320
+ if (leaderHeadObserved === workerHeadAfter) return { status: 'noop', reason: 'worker_already_at_leader' };
321
+
322
+ const leaderAncestor = await gitMaybe(cwd, ['merge-base', '--is-ancestor', leaderHeadObserved, workerHeadAfter]);
323
+ if (leaderAncestor.ok) return { status: 'noop', reason: 'leader_is_worker_ancestor' };
324
+
325
+ const workerAncestor = await gitMaybe(cwd, ['merge-base', '--is-ancestor', workerHeadAfter, leaderHeadObserved]);
326
+ if (workerAncestor.ok) return { status: 'skipped', reason: 'worker_behind_leader_defer_to_leader_integration' };
327
+
328
+ return { status: 'skipped', reason: 'non_fast_forward_defer_to_leader_integration' };
329
+ }
330
+
331
+ async function unstageCheckpointablePaths(cwd: string, paths: string[]): Promise<void> {
332
+ if (paths.length === 0) return;
333
+ const restore = await gitMaybe(cwd, ['restore', '--staged', '--', ...paths]);
334
+ if (restore.ok) return;
335
+ await gitMaybe(cwd, ['reset', '-q', '--', ...paths]);
336
+ }
337
+
338
+ async function checkpointIfEligible(cwd: string, workerName: string): Promise<{
339
+ status: PostToolUseStatus;
340
+ reason?: string;
341
+ checkpointCommit: string | null;
342
+ workerHeadAfter: string | null;
343
+ }> {
344
+ const inProgress = await hasGitOperationInProgress(cwd);
345
+ if (inProgress) {
346
+ return { status: inProgress === 'not_git_repository' ? 'skipped' : 'skipped', reason: inProgress, checkpointCommit: null, workerHeadAfter: await gitHead(cwd) };
347
+ }
348
+
349
+ const unmerged = await git(cwd, ['diff', '--name-only', '--diff-filter=U']);
350
+ if (unmerged.trim()) {
351
+ return { status: 'conflict', reason: 'unmerged_paths', checkpointCommit: null, workerHeadAfter: await gitHead(cwd) };
352
+ }
353
+
354
+ const staged = await git(cwd, ['diff', '--name-only', '--cached']);
355
+ if (staged.trim()) {
356
+ return { status: 'skipped', reason: 'index_not_clean', checkpointCommit: null, workerHeadAfter: await gitHead(cwd) };
357
+ }
358
+
359
+ const status = await git(cwd, ['status', '--porcelain=v1', '-uall']);
360
+ const paths = parsePorcelainPaths(status);
361
+ if (paths.length === 0) {
362
+ return { status: 'noop', checkpointCommit: null, workerHeadAfter: await gitHead(cwd) };
363
+ }
364
+
365
+ const checkpointable = paths.filter((path) => !isProtectedCheckpointPath(path));
366
+ if (checkpointable.length === 0) {
367
+ const onlyRuntimeArtifacts = paths.every((path) => {
368
+ const normalized = path.replace(/\\/g, '/');
369
+ return normalized.startsWith('.omx/state/') || normalized.startsWith('.omx/logs/') || normalized.startsWith('.omx/reports/');
370
+ });
371
+ return onlyRuntimeArtifacts
372
+ ? { status: 'noop', checkpointCommit: null, workerHeadAfter: await gitHead(cwd) }
373
+ : { status: 'skipped', reason: 'only_protected_paths_changed', checkpointCommit: null, workerHeadAfter: await gitHead(cwd) };
374
+ }
375
+
376
+ const addResult = await gitMaybe(cwd, ['add', '--', ...checkpointable]);
377
+ if (!addResult.ok) {
378
+ await unstageCheckpointablePaths(cwd, checkpointable);
379
+ return { status: 'skipped', reason: `git_add_failed:${addResult.stderr.slice(0, 120)}`, checkpointCommit: null, workerHeadAfter: await gitHead(cwd) };
380
+ }
381
+
382
+ const commitResult = await gitMaybe(cwd, ['commit', '--no-verify', '-m', `omx(team): auto-checkpoint ${workerName}`]);
383
+ if (!commitResult.ok) {
384
+ await unstageCheckpointablePaths(cwd, checkpointable);
385
+ const reason = commitResult.stderr.includes('conflict') ? 'git_commit_conflict' : `git_commit_failed:${commitResult.stderr.slice(0, 120)}`;
386
+ return { status: reason.includes('conflict') ? 'conflict' : 'skipped', reason, checkpointCommit: null, workerHeadAfter: await gitHead(cwd) };
387
+ }
388
+
389
+ const head = await gitHead(cwd);
390
+ return { status: 'applied', checkpointCommit: head, workerHeadAfter: head };
391
+ }
392
+
393
+ export async function handleTeamWorkerPostToolUseSuccess(
394
+ payload: JsonRecord,
395
+ cwd: string,
396
+ env: NodeJS.ProcessEnv = process.env,
397
+ ): Promise<TeamWorkerPostToolUseResult> {
398
+ try {
399
+ if (readHookEvent(payload) !== 'PostToolUse') return { handled: false, status: 'skipped', reason: 'not_posttooluse', operationKinds: [] };
400
+ if (readToolName(payload) !== 'Bash') return { handled: false, status: 'skipped', reason: 'not_bash', operationKinds: [] };
401
+ if (readExitCode(payload) !== 0) return { handled: false, status: 'skipped', reason: 'nonzero_exit', operationKinds: [] };
402
+
403
+ const parsedWorker = parseTeamWorkerEnv(env.OMX_TEAM_WORKER);
404
+ if (!parsedWorker) return { handled: false, status: 'skipped', reason: 'missing_worker_env', operationKinds: [] };
405
+
406
+ const resolvedStateRoot = await resolveWorkerTeamStateRoot(cwd, parsedWorker, env);
407
+ if (!resolvedStateRoot.ok || !resolvedStateRoot.stateRoot) {
408
+ return {
409
+ handled: false,
410
+ status: 'skipped',
411
+ reason: resolvedStateRoot.reason || 'missing_team_root',
412
+ teamName: parsedWorker.teamName,
413
+ workerName: parsedWorker.workerName,
414
+ operationKinds: [],
415
+ };
416
+ }
417
+
418
+ const { teamName, workerName } = parsedWorker;
419
+ const stateRoot = resolvedStateRoot.stateRoot;
420
+ const worktreePath = resolvedStateRoot.worktreePath || resolve(cwd);
421
+ if (await readTeamPhaseTerminal(stateRoot, teamName)) {
422
+ return { handled: false, status: 'skipped', reason: 'terminal_phase', teamName, workerName, stateRoot, worktreePath, operationKinds: [] };
423
+ }
424
+
425
+ const nowIso = new Date().toISOString();
426
+ await writeHeartbeat(stateRoot, teamName, workerName, nowIso);
427
+
428
+ const config = await readTeamConfig(stateRoot, teamName);
429
+ const leaderArtifactCwd = readLeaderArtifactCwd(config, cwd);
430
+ const workerHeadBefore = await gitHead(cwd);
431
+ const leaderHeadObserved = await readLeaderHeadObserved(config, cwd);
432
+ const checkpoint = await checkpointIfEligible(cwd, workerName);
433
+ const workerHeadAfter = checkpoint.workerHeadAfter;
434
+ const operationKinds: PostToolUseOperationKind[] = ['auto_checkpoint'];
435
+ await appendLedger({
436
+ teamName,
437
+ workerName,
438
+ cwd,
439
+ leaderArtifactCwd,
440
+ operation: 'auto_checkpoint',
441
+ status: checkpoint.status,
442
+ workerHeadBefore,
443
+ workerHeadAfter,
444
+ leaderHeadObserved,
445
+ operationalCommit: checkpoint.checkpointCommit,
446
+ sourceCommit: workerHeadBefore,
447
+ detail: checkpoint.reason ? `posttooluse:${checkpoint.reason}` : 'posttooluse',
448
+ });
449
+
450
+ const cleanScaffolding = await classifyCleanScaffolding(cwd, leaderHeadObserved, workerHeadAfter);
451
+ operationKinds.push('worker_clean_rebase');
452
+ await appendLedger({
453
+ teamName,
454
+ workerName,
455
+ cwd,
456
+ leaderArtifactCwd,
457
+ operation: 'worker_clean_rebase',
458
+ status: cleanScaffolding.status,
459
+ workerHeadBefore,
460
+ workerHeadAfter,
461
+ leaderHeadObserved,
462
+ sourceCommit: workerHeadAfter,
463
+ detail: `posttooluse:${cleanScaffolding.reason}`,
464
+ });
465
+
466
+ if (workerHeadAfter) operationKinds.push('leader_integration_attempt');
467
+ const dedupeKey = buildDedupeKey({
468
+ teamName,
469
+ workerName,
470
+ workerHeadAfter,
471
+ operationKind: 'leader_integration_attempt',
472
+ });
473
+ const dedupePath = join(stateRoot, 'team', teamName, 'workers', workerName, 'posttooluse-dedupe.json');
474
+ const marker = await readDedupeMarker(dedupePath);
475
+
476
+ if (workerHeadAfter && !marker.keys.includes(dedupeKey)) {
477
+ await appendLeaderSignal({
478
+ teamName,
479
+ workerName,
480
+ workerHeadBefore,
481
+ workerHeadAfter,
482
+ checkpointCommit: checkpoint.checkpointCommit,
483
+ leaderHeadObserved,
484
+ outcomeStatus: checkpoint.status,
485
+ toolUseId: readToolUseId(payload),
486
+ dedupeKey,
487
+ worktreePath,
488
+ leaderArtifactCwd,
489
+ });
490
+ await appendLedger({
491
+ teamName,
492
+ workerName,
493
+ cwd,
494
+ leaderArtifactCwd,
495
+ operation: 'leader_integration_attempt',
496
+ status: checkpoint.status,
497
+ workerHeadBefore,
498
+ workerHeadAfter,
499
+ leaderHeadObserved,
500
+ sourceCommit: workerHeadAfter,
501
+ detail: `posttooluse:${dedupeKey}`,
502
+ });
503
+ await writeDedupeMarker(dedupePath, {
504
+ dedupeKey,
505
+ createdAt: nowIso,
506
+ toolUseId: readToolUseId(payload),
507
+ status: checkpoint.status,
508
+ });
509
+ }
510
+
511
+ return {
512
+ handled: true,
513
+ status: checkpoint.status,
514
+ reason: checkpoint.reason,
515
+ teamName,
516
+ workerName,
517
+ stateRoot,
518
+ worktreePath,
519
+ workerHeadBefore,
520
+ workerHeadAfter,
521
+ checkpointCommit: checkpoint.checkpointCommit,
522
+ leaderHeadObserved,
523
+ operationKinds,
524
+ dedupeKey,
525
+ };
526
+ } catch (error) {
527
+ const reason = error instanceof Error ? error.message : String(error);
528
+ return { handled: false, status: 'skipped', reason: `bridge_error:${reason}`, operationKinds: [] };
529
+ }
530
+ }
531
+
532
+ export const teamWorkerPostToolUseInternals = {
533
+ buildDedupeKey,
534
+ isProtectedCheckpointPath,
535
+ parsePorcelainPaths,
536
+ };
@@ -5,7 +5,8 @@
5
5
 
6
6
  import { readFile, writeFile, mkdir, appendFile, rename, stat, readdir } from 'fs/promises';
7
7
  import { existsSync } from 'fs';
8
- import { join, resolve as resolvePath } from 'path';
8
+ import { join } from 'path';
9
+ import { resolveWorkerNotifyTeamStateRootPath } from '../../team/state-root.js';
9
10
  import { asNumber, safeString, isTerminalPhase } from './utils.js';
10
11
  import { readJsonIfExists } from './state-io.js';
11
12
  import { logTmuxHookEvent } from './log.js';
@@ -19,56 +20,11 @@ import {
19
20
  import { DEFAULT_MARKER } from '../tmux-hook-engine.js';
20
21
  const LEADER_PANE_SHELL_NO_INJECTION_REASON = 'leader_pane_shell_no_injection';
21
22
 
22
- async function readTeamStateRootFromJson(path) {
23
- try {
24
- if (!existsSync(path)) return null;
25
- const parsed = JSON.parse(await readFile(path, 'utf-8'));
26
- const value = parsed && typeof parsed.team_state_root === 'string'
27
- ? parsed.team_state_root.trim()
28
- : '';
29
- return value ? value : null;
30
- } catch {
31
- return null;
32
- }
33
- }
34
-
35
23
  export async function resolveTeamStateDirForWorker(cwd, parsedTeamWorker) {
36
- const explicitStateRoot = safeString(process.env.OMX_TEAM_STATE_ROOT || '').trim();
37
- if (explicitStateRoot) {
38
- return resolvePath(cwd, explicitStateRoot);
39
- }
40
-
41
- const teamName = parsedTeamWorker.teamName;
42
- const workerName = parsedTeamWorker.workerName;
43
- const leaderCwd = safeString(process.env.OMX_TEAM_LEADER_CWD || '').trim();
44
-
45
- const candidateStateDirs = [];
46
- if (leaderCwd) {
47
- candidateStateDirs.push(join(resolvePath(leaderCwd), '.omx', 'state'));
48
- }
49
- candidateStateDirs.push(join(cwd, '.omx', 'state'));
50
-
51
- for (const candidateStateDir of candidateStateDirs) {
52
- const teamRoot = join(candidateStateDir, 'team', teamName);
53
- if (!existsSync(teamRoot)) continue;
54
-
55
- const identityRoot = await readTeamStateRootFromJson(
56
- join(teamRoot, 'workers', workerName, 'identity.json'),
57
- );
58
- if (identityRoot) return resolvePath(cwd, identityRoot);
59
-
60
- const manifestRoot = await readTeamStateRootFromJson(join(teamRoot, 'manifest.v2.json'));
61
- if (manifestRoot) return resolvePath(cwd, manifestRoot);
62
-
63
- const configRoot = await readTeamStateRootFromJson(join(teamRoot, 'config.json'));
64
- if (configRoot) return resolvePath(cwd, configRoot);
65
-
66
- return candidateStateDir;
67
- }
68
-
69
- return join(cwd, '.omx', 'state');
24
+ return resolveWorkerNotifyTeamStateRootPath(cwd, parsedTeamWorker, process.env);
70
25
  }
71
26
 
27
+
72
28
  export function parseTeamWorkerEnv(rawValue) {
73
29
  if (typeof rawValue !== 'string') return null;
74
30
  const match = /^([a-z0-9][a-z0-9-]{0,29})\/(worker-\d+)$/.exec(rawValue.trim());
@@ -20,7 +20,7 @@
20
20
 
21
21
  import { writeFile, appendFile, mkdir, readFile } from 'fs/promises';
22
22
  import { existsSync } from 'fs';
23
- import { dirname, join } from 'path';
23
+ import { dirname, join, resolve } from 'path';
24
24
 
25
25
  import { safeString, asNumber } from './notify-hook/utils.js';
26
26
  import {
@@ -183,9 +183,11 @@ async function main() {
183
183
  const parsedTeamWorker = parseTeamWorkerEnv(teamWorkerEnv);
184
184
  const isTeamWorker = !!parsedTeamWorker;
185
185
 
186
- const stateDir = (isTeamWorker && parsedTeamWorker)
186
+ const resolvedWorkerStateDir = (isTeamWorker && parsedTeamWorker)
187
187
  ? await resolveTeamStateDirForWorker(cwd, parsedTeamWorker)
188
- : join(cwd, '.omx', 'state');
188
+ : null;
189
+ const workerStateRootResolved = !isTeamWorker || !!resolvedWorkerStateDir;
190
+ const stateDir = resolvedWorkerStateDir || join(cwd, '.omx', 'state');
189
191
  const logsDir = join(cwd, '.omx', 'logs');
190
192
  const omxDir = join(cwd, '.omx');
191
193
  let currentOmxSessionId = '';
@@ -193,12 +195,15 @@ async function main() {
193
195
 
194
196
  // Ensure directories exist
195
197
  await mkdir(logsDir, { recursive: true }).catch(() => {});
196
- await mkdir(stateDir, { recursive: true }).catch(() => {});
197
- currentOmxSessionId = await readCurrentSessionId(stateDir).catch(() => '') || '';
198
+ if (workerStateRootResolved) {
199
+ await mkdir(stateDir, { recursive: true }).catch(() => {});
200
+ currentOmxSessionId = await readCurrentSessionId(stateDir).catch(() => '') || '';
201
+ }
198
202
 
199
203
  // Turn-level dedupe prevents double-processing when native notify and fallback
200
204
  // watcher both emit the same completed turn.
201
205
  try {
206
+ if (!workerStateRootResolved) throw new Error('worker_state_root_unresolved');
202
207
  const turnId = safeString(payload['turn-id'] || payload.turn_id || '');
203
208
  if (turnId) {
204
209
  const now = Date.now();
@@ -268,6 +273,32 @@ async function main() {
268
273
  return;
269
274
  }
270
275
 
276
+ if (isTeamWorker && !workerStateRootResolved) {
277
+ await logNotifyHookEvent(logsDir, {
278
+ timestamp: new Date().toISOString(),
279
+ level: 'warn',
280
+ type: 'team_worker_state_root_unresolved',
281
+ team_worker: teamWorkerEnv || null,
282
+ reason: 'skip_team_worker_state_mutations',
283
+ }).catch(() => {});
284
+
285
+ // Keep the fail-closed worker state-root behavior for normal team-worker
286
+ // mutations, but allow the narrow auto-nudge path to use an explicitly
287
+ // supplied, already-existing worker state root. Auto-nudge only needs the
288
+ // worker-scoped state files/pane anchor and should not fall back to creating
289
+ // local `.omx/state` when identity resolution failed.
290
+ const explicitWorkerStateRoot = safeString(process.env.OMX_TEAM_STATE_ROOT || '').trim();
291
+ const autoNudgeStateDir = explicitWorkerStateRoot ? resolve(cwd, explicitWorkerStateRoot) : '';
292
+ if (autoNudgeStateDir && existsSync(autoNudgeStateDir)) {
293
+ try {
294
+ await maybeAutoNudge({ cwd, stateDir: autoNudgeStateDir, logsDir, payload });
295
+ } catch {
296
+ // Non-critical
297
+ }
298
+ }
299
+ return;
300
+ }
301
+
271
302
  // Reconcile Ralph ownership for same-Codex-session continuation before
272
303
  // lifecycle counters or injection read the active scope.
273
304
  if (!isTeamWorker) {