oh-my-codex 0.15.0 → 0.15.2

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 (533) hide show
  1. package/Cargo.lock +5 -5
  2. package/Cargo.toml +1 -1
  3. package/README.md +36 -5
  4. package/crates/omx-explore/src/main.rs +222 -12
  5. package/dist/agents/__tests__/native-config.test.js +40 -0
  6. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  7. package/dist/agents/native-config.d.ts +1 -0
  8. package/dist/agents/native-config.d.ts.map +1 -1
  9. package/dist/agents/native-config.js +6 -1
  10. package/dist/agents/native-config.js.map +1 -1
  11. package/dist/agents/policy.d.ts +1 -0
  12. package/dist/agents/policy.d.ts.map +1 -1
  13. package/dist/agents/policy.js +4 -0
  14. package/dist/agents/policy.js.map +1 -1
  15. package/dist/cli/__tests__/autoresearch-guided.test.js +37 -13
  16. package/dist/cli/__tests__/autoresearch-guided.test.js.map +1 -1
  17. package/dist/cli/__tests__/codex-plugin-layout.test.js +1 -1
  18. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  19. package/dist/cli/__tests__/doctor-team.test.js +46 -1
  20. package/dist/cli/__tests__/doctor-team.test.js.map +1 -1
  21. package/dist/cli/__tests__/doctor-warning-copy.test.js +225 -111
  22. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  23. package/dist/cli/__tests__/exec.test.js +96 -1
  24. package/dist/cli/__tests__/exec.test.js.map +1 -1
  25. package/dist/cli/__tests__/explore.test.js +15 -2
  26. package/dist/cli/__tests__/explore.test.js.map +1 -1
  27. package/dist/cli/__tests__/index.test.js +292 -3
  28. package/dist/cli/__tests__/index.test.js.map +1 -1
  29. package/dist/cli/__tests__/launch-fallback.test.js +223 -0
  30. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  31. package/dist/cli/__tests__/mcp-parity.test.js +86 -0
  32. package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
  33. package/dist/cli/__tests__/package-bin-contract.test.js +23 -0
  34. package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
  35. package/dist/cli/__tests__/question.test.js +76 -11
  36. package/dist/cli/__tests__/question.test.js.map +1 -1
  37. package/dist/cli/__tests__/setup-agents-overwrite.test.js +140 -1
  38. package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
  39. package/dist/cli/__tests__/setup-install-mode.test.js +310 -4
  40. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  41. package/dist/cli/__tests__/setup-prompts-overwrite.test.js +78 -19
  42. package/dist/cli/__tests__/setup-prompts-overwrite.test.js.map +1 -1
  43. package/dist/cli/__tests__/setup-refresh.test.js +79 -2
  44. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  45. package/dist/cli/__tests__/sidecar.test.d.ts +2 -0
  46. package/dist/cli/__tests__/sidecar.test.d.ts.map +1 -0
  47. package/dist/cli/__tests__/sidecar.test.js +24 -0
  48. package/dist/cli/__tests__/sidecar.test.js.map +1 -0
  49. package/dist/cli/__tests__/team.test.js +54 -7
  50. package/dist/cli/__tests__/team.test.js.map +1 -1
  51. package/dist/cli/autoresearch-guided.d.ts.map +1 -1
  52. package/dist/cli/autoresearch-guided.js +12 -4
  53. package/dist/cli/autoresearch-guided.js.map +1 -1
  54. package/dist/cli/codex-home.d.ts +4 -6
  55. package/dist/cli/codex-home.d.ts.map +1 -1
  56. package/dist/cli/codex-home.js +9 -41
  57. package/dist/cli/codex-home.js.map +1 -1
  58. package/dist/cli/doctor.d.ts +1 -1
  59. package/dist/cli/doctor.d.ts.map +1 -1
  60. package/dist/cli/doctor.js +509 -279
  61. package/dist/cli/doctor.js.map +1 -1
  62. package/dist/cli/index.d.ts +6 -4
  63. package/dist/cli/index.d.ts.map +1 -1
  64. package/dist/cli/index.js +284 -25
  65. package/dist/cli/index.js.map +1 -1
  66. package/dist/cli/omx.js +3 -1
  67. package/dist/cli/omx.js.map +1 -1
  68. package/dist/cli/plugin-marketplace.d.ts +13 -0
  69. package/dist/cli/plugin-marketplace.d.ts.map +1 -0
  70. package/dist/cli/plugin-marketplace.js +77 -0
  71. package/dist/cli/plugin-marketplace.js.map +1 -0
  72. package/dist/cli/question.d.ts +1 -1
  73. package/dist/cli/question.d.ts.map +1 -1
  74. package/dist/cli/question.js +26 -12
  75. package/dist/cli/question.js.map +1 -1
  76. package/dist/cli/setup-preferences.d.ts +20 -0
  77. package/dist/cli/setup-preferences.d.ts.map +1 -0
  78. package/dist/cli/setup-preferences.js +71 -0
  79. package/dist/cli/setup-preferences.js.map +1 -0
  80. package/dist/cli/setup.d.ts +7 -5
  81. package/dist/cli/setup.d.ts.map +1 -1
  82. package/dist/cli/setup.js +271 -152
  83. package/dist/cli/setup.js.map +1 -1
  84. package/dist/cli/team.d.ts +1 -0
  85. package/dist/cli/team.d.ts.map +1 -1
  86. package/dist/cli/team.js +70 -15
  87. package/dist/cli/team.js.map +1 -1
  88. package/dist/config/__tests__/generator-idempotent.test.js +100 -3
  89. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  90. package/dist/config/__tests__/generator-notify.test.js +6 -5
  91. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  92. package/dist/config/__tests__/generator-status-line-presets.test.d.ts +2 -0
  93. package/dist/config/__tests__/generator-status-line-presets.test.d.ts.map +1 -0
  94. package/dist/config/__tests__/generator-status-line-presets.test.js +203 -0
  95. package/dist/config/__tests__/generator-status-line-presets.test.js.map +1 -0
  96. package/dist/config/__tests__/models.test.js +23 -1
  97. package/dist/config/__tests__/models.test.js.map +1 -1
  98. package/dist/config/generator.d.ts +9 -1
  99. package/dist/config/generator.d.ts.map +1 -1
  100. package/dist/config/generator.js +184 -16
  101. package/dist/config/generator.js.map +1 -1
  102. package/dist/config/models.d.ts +5 -1
  103. package/dist/config/models.d.ts.map +1 -1
  104. package/dist/config/models.js +12 -2
  105. package/dist/config/models.js.map +1 -1
  106. package/dist/exec/followup.d.ts +44 -0
  107. package/dist/exec/followup.d.ts.map +1 -0
  108. package/dist/exec/followup.js +349 -0
  109. package/dist/exec/followup.js.map +1 -0
  110. package/dist/hooks/__tests__/autopilot-skill-contract.test.d.ts +2 -0
  111. package/dist/hooks/__tests__/autopilot-skill-contract.test.d.ts.map +1 -0
  112. package/dist/hooks/__tests__/autopilot-skill-contract.test.js +37 -0
  113. package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -0
  114. package/dist/hooks/__tests__/codebase-map.test.js +63 -1
  115. package/dist/hooks/__tests__/codebase-map.test.js.map +1 -1
  116. package/dist/hooks/__tests__/consensus-execution-handoff.test.d.ts +1 -1
  117. package/dist/hooks/__tests__/consensus-execution-handoff.test.js +5 -5
  118. package/dist/hooks/__tests__/consensus-execution-handoff.test.js.map +1 -1
  119. package/dist/hooks/__tests__/deep-interview-contract.test.js +12 -9
  120. package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
  121. package/dist/hooks/__tests__/keyword-detector.test.js +25 -18
  122. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  123. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +23 -2
  124. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  125. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +45 -2
  126. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  127. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +17 -0
  128. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
  129. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +121 -0
  130. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
  131. package/dist/hooks/__tests__/notify-hook-regression-205.test.js +4 -4
  132. package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
  133. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +103 -0
  134. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  135. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +2 -2
  136. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  137. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +27 -13
  138. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  139. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.d.ts +2 -0
  140. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.d.ts.map +1 -0
  141. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js +35 -0
  142. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js.map +1 -0
  143. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +215 -0
  144. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  145. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +70 -3
  146. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  147. package/dist/hooks/__tests__/pre-context-gate-skills.test.js +5 -0
  148. package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -1
  149. package/dist/hooks/__tests__/prompt-guidance-fragments.test.js +3 -2
  150. package/dist/hooks/__tests__/prompt-guidance-fragments.test.js.map +1 -1
  151. package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +9 -0
  152. package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +1 -1
  153. package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts +2 -0
  154. package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts.map +1 -0
  155. package/dist/hooks/__tests__/prompt-refactor-contract.test.js +22 -0
  156. package/dist/hooks/__tests__/prompt-refactor-contract.test.js.map +1 -0
  157. package/dist/hooks/codebase-map.d.ts.map +1 -1
  158. package/dist/hooks/codebase-map.js +83 -6
  159. package/dist/hooks/codebase-map.js.map +1 -1
  160. package/dist/hooks/keyword-detector.d.ts +1 -1
  161. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  162. package/dist/hooks/keyword-detector.js +35 -4
  163. package/dist/hooks/keyword-detector.js.map +1 -1
  164. package/dist/hooks/prompt-guidance-contract.d.ts +6 -0
  165. package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
  166. package/dist/hooks/prompt-guidance-contract.js +117 -13
  167. package/dist/hooks/prompt-guidance-contract.js.map +1 -1
  168. package/dist/hooks/session.d.ts +2 -0
  169. package/dist/hooks/session.d.ts.map +1 -1
  170. package/dist/hooks/session.js +6 -0
  171. package/dist/hooks/session.js.map +1 -1
  172. package/dist/hud/__tests__/index.test.js +4 -4
  173. package/dist/hud/__tests__/index.test.js.map +1 -1
  174. package/dist/hud/__tests__/state.test.js +4 -0
  175. package/dist/hud/__tests__/state.test.js.map +1 -1
  176. package/dist/hud/__tests__/types.test.js +27 -0
  177. package/dist/hud/__tests__/types.test.js.map +1 -1
  178. package/dist/hud/state.d.ts.map +1 -1
  179. package/dist/hud/state.js +8 -0
  180. package/dist/hud/state.js.map +1 -1
  181. package/dist/hud/types.d.ts +9 -0
  182. package/dist/hud/types.d.ts.map +1 -1
  183. package/dist/hud/types.js +3 -0
  184. package/dist/hud/types.js.map +1 -1
  185. package/dist/mcp/__tests__/bootstrap.test.js +23 -5
  186. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  187. package/dist/mcp/__tests__/server-lifecycle.test.js +50 -7
  188. package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
  189. package/dist/mcp/__tests__/state-server.test.js +70 -12
  190. package/dist/mcp/__tests__/state-server.test.js.map +1 -1
  191. package/dist/mcp/bootstrap.d.ts +10 -1
  192. package/dist/mcp/bootstrap.d.ts.map +1 -1
  193. package/dist/mcp/bootstrap.js +71 -26
  194. package/dist/mcp/bootstrap.js.map +1 -1
  195. package/dist/mcp/state-server.d.ts +5 -11
  196. package/dist/mcp/state-server.d.ts.map +1 -1
  197. package/dist/mcp/state-server.js +16 -432
  198. package/dist/mcp/state-server.js.map +1 -1
  199. package/dist/modes/__tests__/base-autoresearch-contract.test.js +1 -1
  200. package/dist/modes/__tests__/base-autoresearch-contract.test.js.map +1 -1
  201. package/dist/pipeline/__tests__/orchestrator.test.js +89 -5
  202. package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
  203. package/dist/pipeline/__tests__/stages.test.js +98 -1
  204. package/dist/pipeline/__tests__/stages.test.js.map +1 -1
  205. package/dist/pipeline/index.d.ts +5 -3
  206. package/dist/pipeline/index.d.ts.map +1 -1
  207. package/dist/pipeline/index.js +4 -3
  208. package/dist/pipeline/index.js.map +1 -1
  209. package/dist/pipeline/orchestrator.d.ts +7 -6
  210. package/dist/pipeline/orchestrator.d.ts.map +1 -1
  211. package/dist/pipeline/orchestrator.js +90 -11
  212. package/dist/pipeline/orchestrator.js.map +1 -1
  213. package/dist/pipeline/review-verdict.d.ts +3 -0
  214. package/dist/pipeline/review-verdict.d.ts.map +1 -0
  215. package/dist/pipeline/review-verdict.js +14 -0
  216. package/dist/pipeline/review-verdict.js.map +1 -0
  217. package/dist/pipeline/stages/code-review.d.ts +33 -0
  218. package/dist/pipeline/stages/code-review.d.ts.map +1 -0
  219. package/dist/pipeline/stages/code-review.js +51 -0
  220. package/dist/pipeline/stages/code-review.js.map +1 -0
  221. package/dist/pipeline/stages/ralph-verify.d.ts +12 -2
  222. package/dist/pipeline/stages/ralph-verify.d.ts.map +1 -1
  223. package/dist/pipeline/stages/ralph-verify.js +24 -6
  224. package/dist/pipeline/stages/ralph-verify.js.map +1 -1
  225. package/dist/pipeline/stages/ralplan.d.ts +1 -1
  226. package/dist/pipeline/stages/ralplan.d.ts.map +1 -1
  227. package/dist/pipeline/stages/ralplan.js +21 -1
  228. package/dist/pipeline/stages/ralplan.js.map +1 -1
  229. package/dist/pipeline/types.d.ts +14 -7
  230. package/dist/pipeline/types.d.ts.map +1 -1
  231. package/dist/pipeline/types.js +2 -2
  232. package/dist/planning/__tests__/artifacts.test.js +152 -1
  233. package/dist/planning/__tests__/artifacts.test.js.map +1 -1
  234. package/dist/planning/artifacts.d.ts +9 -0
  235. package/dist/planning/artifacts.d.ts.map +1 -1
  236. package/dist/planning/artifacts.js +60 -1
  237. package/dist/planning/artifacts.js.map +1 -1
  238. package/dist/question/__tests__/client.test.js +23 -3
  239. package/dist/question/__tests__/client.test.js.map +1 -1
  240. package/dist/question/__tests__/renderer.test.js +148 -37
  241. package/dist/question/__tests__/renderer.test.js.map +1 -1
  242. package/dist/question/__tests__/types.test.js +21 -0
  243. package/dist/question/__tests__/types.test.js.map +1 -1
  244. package/dist/question/__tests__/ui.test.js +155 -7
  245. package/dist/question/__tests__/ui.test.js.map +1 -1
  246. package/dist/question/client.d.ts +14 -4
  247. package/dist/question/client.d.ts.map +1 -1
  248. package/dist/question/client.js.map +1 -1
  249. package/dist/question/renderer.d.ts +11 -1
  250. package/dist/question/renderer.d.ts.map +1 -1
  251. package/dist/question/renderer.js +102 -7
  252. package/dist/question/renderer.js.map +1 -1
  253. package/dist/question/state.d.ts +2 -2
  254. package/dist/question/state.d.ts.map +1 -1
  255. package/dist/question/state.js +26 -17
  256. package/dist/question/state.js.map +1 -1
  257. package/dist/question/types.d.ts +25 -1
  258. package/dist/question/types.d.ts.map +1 -1
  259. package/dist/question/types.js +48 -13
  260. package/dist/question/types.js.map +1 -1
  261. package/dist/question/ui.d.ts +15 -2
  262. package/dist/question/ui.d.ts.map +1 -1
  263. package/dist/question/ui.js +268 -162
  264. package/dist/question/ui.js.map +1 -1
  265. package/dist/scripts/__tests__/codex-native-hook.test.js +415 -94
  266. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  267. package/dist/scripts/__tests__/generate-release-body.test.js +36 -0
  268. package/dist/scripts/__tests__/generate-release-body.test.js.map +1 -1
  269. package/dist/scripts/__tests__/prompt-inventory.test.d.ts +2 -0
  270. package/dist/scripts/__tests__/prompt-inventory.test.d.ts.map +1 -0
  271. package/dist/scripts/__tests__/prompt-inventory.test.js +56 -0
  272. package/dist/scripts/__tests__/prompt-inventory.test.js.map +1 -0
  273. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  274. package/dist/scripts/codex-native-hook.js +232 -54
  275. package/dist/scripts/codex-native-hook.js.map +1 -1
  276. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
  277. package/dist/scripts/codex-native-pre-post.js +12 -9
  278. package/dist/scripts/codex-native-pre-post.js.map +1 -1
  279. package/dist/scripts/generate-release-body.d.ts.map +1 -1
  280. package/dist/scripts/generate-release-body.js +12 -3
  281. package/dist/scripts/generate-release-body.js.map +1 -1
  282. package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts +2 -0
  283. package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts.map +1 -0
  284. package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js +153 -0
  285. package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js.map +1 -0
  286. package/dist/scripts/notify-hook/managed-tmux.d.ts +4 -2
  287. package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
  288. package/dist/scripts/notify-hook/managed-tmux.js +188 -6
  289. package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
  290. package/dist/scripts/notify-hook/process-runner.d.ts.map +1 -1
  291. package/dist/scripts/notify-hook/process-runner.js +7 -3
  292. package/dist/scripts/notify-hook/process-runner.js.map +1 -1
  293. package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
  294. package/dist/scripts/notify-hook/team-dispatch.js +96 -11
  295. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  296. package/dist/scripts/notify-hook/team-tmux-guard.js +3 -3
  297. package/dist/scripts/notify-hook/team-worker-posttooluse.d.ts +34 -0
  298. package/dist/scripts/notify-hook/team-worker-posttooluse.d.ts.map +1 -0
  299. package/dist/scripts/notify-hook/team-worker-posttooluse.js +434 -0
  300. package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -0
  301. package/dist/scripts/notify-hook/team-worker.d.ts +1 -1
  302. package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
  303. package/dist/scripts/notify-hook/team-worker.js +3 -43
  304. package/dist/scripts/notify-hook/team-worker.js.map +1 -1
  305. package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
  306. package/dist/scripts/notify-hook/tmux-injection.js +25 -4
  307. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  308. package/dist/scripts/notify-hook.js +36 -5
  309. package/dist/scripts/notify-hook.js.map +1 -1
  310. package/dist/scripts/prompt-inventory.d.ts +29 -0
  311. package/dist/scripts/prompt-inventory.d.ts.map +1 -0
  312. package/dist/scripts/prompt-inventory.js +178 -0
  313. package/dist/scripts/prompt-inventory.js.map +1 -0
  314. package/dist/scripts/run-test-files.js +1 -0
  315. package/dist/scripts/run-test-files.js.map +1 -1
  316. package/dist/sidecar/__tests__/boundary.test.d.ts +2 -0
  317. package/dist/sidecar/__tests__/boundary.test.d.ts.map +1 -0
  318. package/dist/sidecar/__tests__/boundary.test.js +48 -0
  319. package/dist/sidecar/__tests__/boundary.test.js.map +1 -0
  320. package/dist/sidecar/__tests__/collector.test.d.ts +2 -0
  321. package/dist/sidecar/__tests__/collector.test.d.ts.map +1 -0
  322. package/dist/sidecar/__tests__/collector.test.js +162 -0
  323. package/dist/sidecar/__tests__/collector.test.js.map +1 -0
  324. package/dist/sidecar/__tests__/render.test.d.ts +2 -0
  325. package/dist/sidecar/__tests__/render.test.d.ts.map +1 -0
  326. package/dist/sidecar/__tests__/render.test.js +67 -0
  327. package/dist/sidecar/__tests__/render.test.js.map +1 -0
  328. package/dist/sidecar/__tests__/tmux.test.d.ts +2 -0
  329. package/dist/sidecar/__tests__/tmux.test.d.ts.map +1 -0
  330. package/dist/sidecar/__tests__/tmux.test.js +30 -0
  331. package/dist/sidecar/__tests__/tmux.test.js.map +1 -0
  332. package/dist/sidecar/__tests__/watch.test.d.ts +2 -0
  333. package/dist/sidecar/__tests__/watch.test.d.ts.map +1 -0
  334. package/dist/sidecar/__tests__/watch.test.js +42 -0
  335. package/dist/sidecar/__tests__/watch.test.js.map +1 -0
  336. package/dist/sidecar/collector.d.ts +4 -0
  337. package/dist/sidecar/collector.d.ts.map +1 -0
  338. package/dist/sidecar/collector.js +377 -0
  339. package/dist/sidecar/collector.js.map +1 -0
  340. package/dist/sidecar/index.d.ts +25 -0
  341. package/dist/sidecar/index.d.ts.map +1 -0
  342. package/dist/sidecar/index.js +165 -0
  343. package/dist/sidecar/index.js.map +1 -0
  344. package/dist/sidecar/render.d.ts +3 -0
  345. package/dist/sidecar/render.d.ts.map +1 -0
  346. package/dist/sidecar/render.js +72 -0
  347. package/dist/sidecar/render.js.map +1 -0
  348. package/dist/sidecar/tmux.d.ts +13 -0
  349. package/dist/sidecar/tmux.d.ts.map +1 -0
  350. package/dist/sidecar/tmux.js +44 -0
  351. package/dist/sidecar/tmux.js.map +1 -0
  352. package/dist/sidecar/types.d.ts +125 -0
  353. package/dist/sidecar/types.d.ts.map +1 -0
  354. package/dist/sidecar/types.js +2 -0
  355. package/dist/sidecar/types.js.map +1 -0
  356. package/dist/state/__tests__/operations.test.js +50 -22
  357. package/dist/state/__tests__/operations.test.js.map +1 -1
  358. package/dist/state/__tests__/workflow-transition.test.js +9 -1
  359. package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
  360. package/dist/state/operations.d.ts +1 -1
  361. package/dist/state/operations.d.ts.map +1 -1
  362. package/dist/state/operations.js +19 -7
  363. package/dist/state/operations.js.map +1 -1
  364. package/dist/state/workflow-transition.d.ts.map +1 -1
  365. package/dist/state/workflow-transition.js +1 -0
  366. package/dist/state/workflow-transition.js.map +1 -1
  367. package/dist/team/__tests__/commit-hygiene.test.d.ts +2 -0
  368. package/dist/team/__tests__/commit-hygiene.test.d.ts.map +1 -0
  369. package/dist/team/__tests__/commit-hygiene.test.js +93 -0
  370. package/dist/team/__tests__/commit-hygiene.test.js.map +1 -0
  371. package/dist/team/__tests__/delegation-policy.test.d.ts +2 -0
  372. package/dist/team/__tests__/delegation-policy.test.d.ts.map +1 -0
  373. package/dist/team/__tests__/delegation-policy.test.js +69 -0
  374. package/dist/team/__tests__/delegation-policy.test.js.map +1 -0
  375. package/dist/team/__tests__/events.test.js +54 -4
  376. package/dist/team/__tests__/events.test.js.map +1 -1
  377. package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts +2 -0
  378. package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts.map +1 -0
  379. package/dist/team/__tests__/hook-primary-e2e-contract.test.js +78 -0
  380. package/dist/team/__tests__/hook-primary-e2e-contract.test.js.map +1 -0
  381. package/dist/team/__tests__/model-contract.test.js +16 -0
  382. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  383. package/dist/team/__tests__/repo-aware-decomposition.test.d.ts +2 -0
  384. package/dist/team/__tests__/repo-aware-decomposition.test.d.ts.map +1 -0
  385. package/dist/team/__tests__/repo-aware-decomposition.test.js +95 -0
  386. package/dist/team/__tests__/repo-aware-decomposition.test.js.map +1 -0
  387. package/dist/team/__tests__/runtime.test.js +623 -14
  388. package/dist/team/__tests__/runtime.test.js.map +1 -1
  389. package/dist/team/__tests__/state-root.test.js +177 -1
  390. package/dist/team/__tests__/state-root.test.js.map +1 -1
  391. package/dist/team/__tests__/state.test.js +110 -0
  392. package/dist/team/__tests__/state.test.js.map +1 -1
  393. package/dist/team/__tests__/tmux-session.test.js +399 -2
  394. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  395. package/dist/team/__tests__/worker-bootstrap.test.js +94 -0
  396. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  397. package/dist/team/commit-hygiene.d.ts +22 -3
  398. package/dist/team/commit-hygiene.d.ts.map +1 -1
  399. package/dist/team/commit-hygiene.js +134 -2
  400. package/dist/team/commit-hygiene.js.map +1 -1
  401. package/dist/team/contracts.d.ts +1 -1
  402. package/dist/team/contracts.d.ts.map +1 -1
  403. package/dist/team/contracts.js +2 -0
  404. package/dist/team/contracts.js.map +1 -1
  405. package/dist/team/dag-schema.d.ts +38 -0
  406. package/dist/team/dag-schema.d.ts.map +1 -0
  407. package/dist/team/dag-schema.js +221 -0
  408. package/dist/team/dag-schema.js.map +1 -0
  409. package/dist/team/delegation-policy.d.ts +3 -0
  410. package/dist/team/delegation-policy.d.ts.map +1 -0
  411. package/dist/team/delegation-policy.js +82 -0
  412. package/dist/team/delegation-policy.js.map +1 -0
  413. package/dist/team/model-contract.d.ts +3 -1
  414. package/dist/team/model-contract.d.ts.map +1 -1
  415. package/dist/team/model-contract.js +44 -5
  416. package/dist/team/model-contract.js.map +1 -1
  417. package/dist/team/repo-aware-decomposition.d.ts +60 -0
  418. package/dist/team/repo-aware-decomposition.d.ts.map +1 -0
  419. package/dist/team/repo-aware-decomposition.js +229 -0
  420. package/dist/team/repo-aware-decomposition.js.map +1 -0
  421. package/dist/team/runtime.d.ts +27 -0
  422. package/dist/team/runtime.d.ts.map +1 -1
  423. package/dist/team/runtime.js +172 -52
  424. package/dist/team/runtime.js.map +1 -1
  425. package/dist/team/state/tasks.d.ts.map +1 -1
  426. package/dist/team/state/tasks.js +33 -0
  427. package/dist/team/state/tasks.js.map +1 -1
  428. package/dist/team/state/types.d.ts +23 -1
  429. package/dist/team/state/types.d.ts.map +1 -1
  430. package/dist/team/state/types.js.map +1 -1
  431. package/dist/team/state-root.d.ts +35 -0
  432. package/dist/team/state-root.d.ts.map +1 -1
  433. package/dist/team/state-root.js +281 -1
  434. package/dist/team/state-root.js.map +1 -1
  435. package/dist/team/state.d.ts +27 -1
  436. package/dist/team/state.d.ts.map +1 -1
  437. package/dist/team/state.js +6 -0
  438. package/dist/team/state.js.map +1 -1
  439. package/dist/team/tmux-session.d.ts +1 -0
  440. package/dist/team/tmux-session.d.ts.map +1 -1
  441. package/dist/team/tmux-session.js +105 -6
  442. package/dist/team/tmux-session.js.map +1 -1
  443. package/dist/team/worker-bootstrap.d.ts +3 -0
  444. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  445. package/dist/team/worker-bootstrap.js +77 -4
  446. package/dist/team/worker-bootstrap.js.map +1 -1
  447. package/dist/utils/agents-md.d.ts +3 -0
  448. package/dist/utils/agents-md.d.ts.map +1 -1
  449. package/dist/utils/agents-md.js +25 -0
  450. package/dist/utils/agents-md.js.map +1 -1
  451. package/package.json +3 -2
  452. package/plugins/oh-my-codex/.codex-plugin/plugin.json +2 -2
  453. package/plugins/oh-my-codex/skills/ai-slop-cleaner/SKILL.md +1 -1
  454. package/plugins/oh-my-codex/skills/analyze/SKILL.md +1 -1
  455. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +134 -205
  456. package/plugins/oh-my-codex/skills/code-review/SKILL.md +4 -4
  457. package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +14 -7
  458. package/plugins/oh-my-codex/skills/doctor/SKILL.md +1 -1
  459. package/plugins/oh-my-codex/skills/help/SKILL.md +1 -1
  460. package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +41 -10
  461. package/plugins/oh-my-codex/skills/plan/SKILL.md +12 -14
  462. package/plugins/oh-my-codex/skills/ralph/SKILL.md +2 -4
  463. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +5 -9
  464. package/plugins/oh-my-codex/skills/security-review/SKILL.md +4 -4
  465. package/plugins/oh-my-codex/skills/team/SKILL.md +2 -5
  466. package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +2 -5
  467. package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +2 -3
  468. package/prompts/analyst.md +2 -2
  469. package/prompts/api-reviewer.md +2 -2
  470. package/prompts/architect.md +2 -2
  471. package/prompts/build-fixer.md +2 -2
  472. package/prompts/code-reviewer.md +15 -5
  473. package/prompts/code-simplifier.md +1 -1
  474. package/prompts/critic.md +35 -83
  475. package/prompts/debugger.md +2 -2
  476. package/prompts/dependency-expert.md +2 -2
  477. package/prompts/designer.md +2 -2
  478. package/prompts/executor.md +40 -114
  479. package/prompts/explore-harness.md +1 -1
  480. package/prompts/explore.md +37 -90
  481. package/prompts/git-master.md +2 -2
  482. package/prompts/information-architect.md +1 -1
  483. package/prompts/performance-reviewer.md +2 -2
  484. package/prompts/planner.md +35 -62
  485. package/prompts/product-analyst.md +2 -2
  486. package/prompts/product-manager.md +2 -2
  487. package/prompts/qa-tester.md +2 -2
  488. package/prompts/quality-reviewer.md +2 -2
  489. package/prompts/quality-strategist.md +2 -2
  490. package/prompts/researcher.md +46 -78
  491. package/prompts/security-reviewer.md +2 -2
  492. package/prompts/sisyphus-lite.md +2 -2
  493. package/prompts/style-reviewer.md +2 -2
  494. package/prompts/team-executor.md +1 -1
  495. package/prompts/test-engineer.md +2 -2
  496. package/prompts/ux-researcher.md +2 -2
  497. package/prompts/verifier.md +29 -34
  498. package/prompts/vision.md +2 -2
  499. package/prompts/writer.md +2 -2
  500. package/skills/ai-slop-cleaner/SKILL.md +1 -1
  501. package/skills/analyze/SKILL.md +1 -1
  502. package/skills/autopilot/SKILL.md +134 -205
  503. package/skills/build-fix/SKILL.md +4 -4
  504. package/skills/code-review/SKILL.md +4 -4
  505. package/skills/deep-interview/SKILL.md +14 -7
  506. package/skills/doctor/SKILL.md +1 -1
  507. package/skills/help/SKILL.md +1 -1
  508. package/skills/omx-setup/SKILL.md +41 -10
  509. package/skills/plan/SKILL.md +12 -14
  510. package/skills/ralph/SKILL.md +2 -4
  511. package/skills/ralplan/SKILL.md +5 -9
  512. package/skills/security-review/SKILL.md +4 -4
  513. package/skills/team/SKILL.md +2 -5
  514. package/skills/ultraqa/SKILL.md +2 -5
  515. package/skills/ultrawork/SKILL.md +2 -3
  516. package/src/scripts/__tests__/codex-native-hook.test.ts +502 -94
  517. package/src/scripts/__tests__/generate-release-body.test.ts +41 -0
  518. package/src/scripts/__tests__/prompt-inventory.test.ts +64 -0
  519. package/src/scripts/codex-native-hook.ts +293 -61
  520. package/src/scripts/codex-native-pre-post.ts +10 -8
  521. package/src/scripts/generate-release-body.ts +13 -2
  522. package/src/scripts/notify-hook/__tests__/team-worker-posttooluse.test.ts +180 -0
  523. package/src/scripts/notify-hook/managed-tmux.ts +196 -9
  524. package/src/scripts/notify-hook/process-runner.ts +7 -3
  525. package/src/scripts/notify-hook/team-dispatch.ts +103 -11
  526. package/src/scripts/notify-hook/team-tmux-guard.ts +3 -3
  527. package/src/scripts/notify-hook/team-worker-posttooluse.ts +536 -0
  528. package/src/scripts/notify-hook/team-worker.ts +4 -48
  529. package/src/scripts/notify-hook/tmux-injection.ts +24 -6
  530. package/src/scripts/notify-hook.ts +36 -5
  531. package/src/scripts/prompt-inventory.ts +218 -0
  532. package/src/scripts/run-test-files.ts +1 -0
  533. package/templates/AGENTS.md +34 -95
@@ -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());
@@ -211,6 +211,28 @@ export async function resolvePaneTarget(target: any, expectedCwd: any, modePane:
211
211
  return { paneTarget: null, reason: managedContext.reason || 'unmanaged_session' };
212
212
  }
213
213
 
214
+ const taggedSessionTarget = safeString(managedContext.taggedTmuxSessionName).trim();
215
+ if (taggedSessionTarget) {
216
+ try {
217
+ const paneId = await resolveSessionToPane(taggedSessionTarget);
218
+ if (paneId) {
219
+ const resolved = await finalizeResolvedPane(paneId, 'managed_instance_target', expectedCwd);
220
+ if (!resolved.paneTarget) return resolved;
221
+ const ownership = await verifyManagedPaneTarget(resolved.paneTarget, cwd, payload, { allowTeamWorker: false });
222
+ if (ownership.ok) {
223
+ return {
224
+ ...resolved,
225
+ source: 'managed_instance',
226
+ healTarget: true,
227
+ };
228
+ }
229
+ return { paneTarget: null, reason: ownership.reason || 'pane_not_managed_session' };
230
+ }
231
+ } catch {
232
+ // Fall through to legacy pane/session targets.
233
+ }
234
+ }
235
+
214
236
  const canonicalModePane = safeString(modePane).trim();
215
237
  if (canonicalModePane) {
216
238
  try {
@@ -262,7 +284,7 @@ export async function resolvePaneTarget(target: any, expectedCwd: any, modePane:
262
284
  try {
263
285
  if (!requiresManagedOwnership) return { paneTarget: null, reason: 'target_session_requires_managed_context' };
264
286
  const explicitSessionTarget = safeString(target.value).trim();
265
- const expectedSessionTarget = safeString(managedContext.expectedTmuxSessionName).trim();
287
+ const expectedSessionTarget = safeString(managedContext.taggedTmuxSessionName || managedContext.expectedTmuxSessionName).trim();
266
288
  const sessionIdTarget = safeString(managedContext.invocationSessionId).trim();
267
289
  const stateSessionTarget = safeString(managedContext.sessionState?.session_id).trim();
268
290
  const nativeSessionTarget = safeString(managedContext.nativeSessionId).trim();
@@ -440,11 +462,7 @@ export async function handleTmuxInjection({
440
462
  }), sourceText);
441
463
  const preferredPaneTarget = modePane || await resolveManagedCurrentPane(cwd, payload, { allowTeamWorker: false });
442
464
  let resolution = preferredModePane
443
- ? await resolveCanonicalPaneFromPaneTarget(preferredModePane.pane, cwd).then((resolved) => (
444
- resolved.paneTarget
445
- ? { ...resolved, reason: 'fallback_mode_state_pane', source: 'mode_state', healTarget: true }
446
- : resolved
447
- ))
465
+ ? await resolvePaneTarget({ type: 'pane', value: preferredModePane.pane }, cwd, preferredModePane.pane, cwd, payload)
448
466
  : preferredPaneTarget
449
467
  ? await resolvePaneTarget({ type: 'pane', value: preferredPaneTarget }, cwd, '', cwd, payload)
450
468
  : await resolvePaneTarget(config.target, cwd, modePane, cwd, payload);