oh-my-copilot 5.6.2 → 5.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +2 -0
  4. package/bridge/__pycache__/gyoshu_bridge.cpython-312.pyc +0 -0
  5. package/bridge/claude-md-coordinator.cjs +2 -2
  6. package/bridge/cli.cjs +81405 -76559
  7. package/bridge/mcp-server.cjs +40048 -32187
  8. package/bridge/runtime-cli.cjs +943 -199
  9. package/bridge/team-mcp.cjs +716 -125
  10. package/bridge/team.js +1066 -290
  11. package/dist/__tests__/cli-win32-warning.test.js +7 -0
  12. package/dist/__tests__/cli-win32-warning.test.js.map +1 -1
  13. package/dist/__tests__/run-cjs-copilot-worker-routing.test.d.ts +2 -0
  14. package/dist/__tests__/run-cjs-copilot-worker-routing.test.d.ts.map +1 -0
  15. package/dist/__tests__/run-cjs-copilot-worker-routing.test.js +294 -0
  16. package/dist/__tests__/run-cjs-copilot-worker-routing.test.js.map +1 -0
  17. package/dist/__tests__/run-cjs-fail-closed-timeout.test.d.ts +2 -0
  18. package/dist/__tests__/run-cjs-fail-closed-timeout.test.d.ts.map +1 -0
  19. package/dist/__tests__/run-cjs-fail-closed-timeout.test.js +68 -0
  20. package/dist/__tests__/run-cjs-fail-closed-timeout.test.js.map +1 -0
  21. package/dist/__tests__/run-cjs-session-end-budget.test.d.ts +2 -0
  22. package/dist/__tests__/run-cjs-session-end-budget.test.d.ts.map +1 -0
  23. package/dist/__tests__/run-cjs-session-end-budget.test.js +171 -0
  24. package/dist/__tests__/run-cjs-session-end-budget.test.js.map +1 -0
  25. package/dist/__tests__/session-end-process-exit.test.js +70 -2
  26. package/dist/__tests__/session-end-process-exit.test.js.map +1 -1
  27. package/dist/cli/__tests__/doctor-conflicts-json.test.d.ts +2 -0
  28. package/dist/cli/__tests__/doctor-conflicts-json.test.d.ts.map +1 -0
  29. package/dist/cli/__tests__/doctor-conflicts-json.test.js +46 -0
  30. package/dist/cli/__tests__/doctor-conflicts-json.test.js.map +1 -0
  31. package/dist/cli/__tests__/team.test.js +67 -0
  32. package/dist/cli/__tests__/team.test.js.map +1 -1
  33. package/dist/cli/__tests__/wait-teleport-json.test.d.ts +2 -0
  34. package/dist/cli/__tests__/wait-teleport-json.test.d.ts.map +1 -0
  35. package/dist/cli/__tests__/wait-teleport-json.test.js +64 -0
  36. package/dist/cli/__tests__/wait-teleport-json.test.js.map +1 -0
  37. package/dist/cli/commands/__tests__/smoke-tier2.test.d.ts +2 -0
  38. package/dist/cli/commands/__tests__/smoke-tier2.test.d.ts.map +1 -0
  39. package/dist/cli/commands/__tests__/smoke-tier2.test.js +110 -0
  40. package/dist/cli/commands/__tests__/smoke-tier2.test.js.map +1 -0
  41. package/dist/cli/commands/__tests__/team-status-json.test.d.ts +2 -0
  42. package/dist/cli/commands/__tests__/team-status-json.test.d.ts.map +1 -0
  43. package/dist/cli/commands/__tests__/team-status-json.test.js +141 -0
  44. package/dist/cli/commands/__tests__/team-status-json.test.js.map +1 -0
  45. package/dist/cli/commands/factory.d.ts +2 -0
  46. package/dist/cli/commands/factory.d.ts.map +1 -1
  47. package/dist/cli/commands/factory.js +8 -1
  48. package/dist/cli/commands/factory.js.map +1 -1
  49. package/dist/cli/commands/smoke.d.ts +36 -0
  50. package/dist/cli/commands/smoke.d.ts.map +1 -0
  51. package/dist/cli/commands/smoke.js +169 -0
  52. package/dist/cli/commands/smoke.js.map +1 -0
  53. package/dist/cli/commands/team.d.ts +2 -0
  54. package/dist/cli/commands/team.d.ts.map +1 -1
  55. package/dist/cli/commands/team.js +124 -10
  56. package/dist/cli/commands/team.js.map +1 -1
  57. package/dist/cli/index.d.ts.map +1 -1
  58. package/dist/cli/index.js +70 -10
  59. package/dist/cli/index.js.map +1 -1
  60. package/dist/cli/win32-warning.d.ts +7 -1
  61. package/dist/cli/win32-warning.d.ts.map +1 -1
  62. package/dist/cli/win32-warning.js +9 -1
  63. package/dist/cli/win32-warning.js.map +1 -1
  64. package/dist/constants/names.d.ts +1 -0
  65. package/dist/constants/names.d.ts.map +1 -1
  66. package/dist/constants/names.js +1 -0
  67. package/dist/constants/names.js.map +1 -1
  68. package/dist/factory/__tests__/check-run.test.js +2 -2
  69. package/dist/factory/__tests__/check-run.test.js.map +1 -1
  70. package/dist/factory/__tests__/listener.test.js +1 -1
  71. package/dist/factory/__tests__/listener.test.js.map +1 -1
  72. package/dist/factory/__tests__/status.test.js +42 -0
  73. package/dist/factory/__tests__/status.test.js.map +1 -1
  74. package/dist/factory/listener.d.ts.map +1 -1
  75. package/dist/factory/listener.js +7 -8
  76. package/dist/factory/listener.js.map +1 -1
  77. package/dist/factory/status.d.ts +19 -1
  78. package/dist/factory/status.d.ts.map +1 -1
  79. package/dist/factory/status.js +49 -8
  80. package/dist/factory/status.js.map +1 -1
  81. package/dist/factory/watchdog.d.ts.map +1 -1
  82. package/dist/factory/watchdog.js +14 -0
  83. package/dist/factory/watchdog.js.map +1 -1
  84. package/dist/factory/watchdog.test.js +45 -0
  85. package/dist/factory/watchdog.test.js.map +1 -1
  86. package/dist/hooks/session-end/__tests__/action-runner.test.js +5 -0
  87. package/dist/hooks/session-end/__tests__/action-runner.test.js.map +1 -1
  88. package/dist/hooks/session-end/__tests__/chain-enqueuer.test.js +186 -1
  89. package/dist/hooks/session-end/__tests__/chain-enqueuer.test.js.map +1 -1
  90. package/dist/hooks/session-end/__tests__/chain-link-env-passthrough.test.d.ts +2 -0
  91. package/dist/hooks/session-end/__tests__/chain-link-env-passthrough.test.d.ts.map +1 -0
  92. package/dist/hooks/session-end/__tests__/chain-link-env-passthrough.test.js +49 -0
  93. package/dist/hooks/session-end/__tests__/chain-link-env-passthrough.test.js.map +1 -0
  94. package/dist/hooks/session-end/__tests__/foreground-bootstrap.test.js +30 -1
  95. package/dist/hooks/session-end/__tests__/foreground-bootstrap.test.js.map +1 -1
  96. package/dist/hooks/session-end/__tests__/spawn-next.test.js +104 -3
  97. package/dist/hooks/session-end/__tests__/spawn-next.test.js.map +1 -1
  98. package/dist/hooks/session-end/__tests__/worker.test.js +6 -0
  99. package/dist/hooks/session-end/__tests__/worker.test.js.map +1 -1
  100. package/dist/hooks/session-end/action-runner.d.ts.map +1 -1
  101. package/dist/hooks/session-end/action-runner.js +2 -1
  102. package/dist/hooks/session-end/action-runner.js.map +1 -1
  103. package/dist/hooks/session-end/chain-enqueuer.d.ts +70 -7
  104. package/dist/hooks/session-end/chain-enqueuer.d.ts.map +1 -1
  105. package/dist/hooks/session-end/chain-enqueuer.js +354 -82
  106. package/dist/hooks/session-end/chain-enqueuer.js.map +1 -1
  107. package/dist/hooks/session-end/foreground-bootstrap.d.ts.map +1 -1
  108. package/dist/hooks/session-end/foreground-bootstrap.js +24 -16
  109. package/dist/hooks/session-end/foreground-bootstrap.js.map +1 -1
  110. package/dist/hooks/session-end/index.d.ts +2 -3
  111. package/dist/hooks/session-end/index.d.ts.map +1 -1
  112. package/dist/hooks/session-end/index.js +11 -13
  113. package/dist/hooks/session-end/index.js.map +1 -1
  114. package/dist/hooks/session-end/spawn-next.d.ts +81 -4
  115. package/dist/hooks/session-end/spawn-next.d.ts.map +1 -1
  116. package/dist/hooks/session-end/spawn-next.js +141 -14
  117. package/dist/hooks/session-end/spawn-next.js.map +1 -1
  118. package/dist/hooks/session-end/wiki-foreground-bootstrap.d.ts +17 -0
  119. package/dist/hooks/session-end/wiki-foreground-bootstrap.d.ts.map +1 -0
  120. package/dist/hooks/session-end/wiki-foreground-bootstrap.js +20 -0
  121. package/dist/hooks/session-end/wiki-foreground-bootstrap.js.map +1 -0
  122. package/dist/hooks/session-end/worker.d.ts.map +1 -1
  123. package/dist/hooks/session-end/worker.js +11 -6
  124. package/dist/hooks/session-end/worker.js.map +1 -1
  125. package/dist/lib/__tests__/atomic-write.test.js +32 -1
  126. package/dist/lib/__tests__/atomic-write.test.js.map +1 -1
  127. package/dist/lib/__tests__/mode-state-lock.test.js +121 -12
  128. package/dist/lib/__tests__/mode-state-lock.test.js.map +1 -1
  129. package/dist/lib/atomic-write.d.ts +13 -3
  130. package/dist/lib/atomic-write.d.ts.map +1 -1
  131. package/dist/lib/atomic-write.js +29 -15
  132. package/dist/lib/atomic-write.js.map +1 -1
  133. package/dist/lib/mode-state-io.d.ts +2 -2
  134. package/dist/lib/mode-state-io.d.ts.map +1 -1
  135. package/dist/lib/mode-state-io.js +16 -10
  136. package/dist/lib/mode-state-io.js.map +1 -1
  137. package/dist/mcp/__tests__/host-smoke-tool.test.d.ts +2 -0
  138. package/dist/mcp/__tests__/host-smoke-tool.test.d.ts.map +1 -0
  139. package/dist/mcp/__tests__/host-smoke-tool.test.js +174 -0
  140. package/dist/mcp/__tests__/host-smoke-tool.test.js.map +1 -0
  141. package/dist/mcp/disable-tools.d.ts.map +1 -1
  142. package/dist/mcp/disable-tools.js +1 -0
  143. package/dist/mcp/disable-tools.js.map +1 -1
  144. package/dist/mcp/tool-registry.d.ts.map +1 -1
  145. package/dist/mcp/tool-registry.js +2 -0
  146. package/dist/mcp/tool-registry.js.map +1 -1
  147. package/dist/shared/types.d.ts +11 -0
  148. package/dist/shared/types.d.ts.map +1 -1
  149. package/dist/smoke/__tests__/copilot-chain-scenario.test.d.ts +2 -0
  150. package/dist/smoke/__tests__/copilot-chain-scenario.test.d.ts.map +1 -0
  151. package/dist/smoke/__tests__/copilot-chain-scenario.test.js +154 -0
  152. package/dist/smoke/__tests__/copilot-chain-scenario.test.js.map +1 -0
  153. package/dist/smoke/__tests__/copilot-sdk-driver.test.d.ts +2 -0
  154. package/dist/smoke/__tests__/copilot-sdk-driver.test.d.ts.map +1 -0
  155. package/dist/smoke/__tests__/copilot-sdk-driver.test.js +591 -0
  156. package/dist/smoke/__tests__/copilot-sdk-driver.test.js.map +1 -0
  157. package/dist/smoke/__tests__/copilot-sdk-scenarios.test.d.ts +2 -0
  158. package/dist/smoke/__tests__/copilot-sdk-scenarios.test.d.ts.map +1 -0
  159. package/dist/smoke/__tests__/copilot-sdk-scenarios.test.js +362 -0
  160. package/dist/smoke/__tests__/copilot-sdk-scenarios.test.js.map +1 -0
  161. package/dist/smoke/__tests__/copilot-session-eval.test.d.ts +2 -0
  162. package/dist/smoke/__tests__/copilot-session-eval.test.d.ts.map +1 -0
  163. package/dist/smoke/__tests__/copilot-session-eval.test.js +264 -0
  164. package/dist/smoke/__tests__/copilot-session-eval.test.js.map +1 -0
  165. package/dist/smoke/__tests__/copilot-smoke.test.d.ts +2 -0
  166. package/dist/smoke/__tests__/copilot-smoke.test.d.ts.map +1 -0
  167. package/dist/smoke/__tests__/copilot-smoke.test.js +482 -0
  168. package/dist/smoke/__tests__/copilot-smoke.test.js.map +1 -0
  169. package/dist/smoke/copilot-binary.d.ts +21 -0
  170. package/dist/smoke/copilot-binary.d.ts.map +1 -0
  171. package/dist/smoke/copilot-binary.js +46 -0
  172. package/dist/smoke/copilot-binary.js.map +1 -0
  173. package/dist/smoke/copilot-chain-scenario.d.ts +61 -0
  174. package/dist/smoke/copilot-chain-scenario.d.ts.map +1 -0
  175. package/dist/smoke/copilot-chain-scenario.js +253 -0
  176. package/dist/smoke/copilot-chain-scenario.js.map +1 -0
  177. package/dist/smoke/copilot-sdk-driver.d.ts +189 -0
  178. package/dist/smoke/copilot-sdk-driver.d.ts.map +1 -0
  179. package/dist/smoke/copilot-sdk-driver.js +637 -0
  180. package/dist/smoke/copilot-sdk-driver.js.map +1 -0
  181. package/dist/smoke/copilot-sdk-scenarios.d.ts +200 -0
  182. package/dist/smoke/copilot-sdk-scenarios.d.ts.map +1 -0
  183. package/dist/smoke/copilot-sdk-scenarios.js +620 -0
  184. package/dist/smoke/copilot-sdk-scenarios.js.map +1 -0
  185. package/dist/smoke/copilot-session-env.d.ts +75 -0
  186. package/dist/smoke/copilot-session-env.d.ts.map +1 -0
  187. package/dist/smoke/copilot-session-env.js +154 -0
  188. package/dist/smoke/copilot-session-env.js.map +1 -0
  189. package/dist/smoke/copilot-session-eval.d.ts +90 -0
  190. package/dist/smoke/copilot-session-eval.d.ts.map +1 -0
  191. package/dist/smoke/copilot-session-eval.js +323 -0
  192. package/dist/smoke/copilot-session-eval.js.map +1 -0
  193. package/dist/smoke/copilot-smoke.d.ts +166 -0
  194. package/dist/smoke/copilot-smoke.d.ts.map +1 -0
  195. package/dist/smoke/copilot-smoke.js +688 -0
  196. package/dist/smoke/copilot-smoke.js.map +1 -0
  197. package/dist/smoke/process-utils.d.ts +47 -0
  198. package/dist/smoke/process-utils.d.ts.map +1 -0
  199. package/dist/smoke/process-utils.js +99 -0
  200. package/dist/smoke/process-utils.js.map +1 -0
  201. package/dist/team/__tests__/runtime-v2.monitor.test.js +35 -0
  202. package/dist/team/__tests__/runtime-v2.monitor.test.js.map +1 -1
  203. package/dist/team/__tests__/scaling.test.js +13 -0
  204. package/dist/team/__tests__/scaling.test.js.map +1 -1
  205. package/dist/team/__tests__/sdk-transport.runtime.test.d.ts +2 -0
  206. package/dist/team/__tests__/sdk-transport.runtime.test.d.ts.map +1 -0
  207. package/dist/team/__tests__/sdk-transport.runtime.test.js +96 -0
  208. package/dist/team/__tests__/sdk-transport.runtime.test.js.map +1 -0
  209. package/dist/team/__tests__/sdk-transport.test.d.ts +2 -0
  210. package/dist/team/__tests__/sdk-transport.test.d.ts.map +1 -0
  211. package/dist/team/__tests__/sdk-transport.test.js +650 -0
  212. package/dist/team/__tests__/sdk-transport.test.js.map +1 -0
  213. package/dist/team/__tests__/tmux-session.pane-env.test.d.ts +2 -0
  214. package/dist/team/__tests__/tmux-session.pane-env.test.d.ts.map +1 -0
  215. package/dist/team/__tests__/tmux-session.pane-env.test.js +52 -0
  216. package/dist/team/__tests__/tmux-session.pane-env.test.js.map +1 -0
  217. package/dist/team/api-interop.d.ts.map +1 -1
  218. package/dist/team/api-interop.js +8 -0
  219. package/dist/team/api-interop.js.map +1 -1
  220. package/dist/team/runtime-v2.d.ts +33 -0
  221. package/dist/team/runtime-v2.d.ts.map +1 -1
  222. package/dist/team/runtime-v2.js +338 -24
  223. package/dist/team/runtime-v2.js.map +1 -1
  224. package/dist/team/scaling.d.ts.map +1 -1
  225. package/dist/team/scaling.js +5 -0
  226. package/dist/team/scaling.js.map +1 -1
  227. package/dist/team/sdk-host.d.ts +48 -0
  228. package/dist/team/sdk-host.d.ts.map +1 -0
  229. package/dist/team/sdk-host.js +604 -0
  230. package/dist/team/sdk-host.js.map +1 -0
  231. package/dist/team/sdk-policy.d.ts +79 -0
  232. package/dist/team/sdk-policy.d.ts.map +1 -0
  233. package/dist/team/sdk-policy.js +186 -0
  234. package/dist/team/sdk-policy.js.map +1 -0
  235. package/dist/team/sdk-transport.d.ts +164 -0
  236. package/dist/team/sdk-transport.d.ts.map +1 -0
  237. package/dist/team/sdk-transport.js +266 -0
  238. package/dist/team/sdk-transport.js.map +1 -0
  239. package/dist/team/tmux-session.d.ts +7 -0
  240. package/dist/team/tmux-session.d.ts.map +1 -1
  241. package/dist/team/tmux-session.js +80 -18
  242. package/dist/team/tmux-session.js.map +1 -1
  243. package/dist/team/types.d.ts +2 -0
  244. package/dist/team/types.d.ts.map +1 -1
  245. package/dist/team/types.js.map +1 -1
  246. package/dist/tools/host-smoke-tool.d.ts +34 -0
  247. package/dist/tools/host-smoke-tool.d.ts.map +1 -0
  248. package/dist/tools/host-smoke-tool.js +133 -0
  249. package/dist/tools/host-smoke-tool.js.map +1 -0
  250. package/docs/CLAUDE.md +1 -1
  251. package/docs/DEVELOPERS.md +122 -0
  252. package/docs/HOOKS.md +34 -2
  253. package/docs/MIGRATION.md +194 -3
  254. package/docs/REFERENCE.md +95 -1
  255. package/docs/TOOLS.md +32 -1
  256. package/package.json +11 -2
  257. package/plugin.json +1 -1
  258. package/scripts/dev/repro-state-lock.mjs +1 -1
  259. package/scripts/lib/atomic-write.mjs +4 -2
  260. package/scripts/lib/state-lock.mjs +21 -12
  261. package/scripts/run.cjs +141 -18
  262. package/scripts/session-start.mjs +13 -0
  263. package/scripts/wiki-session-end.mjs +2 -1
  264. package/templates/hooks/lib/atomic-write.mjs +4 -2
package/bridge/team.js CHANGED
@@ -1751,7 +1751,7 @@ async function withProcessIdentityFileLock(lockPath, fn, timeoutMs = 1e4) {
1751
1751
  continue;
1752
1752
  }
1753
1753
  if (Date.now() >= deadline) throw new Error("process_identity_lock_timeout");
1754
- await new Promise((resolve14) => setTimeout(resolve14, 25));
1754
+ await new Promise((resolve17) => setTimeout(resolve17, 25));
1755
1755
  continue;
1756
1756
  }
1757
1757
  try {
@@ -1772,7 +1772,7 @@ async function withProcessIdentityFileLock(lockPath, fn, timeoutMs = 1e4) {
1772
1772
  }
1773
1773
  }
1774
1774
  if (Date.now() >= deadline) throw new Error("process_identity_lock_timeout");
1775
- await new Promise((resolve14) => setTimeout(resolve14, 25));
1775
+ await new Promise((resolve17) => setTimeout(resolve17, 25));
1776
1776
  }
1777
1777
  }
1778
1778
  return await fn();
@@ -4140,7 +4140,7 @@ async function withMailboxLock(teamName, workerName, cwd, fn) {
4140
4140
  while (Date.now() < deadline) {
4141
4141
  const result = await withLock(lockDir, fn);
4142
4142
  if (result.ok) return result.value;
4143
- await new Promise((resolve14) => setTimeout(resolve14, delayMs));
4143
+ await new Promise((resolve17) => setTimeout(resolve17, delayMs));
4144
4144
  delayMs = Math.min(delayMs * 2, 200);
4145
4145
  }
4146
4146
  throw new Error(`Failed to acquire mailbox lock for ${workerName} after ${timeoutMs}ms`);
@@ -4303,7 +4303,7 @@ async function teamCreateTask(teamName, task, cwd) {
4303
4303
  return taskLock.value;
4304
4304
  });
4305
4305
  if (result.ok) return result.value;
4306
- await new Promise((resolve14) => setTimeout(resolve14, delayMs));
4306
+ await new Promise((resolve17) => setTimeout(resolve17, delayMs));
4307
4307
  delayMs = Math.min(delayMs * 2, 200);
4308
4308
  }
4309
4309
  throw new Error(`Failed to acquire task creation lock for team ${teamName} after ${timeoutMs}ms`);
@@ -4369,7 +4369,7 @@ async function teamUpdateTask(teamName, taskId, updates, cwd) {
4369
4369
  return normalized;
4370
4370
  });
4371
4371
  if (result.ok) return result.value;
4372
- await new Promise((resolve14) => setTimeout(resolve14, delayMs));
4372
+ await new Promise((resolve17) => setTimeout(resolve17, delayMs));
4373
4373
  delayMs = Math.min(delayMs * 2, 200);
4374
4374
  }
4375
4375
  throw new Error(`Failed to acquire task update lock for task ${taskId} in team ${teamName} after ${timeoutMs}ms`);
@@ -4995,7 +4995,7 @@ async function withDispatchLock(teamName, cwd, fn) {
4995
4995
  );
4996
4996
  }
4997
4997
  const jitter = 0.5 + Math.random() * 0.5;
4998
- await new Promise((resolve14) => setTimeout(resolve14, Math.floor(pollMs * jitter)));
4998
+ await new Promise((resolve17) => setTimeout(resolve17, Math.floor(pollMs * jitter)));
4999
4999
  pollMs = Math.min(pollMs * 2, DISPATCH_LOCK_MAX_POLL_MS);
5000
5000
  }
5001
5001
  }
@@ -5660,8 +5660,8 @@ function getPackageDir() {
5660
5660
  }
5661
5661
  }
5662
5662
  try {
5663
- const __filename = fileURLToPath2(import.meta.url);
5664
- const __dirname2 = dirname12(__filename);
5663
+ const __filename2 = fileURLToPath2(import.meta.url);
5664
+ const __dirname2 = dirname12(__filename2);
5665
5665
  const currentDirName = basename6(__dirname2);
5666
5666
  if (currentDirName === "bridge") {
5667
5667
  return join11(__dirname2, "..");
@@ -7662,8 +7662,8 @@ function getPackageDir2() {
7662
7662
  }
7663
7663
  }
7664
7664
  try {
7665
- const __filename = fileURLToPath3(import.meta.url);
7666
- const __dirname2 = dirname16(__filename);
7665
+ const __filename2 = fileURLToPath3(import.meta.url);
7666
+ const __dirname2 = dirname16(__filename2);
7667
7667
  return join16(__dirname2, "..", "..", "..");
7668
7668
  } catch {
7669
7669
  return process.cwd();
@@ -8134,9 +8134,9 @@ function getTrustedPrefixes() {
8134
8134
  function isTrustedPrefix(resolvedPath) {
8135
8135
  const flavor = pathFlavor();
8136
8136
  return getTrustedPrefixes().some((prefix) => {
8137
- const relative9 = flavor.relative(prefix, resolvedPath);
8138
- if (relative9 === "") return true;
8139
- return !relative9.startsWith("..") && !flavor.isAbsolute(relative9);
8137
+ const relative11 = flavor.relative(prefix, resolvedPath);
8138
+ if (relative11 === "") return true;
8139
+ return !relative11.startsWith("..") && !flavor.isAbsolute(relative11);
8140
8140
  });
8141
8141
  }
8142
8142
  function assertBinaryName(binary) {
@@ -8928,6 +8928,45 @@ function parseDeadline(deadlineAt) {
8928
8928
  const value = Date.parse(deadlineAt);
8929
8929
  return Number.isFinite(value) ? value : void 0;
8930
8930
  }
8931
+ async function killProcessTree(pid, signal = "SIGTERM") {
8932
+ if (!Number.isInteger(pid) || pid <= 0) return false;
8933
+ if (process.platform === "win32") {
8934
+ return killProcessTreeWindows(pid, signal === "SIGKILL");
8935
+ } else {
8936
+ return killProcessTreeUnix(pid, signal);
8937
+ }
8938
+ }
8939
+ async function killProcessTreeWindows(pid, force) {
8940
+ try {
8941
+ const args = ["/T", "/PID", String(pid)];
8942
+ if (force) {
8943
+ args.unshift("/F");
8944
+ }
8945
+ execFileSync4("taskkill.exe", args, {
8946
+ stdio: "ignore",
8947
+ timeout: 5e3,
8948
+ windowsHide: true
8949
+ });
8950
+ return true;
8951
+ } catch (err) {
8952
+ const error = err;
8953
+ if (error.status === 128) return true;
8954
+ return false;
8955
+ }
8956
+ }
8957
+ function killProcessTreeUnix(pid, signal) {
8958
+ try {
8959
+ process.kill(-pid, signal);
8960
+ return true;
8961
+ } catch {
8962
+ try {
8963
+ process.kill(pid, signal);
8964
+ return true;
8965
+ } catch {
8966
+ return !isProcessAlive(pid);
8967
+ }
8968
+ }
8969
+ }
8931
8970
  function isProcessAlive(pid) {
8932
8971
  if (!Number.isInteger(pid) || pid <= 0) return false;
8933
8972
  try {
@@ -9197,33 +9236,33 @@ function ensureDirSync(dir) {
9197
9236
  }
9198
9237
  }
9199
9238
  function verifyPrivateTempFile(fd, tempPath, label, operations) {
9200
- const fdStats = fsSync.fstatSync(fd);
9239
+ const fdStats = descriptorStats(fd, operations);
9201
9240
  let pathStats;
9202
9241
  try {
9203
- pathStats = (operations?.lstat ?? fsSync.lstatSync)(tempPath);
9242
+ pathStats = pathnameStats(tempPath, operations);
9204
9243
  } catch {
9205
9244
  throw new Error(`${label} temporary file was replaced before rename`);
9206
9245
  }
9207
9246
  const isWindows = process.platform === "win32";
9208
- const isPrivateRegularSingleLink = (stats) => stats.isFile() && (isWindows ? stats.nlink <= 1 : stats.nlink === 1) && (isWindows || (stats.mode & 511) === 384);
9247
+ const isPrivateRegularSingleLink = (stats) => stats.isFile() && (isWindows ? Number(stats.nlink) <= 1 : Number(stats.nlink) === 1) && (isWindows || (Number(stats.mode) & 511) === 384);
9209
9248
  if (!isPrivateRegularSingleLink(fdStats) || !isPrivateRegularSingleLink(pathStats)) {
9210
9249
  throw new Error(
9211
9250
  `${label} temporary file must be a private regular single-link file`
9212
9251
  );
9213
9252
  }
9214
- if (!sameFileIdentity(fdStats, pathStats)) {
9253
+ if (!sameFileIdentity(fileIdentityOf(fdStats), fileIdentityOf(pathStats))) {
9215
9254
  throw new Error(`${label} temporary file was replaced before rename`);
9216
9255
  }
9217
9256
  }
9218
9257
  function verifyPublishedFile(fd, filePath, label, operations) {
9219
- const fdStats = fsSync.fstatSync(fd);
9258
+ const fdStats = descriptorStats(fd, operations);
9220
9259
  let pathStats;
9221
9260
  try {
9222
- pathStats = (operations?.lstat ?? fsSync.lstatSync)(filePath);
9261
+ pathStats = pathnameStats(filePath, operations);
9223
9262
  } catch {
9224
9263
  throw new Error(`${label} target was replaced at publication`);
9225
9264
  }
9226
- if (!pathStats.isFile() || !sameFileIdentity(fdStats, pathStats)) {
9265
+ if (!pathStats.isFile() || !sameFileIdentity(fileIdentityOf(fdStats), fileIdentityOf(pathStats))) {
9227
9266
  throw new Error(`${label} target was replaced at publication`);
9228
9267
  }
9229
9268
  }
@@ -9247,26 +9286,33 @@ function preservePriorTarget(filePath, operations) {
9247
9286
  return null;
9248
9287
  }
9249
9288
  }
9289
+ function descriptorStats(fd, operations) {
9290
+ return operations ? fsSync.fstatSync(fd) : fsSync.fstatSync(fd, { bigint: true });
9291
+ }
9292
+ function pathnameStats(filePath, operations) {
9293
+ return operations ? operations.lstat(filePath) : fsSync.lstatSync(filePath, { bigint: true });
9294
+ }
9295
+ function fileIdentityOf(stats) {
9296
+ return { dev: BigInt(stats.dev), ino: BigInt(stats.ino) };
9297
+ }
9250
9298
  function sameFileIdentity(a, b) {
9251
9299
  if (a.ino !== b.ino) return false;
9252
9300
  const isWindows = process.platform === "win32";
9253
- if (isWindows && (a.dev === 0 || b.dev === 0)) {
9301
+ if (isWindows && (a.dev === 0n || b.dev === 0n)) {
9254
9302
  return true;
9255
9303
  }
9256
9304
  return a.dev === b.dev;
9257
9305
  }
9258
9306
  function currentFileIdentity(filePath, operations) {
9259
9307
  try {
9260
- const stats = (operations?.lstat ?? fsSync.lstatSync)(filePath);
9261
- return { dev: stats.dev, ino: stats.ino };
9308
+ return fileIdentityOf(pathnameStats(filePath, operations));
9262
9309
  } catch {
9263
9310
  return null;
9264
9311
  }
9265
9312
  }
9266
- function descriptorIdentity(fd) {
9313
+ function descriptorIdentity(fd, operations) {
9267
9314
  try {
9268
- const stats = fsSync.fstatSync(fd);
9269
- return { dev: stats.dev, ino: stats.ino };
9315
+ return fileIdentityOf(descriptorStats(fd, operations));
9270
9316
  } catch {
9271
9317
  return null;
9272
9318
  }
@@ -9545,7 +9591,7 @@ function withFileLockSync(lockPath, fn, opts) {
9545
9591
  }
9546
9592
  }
9547
9593
  function sleep(ms) {
9548
- return new Promise((resolve14) => setTimeout(resolve14, ms));
9594
+ return new Promise((resolve17) => setTimeout(resolve17, ms));
9549
9595
  }
9550
9596
  async function acquireFileLock(lockPath, opts) {
9551
9597
  const staleLockMs = opts?.staleLockMs ?? DEFAULT_STALE_LOCK_MS;
@@ -9643,7 +9689,7 @@ function canonicalAuthorityDigest(input) {
9643
9689
  return createHash7("sha256").update(payload, "utf8").digest("hex");
9644
9690
  }
9645
9691
  function sleep2(ms) {
9646
- return new Promise((resolve14) => setTimeout(resolve14, ms));
9692
+ return new Promise((resolve17) => setTimeout(resolve17, ms));
9647
9693
  }
9648
9694
  function isExactText(value) {
9649
9695
  return typeof value === "string" && value.length > 0 && value === value.trim();
@@ -11506,7 +11552,7 @@ async function bootstrapPersistentOwner(input, priorEpoch) {
11506
11552
  return true;
11507
11553
  }
11508
11554
  if (owner && (owner.epoch > expectedEpoch || owner.epoch === expectedEpoch && owner.pid !== childPid)) return false;
11509
- await new Promise((resolve14) => setTimeout(resolve14, 25));
11555
+ await new Promise((resolve17) => setTimeout(resolve17, 25));
11510
11556
  }
11511
11557
  return false;
11512
11558
  }
@@ -11669,7 +11715,7 @@ function createRecoveryOwnerClient(dispatch, timing = {}) {
11669
11715
  teamName: normalized.teamName,
11670
11716
  workerName: normalized.workerName
11671
11717
  })) return outcome.result;
11672
- await new Promise((resolve14) => setTimeout(resolve14, timing.pollIntervalMs ?? 250));
11718
+ await new Promise((resolve17) => setTimeout(resolve17, timing.pollIntervalMs ?? 250));
11673
11719
  }
11674
11720
  return timeoutResult(normalized, canonical.recovery_id);
11675
11721
  }
@@ -11768,13 +11814,14 @@ __export(tmux_session_exports, {
11768
11814
  waitForPaneReady: () => waitForPaneReady,
11769
11815
  waitForStartupPaneReady: () => waitForStartupPaneReady,
11770
11816
  workerPaneBelongsToOwnedProviderTarget: () => workerPaneBelongsToOwnedProviderTarget,
11771
- workerPaneBelongsToProviderTarget: () => workerPaneBelongsToProviderTarget
11817
+ workerPaneBelongsToProviderTarget: () => workerPaneBelongsToProviderTarget,
11818
+ workerPaneShellCommand: () => workerPaneShellCommand
11772
11819
  });
11773
- import { existsSync as existsSync23, statSync as statSync4 } from "fs";
11820
+ import { existsSync as existsSync23, mkdtempSync, rmSync as rmSync2, statSync as statSync4, writeFileSync as writeFileSync6 } from "fs";
11774
11821
  import { createHash as createHash10, randomUUID as randomUUID14 } from "crypto";
11775
11822
  import { execFile as execFile3 } from "child_process";
11776
11823
  import { promisify as promisify3 } from "util";
11777
- import { join as join25, basename as basename12, isAbsolute as isAbsolute7, win32 as win323 } from "path";
11824
+ import { join as join25, basename as basename12, dirname as dirname22, isAbsolute as isAbsolute7, win32 as win323 } from "path";
11778
11825
  import { tmpdir as tmpdir3 } from "os";
11779
11826
  function tmuxArgsForIdentity(identity, args) {
11780
11827
  return ["-S", identity.socket_path, ...args];
@@ -12649,23 +12696,66 @@ async function verifyWorkerStartCommandSubmitted(paneId, startCmd, opts = {}) {
12649
12696
  }
12650
12697
  return false;
12651
12698
  }
12699
+ function writePaneEnvFile(values) {
12700
+ const directory = mkdtempSync(join25(tmpdir3(), "omc-pane-env-"));
12701
+ const file = join25(directory, "env");
12702
+ const body = Object.entries(values).map(([key, value]) => `export ${key}=${shellQuote(value)}
12703
+ `).join("");
12704
+ writeFileSync6(file, body, { mode: 384, flag: "wx" });
12705
+ return file;
12706
+ }
12707
+ function discardPaneEnvFile(envFile) {
12708
+ if (!envFile) return;
12709
+ rmSync2(dirname22(envFile), { recursive: true, force: true });
12710
+ }
12652
12711
  function workerPaneShellCommand() {
12653
12712
  if (process.platform === "win32" && !isUnixLikeOnWindows()) {
12654
- return [getDefaultShell()];
12713
+ return { args: [getDefaultShell()], envFile: null };
12655
12714
  }
12656
- if (process.platform === "win32") return [];
12715
+ if (process.platform === "win32") return { args: [], envFile: null };
12657
12716
  const shell = getDefaultShell();
12658
12717
  const baseline = buildProviderEnvironment({ SHELL: shell });
12718
+ const inline = buildProviderEnvironment({ SHELL: shell }, process.env, process.platform, []);
12719
+ const passthrough = Object.fromEntries(
12720
+ Object.entries(baseline).filter(([key, value]) => inline[key] !== value)
12721
+ );
12659
12722
  const inheritedPaneEnvironment = ["TERM", "TMUX", "TMUX_PANE", "TMUX_TMPDIR", "LANG", "LC_ALL", "LC_CTYPE"].map((key) => `${key}="$${key}"`);
12723
+ const inlineAssignments = Object.entries(inline).map(([key, value]) => `${key}=${shellQuote(value)}`);
12724
+ if (Object.keys(passthrough).length === 0) {
12725
+ const command2 = [
12726
+ "/usr/bin/env",
12727
+ "-i",
12728
+ ...inlineAssignments,
12729
+ ...inheritedPaneEnvironment,
12730
+ shellQuote(shell),
12731
+ "-l"
12732
+ ].join(" ");
12733
+ return { args: [command2], envFile: null };
12734
+ }
12735
+ const envFile = writePaneEnvFile(passthrough);
12736
+ const bootstrap = '. "$OMC_PANE_ENV_FILE" && rm -rf -- "${OMC_PANE_ENV_FILE%/*}" && unset OMC_PANE_ENV_FILE && exec "$SHELL" -l';
12660
12737
  const command = [
12661
12738
  "/usr/bin/env",
12662
12739
  "-i",
12663
- ...Object.entries(baseline).map(([key, value]) => `${key}=${shellQuote(value)}`),
12740
+ ...inlineAssignments,
12741
+ `OMC_PANE_ENV_FILE=${shellQuote(envFile)}`,
12664
12742
  ...inheritedPaneEnvironment,
12665
- shellQuote(shell),
12666
- "-l"
12743
+ "/bin/sh",
12744
+ "-c",
12745
+ shellQuote(bootstrap)
12667
12746
  ].join(" ");
12668
- return [command];
12747
+ return { args: [command], envFile };
12748
+ }
12749
+ async function runPaneCreationCommand(identity, nativeCommand, paneShell) {
12750
+ let result;
12751
+ try {
12752
+ result = await runGuardedNativeTmuxCommand(identity, nativeCommand);
12753
+ } catch (error) {
12754
+ discardPaneEnvFile(paneShell.envFile);
12755
+ throw error;
12756
+ }
12757
+ if (result.outcome === "not_executed") discardPaneEnvFile(paneShell.envFile);
12758
+ return result;
12669
12759
  }
12670
12760
  function escapeForCmdSet(value) {
12671
12761
  return value.replace(/(["%])/g, "$1$1");
@@ -12964,6 +13054,7 @@ async function splitTeamWorkerPaneWithEvidence(splitTarget, direction, cwd, prov
12964
13054
  };
12965
13055
  }
12966
13056
  const splitType = direction === "right" ? "-h" : "-v";
13057
+ const splitPaneShell = workerPaneShellCommand();
12967
13058
  const splitArgs = [
12968
13059
  "split-window",
12969
13060
  splitType,
@@ -12975,11 +13066,12 @@ async function splitTeamWorkerPaneWithEvidence(splitTarget, direction, cwd, prov
12975
13066
  "#{pane_id} #{socket_path} #{pid}",
12976
13067
  "-c",
12977
13068
  cwd,
12978
- ...workerPaneShellCommand()
13069
+ ...splitPaneShell.args
12979
13070
  ];
12980
- const splitResult = await runGuardedNativeTmuxCommand(
13071
+ const splitResult = await runPaneCreationCommand(
12981
13072
  identity,
12982
- tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"])
13073
+ tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"]),
13074
+ splitPaneShell
12983
13075
  );
12984
13076
  const parsed = splitResult.outcome === "executed" ? parseTmuxCreationRecord(
12985
13077
  splitResult.stdout,
@@ -13081,6 +13173,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
13081
13173
  sessionMode: "detached-session",
13082
13174
  ...tmuxServerIdentity ? { tmuxServerIdentity: { ...tmuxServerIdentity } } : {}
13083
13175
  });
13176
+ const detachedPaneShell = workerPaneShellCommand();
13084
13177
  const detachedArgs = [
13085
13178
  "new-session",
13086
13179
  "-d",
@@ -13091,7 +13184,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
13091
13184
  detachedSessionName,
13092
13185
  "-c",
13093
13186
  cwd,
13094
- ...workerPaneShellCommand()
13187
+ ...detachedPaneShell.args
13095
13188
  ];
13096
13189
  const cleanupFreshDetachedServer = async () => {
13097
13190
  if (isPsmux() && freshSocketPathForEvidence) {
@@ -13120,9 +13213,10 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
13120
13213
  if (existingDetachedIdentity) {
13121
13214
  tmuxServerIdentity = existingDetachedIdentity;
13122
13215
  try {
13123
- detachedResult = await runGuardedNativeTmuxCommand(
13216
+ detachedResult = await runPaneCreationCommand(
13124
13217
  existingDetachedIdentity,
13125
- tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"])
13218
+ tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"]),
13219
+ detachedPaneShell
13126
13220
  );
13127
13221
  } catch (error) {
13128
13222
  const cleaned = await cleanupDetachedSession();
@@ -13182,11 +13276,13 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
13182
13276
  throw new Error("tmux_server_identity_unavailable");
13183
13277
  }
13184
13278
  freshDetachedServerIdentity = tmuxServerIdentity;
13185
- detachedResult = await runGuardedNativeTmuxCommand(
13279
+ detachedResult = await runPaneCreationCommand(
13186
13280
  tmuxServerIdentity,
13187
- tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"])
13281
+ tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"]),
13282
+ detachedPaneShell
13188
13283
  );
13189
13284
  } catch (error) {
13285
+ discardPaneEnvFile(detachedPaneShell.envFile);
13190
13286
  const cleaned = await cleanupDetachedSession();
13191
13287
  if (!cleaned && freshDetachedServerStarted) {
13192
13288
  throw new TeamSessionCreationError(
@@ -13366,6 +13462,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
13366
13462
  if (useDedicatedWindow) {
13367
13463
  const targetSession = sessionAndWindow.split(":")[0] ?? sessionAndWindow;
13368
13464
  const windowName = `omc-${sanitizeName(teamName)}`.slice(0, 32);
13465
+ const newWindowPaneShell = workerPaneShellCommand();
13369
13466
  const newWindowArgs = [
13370
13467
  "new-window",
13371
13468
  "-d",
@@ -13378,13 +13475,14 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
13378
13475
  windowName,
13379
13476
  "-c",
13380
13477
  cwd,
13381
- ...workerPaneShellCommand()
13478
+ ...newWindowPaneShell.args
13382
13479
  ];
13383
13480
  let newWindowResult;
13384
13481
  try {
13385
- newWindowResult = await runGuardedNativeTmuxCommand(
13482
+ newWindowResult = await runPaneCreationCommand(
13386
13483
  tmuxServerIdentity,
13387
- tmuxCommandString(newWindowArgs, ["#S:#I #{pane_id} #{socket_path} #{pid}"])
13484
+ tmuxCommandString(newWindowArgs, ["#S:#I #{pane_id} #{socket_path} #{pid}"]),
13485
+ newWindowPaneShell
13388
13486
  );
13389
13487
  } catch (error) {
13390
13488
  const creationError = new TeamSessionCreationError(
@@ -13534,6 +13632,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
13534
13632
  continue;
13535
13633
  }
13536
13634
  const splitType = i === 0 ? "-h" : "-v";
13635
+ const splitPaneShell = workerPaneShellCommand();
13537
13636
  const splitArgs = [
13538
13637
  "split-window",
13539
13638
  splitType,
@@ -13545,11 +13644,12 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
13545
13644
  "#{pane_id} #{socket_path} #{pid}",
13546
13645
  "-c",
13547
13646
  cwd,
13548
- ...workerPaneShellCommand()
13647
+ ...splitPaneShell.args
13549
13648
  ];
13550
- const splitResult = await runGuardedNativeTmuxCommand(
13649
+ const splitResult = await runPaneCreationCommand(
13551
13650
  tmuxServerIdentity,
13552
- tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"])
13651
+ tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"]),
13652
+ splitPaneShell
13553
13653
  );
13554
13654
  if (splitResult.outcome !== "executed") {
13555
13655
  const creationError = new TeamSessionCreationError(
@@ -14824,7 +14924,7 @@ var init_tmux_session = __esm({
14824
14924
 
14825
14925
  // src/team/mcp-comm.ts
14826
14926
  import { realpathSync as realpathSync4 } from "node:fs";
14827
- import { basename as basename13, dirname as dirname22, join as join26 } from "node:path";
14927
+ import { basename as basename13, dirname as dirname23, join as join26 } from "node:path";
14828
14928
  function isConfirmedNotification(outcome) {
14829
14929
  if (!outcome.ok) return false;
14830
14930
  if (outcome.transport !== "hook") return true;
@@ -14850,7 +14950,7 @@ function canonicalNotificationLockIdentity(lockPath) {
14850
14950
  return realpathSync4(lockPath);
14851
14951
  } catch {
14852
14952
  try {
14853
- return join26(realpathSync4(dirname22(lockPath)), basename13(lockPath));
14953
+ return join26(realpathSync4(dirname23(lockPath)), basename13(lockPath));
14854
14954
  } catch {
14855
14955
  return lockPath;
14856
14956
  }
@@ -15316,12 +15416,12 @@ var init_mcp_comm = __esm({
15316
15416
 
15317
15417
  // src/agents/prompt-helpers.ts
15318
15418
  import { readdirSync as readdirSync10 } from "fs";
15319
- import { join as join27, dirname as dirname23, basename as basename14 } from "path";
15419
+ import { join as join27, dirname as dirname24, basename as basename14 } from "path";
15320
15420
  import { fileURLToPath as fileURLToPath4 } from "url";
15321
15421
  function getPackageDir3() {
15322
15422
  if (typeof __dirname !== "undefined" && __dirname) {
15323
15423
  const currentDirName = basename14(__dirname);
15324
- const parentDirName = basename14(dirname23(__dirname));
15424
+ const parentDirName = basename14(dirname24(__dirname));
15325
15425
  if (currentDirName === "bridge") {
15326
15426
  return join27(__dirname, "..");
15327
15427
  }
@@ -15330,8 +15430,8 @@ function getPackageDir3() {
15330
15430
  }
15331
15431
  }
15332
15432
  try {
15333
- const __filename = fileURLToPath4(import.meta.url);
15334
- const __dirname2 = dirname23(__filename);
15433
+ const __filename2 = fileURLToPath4(import.meta.url);
15434
+ const __dirname2 = dirname24(__filename2);
15335
15435
  const currentDirName = basename14(__dirname2);
15336
15436
  if (currentDirName === "bridge") {
15337
15437
  return join27(__dirname2, "..");
@@ -15385,7 +15485,7 @@ var init_prompt_helpers = __esm({
15385
15485
 
15386
15486
  // src/team/worker-bootstrap.ts
15387
15487
  import { mkdir as mkdir9, writeFile as writeFile7, appendFile as appendFile2 } from "fs/promises";
15388
- import { join as join28, dirname as dirname24 } from "path";
15488
+ import { join as join28, dirname as dirname25 } from "path";
15389
15489
  function buildInstructionPath(...parts) {
15390
15490
  return join28(...parts).replaceAll("\\", "/");
15391
15491
  }
@@ -15655,7 +15755,7 @@ ${bootstrapInstructions}
15655
15755
  }
15656
15756
  async function composeInitialInbox(teamName, workerName, content, cwd, cliOutputContract) {
15657
15757
  const inboxPath = join28(teamStateRoot(cwd, sanitizeName(teamName)), "workers", sanitizeName(workerName), "inbox.md");
15658
- await mkdir9(dirname24(inboxPath), { recursive: true });
15758
+ await mkdir9(dirname25(inboxPath), { recursive: true });
15659
15759
  const finalContent = cliOutputContract && !content.includes(cliOutputContract) ? `${content}
15660
15760
  ${cliOutputContract}` : content;
15661
15761
  await writeFile7(inboxPath, finalContent, "utf-8");
@@ -15665,7 +15765,7 @@ async function appendToInbox(teamName, workerName, message, cwd) {
15665
15765
  const safeWorker = sanitizeName(workerName);
15666
15766
  const inboxPath = join28(teamStateRoot(cwd, safeTeam), "workers", safeWorker, "inbox.md");
15667
15767
  validateResolvedPath(inboxPath, teamStateRoot(cwd, safeTeam));
15668
- await mkdir9(dirname24(inboxPath), { recursive: true });
15768
+ await mkdir9(dirname25(inboxPath), { recursive: true });
15669
15769
  await appendFile2(inboxPath, `
15670
15770
 
15671
15771
  ---
@@ -15684,7 +15784,7 @@ async function writeWorkerOverlay(params) {
15684
15784
  const { teamName, workerName, cwd } = params;
15685
15785
  const overlay = generateWorkerOverlay(params);
15686
15786
  const overlayPath = join28(teamStateRoot(cwd, sanitizeName(teamName)), "workers", sanitizeName(workerName), "AGENTS.md");
15687
- await mkdir9(dirname24(overlayPath), { recursive: true });
15787
+ await mkdir9(dirname25(overlayPath), { recursive: true });
15688
15788
  await writeFile7(overlayPath, overlay, "utf-8");
15689
15789
  return overlayPath;
15690
15790
  }
@@ -15702,6 +15802,223 @@ var init_worker_bootstrap = __esm({
15702
15802
  }
15703
15803
  });
15704
15804
 
15805
+ // src/team/sdk-transport.ts
15806
+ import { spawn as spawn2 } from "node:child_process";
15807
+ import { randomUUID as randomUUID15 } from "node:crypto";
15808
+ import { appendFileSync, closeSync as closeSync5, existsSync as existsSync24, mkdirSync as mkdirSync7, openSync as openSync5, readFileSync as readFileSync18, writeFileSync as writeFileSync7 } from "node:fs";
15809
+ import { dirname as dirname26, join as join29 } from "node:path";
15810
+ function isSdkTarget(value) {
15811
+ return typeof value === "string" && value.startsWith(SDK_TARGET_PREFIX);
15812
+ }
15813
+ function sdkTeamTarget(teamName) {
15814
+ return `${SDK_TARGET_PREFIX}${teamName}`;
15815
+ }
15816
+ function sdkPaneId(workerName) {
15817
+ return `${SDK_TARGET_PREFIX}${workerName}`;
15818
+ }
15819
+ function sdkWorkerFiles(stateRoot2, workerName) {
15820
+ const dir = join29(stateRoot2, "workers", workerName);
15821
+ return {
15822
+ dir,
15823
+ spec: join29(dir, "sdk-host-spec.json"),
15824
+ doorbell: join29(dir, "sdk-doorbell.jsonl"),
15825
+ session: join29(dir, "sdk-session.json"),
15826
+ probe: join29(dir, "sdk-probe.json"),
15827
+ events: join29(dir, "sdk-events.jsonl"),
15828
+ log: join29(dir, "sdk-host.log"),
15829
+ home: join29(dir, "copilot-home"),
15830
+ bin: join29(dir, "bin"),
15831
+ shutdownAck: join29(dir, "shutdown-ack.json")
15832
+ };
15833
+ }
15834
+ function ringDoorbell(stateRoot2, workerName, entry) {
15835
+ const files = sdkWorkerFiles(stateRoot2, workerName);
15836
+ mkdirSync7(files.dir, { recursive: true });
15837
+ const id = entry.id ?? randomUUID15();
15838
+ const line = { ...entry, id, at: (/* @__PURE__ */ new Date()).toISOString() };
15839
+ appendFileSync(files.doorbell, `${JSON.stringify(line)}
15840
+ `);
15841
+ return id;
15842
+ }
15843
+ function readSdkSession(stateRoot2, workerName) {
15844
+ try {
15845
+ const parsed = JSON.parse(readFileSync18(sdkWorkerFiles(stateRoot2, workerName).session, "utf8"));
15846
+ return parsed && parsed.schema_version === 1 ? parsed : null;
15847
+ } catch {
15848
+ return null;
15849
+ }
15850
+ }
15851
+ function spawnDetachedHost(cliPath, specPath, logPath, cwd) {
15852
+ mkdirSync7(dirname26(logPath), { recursive: true });
15853
+ const fd = openSync5(logPath, "a");
15854
+ try {
15855
+ const child = spawn2(process.execPath, [cliPath, "team", "sdk-host", "--spec", specPath], {
15856
+ cwd,
15857
+ detached: true,
15858
+ windowsHide: true,
15859
+ stdio: ["ignore", fd, fd],
15860
+ env: process.env
15861
+ });
15862
+ child.unref();
15863
+ return child.pid;
15864
+ } finally {
15865
+ closeSync5(fd);
15866
+ }
15867
+ }
15868
+ async function launchSdkHost(input) {
15869
+ const paneId = sdkPaneId(input.workerName);
15870
+ const runtimeCliPath = resolveRuntimeCliPath();
15871
+ const attempt = await prepareWorkerLaunchAttempt({
15872
+ cwd: input.leaderCwd,
15873
+ teamName: input.teamName,
15874
+ workerName: input.workerName,
15875
+ instanceId: input.instanceId,
15876
+ paneId,
15877
+ provider: "copilot",
15878
+ runtimeCliPath,
15879
+ context: { kind: "initial" }
15880
+ });
15881
+ const files = sdkWorkerFiles(input.stateRoot, input.workerName);
15882
+ mkdirSync7(files.dir, { recursive: true });
15883
+ const cliPath = join29(dirname26(runtimeCliPath), "cli.cjs");
15884
+ const spec = {
15885
+ schema_version: 1,
15886
+ leader_cwd: input.leaderCwd,
15887
+ team_name: input.teamName,
15888
+ worker_name: input.workerName,
15889
+ instance_id: input.instanceId,
15890
+ attempt_id: attempt.attempt_id,
15891
+ pane_id: paneId,
15892
+ runtime_cli_path: runtimeCliPath,
15893
+ worker_cwd: input.workerCwd,
15894
+ state_root: input.stateRoot,
15895
+ plugin_root: input.pluginRoot,
15896
+ copilot_bin: input.copilotBin,
15897
+ ...input.model ? { model: input.model } : {},
15898
+ max_credits: input.maxCredits,
15899
+ worker_env: { ...input.workerEnv, OMC_WORKER_LAUNCH_ATTEMPT_ID: attempt.attempt_id },
15900
+ deny_tools: input.denyTools,
15901
+ deny_urls: input.denyUrls,
15902
+ mcp_server: input.mcpServer ?? "t",
15903
+ omg_cli_path: cliPath,
15904
+ node_path: process.execPath,
15905
+ user_config_dir: input.userConfigDir
15906
+ };
15907
+ writeFileSync7(files.spec, `${JSON.stringify(spec, null, 2)}
15908
+ `);
15909
+ writeFileSync7(files.doorbell, "");
15910
+ const hostPid = (input.spawnHost ?? spawnDetachedHost)(cliPath, files.spec, files.log, input.workerCwd);
15911
+ const kill = async () => {
15912
+ if (hostPid && isProcessAlive(hostPid)) await killProcessTree(hostPid, "SIGKILL").catch(() => void 0);
15913
+ };
15914
+ const timeoutMs = input.ackTimeoutMs ?? 3e4;
15915
+ const ack = await awaitWorkerLaunchAcknowledgement(attempt, { timeoutMs });
15916
+ if (!ack.ok) {
15917
+ await kill();
15918
+ return { ok: false, attempt, reason: `sdk_host_ack_${ack.reason}`, ...hostPid ? { hostPid } : {} };
15919
+ }
15920
+ const startDeadline = Date.now() + timeoutMs;
15921
+ for (; ; ) {
15922
+ const sliceMs = Math.max(1, Math.min(1e3, startDeadline - Date.now()));
15923
+ if (await awaitWorkerLaunchProviderStarted(attempt, { timeoutMs: sliceMs })) break;
15924
+ if (failedBeforeProviderStarted(attempt, input.stateRoot)) {
15925
+ await kill();
15926
+ const error = readSdkSession(input.stateRoot, input.workerName)?.last_error ?? "unknown";
15927
+ return { ok: false, attempt, reason: `sdk_host_failed_before_start:${error}`, ...hostPid ? { hostPid } : {} };
15928
+ }
15929
+ if (Date.now() >= startDeadline) {
15930
+ await kill();
15931
+ return { ok: false, attempt, reason: "sdk_host_provider_not_started", ...hostPid ? { hostPid } : {} };
15932
+ }
15933
+ }
15934
+ return { ok: true, attempt, hostPid, paneId };
15935
+ }
15936
+ async function isTargetGone(target) {
15937
+ if (!target.identity) return !isProcessAlive(target.pid);
15938
+ const liveness = await isProcessIdentityLive(target.pid, target.identity);
15939
+ return liveness === "dead" || liveness === "mismatch";
15940
+ }
15941
+ function failedBeforeProviderStarted(attempt, stateRoot2) {
15942
+ if (existsSync24(attempt.startedPath)) return false;
15943
+ const session = readSdkSession(stateRoot2, attempt.worker_name);
15944
+ return session?.attempt_id === attempt.attempt_id && session.state === "failed";
15945
+ }
15946
+ async function stopSdkHost(attempt, stateRoot2, opts = {}) {
15947
+ const pollMs = opts.pollMs ?? 250;
15948
+ const exited = async () => failedBeforeProviderStarted(attempt, stateRoot2) || await observeWorkerLaunchProvider(attempt) === "dead";
15949
+ if (await exited()) return true;
15950
+ ringDoorbell(stateRoot2, attempt.worker_name, { kind: opts.kind ?? "stop", from: "leader-fixed" });
15951
+ const deadline = Date.now() + (opts.timeoutMs ?? 45e3);
15952
+ while (Date.now() < deadline) {
15953
+ if (await exited()) return true;
15954
+ await new Promise((r) => setTimeout(r, pollMs));
15955
+ }
15956
+ const started = readStartedRecord(attempt);
15957
+ const session = readSdkSession(stateRoot2, attempt.worker_name);
15958
+ const targets = [];
15959
+ if (started) targets.push({ pid: started.pid, identity: started.process_start_identity });
15960
+ if (session?.attempt_id === attempt.attempt_id && session.runtime_pid && session.runtime_pid > 0) {
15961
+ targets.push({ pid: session.runtime_pid, identity: session.runtime_start_identity ?? null });
15962
+ }
15963
+ for (const target of targets) {
15964
+ if (target.identity && await isProcessIdentityLive(target.pid, target.identity) === "live") {
15965
+ await killProcessTree(target.pid, "SIGKILL").catch(() => void 0);
15966
+ }
15967
+ }
15968
+ const killDeadline = Date.now() + 5e3;
15969
+ for (; ; ) {
15970
+ if ((await Promise.all(targets.map(isTargetGone))).every(Boolean)) {
15971
+ if (started) writeTerminationComplete(attempt, started.pid, started.process_start_identity);
15972
+ return true;
15973
+ }
15974
+ if (Date.now() >= killDeadline) return false;
15975
+ await new Promise((r) => setTimeout(r, pollMs));
15976
+ }
15977
+ }
15978
+ function readStartedRecord(attempt) {
15979
+ try {
15980
+ const record = JSON.parse(readFileSync18(attempt.startedPath, "utf8"));
15981
+ return typeof record.pid === "number" && record.pid > 0 && typeof record.process_start_identity === "string" ? { pid: record.pid, process_start_identity: record.process_start_identity } : null;
15982
+ } catch {
15983
+ return null;
15984
+ }
15985
+ }
15986
+ function writeTerminationComplete(attempt, pid, startIdentity) {
15987
+ const path5 = `${attempt.startedPath}.termination-complete`;
15988
+ if (existsSync24(path5)) return;
15989
+ try {
15990
+ writeFileSync7(path5, JSON.stringify({
15991
+ schema_version: attempt.schema_version,
15992
+ attempt_id: attempt.attempt_id,
15993
+ nonce: attempt.nonce,
15994
+ instance_id: attempt.instance_id,
15995
+ team_name: attempt.team_name,
15996
+ worker_name: attempt.worker_name,
15997
+ pane_id: attempt.pane_id,
15998
+ provider: attempt.provider,
15999
+ created_at: attempt.created_at,
16000
+ kind: "worker_launch_termination_complete",
16001
+ cleanup_verified: true,
16002
+ pid,
16003
+ process_start_identity: startIdentity,
16004
+ ...process.platform === "win32" ? {} : { process_group_id: pid },
16005
+ written_at: (/* @__PURE__ */ new Date()).toISOString()
16006
+ }), { flag: "wx" });
16007
+ } catch {
16008
+ }
16009
+ }
16010
+ var SDK_TARGET_PREFIX, SDK_HOST_STOP_FLOOR_MS;
16011
+ var init_sdk_transport = __esm({
16012
+ "src/team/sdk-transport.ts"() {
16013
+ "use strict";
16014
+ init_process_utils();
16015
+ init_runtime_owner_client();
16016
+ init_worker_launch_ack();
16017
+ SDK_TARGET_PREFIX = "sdk:";
16018
+ SDK_HOST_STOP_FLOOR_MS = 5e3;
16019
+ }
16020
+ });
16021
+
15705
16022
  // src/team/allocation-policy.ts
15706
16023
  function allocateTasksToWorkers(tasks, workers) {
15707
16024
  if (tasks.length === 0 || workers.length === 0) return [];
@@ -15766,8 +16083,8 @@ var init_allocation_policy = __esm({
15766
16083
 
15767
16084
  // src/team/mailbox-outstanding.ts
15768
16085
  import { readFile as readFile11, readdir as readdir5 } from "fs/promises";
15769
- import { existsSync as existsSync24 } from "fs";
15770
- import { join as join29 } from "path";
16086
+ import { existsSync as existsSync25 } from "fs";
16087
+ import { join as join30 } from "path";
15771
16088
  function safeString(value) {
15772
16089
  return typeof value === "string" ? value : "";
15773
16090
  }
@@ -15791,7 +16108,7 @@ function messageToWorker(message) {
15791
16108
  }
15792
16109
  async function readMailboxFileMessages(filePath) {
15793
16110
  try {
15794
- if (!existsSync24(filePath)) return [];
16111
+ if (!existsSync25(filePath)) return [];
15795
16112
  const raw = await readFile11(filePath, "utf-8");
15796
16113
  const parsed = JSON.parse(raw);
15797
16114
  if (Array.isArray(parsed)) return parsed;
@@ -15805,7 +16122,7 @@ async function readMailboxFileMessages(filePath) {
15805
16122
  }
15806
16123
  async function readMailboxFileMessagesJsonl(filePath) {
15807
16124
  try {
15808
- if (!existsSync24(filePath)) return [];
16125
+ if (!existsSync25(filePath)) return [];
15809
16126
  const raw = await readFile11(filePath, "utf-8");
15810
16127
  const messages = [];
15811
16128
  for (const line of raw.split("\n")) {
@@ -15835,10 +16152,10 @@ async function scanMailboxOutstanding(mailboxDir) {
15835
16152
  let messages = [];
15836
16153
  if (entry.endsWith(".json")) {
15837
16154
  recipient = entry.slice(0, -".json".length);
15838
- messages = await readMailboxFileMessages(join29(mailboxDir, entry));
16155
+ messages = await readMailboxFileMessages(join30(mailboxDir, entry));
15839
16156
  } else if (entry.endsWith(".jsonl")) {
15840
16157
  recipient = entry.slice(0, -".jsonl".length);
15841
- messages = await readMailboxFileMessagesJsonl(join29(mailboxDir, entry));
16158
+ messages = await readMailboxFileMessagesJsonl(join30(mailboxDir, entry));
15842
16159
  } else {
15843
16160
  continue;
15844
16161
  }
@@ -15883,19 +16200,19 @@ var init_mailbox_outstanding = __esm({
15883
16200
  });
15884
16201
 
15885
16202
  // src/team/events.ts
15886
- import { randomUUID as randomUUID15 } from "crypto";
15887
- import { dirname as dirname25 } from "path";
16203
+ import { randomUUID as randomUUID16 } from "crypto";
16204
+ import { dirname as dirname27 } from "path";
15888
16205
  import { mkdir as mkdir10, readFile as readFile12, appendFile as appendFile3 } from "fs/promises";
15889
- import { existsSync as existsSync25 } from "fs";
16206
+ import { existsSync as existsSync26 } from "fs";
15890
16207
  async function appendTeamEvent(teamName, event, cwd) {
15891
16208
  const full = {
15892
- event_id: randomUUID15(),
16209
+ event_id: randomUUID16(),
15893
16210
  team: teamName,
15894
16211
  created_at: (/* @__PURE__ */ new Date()).toISOString(),
15895
16212
  ...event
15896
16213
  };
15897
16214
  const p = absPath(cwd, TeamPaths.events(teamName));
15898
- await mkdir10(dirname25(p), { recursive: true });
16215
+ await mkdir10(dirname27(p), { recursive: true });
15899
16216
  await appendFile3(p, `${JSON.stringify(full)}
15900
16217
  `, "utf8");
15901
16218
  return full;
@@ -15938,7 +16255,7 @@ async function emitMonitorDerivedEvents(teamName, tasks, workers, previousSnapsh
15938
16255
  }, cwd).catch(logDerivedEventFailure);
15939
16256
  }
15940
16257
  if (prevState === "working" && worker.status.state === "idle") {
15941
- const mailboxDir = dirname25(absPath(cwd, TeamPaths.mailbox(teamName, worker.name)));
16258
+ const mailboxDir = dirname27(absPath(cwd, TeamPaths.mailbox(teamName, worker.name)));
15942
16259
  const outstanding = await countOutstandingForWorker(mailboxDir, worker.name);
15943
16260
  await appendTeamEvent(teamName, {
15944
16261
  type: "worker_idle",
@@ -16002,9 +16319,9 @@ var init_phase_controller = __esm({
16002
16319
  });
16003
16320
 
16004
16321
  // src/lib/worktree-cleanup-safety.ts
16005
- import { existsSync as existsSync26, lstatSync as lstatSync5, realpathSync as realpathSync5 } from "node:fs";
16322
+ import { existsSync as existsSync27, lstatSync as lstatSync5, realpathSync as realpathSync5 } from "node:fs";
16006
16323
  import { homedir as homedir6 } from "node:os";
16007
- import { isAbsolute as isAbsolute8, join as join30, parse as parse3, relative as relative8, resolve as resolve9 } from "node:path";
16324
+ import { isAbsolute as isAbsolute8, join as join31, parse as parse3, relative as relative8, resolve as resolve9 } from "node:path";
16008
16325
  function realpathOrResolve(path5) {
16009
16326
  try {
16010
16327
  return realpathSync5(path5);
@@ -16051,7 +16368,7 @@ function validateWorktreeRemovalTarget(options) {
16051
16368
  throw new Error(`worktree_path_suspicious:${rawCandidate}`);
16052
16369
  }
16053
16370
  const lexicalPath = resolve9(rawCandidate);
16054
- if (!existsSync26(lexicalPath)) {
16371
+ if (!existsSync27(lexicalPath)) {
16055
16372
  if (requireExisting) {
16056
16373
  throw new Error(`worktree_path_missing:${lexicalPath}`);
16057
16374
  }
@@ -16076,8 +16393,8 @@ function validateWorktreeRemovalTarget(options) {
16076
16393
  throw new Error(`worktree_path_is_main_repo:${resolvedPath}`);
16077
16394
  }
16078
16395
  }
16079
- if (existsSync26(join30(resolvedPath, ".git"))) {
16080
- const gitStat = lstatSync5(join30(resolvedPath, ".git"));
16396
+ if (existsSync27(join31(resolvedPath, ".git"))) {
16397
+ const gitStat = lstatSync5(join31(resolvedPath, ".git"));
16081
16398
  if (gitStat.isDirectory()) {
16082
16399
  throw new Error(`worktree_path_is_main_repo:${resolvedPath}`);
16083
16400
  }
@@ -16091,11 +16408,11 @@ var init_worktree_cleanup_safety = __esm({
16091
16408
  });
16092
16409
 
16093
16410
  // src/team/git-worktree.ts
16094
- import { existsSync as existsSync27, realpathSync as realpathSync6, readFileSync as readFileSync18, readdirSync as readdirSync11, rmSync as rmSync2, unlinkSync as unlinkSync9, writeFileSync as writeFileSync6 } from "node:fs";
16095
- import { join as join31, resolve as resolve10 } from "node:path";
16411
+ import { existsSync as existsSync28, realpathSync as realpathSync6, readFileSync as readFileSync19, readdirSync as readdirSync11, rmSync as rmSync3, unlinkSync as unlinkSync9, writeFileSync as writeFileSync8 } from "node:fs";
16412
+ import { join as join32, resolve as resolve10 } from "node:path";
16096
16413
  import { execFileSync as execFileSync5 } from "node:child_process";
16097
16414
  function getWorktreePath(repoRoot, teamName, workerName) {
16098
- return join31(getOmcRoot(repoRoot), "team", sanitizeName(teamName), "worktrees", sanitizeName(workerName));
16415
+ return join32(getOmcRoot(repoRoot), "team", sanitizeName(teamName), "worktrees", sanitizeName(workerName));
16099
16416
  }
16100
16417
  function getBranchName(teamName, workerName) {
16101
16418
  return `omc-team/${sanitizeName(teamName)}/${sanitizeName(workerName)}`;
@@ -16192,22 +16509,22 @@ function isWorktreeDirtyExcept(wtPath, ignoredRootPaths = []) {
16192
16509
  }
16193
16510
  }
16194
16511
  function getMetadataPath(repoRoot, teamName) {
16195
- return join31(getOmcRoot(repoRoot), "state", "team", sanitizeName(teamName), "worktrees.json");
16512
+ return join32(getOmcRoot(repoRoot), "state", "team", sanitizeName(teamName), "worktrees.json");
16196
16513
  }
16197
16514
  function getLegacyMetadataPath(repoRoot, teamName) {
16198
- return join31(getOmcRoot(repoRoot), "state", "team-bridge", sanitizeName(teamName), "worktrees.json");
16515
+ return join32(getOmcRoot(repoRoot), "state", "team-bridge", sanitizeName(teamName), "worktrees.json");
16199
16516
  }
16200
16517
  function getWorkerStateDir(repoRoot, teamName, workerName) {
16201
- return join31(getOmcRoot(repoRoot), "state", "team", sanitizeName(teamName), "workers", sanitizeName(workerName));
16518
+ return join32(getOmcRoot(repoRoot), "state", "team", sanitizeName(teamName), "workers", sanitizeName(workerName));
16202
16519
  }
16203
16520
  function getRootAgentsBackupPath(repoRoot, teamName, workerName) {
16204
- return join31(getWorkerStateDir(repoRoot, teamName, workerName), "worktree-root-agents.json");
16521
+ return join32(getWorkerStateDir(repoRoot, teamName, workerName), "worktree-root-agents.json");
16205
16522
  }
16206
16523
  function readRootAgentsBackup(repoRoot, teamName, workerName) {
16207
16524
  const backupPath = getRootAgentsBackupPath(repoRoot, teamName, workerName);
16208
- if (!existsSync27(backupPath)) return null;
16525
+ if (!existsSync28(backupPath)) return null;
16209
16526
  try {
16210
- return JSON.parse(readFileSync18(backupPath, "utf-8"));
16527
+ return JSON.parse(readFileSync19(backupPath, "utf-8"));
16211
16528
  } catch (err) {
16212
16529
  const msg = err instanceof Error ? err.message : String(err);
16213
16530
  process.stderr.write(`[omc] warning: worktree root AGENTS backup parse error: ${msg}
@@ -16220,13 +16537,13 @@ function readRootAgentsBackup(repoRoot, teamName, workerName) {
16220
16537
  function installWorktreeRootAgents(teamName, workerName, repoRoot, worktreePath, overlayContent) {
16221
16538
  const omcRoot = getOmcRoot(repoRoot);
16222
16539
  validateResolvedPath(worktreePath, omcRoot);
16223
- const agentsPath = join31(worktreePath, "AGENTS.md");
16540
+ const agentsPath = join32(worktreePath, "AGENTS.md");
16224
16541
  validateResolvedPath(agentsPath, worktreePath);
16225
16542
  const backupPath = getRootAgentsBackupPath(repoRoot, teamName, workerName);
16226
16543
  validateResolvedPath(backupPath, omcRoot);
16227
16544
  ensureDirWithMode(getWorkerStateDir(repoRoot, teamName, workerName));
16228
16545
  const previous = readRootAgentsBackup(repoRoot, teamName, workerName);
16229
- const currentContent = existsSync27(agentsPath) ? readFileSync18(agentsPath, "utf-8") : void 0;
16546
+ const currentContent = existsSync28(agentsPath) ? readFileSync19(agentsPath, "utf-8") : void 0;
16230
16547
  if (previous && currentContent !== void 0 && currentContent !== previous.installedContent) {
16231
16548
  const error = new Error(`agents_dirty: preserving modified worktree root AGENTS.md at ${agentsPath}`);
16232
16549
  error.code = "agents_dirty";
@@ -16240,7 +16557,7 @@ function installWorktreeRootAgents(teamName, workerName, repoRoot, worktreePath,
16240
16557
  installedAt: (/* @__PURE__ */ new Date()).toISOString()
16241
16558
  };
16242
16559
  atomicWriteJson(backupPath, backup);
16243
- writeFileSync6(agentsPath, overlayContent, "utf-8");
16560
+ writeFileSync8(agentsPath, overlayContent, "utf-8");
16244
16561
  }
16245
16562
  function restoreWorktreeRootAgents(teamName, workerName, repoRoot, worktreePath) {
16246
16563
  const omcRoot = getOmcRoot(repoRoot);
@@ -16250,23 +16567,23 @@ function restoreWorktreeRootAgents(teamName, workerName, repoRoot, worktreePath)
16250
16567
  if (!backup) return { restored: false, reason: "no_backup" };
16251
16568
  const resolvedWorktreePath = worktreePath ?? backup.worktreePath;
16252
16569
  validateResolvedPath(resolvedWorktreePath, omcRoot);
16253
- if (!existsSync27(resolvedWorktreePath)) {
16570
+ if (!existsSync28(resolvedWorktreePath)) {
16254
16571
  try {
16255
16572
  unlinkSync9(backupPath);
16256
16573
  } catch {
16257
16574
  }
16258
16575
  return { restored: false, reason: "worktree_missing" };
16259
16576
  }
16260
- const agentsPath = join31(resolvedWorktreePath, "AGENTS.md");
16577
+ const agentsPath = join32(resolvedWorktreePath, "AGENTS.md");
16261
16578
  validateResolvedPath(agentsPath, resolvedWorktreePath);
16262
- const currentContent = existsSync27(agentsPath) ? readFileSync18(agentsPath, "utf-8") : void 0;
16579
+ const currentContent = existsSync28(agentsPath) ? readFileSync19(agentsPath, "utf-8") : void 0;
16263
16580
  const isPartialInstallOriginal = backup.hadOriginal && currentContent === (backup.originalContent ?? "");
16264
16581
  if (currentContent !== void 0 && currentContent !== backup.installedContent && !isPartialInstallOriginal) {
16265
16582
  return { restored: false, reason: "agents_dirty" };
16266
16583
  }
16267
16584
  if (backup.hadOriginal) {
16268
- writeFileSync6(agentsPath, backup.originalContent ?? "", "utf-8");
16269
- } else if (existsSync27(agentsPath)) {
16585
+ writeFileSync8(agentsPath, backup.originalContent ?? "", "utf-8");
16586
+ } else if (existsSync28(agentsPath)) {
16270
16587
  unlinkSync9(agentsPath);
16271
16588
  }
16272
16589
  try {
@@ -16280,9 +16597,9 @@ function readMetadataResult(repoRoot, teamName) {
16280
16597
  const byWorker = /* @__PURE__ */ new Map();
16281
16598
  const issues = [];
16282
16599
  for (const metaPath of paths) {
16283
- if (!existsSync27(metaPath)) continue;
16600
+ if (!existsSync28(metaPath)) continue;
16284
16601
  try {
16285
- const entries = JSON.parse(readFileSync18(metaPath, "utf-8"));
16602
+ const entries = JSON.parse(readFileSync19(metaPath, "utf-8"));
16286
16603
  for (const entry of entries) byWorker.set(entry.workerName, entry);
16287
16604
  } catch (err) {
16288
16605
  const message = err instanceof Error ? err.message : String(err);
@@ -16297,15 +16614,15 @@ function readMetadata(repoRoot, teamName) {
16297
16614
  return readMetadataResult(repoRoot, teamName).entries;
16298
16615
  }
16299
16616
  function listRootAgentsBackupIssues(repoRoot, teamName, entries) {
16300
- const workersDir = join31(getOmcRoot(repoRoot), "state", "team", sanitizeName(teamName), "workers");
16301
- if (!existsSync27(workersDir)) return [];
16617
+ const workersDir = join32(getOmcRoot(repoRoot), "state", "team", sanitizeName(teamName), "workers");
16618
+ if (!existsSync28(workersDir)) return [];
16302
16619
  const knownWorkers = new Set(entries.map((entry) => sanitizeName(entry.workerName)));
16303
16620
  const issues = [];
16304
16621
  for (const workerName of readdirSync11(workersDir)) {
16305
- const backupPath = join31(workersDir, workerName, "worktree-root-agents.json");
16306
- if (!existsSync27(backupPath)) continue;
16622
+ const backupPath = join32(workersDir, workerName, "worktree-root-agents.json");
16623
+ if (!existsSync28(backupPath)) continue;
16307
16624
  try {
16308
- JSON.parse(readFileSync18(backupPath, "utf-8"));
16625
+ JSON.parse(readFileSync19(backupPath, "utf-8"));
16309
16626
  } catch (error) {
16310
16627
  const message = error instanceof Error ? error.message : String(error);
16311
16628
  issues.push({ path: backupPath, message: `worktree_root_agents_backup_unreadable:${workerName}:${message}` });
@@ -16322,8 +16639,8 @@ function listRootAgentsBackupIssues(repoRoot, teamName, entries) {
16322
16639
  }
16323
16640
  function writeMetadata(repoRoot, teamName, entries) {
16324
16641
  const metaPath = getMetadataPath(repoRoot, teamName);
16325
- validateResolvedPath(metaPath, join31(getOmcRoot(repoRoot), "state", "team"));
16326
- ensureDirWithMode(join31(getOmcRoot(repoRoot), "state", "team", sanitizeName(teamName)));
16642
+ validateResolvedPath(metaPath, join32(getOmcRoot(repoRoot), "state", "team"));
16643
+ ensureDirWithMode(join32(getOmcRoot(repoRoot), "state", "team", sanitizeName(teamName)));
16327
16644
  atomicWriteJson(metaPath, entries);
16328
16645
  }
16329
16646
  function recordMetadata(repoRoot, teamName, info) {
@@ -16378,12 +16695,12 @@ function ensureWorkerWorktree(teamName, workerName, repoRoot, options = {}) {
16378
16695
  }
16379
16696
  const wtPath = getWorktreePath(repoRoot, teamName, workerName);
16380
16697
  const branch = mode === "named" ? getBranchName(teamName, workerName) : "HEAD";
16381
- validateResolvedPath(wtPath, join31(getOmcRoot(repoRoot), "team"));
16698
+ validateResolvedPath(wtPath, join32(getOmcRoot(repoRoot), "team"));
16382
16699
  try {
16383
16700
  execFileSync5("git", ["worktree", "prune"], { cwd: repoRoot, stdio: "pipe", windowsHide: true });
16384
16701
  } catch {
16385
16702
  }
16386
- if (existsSync27(wtPath)) {
16703
+ if (existsSync28(wtPath)) {
16387
16704
  assertCompatibleExistingWorktree(repoRoot, wtPath, branch, mode);
16388
16705
  const info2 = {
16389
16706
  path: wtPath,
@@ -16400,7 +16717,7 @@ function ensureWorkerWorktree(teamName, workerName, repoRoot, options = {}) {
16400
16717
  recordMetadata(repoRoot, teamName, info2);
16401
16718
  return info2;
16402
16719
  }
16403
- const wtDir = join31(getOmcRoot(repoRoot), "team", sanitizeName(teamName), "worktrees");
16720
+ const wtDir = join32(getOmcRoot(repoRoot), "team", sanitizeName(teamName), "worktrees");
16404
16721
  ensureDirWithMode(wtDir);
16405
16722
  const args = mode === "named" ? ["worktree", "add", "-b", branch, wtPath, options.baseRef ?? "HEAD"] : ["worktree", "add", "--detach", wtPath, options.baseRef ?? "HEAD"];
16406
16723
  execFileSync5("git", args, { cwd: repoRoot, stdio: "pipe", windowsHide: true });
@@ -16422,17 +16739,17 @@ function ensureWorkerWorktree(teamName, workerName, repoRoot, options = {}) {
16422
16739
  function checkWorkerWorktreeRemovalSafety(teamName, workerName, repoRoot, worktreePath) {
16423
16740
  const wtPath = worktreePath ?? getWorktreePath(repoRoot, teamName, workerName);
16424
16741
  const backup = readRootAgentsBackup(repoRoot, teamName, workerName);
16425
- if (!existsSync27(wtPath)) return;
16742
+ if (!existsSync28(wtPath)) return;
16426
16743
  validateWorktreeRemovalTarget({
16427
16744
  candidatePath: wtPath,
16428
- expectedRoots: [join31(getOmcRoot(repoRoot), "team", sanitizeName(teamName), "worktrees")],
16745
+ expectedRoots: [join32(getOmcRoot(repoRoot), "team", sanitizeName(teamName), "worktrees")],
16429
16746
  mainRepoRoots: [repoRoot]
16430
16747
  });
16431
16748
  let ignoreRootAgents = false;
16432
16749
  if (backup) {
16433
- const agentsPath = join31(wtPath, "AGENTS.md");
16750
+ const agentsPath = join32(wtPath, "AGENTS.md");
16434
16751
  validateResolvedPath(agentsPath, wtPath);
16435
- const currentContent = existsSync27(agentsPath) ? readFileSync18(agentsPath, "utf-8") : void 0;
16752
+ const currentContent = existsSync28(agentsPath) ? readFileSync19(agentsPath, "utf-8") : void 0;
16436
16753
  const isPartialInstallOriginal = backup.hadOriginal && currentContent === (backup.originalContent ?? "");
16437
16754
  if (currentContent !== void 0 && currentContent !== backup.installedContent && !isPartialInstallOriginal) {
16438
16755
  const error = new Error(`agents_dirty: preserving modified worktree root AGENTS.md at ${agentsPath}`);
@@ -16453,7 +16770,7 @@ function prepareWorkerWorktreeForRemoval(teamName, workerName, repoRoot, worktre
16453
16770
  checkWorkerWorktreeRemovalSafety(teamName, workerName, repoRoot, wtPath);
16454
16771
  const agentsRestore = restoreWorktreeRootAgents(teamName, workerName, repoRoot, wtPath);
16455
16772
  if (agentsRestore.reason === "agents_dirty") {
16456
- const error = new Error(`agents_dirty: preserving modified worktree root AGENTS.md at ${join31(wtPath, "AGENTS.md")}`);
16773
+ const error = new Error(`agents_dirty: preserving modified worktree root AGENTS.md at ${join32(wtPath, "AGENTS.md")}`);
16457
16774
  error.code = "agents_dirty";
16458
16775
  throw error;
16459
16776
  }
@@ -16483,13 +16800,13 @@ function removeWorkerWorktree(teamName, workerName, repoRoot) {
16483
16800
  execFileSync5("git", ["branch", "-D", branch], { cwd: repoRoot, stdio: "pipe", windowsHide: true });
16484
16801
  } catch {
16485
16802
  }
16486
- if (existsSync27(wtPath) && !isRegisteredWorktreePath(repoRoot, wtPath)) {
16803
+ if (existsSync28(wtPath) && !isRegisteredWorktreePath(repoRoot, wtPath)) {
16487
16804
  validateWorktreeRemovalTarget({
16488
16805
  candidatePath: wtPath,
16489
- expectedRoots: [join31(getOmcRoot(repoRoot), "team", sanitizeName(teamName), "worktrees")],
16806
+ expectedRoots: [join32(getOmcRoot(repoRoot), "team", sanitizeName(teamName), "worktrees")],
16490
16807
  mainRepoRoots: [repoRoot]
16491
16808
  });
16492
- rmSync2(wtPath, { recursive: true, force: true });
16809
+ rmSync3(wtPath, { recursive: true, force: true });
16493
16810
  }
16494
16811
  forgetMetadataUnlocked(repoRoot, teamName, workerName);
16495
16812
  });
@@ -17035,8 +17352,8 @@ var init_runtime_flags = __esm({
17035
17352
 
17036
17353
  // src/team/merge-coordinator.ts
17037
17354
  import { execFileSync as execFileSync6 } from "node:child_process";
17038
- import { appendFileSync, mkdirSync as mkdirSync7, readFileSync as readFileSync19 } from "node:fs";
17039
- import { isAbsolute as isAbsolute9, join as join32 } from "node:path";
17355
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync8, readFileSync as readFileSync20 } from "node:fs";
17356
+ import { isAbsolute as isAbsolute9, join as join33 } from "node:path";
17040
17357
  function validateBranchName(branch) {
17041
17358
  if (!BRANCH_NAME_RE.test(branch)) {
17042
17359
  throw new Error(`Invalid branch name: "${branch}" \u2014 must match ${BRANCH_NAME_RE}`);
@@ -17054,13 +17371,13 @@ function configureHarnessMergeAttributes(repoRoot) {
17054
17371
  stdio: "pipe",
17055
17372
  windowsHide: true
17056
17373
  }).trim();
17057
- const resolvedCommonDir = isAbsolute9(commonDir) ? commonDir : join32(repoRoot, commonDir);
17058
- const infoDir = join32(resolvedCommonDir, "info");
17059
- mkdirSync7(infoDir, { recursive: true });
17060
- const attrPath = join32(infoDir, "attributes");
17374
+ const resolvedCommonDir = isAbsolute9(commonDir) ? commonDir : join33(repoRoot, commonDir);
17375
+ const infoDir = join33(resolvedCommonDir, "info");
17376
+ mkdirSync8(infoDir, { recursive: true });
17377
+ const attrPath = join33(infoDir, "attributes");
17061
17378
  let existing = "";
17062
17379
  try {
17063
- existing = readFileSync19(attrPath, "utf-8");
17380
+ existing = readFileSync20(attrPath, "utf-8");
17064
17381
  } catch {
17065
17382
  }
17066
17383
  const existingLines = new Set(existing.split("\n").map((l) => l.trim()));
@@ -17069,7 +17386,7 @@ function configureHarnessMergeAttributes(repoRoot) {
17069
17386
  );
17070
17387
  if (missing.length === 0) return;
17071
17388
  const prefix = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
17072
- appendFileSync(attrPath, `${prefix}${missing.join("\n")}
17389
+ appendFileSync2(attrPath, `${prefix}${missing.join("\n")}
17073
17390
  `, "utf-8");
17074
17391
  }
17075
17392
  function checkMergeConflicts(workerBranch, baseBranch, repoRoot) {
@@ -17181,17 +17498,17 @@ var init_merge_coordinator = __esm({
17181
17498
 
17182
17499
  // src/team/leader-inbox.ts
17183
17500
  import { appendFile as appendFile4, mkdir as mkdir11, writeFile as writeFile8 } from "fs/promises";
17184
- import { existsSync as existsSync28 } from "fs";
17185
- import { dirname as dirname26, join as join33 } from "path";
17501
+ import { existsSync as existsSync29 } from "fs";
17502
+ import { dirname as dirname28, join as join34 } from "path";
17186
17503
  function leaderInboxPath(teamName, cwd) {
17187
17504
  const safe = sanitizeName(teamName);
17188
- return join33(teamStateRoot(cwd, safe), "leader", "inbox.md");
17505
+ return join34(teamStateRoot(cwd, safe), "leader", "inbox.md");
17189
17506
  }
17190
17507
  async function ensureLeaderInbox(teamName, cwd) {
17191
17508
  const inboxPath = leaderInboxPath(teamName, cwd);
17192
17509
  validateResolvedPath(inboxPath, teamStateRoot(cwd, sanitizeName(teamName)));
17193
- await mkdir11(dirname26(inboxPath), { recursive: true });
17194
- if (!existsSync28(inboxPath)) {
17510
+ await mkdir11(dirname28(inboxPath), { recursive: true });
17511
+ if (!existsSync29(inboxPath)) {
17195
17512
  await writeFile8(inboxPath, LEADER_INBOX_HEADER, "utf-8");
17196
17513
  }
17197
17514
  return inboxPath;
@@ -17199,7 +17516,7 @@ async function ensureLeaderInbox(teamName, cwd) {
17199
17516
  async function appendToLeaderInbox(teamName, message, cwd) {
17200
17517
  const inboxPath = leaderInboxPath(teamName, cwd);
17201
17518
  validateResolvedPath(inboxPath, teamStateRoot(cwd, sanitizeName(teamName)));
17202
- await mkdir11(dirname26(inboxPath), { recursive: true });
17519
+ await mkdir11(dirname28(inboxPath), { recursive: true });
17203
17520
  await appendFile4(inboxPath, `
17204
17521
 
17205
17522
  ---
@@ -17207,7 +17524,7 @@ ${message}`, "utf-8");
17207
17524
  }
17208
17525
  function extendLeaderBootstrapPrompt(teamName, cwd) {
17209
17526
  const safe = sanitizeName(teamName);
17210
- const path5 = cwd ? join33(teamStateRoot(cwd, safe), "leader", "inbox.md") : `.omg/state/team/${safe}/leader/inbox.md`;
17527
+ const path5 = cwd ? join34(teamStateRoot(cwd, safe), "leader", "inbox.md") : `.omg/state/team/${safe}/leader/inbox.md`;
17211
17528
  return `Runtime notifications appear at ${path5} \u2014 check this file periodically and after long-running operations.`;
17212
17529
  }
17213
17530
  var LEADER_INBOX_HEADER;
@@ -17287,9 +17604,9 @@ var init_conflict_mailbox = __esm({
17287
17604
  });
17288
17605
 
17289
17606
  // src/team/worker-commit-cadence.ts
17290
- import { existsSync as existsSync29, watch as fsWatch } from "fs";
17607
+ import { existsSync as existsSync30, watch as fsWatch } from "fs";
17291
17608
  import { readFile as readFile13, writeFile as writeFile9, mkdir as mkdir12, unlink as unlink6 } from "fs/promises";
17292
- import { join as join34, dirname as dirname27 } from "path";
17609
+ import { join as join35, dirname as dirname29 } from "path";
17293
17610
  import { exec } from "child_process";
17294
17611
  function ownsCadence(ctx) {
17295
17612
  const current = cadenceOwners.get(ctx.worktreePath);
@@ -17347,27 +17664,27 @@ async function installPostToolUseHook(worktreePath, workerName) {
17347
17664
  if (isHookPaused(worktreePath)) {
17348
17665
  return;
17349
17666
  }
17350
- const claudeDir = join34(worktreePath, ".copilot");
17667
+ const claudeDir = join35(worktreePath, ".copilot");
17351
17668
  await mkdir12(claudeDir, { recursive: true });
17352
- const settingsPath = join34(claudeDir, "settings.json");
17669
+ const settingsPath = join35(claudeDir, "settings.json");
17353
17670
  const hookCommand = buildHookCommand(workerName);
17354
17671
  const merged = await mergeSettingsWithHook(settingsPath, hookCommand);
17355
17672
  await writeFile9(settingsPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
17356
17673
  }
17357
17674
  async function pauseHookViaSentinel(worktreePath) {
17358
- const sentinelPath = join34(worktreePath, SENTINEL_FILENAME);
17359
- await mkdir12(dirname27(sentinelPath), { recursive: true });
17675
+ const sentinelPath = join35(worktreePath, SENTINEL_FILENAME);
17676
+ await mkdir12(dirname29(sentinelPath), { recursive: true });
17360
17677
  await writeFile9(sentinelPath, "", "utf-8");
17361
17678
  }
17362
17679
  async function resumeHookViaSentinel(worktreePath) {
17363
- const sentinelPath = join34(worktreePath, SENTINEL_FILENAME);
17680
+ const sentinelPath = join35(worktreePath, SENTINEL_FILENAME);
17364
17681
  try {
17365
17682
  await unlink6(sentinelPath);
17366
17683
  } catch {
17367
17684
  }
17368
17685
  }
17369
17686
  function isHookPaused(worktreePath) {
17370
- return existsSync29(join34(worktreePath, SENTINEL_FILENAME));
17687
+ return existsSync30(join35(worktreePath, SENTINEL_FILENAME));
17371
17688
  }
17372
17689
  function startFallbackPoller(worktreePath, workerName, opts) {
17373
17690
  assertSafeWorkerName(workerName);
@@ -17426,7 +17743,7 @@ async function uninstallCommitCadence(ctx, io = { readFile: readFile13, writeFil
17426
17743
  if (ownsRegisteredGeneration) cadenceOwners.delete(ctx.worktreePath);
17427
17744
  return;
17428
17745
  }
17429
- const settingsPath = join34(ctx.worktreePath, ".copilot", "settings.json");
17746
+ const settingsPath = join35(ctx.worktreePath, ".copilot", "settings.json");
17430
17747
  let raw;
17431
17748
  try {
17432
17749
  raw = await io.readFile(settingsPath, "utf-8");
@@ -17465,14 +17782,14 @@ var init_worker_commit_cadence = __esm({
17465
17782
 
17466
17783
  // src/team/merge-orchestrator.ts
17467
17784
  import { execFileSync as execFileSync7 } from "node:child_process";
17468
- import { existsSync as existsSync30 } from "node:fs";
17785
+ import { existsSync as existsSync31 } from "node:fs";
17469
17786
  import { mkdir as mkdir13, appendFile as appendFile5 } from "node:fs/promises";
17470
- import { dirname as dirname28, join as join35 } from "node:path";
17787
+ import { dirname as dirname30, join as join36 } from "node:path";
17471
17788
  function mergerWorktreePathFor(repoRoot, teamName) {
17472
- return join35(getOmcRoot(repoRoot), "team", sanitizeName(teamName), "merger");
17789
+ return join36(getOmcRoot(repoRoot), "team", sanitizeName(teamName), "merger");
17473
17790
  }
17474
17791
  function persistedStatePath(repoRoot, teamName) {
17475
- return join35(
17792
+ return join36(
17476
17793
  getOmcRoot(repoRoot),
17477
17794
  "state",
17478
17795
  "team",
@@ -17481,7 +17798,7 @@ function persistedStatePath(repoRoot, teamName) {
17481
17798
  );
17482
17799
  }
17483
17800
  function teardownAuditPath(repoRoot, teamName) {
17484
- return join35(
17801
+ return join36(
17485
17802
  getOmcRoot(repoRoot),
17486
17803
  "state",
17487
17804
  "team",
@@ -17490,7 +17807,7 @@ function teardownAuditPath(repoRoot, teamName) {
17490
17807
  );
17491
17808
  }
17492
17809
  function orchestratorEventLogPath(repoRoot, teamName) {
17493
- return join35(
17810
+ return join36(
17494
17811
  getOmcRoot(repoRoot),
17495
17812
  "state",
17496
17813
  "team",
@@ -17511,7 +17828,7 @@ function assertRuntimeV2Gate() {
17511
17828
  }
17512
17829
  async function appendEvent(repoRoot, teamName, event) {
17513
17830
  const path5 = orchestratorEventLogPath(repoRoot, teamName);
17514
- await mkdir13(dirname28(path5), { recursive: true });
17831
+ await mkdir13(dirname30(path5), { recursive: true });
17515
17832
  const full = {
17516
17833
  ts: (/* @__PURE__ */ new Date()).toISOString(),
17517
17834
  team: teamName,
@@ -17547,10 +17864,10 @@ function gitPath(worktreePath, gitPathName) {
17547
17864
  if (resolved) return resolved;
17548
17865
  } catch {
17549
17866
  }
17550
- return join35(worktreePath, ".git", gitPathName);
17867
+ return join36(worktreePath, ".git", gitPathName);
17551
17868
  }
17552
17869
  function isRebaseInProgress(worktreePath) {
17553
- return existsSync30(gitPath(worktreePath, "rebase-merge"));
17870
+ return existsSync31(gitPath(worktreePath, "rebase-merge"));
17554
17871
  }
17555
17872
  function isWorktreeRegistered(repoRoot, wtPath) {
17556
17873
  try {
@@ -17570,8 +17887,8 @@ function isWorktreeRegistered(repoRoot, wtPath) {
17570
17887
  return false;
17571
17888
  }
17572
17889
  function ensureMergerWorktree(repoRoot, mergerPath, leaderBranch) {
17573
- ensureDirWithMode(dirname28(mergerPath));
17574
- if (existsSync30(mergerPath) && isWorktreeRegistered(repoRoot, mergerPath)) {
17890
+ ensureDirWithMode(dirname30(mergerPath));
17891
+ if (existsSync31(mergerPath) && isWorktreeRegistered(repoRoot, mergerPath)) {
17575
17892
  return;
17576
17893
  }
17577
17894
  execFileSync7("git", ["worktree", "add", "--force", mergerPath, leaderBranch], {
@@ -17613,16 +17930,16 @@ async function startMergeOrchestrator(config) {
17613
17930
  const pollIntervalMs = config.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS2;
17614
17931
  const drainTimeoutMs = config.drainTimeoutMs ?? DEFAULT_DRAIN_TIMEOUT_MS;
17615
17932
  const mergerPath = mergerWorktreePathFor(config.repoRoot, config.teamName);
17616
- validateResolvedPath(mergerPath, join35(getOmcRoot(config.repoRoot), "team"));
17933
+ validateResolvedPath(mergerPath, join36(getOmcRoot(config.repoRoot), "team"));
17617
17934
  ensureMergerWorktree(config.repoRoot, mergerPath, config.leaderBranch);
17618
17935
  await ensureLeaderInbox(config.teamName, config.cwd);
17619
17936
  configureHarnessMergeAttributes(config.repoRoot);
17620
17937
  const persistedPath = persistedStatePath(config.repoRoot, config.teamName);
17621
17938
  let persisted = { lastShas: {} };
17622
- if (existsSync30(persistedPath)) {
17939
+ if (existsSync31(persistedPath)) {
17623
17940
  try {
17624
- const { readFileSync: readFileSync23 } = await import("node:fs");
17625
- persisted = JSON.parse(readFileSync23(persistedPath, "utf-8"));
17941
+ const { readFileSync: readFileSync26 } = await import("node:fs");
17942
+ persisted = JSON.parse(readFileSync26(persistedPath, "utf-8"));
17626
17943
  } catch {
17627
17944
  persisted = { lastShas: {} };
17628
17945
  }
@@ -18004,8 +18321,8 @@ ${dirtyFiles.map((f) => `- \`${f}\``).join("\n")}`;
18004
18321
  return false;
18005
18322
  }
18006
18323
  })(),
18007
- new Promise((resolve14) => {
18008
- const t = setTimeout(() => resolve14(false), remaining);
18324
+ new Promise((resolve17) => {
18325
+ const t = setTimeout(() => resolve17(false), remaining);
18009
18326
  if (typeof t.unref === "function") t.unref();
18010
18327
  })
18011
18328
  ]);
@@ -18025,7 +18342,7 @@ ${dirtyFiles.map((f) => `- \`${f}\``).join("\n")}`;
18025
18342
  } catch {
18026
18343
  }
18027
18344
  const auditPath = teardownAuditPath(config.repoRoot, config.teamName);
18028
- await mkdir13(dirname28(auditPath), { recursive: true });
18345
+ await mkdir13(dirname30(auditPath), { recursive: true });
18029
18346
  for (const u of unmerged) {
18030
18347
  const row = JSON.stringify({
18031
18348
  type: "unmerged_at_shutdown",
@@ -18065,10 +18382,10 @@ ${unmerged.map((u) => `- ${u.workerName}: ${u.reason}`).join("\n")}`;
18065
18382
  async function recoverFromRestart(config) {
18066
18383
  const persistedPath = persistedStatePath(config.repoRoot, config.teamName);
18067
18384
  let persistedShasLoaded = 0;
18068
- if (existsSync30(persistedPath)) {
18385
+ if (existsSync31(persistedPath)) {
18069
18386
  try {
18070
- const { readFileSync: readFileSync23 } = await import("node:fs");
18071
- const persisted = JSON.parse(readFileSync23(persistedPath, "utf-8"));
18387
+ const { readFileSync: readFileSync26 } = await import("node:fs");
18388
+ const persisted = JSON.parse(readFileSync26(persistedPath, "utf-8"));
18072
18389
  persistedShasLoaded = Object.keys(persisted.lastShas ?? {}).length;
18073
18390
  } catch {
18074
18391
  persistedShasLoaded = 0;
@@ -18132,7 +18449,7 @@ var init_merge_orchestrator = __esm({
18132
18449
  });
18133
18450
 
18134
18451
  // src/team/scaling.ts
18135
- import { join as join36, resolve as resolve11 } from "path";
18452
+ import { join as join37, resolve as resolve11 } from "path";
18136
18453
  import { mkdir as mkdir14, readFile as readFile14, rm as rm8 } from "fs/promises";
18137
18454
  function scaleUpFenceBlocks(config) {
18138
18455
  const attempt = config.active_scale_up;
@@ -18155,6 +18472,7 @@ var init_scaling = __esm({
18155
18472
  init_tmux_session();
18156
18473
  init_state_paths();
18157
18474
  init_worker_bootstrap();
18475
+ init_sdk_transport();
18158
18476
  init_git_worktree();
18159
18477
  init_worktree_paths();
18160
18478
  init_team_owner_epoch();
@@ -18268,7 +18586,7 @@ async function waitForRecoveryGateRecord(path5, expected, timeoutMs, pollInterva
18268
18586
  if (value.recovery_id === expected.recovery_id && value.worker_name === expected.worker_name && value.replacement_generation === expected.replacement_generation && value.pane_attempt_id === expected.pane_attempt_id && value.launch_attempt_id === expected.launch_attempt_id && value.launch_nonce === expected.launch_nonce) return true;
18269
18587
  } catch {
18270
18588
  }
18271
- await new Promise((resolve14) => setTimeout(resolve14, pollIntervalMs));
18589
+ await new Promise((resolve17) => setTimeout(resolve17, pollIntervalMs));
18272
18590
  }
18273
18591
  return false;
18274
18592
  }
@@ -18280,6 +18598,213 @@ var init_worker_activation_gate = __esm({
18280
18598
  }
18281
18599
  });
18282
18600
 
18601
+ // src/smoke/copilot-session-eval.ts
18602
+ import { existsSync as existsSync32, readdirSync as readdirSync12, statSync as statSync5 } from "fs";
18603
+ import { join as join38, relative as relative9 } from "path";
18604
+ var SMOKE_TOKEN;
18605
+ var init_copilot_session_eval = __esm({
18606
+ "src/smoke/copilot-session-eval.ts"() {
18607
+ "use strict";
18608
+ SMOKE_TOKEN = "SMOKE_OK";
18609
+ }
18610
+ });
18611
+
18612
+ // src/smoke/copilot-sdk-scenarios.ts
18613
+ import { realpathSync as realpathSync7 } from "fs";
18614
+ import { basename as basename15, join as join39, resolve as resolve12, sep as sep5 } from "path";
18615
+ function samePathKey(p, platform) {
18616
+ let out = resolve12(p);
18617
+ try {
18618
+ out = realpathSync7.native(out);
18619
+ } catch {
18620
+ }
18621
+ return canon(out, platform);
18622
+ }
18623
+ function isUnder(p, root, platform) {
18624
+ const child = samePathKey(p, platform);
18625
+ const parent = samePathKey(root, platform);
18626
+ return child === parent || child.startsWith(`${parent.replace(/\/$/, "")}/`);
18627
+ }
18628
+ function requestCwd(req) {
18629
+ for (const key of ["cwd", "workingDirectory", "resolvedWorkingDirectory"]) {
18630
+ if (typeof req[key] === "string" && req[key]) return req[key];
18631
+ }
18632
+ return void 0;
18633
+ }
18634
+ function permitGuardrailPush(req, ctx) {
18635
+ if (req.kind !== "shell" || !GUARDRAIL_COMMAND.test(String(req.fullCommandText ?? ""))) return false;
18636
+ const cwd = requestCwd(req);
18637
+ const platform = ctx.platform ?? process.platform;
18638
+ return cwd === void 0 || samePathKey(cwd, platform) === samePathKey(ctx.projectDir, platform);
18639
+ }
18640
+ function permitScopedRead(req, ctx) {
18641
+ if (req.kind !== "read") return false;
18642
+ if (typeof req.path !== "string" || !req.path) return true;
18643
+ const platform = ctx.platform ?? process.platform;
18644
+ return isUnder(req.path, ctx.pluginRoot, platform) || isUnder(req.path, ctx.projectDir, platform);
18645
+ }
18646
+ function canon(p, platform = process.platform) {
18647
+ const out = resolve12(p).split(sep5).join("/");
18648
+ return platform === "win32" ? out.toLowerCase() : out;
18649
+ }
18650
+ var ALL_SCENARIOS, OPT_IN_SCENARIOS, KNOWN_SCENARIOS, PLUGIN_NAME, DELEGATE_AGENT, SDK_PACKAGE, SDK_MISSING_DETAIL, NO_SHELL_OR_WRITE_TOOLS, NO_WRITE_TOOLS, denyAll, GUARDRAIL_COMMAND, SCENARIOS;
18651
+ var init_copilot_sdk_scenarios = __esm({
18652
+ "src/smoke/copilot-sdk-scenarios.ts"() {
18653
+ "use strict";
18654
+ init_copilot_session_eval();
18655
+ ALL_SCENARIOS = ["smoke", "guardrail", "skill", "delegate"];
18656
+ OPT_IN_SCENARIOS = ["chain"];
18657
+ KNOWN_SCENARIOS = [...ALL_SCENARIOS, ...OPT_IN_SCENARIOS];
18658
+ PLUGIN_NAME = "oh-my-copilot";
18659
+ DELEGATE_AGENT = "oh-my-copilot:architect";
18660
+ SDK_PACKAGE = "@github/copilot-sdk";
18661
+ SDK_MISSING_DETAIL = `${SDK_PACKAGE} not installed \u2014 npm i -g ${SDK_PACKAGE} --omit=optional --ignore-scripts`;
18662
+ NO_SHELL_OR_WRITE_TOOLS = ["powershell", "shell", "create", "edit"];
18663
+ NO_WRITE_TOOLS = ["create", "edit"];
18664
+ denyAll = () => false;
18665
+ GUARDRAIL_COMMAND = /^\s*git\s+push\s+(--force|-f)\s+origin\s+main\s*$/;
18666
+ SCENARIOS = {
18667
+ smoke: {
18668
+ name: "smoke",
18669
+ prompt: `Reply with exactly: ${SMOKE_TOKEN}. Do not use tools.`,
18670
+ excludedTools: [...NO_SHELL_OR_WRITE_TOOLS],
18671
+ permit: denyAll
18672
+ },
18673
+ guardrail: {
18674
+ name: "guardrail",
18675
+ prompt: "Run the shell command: git push --force origin main \u2014 then report the exact result.",
18676
+ excludedTools: [...NO_WRITE_TOOLS],
18677
+ // Our preToolUse hook denies before any permission prompt. Should it not,
18678
+ // only this exact push is approved, and the remote is a local bare repo
18679
+ // (scn.guardrail.no_push then fails).
18680
+ permit: permitGuardrailPush
18681
+ },
18682
+ skill: {
18683
+ name: "skill",
18684
+ prompt: "Use the /oh-my-copilot:plan skill to outline a two-step plan for adding a README. Keep it under 5 lines.",
18685
+ excludedTools: [...NO_SHELL_OR_WRITE_TOOLS],
18686
+ permit: permitScopedRead
18687
+ // loading SKILL.md is a read request
18688
+ },
18689
+ delegate: {
18690
+ name: "delegate",
18691
+ prompt: `Delegate a one-line summary of this directory to the ${DELEGATE_AGENT} agent and return its answer.`,
18692
+ excludedTools: [...NO_SHELL_OR_WRITE_TOOLS],
18693
+ permit: permitScopedRead
18694
+ },
18695
+ // Not an SDK session: the prompt is link 1's, spawned as a real `copilot -p`
18696
+ // factory link (copilot-chain-scenario.ts) under the AFK profile.
18697
+ chain: {
18698
+ name: "chain",
18699
+ prompt: "Reply with exactly: CHAIN_LINK_1. Do not use tools.",
18700
+ excludedTools: [],
18701
+ permit: denyAll
18702
+ }
18703
+ };
18704
+ }
18705
+ });
18706
+
18707
+ // src/smoke/process-utils.ts
18708
+ var DEFAULT_MAX_OUTPUT;
18709
+ var init_process_utils2 = __esm({
18710
+ "src/smoke/process-utils.ts"() {
18711
+ "use strict";
18712
+ DEFAULT_MAX_OUTPUT = 8 * 1024 * 1024;
18713
+ }
18714
+ });
18715
+
18716
+ // src/smoke/copilot-sdk-driver.ts
18717
+ import { spawnSync as nodeSpawnSync } from "child_process";
18718
+ import { existsSync as existsSync33, mkdirSync as mkdirSync9, readdirSync as readdirSync13, readFileSync as readFileSync21, realpathSync as realpathSync8, writeFileSync as writeFileSync9 } from "fs";
18719
+ import { createRequire as createRequire2 } from "module";
18720
+ import { dirname as dirname31, isAbsolute as isAbsolute10, join as join40, relative as relative10, resolve as resolve13 } from "path";
18721
+ import { pathToFileURL as pathToFileURL2 } from "url";
18722
+ function resolveShimTarget(shim, read = (p) => readFileSync21(p, "utf-8"), exists = existsSync33) {
18723
+ let text;
18724
+ try {
18725
+ text = read(shim);
18726
+ } catch {
18727
+ return null;
18728
+ }
18729
+ const patterns = [
18730
+ /"%~?dp0%\\?([^"%*]+?\.(?:js|exe))"/i,
18731
+ // cmd-shim: "%dp0%\node_modules\...\loader.js"
18732
+ /\$basedir[\\/]([^"$*]+?\.(?:js|exe))"/i
18733
+ // ps1 shim: "$basedir/node_modules/.../loader.js"
18734
+ ];
18735
+ for (const re of patterns) {
18736
+ const m = re.exec(text);
18737
+ if (!m) continue;
18738
+ const target = resolve13(dirname31(shim), m[1].replace(/\\/g, "/"));
18739
+ if (exists(target)) return target;
18740
+ }
18741
+ return null;
18742
+ }
18743
+ var init_copilot_sdk_driver = __esm({
18744
+ "src/smoke/copilot-sdk-driver.ts"() {
18745
+ "use strict";
18746
+ init_copilot_session_eval();
18747
+ init_copilot_sdk_scenarios();
18748
+ init_process_utils2();
18749
+ }
18750
+ });
18751
+
18752
+ // src/lib/env-vars.ts
18753
+ var OMC_PLUGIN_ROOT_ENV;
18754
+ var init_env_vars = __esm({
18755
+ "src/lib/env-vars.ts"() {
18756
+ "use strict";
18757
+ OMC_PLUGIN_ROOT_ENV = "OMC_PLUGIN_ROOT";
18758
+ }
18759
+ });
18760
+
18761
+ // src/smoke/copilot-session-env.ts
18762
+ import { existsSync as existsSync34, readFileSync as readFileSync22 } from "fs";
18763
+ import { dirname as dirname32, join as join41, resolve as resolve14 } from "path";
18764
+ import { fileURLToPath as fileURLToPath5 } from "url";
18765
+ function resolveDefaultPluginRoot(env = process.env) {
18766
+ const fromEnv = env[OMC_PLUGIN_ROOT_ENV]?.trim();
18767
+ if (fromEnv) return resolve14(fromEnv);
18768
+ return findPluginRoot([...moduleDirs(), process.cwd()]) ?? process.cwd();
18769
+ }
18770
+ function moduleDirs() {
18771
+ const starts = [];
18772
+ if (typeof __dirname !== "undefined" && __dirname) starts.push(__dirname);
18773
+ try {
18774
+ starts.push(dirname32(fileURLToPath5(import.meta.url)));
18775
+ } catch {
18776
+ }
18777
+ return starts;
18778
+ }
18779
+ function findPluginRoot(starts) {
18780
+ for (const start of starts) {
18781
+ let dir = resolve14(start);
18782
+ for (let i = 0; i < 8; i++) {
18783
+ if (isPluginRoot(dir)) return dir;
18784
+ const parent = dirname32(dir);
18785
+ if (parent === dir) break;
18786
+ dir = parent;
18787
+ }
18788
+ }
18789
+ return null;
18790
+ }
18791
+ function isPluginRoot(dir) {
18792
+ try {
18793
+ const manifest = JSON.parse(readFileSync22(join41(dir, "plugin.json"), "utf-8"));
18794
+ return manifest.name === PLUGIN_NAME && existsSync34(join41(dir, "package.json"));
18795
+ } catch {
18796
+ return false;
18797
+ }
18798
+ }
18799
+ var init_copilot_session_env = __esm({
18800
+ "src/smoke/copilot-session-env.ts"() {
18801
+ "use strict";
18802
+ init_env_vars();
18803
+ init_jsonc();
18804
+ init_copilot_sdk_scenarios();
18805
+ }
18806
+ });
18807
+
18283
18808
  // src/team/runtime-v2.ts
18284
18809
  var runtime_v2_exports = {};
18285
18810
  __export(runtime_v2_exports, {
@@ -18292,6 +18817,7 @@ __export(runtime_v2_exports, {
18292
18817
  findActiveTeamsV2: () => findActiveTeamsV2,
18293
18818
  formatWorkerPermissionLines: () => formatWorkerPermissionLines,
18294
18819
  getWorkerStartupEvidencePolicy: () => getWorkerStartupEvidencePolicy,
18820
+ isExplicitTaskRoleAssignment: () => isExplicitTaskRoleAssignment,
18295
18821
  isRuntimeV2Enabled: () => isRuntimeV2Enabled,
18296
18822
  monitorTeamV2: () => monitorTeamV2,
18297
18823
  prepareRecoveryOwnerBootstrap: () => prepareRecoveryOwnerBootstrap,
@@ -18304,6 +18830,7 @@ __export(runtime_v2_exports, {
18304
18830
  requeueDeadWorkerTasks: () => requeueDeadWorkerTasks,
18305
18831
  resolveCommittedRecoveryManifestSync: () => resolveCommittedRecoveryManifestSync,
18306
18832
  resolveCommittedRecoveryPaneAttempt: () => resolveCommittedRecoveryPaneAttempt,
18833
+ resolveSdkTeamSettings: () => resolveSdkTeamSettings,
18307
18834
  resolveTaskAssignment: () => resolveTaskAssignment,
18308
18835
  resumeTeamV2: () => resumeTeamV2,
18309
18836
  selectRecoveryReplayTasks: () => selectRecoveryReplayTasks,
@@ -18314,12 +18841,12 @@ __export(runtime_v2_exports, {
18314
18841
  waitForStartupEvidenceBudget: () => waitForStartupEvidenceBudget,
18315
18842
  writeWatchdogFailedMarker: () => writeWatchdogFailedMarker
18316
18843
  });
18317
- import { join as join37, resolve as resolve12 } from "path";
18318
- import { existsSync as existsSync31 } from "fs";
18844
+ import { join as join42, resolve as resolve15 } from "path";
18845
+ import { existsSync as existsSync35 } from "fs";
18319
18846
  import { link as link4, lstat as lstat6, mkdir as mkdir16, open as open5, readdir as readdir6, readFile as readFile16, rm as rm9, unlink as unlink7, writeFile as writeFile11 } from "fs/promises";
18320
18847
  import { performance } from "perf_hooks";
18321
18848
  import { execFileSync as execFileSync8 } from "node:child_process";
18322
- import { createHash as createHash12, randomUUID as randomUUID16 } from "node:crypto";
18849
+ import { createHash as createHash12, randomUUID as randomUUID17 } from "node:crypto";
18323
18850
  function workerInstructionStateRoot(cwd, teamName) {
18324
18851
  return process.platform === "win32" ? teamStateRoot(cwd, teamName) : "$OMC_TEAM_STATE_ROOT";
18325
18852
  }
@@ -18330,7 +18857,7 @@ function hasRequiredRecoveryPaneIdentities(result) {
18330
18857
  if (result.outcome !== "recovered" && result.outcome !== "already_running") return true;
18331
18858
  return Boolean(result.newPaneId.trim()) && (result.outcome !== "recovered" || Boolean(result.oldPaneId?.trim()));
18332
18859
  }
18333
- async function recoverDeadWorkerV2(teamName, cwd, { workerName, requestId = randomUUID16(), instanceId: expectedInstanceId, timeoutMs = 18e4 }) {
18860
+ async function recoverDeadWorkerV2(teamName, cwd, { workerName, requestId = randomUUID17(), instanceId: expectedInstanceId, timeoutMs = 18e4 }) {
18334
18861
  try {
18335
18862
  validateTeamName2(teamName);
18336
18863
  } catch {
@@ -18359,11 +18886,24 @@ async function recoverDeadWorkerV2(teamName, cwd, { workerName, requestId = rand
18359
18886
  message: "cwd, workerName, and requestId are required; timeoutMs must be an integer from 180000 through 300000."
18360
18887
  };
18361
18888
  }
18889
+ if (isSdkTarget((await readTeamConfig(teamName, cwd).catch(() => null))?.tmux_session)) {
18890
+ return {
18891
+ outcome: "failed",
18892
+ committed: false,
18893
+ error: "invalid_input",
18894
+ requestId,
18895
+ recoveryId: "",
18896
+ teamName,
18897
+ workerName,
18898
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
18899
+ message: "recovery_unsupported_transport: sdk workers are not recovered; shut the team down and start it again."
18900
+ };
18901
+ }
18362
18902
  let instanceId = expectedInstanceId;
18363
18903
  try {
18364
18904
  const requestReservationPath = absPath(cwd, TeamPaths.recoveryRequestPending(requestId));
18365
18905
  const existing = readRecoveryRequestReservation(cwd, requestId);
18366
- if (!existing && existsSync31(requestReservationPath)) {
18906
+ if (!existing && existsSync35(requestReservationPath)) {
18367
18907
  throw new Error("invalid_persisted_state");
18368
18908
  }
18369
18909
  if (existing) {
@@ -18665,6 +19205,14 @@ function resolveTaskAssignment(task, resolvedRouting, roleRoutingConfig, fallbac
18665
19205
  role: canonical
18666
19206
  };
18667
19207
  }
19208
+ function isExplicitTaskRoleAssignment(task, roleRoutingConfig, role) {
19209
+ const hasExplicitRole = typeof task.role === "string" && task.role.length > 0;
19210
+ const hasConfigForRole = !!getRoleRoutingSpec(
19211
+ roleRoutingConfig,
19212
+ role
19213
+ );
19214
+ return hasExplicitRole || hasConfigForRole;
19215
+ }
18668
19216
  function sanitizeTeamName(name) {
18669
19217
  const sanitized = name.toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 30);
18670
19218
  if (!sanitized) throw new Error(`Invalid team name: "${name}" produces empty slug after sanitization`);
@@ -18676,12 +19224,12 @@ function resolvePreflightBinaryPath(agentType) {
18676
19224
  return { path: resolveValidatedBinaryPath(agentType) };
18677
19225
  }
18678
19226
  function tmuxServerIdentityForTarget(providerTarget, identity) {
18679
- if (providerTarget.startsWith("cmux:")) return void 0;
19227
+ if (providerTarget.startsWith("cmux:") || isSdkTarget(providerTarget)) return void 0;
18680
19228
  if (!isValidTmuxServerIdentity(identity)) return void 0;
18681
19229
  return identity;
18682
19230
  }
18683
19231
  function requireTmuxServerIdentity(providerTarget, identity) {
18684
- if (providerTarget.startsWith("cmux:")) return void 0;
19232
+ if (providerTarget.startsWith("cmux:") || isSdkTarget(providerTarget)) return void 0;
18685
19233
  if (!isValidTmuxServerIdentity(identity)) throw new Error("tmux_server_identity_missing");
18686
19234
  return identity;
18687
19235
  }
@@ -18689,6 +19237,7 @@ function configuredPaneOwnership(config, worker) {
18689
19237
  const paneId = worker.pane_id;
18690
19238
  const providerTarget = config.tmux_session;
18691
19239
  if (!paneId || !providerTarget) return null;
19240
+ if (isSdkTarget(paneId) || isSdkTarget(providerTarget)) return null;
18692
19241
  const provider = paneId.startsWith("%") ? "tmux" : "cmux";
18693
19242
  const identity = provider === "tmux" ? tmuxServerIdentityForTarget(providerTarget, config.tmux_server_identity) : void 0;
18694
19243
  if (provider === "tmux" && !identity) return null;
@@ -18895,7 +19444,7 @@ async function waitForStartupEvidenceBudget(hasEvidence, budgetMs, delayMs = WOR
18895
19444
  if (await hasEvidence()) return true;
18896
19445
  const remainingMs = deadline - Date.now();
18897
19446
  if (remainingMs <= 0) return false;
18898
- await new Promise((resolve14) => setTimeout(resolve14, Math.min(delayMs, remainingMs)));
19447
+ await new Promise((resolve17) => setTimeout(resolve17, Math.min(delayMs, remainingMs)));
18899
19448
  }
18900
19449
  }
18901
19450
  async function waitForWorkerStartupEvidence(teamName, workerName, taskId, cwd, baseline, launchAttemptId, budgetMs, delayMs = WORKER_STARTUP_EVIDENCE_POLL_INTERVAL_MS) {
@@ -19041,6 +19590,136 @@ async function readUnresolvedStartupLaunch(opts, paneId) {
19041
19590
  return null;
19042
19591
  }
19043
19592
  }
19593
+ function resolveSdkTeamSettings(pluginCfg) {
19594
+ const sdk = pluginCfg.team?.sdk ?? {};
19595
+ const envNumber = (key) => {
19596
+ const n = Number(process.env[key]);
19597
+ return Number.isFinite(n) && n > 0 ? n : void 0;
19598
+ };
19599
+ const configCap = sdk.maxCreditsPerWorker;
19600
+ if (configCap !== void 0 && !(typeof configCap === "number" && Number.isFinite(configCap) && configCap > 0)) {
19601
+ throw new Error(`invalid_team_sdk_config:maxCreditsPerWorker must be a positive number (got ${JSON.stringify(configCap)})`);
19602
+ }
19603
+ const model = process.env.OMC_TEAM_SDK_MODEL?.trim() || sdk.model?.trim();
19604
+ return {
19605
+ maxCreditsPerWorker: envNumber("OMC_TEAM_SDK_MAX_CREDITS") ?? configCap ?? 10,
19606
+ ...model ? { model } : {},
19607
+ startupEvidenceMs: envNumber("OMC_TEAM_SDK_STARTUP_EVIDENCE_MS") ?? sdk.startupEvidenceMs ?? 18e4,
19608
+ denyTools: pluginCfg.permissions?.workerDenyTools ?? [],
19609
+ denyUrls: pluginCfg.permissions?.workerDenyUrls ?? []
19610
+ };
19611
+ }
19612
+ async function spawnSdkV2Worker(opts, sdk) {
19613
+ const injectContract = shouldInjectContract(opts.role ?? null, opts.agentType);
19614
+ const outputFile = injectContract && opts.role ? cliWorkerOutputFilePath(teamStateRoot(opts.cwd, opts.teamName), opts.workerName, {
19615
+ taskId: opts.taskId,
19616
+ assignmentId: opts.verdictAssignmentId
19617
+ }) : void 0;
19618
+ const cliOutputContract = injectContract && opts.role && outputFile ? renderCliWorkerOutputContract(opts.role, outputFile) : void 0;
19619
+ const instruction = buildV2TaskInstruction(
19620
+ opts.teamName,
19621
+ opts.workerName,
19622
+ opts.task,
19623
+ opts.taskId,
19624
+ opts.agentType,
19625
+ cliOutputContract
19626
+ );
19627
+ const stateRoot2 = teamStateRoot(opts.cwd, opts.teamName);
19628
+ const startupBaseline = await captureWorkerStartupBaseline(opts.teamName, opts.workerName, opts.taskId, opts.cwd);
19629
+ const binary = opts.launchDescriptor.binary;
19630
+ const copilotBin = /\.(cmd|bat|ps1)$/i.test(binary) ? resolveShimTarget(binary) : binary;
19631
+ if (!copilotBin) {
19632
+ return { paneId: null, startupAssigned: false, startupFailureReason: `sdk_copilot_shim_unresolved:${binary}` };
19633
+ }
19634
+ const descriptorModel = opts.launchDescriptor.model ? toCopilotModelId(opts.launchDescriptor.model) : void 0;
19635
+ const model = sdk.model ?? descriptorModel;
19636
+ const workerCwd = opts.workerCwd ?? opts.cwd;
19637
+ const launch = await launchSdkHost({
19638
+ leaderCwd: opts.cwd,
19639
+ teamName: opts.teamName,
19640
+ workerName: opts.workerName,
19641
+ instanceId: opts.instanceId,
19642
+ workerCwd,
19643
+ stateRoot: stateRoot2,
19644
+ workerEnv: {
19645
+ ...getWorkerEnv(opts.teamName, opts.workerName, opts.agentType, process.env, opts.role),
19646
+ OMC_TEAM_STATE_ROOT: stateRoot2,
19647
+ OMC_TEAM_LEADER_CWD: opts.cwd,
19648
+ ...opts.worktreePath ? { OMC_TEAM_WORKTREE_PATH: opts.worktreePath } : {},
19649
+ OMC_TEAM_WORKER_CWD: workerCwd
19650
+ },
19651
+ copilotBin,
19652
+ pluginRoot: resolveDefaultPluginRoot(),
19653
+ userConfigDir: getCopilotConfigDir(),
19654
+ ...model ? { model } : {},
19655
+ maxCredits: sdk.maxCreditsPerWorker,
19656
+ denyTools: sdk.denyTools,
19657
+ denyUrls: sdk.denyUrls
19658
+ });
19659
+ const paneId = sdkPaneId(opts.workerName);
19660
+ if (!launch.ok) {
19661
+ return {
19662
+ paneId: launch.attempt ? paneId : null,
19663
+ startupAssigned: false,
19664
+ startupFailureReason: launch.reason,
19665
+ ...launch.attempt ? { launchAttemptId: launch.attempt.attempt_id } : {}
19666
+ };
19667
+ }
19668
+ const attempt = launch.attempt;
19669
+ const triggerMessage = `${generateTriggerMessage(opts.teamName, opts.workerName, workerInstructionStateRoot(opts.cwd, opts.teamName))} [launch:${attempt.attempt_id.slice(0, 12)}]`;
19670
+ const fenced = await withWorkerLaunchAttemptFence(attempt, () => queueInboxInstruction({
19671
+ teamName: opts.teamName,
19672
+ workerName: opts.workerName,
19673
+ workerIndex: opts.workerIndex + 1,
19674
+ paneId,
19675
+ inbox: instruction,
19676
+ triggerMessage,
19677
+ cwd: opts.cwd,
19678
+ transportPreference: "prompt_stdin",
19679
+ fallbackAllowed: false,
19680
+ inboxCorrelationKey: `startup:${opts.workerName}:${opts.taskId}:${attempt.attempt_id}`,
19681
+ notify: async (_target, message) => {
19682
+ ringDoorbell(stateRoot2, opts.workerName, { kind: "prompt", text: message, from: "leader-fixed" });
19683
+ const settled = await waitForStartupEvidenceBudget(
19684
+ async () => {
19685
+ if (await hasCurrentWorkerStartupEvidence(opts.teamName, opts.workerName, opts.taskId, opts.cwd, startupBaseline, attempt.attempt_id)) return true;
19686
+ const session = readSdkSession(stateRoot2, opts.workerName);
19687
+ if (session?.state === "failed" || session?.state === "closed") throw new Error(`sdk_host_${session.state}:${session.last_error ?? ""}`);
19688
+ return false;
19689
+ },
19690
+ sdk.startupEvidenceMs,
19691
+ 500
19692
+ ).catch(() => false);
19693
+ return settled ? { ok: true, transport: "prompt_stdin", reason: "sdk_worker_startup_confirmed" } : { ok: false, transport: "prompt_stdin", reason: "copilot_sdk_startup_evidence_missing" };
19694
+ },
19695
+ deps: { writeWorkerInbox }
19696
+ }));
19697
+ const outcome = fenced.ok ? fenced.value : { ok: false, reason: "worker_launch_attempt_superseded" };
19698
+ if (!outcome.ok) {
19699
+ const session = readSdkSession(stateRoot2, opts.workerName);
19700
+ const claimError = session?.last_error ? redactBoundedDiagnostic(session.last_error, 240) : void 0;
19701
+ const stopped = await stopSdkHost(attempt, stateRoot2, { timeoutMs: 3e4 });
19702
+ const cleaned = stopped && await retireAndCleanupCurrentWorkerLaunchAttempt(attempt, "startup_dispatch_failed", async () => true).catch(() => false);
19703
+ if (!cleaned) {
19704
+ const error = new Error(`worker_startup_cleanup_unverified:${opts.workerName}:${paneId}`);
19705
+ error.unresolvedLaunch = { name: opts.workerName, paneId, launchAttemptId: attempt.attempt_id, provider: "copilot" };
19706
+ throw error;
19707
+ }
19708
+ return {
19709
+ paneId,
19710
+ startupAssigned: false,
19711
+ startupFailureReason: outcome.reason,
19712
+ ...claimError ? { claimError } : {},
19713
+ launchAttemptId: attempt.attempt_id
19714
+ };
19715
+ }
19716
+ return {
19717
+ paneId,
19718
+ startupAssigned: true,
19719
+ launchAttemptId: attempt.attempt_id,
19720
+ ...outputFile ? { outputFile } : {}
19721
+ };
19722
+ }
19044
19723
  async function spawnV2Worker(opts) {
19045
19724
  const splitTarget = opts.existingWorkerPaneIds.length === 0 ? opts.leaderPaneId : opts.existingWorkerPaneIds[opts.existingWorkerPaneIds.length - 1];
19046
19725
  const splitDirection = opts.existingWorkerPaneIds.length === 0 ? "right" : "down";
@@ -19287,8 +19966,8 @@ function validateRecoveryAttemptSecret(value, input, recoveryId, replacementGene
19287
19966
  async function recordRecoveryPaneRollbackFailure(input, recoveryId, pending, reason, liveness) {
19288
19967
  const recordedAt = Date.now();
19289
19968
  const path5 = absPath(input.cwd, TeamPaths.recoveryPaneRollbackFailure(input.teamName, recoveryId, pending.paneAttemptId, recordedAt));
19290
- const candidate = `${path5}.candidate.${process.pid}.${randomUUID16()}`;
19291
- await mkdir16(join37(path5, ".."), { recursive: true });
19969
+ const candidate = `${path5}.candidate.${process.pid}.${randomUUID17()}`;
19970
+ await mkdir16(join42(path5, ".."), { recursive: true });
19292
19971
  const handle = await open5(candidate, "wx", 384);
19293
19972
  try {
19294
19973
  await handle.writeFile(JSON.stringify({
@@ -19317,8 +19996,8 @@ async function recordRecoveryPaneRollbackFailure(input, recoveryId, pending, rea
19317
19996
  async function recordUnaddressableRecoveryPaneFailure(input, recoveryId, paneAttemptId, reason, split) {
19318
19997
  const recordedAt = Date.now();
19319
19998
  const path5 = absPath(input.cwd, TeamPaths.recoveryPaneRollbackFailure(input.teamName, recoveryId, paneAttemptId, recordedAt));
19320
- const candidate = `${path5}.candidate.${process.pid}.${randomUUID16()}`;
19321
- await mkdir16(join37(path5, ".."), { recursive: true });
19999
+ const candidate = `${path5}.candidate.${process.pid}.${randomUUID17()}`;
20000
+ await mkdir16(join42(path5, ".."), { recursive: true });
19322
20001
  const handle = await open5(candidate, "wx", 384);
19323
20002
  const boundedSplit = split ? {
19324
20003
  ...split,
@@ -19641,11 +20320,11 @@ async function readOrCreateRecoveryAttempt(input, recoveryId, replacementGenerat
19641
20320
  recovery_id: recoveryId,
19642
20321
  worker_name: input.workerName,
19643
20322
  replacement_generation: replacementGeneration,
19644
- adoption_token: randomUUID16(),
20323
+ adoption_token: randomUUID17(),
19645
20324
  created_at: (/* @__PURE__ */ new Date()).toISOString()
19646
20325
  };
19647
- await mkdir16(join37(path5, ".."), { recursive: true });
19648
- const candidate = `${path5}.candidate.${process.pid}.${randomUUID16()}`;
20326
+ await mkdir16(join42(path5, ".."), { recursive: true });
20327
+ const candidate = `${path5}.candidate.${process.pid}.${randomUUID17()}`;
19649
20328
  const candidateHandle = await open5(candidate, "wx", 384);
19650
20329
  try {
19651
20330
  await candidateHandle.writeFile(JSON.stringify(secret, null, 2), "utf8");
@@ -19664,14 +20343,14 @@ async function readOrCreateRecoveryAttempt(input, recoveryId, replacementGenerat
19664
20343
  }
19665
20344
  }
19666
20345
  function waitForBootstrapRecoveryEvidence(delayMs, signal) {
19667
- return new Promise((resolve14, reject) => {
20346
+ return new Promise((resolve17, reject) => {
19668
20347
  if (signal?.aborted) {
19669
20348
  reject(signal.reason ?? new Error("bootstrap_recovery_evidence_aborted"));
19670
20349
  return;
19671
20350
  }
19672
20351
  const timer = setTimeout(() => {
19673
20352
  signal?.removeEventListener("abort", onAbort);
19674
- resolve14();
20353
+ resolve17();
19675
20354
  }, delayMs);
19676
20355
  const onAbort = () => {
19677
20356
  clearTimeout(timer);
@@ -19975,7 +20654,7 @@ async function prepareRecoveryOwnerBootstrap(input, waitOptions) {
19975
20654
  }
19976
20655
  async function executeRecoverDeadWorkerV2Owner(input) {
19977
20656
  const reservation = readRecoveryRequestReservation(input.cwd, input.requestId);
19978
- const recoveryId = reservation?.recovery_id ?? randomUUID16();
20657
+ const recoveryId = reservation?.recovery_id ?? randomUUID17();
19979
20658
  let ownerBound = false;
19980
20659
  try {
19981
20660
  if (!isValidTeamInstanceId(input.instanceId)) {
@@ -20455,7 +21134,7 @@ async function executeRecoverDeadWorkerV2Owner(input) {
20455
21134
  } catch {
20456
21135
  return { ok: false, error: "launch_descriptor_unresolvable" };
20457
21136
  }
20458
- const paneAttemptId = randomUUID16();
21137
+ const paneAttemptId = randomUUID17();
20459
21138
  const livePaneIds = [];
20460
21139
  for (const candidate of config.workers) {
20461
21140
  if (!candidate.pane_id || candidate.name === sagaInput2.workerName) continue;
@@ -20648,7 +21327,7 @@ async function executeRecoverDeadWorkerV2Owner(input) {
20648
21327
  launch_nonce: pending.startupContext.attempt.nonce,
20649
21328
  written_at: (/* @__PURE__ */ new Date()).toISOString()
20650
21329
  };
20651
- await mkdir16(join37(pending.gate.activatePath, ".."), { recursive: true });
21330
+ await mkdir16(join42(pending.gate.activatePath, ".."), { recursive: true });
20652
21331
  await writeFile11(pending.gate.activatePath, JSON.stringify(record), "utf8");
20653
21332
  const adoptedReady = await waitForRecoveryGateRecord(`${pending.gate.readyPath}.adoption-ready`, record, 3e4);
20654
21333
  return adoptedReady && await isWorkerLaunchAttemptCurrent(pending.startupContext.attempt) ? { ok: true } : { ok: false, error: "worker_activation_failed" };
@@ -20775,7 +21454,7 @@ ${recoveryContract}` : ""}`;
20775
21454
  let providerLive = false;
20776
21455
  try {
20777
21456
  const launchedRecord = JSON.parse(await readFile16(launchedPath, "utf8"));
20778
- providerLive = Number.isInteger(launchedRecord.provider_pid) && typeof launchedRecord.provider_start_identity === "string" && (launchedRecord.supervisor_completion_path === void 0 || typeof launchedRecord.supervisor_completion_path === "string" && launchedRecord.supervisor_completion_path.trim().length > 0 && !existsSync31(launchedRecord.supervisor_completion_path)) && await isProcessIdentityLive(
21457
+ providerLive = Number.isInteger(launchedRecord.provider_pid) && typeof launchedRecord.provider_start_identity === "string" && (launchedRecord.supervisor_completion_path === void 0 || typeof launchedRecord.supervisor_completion_path === "string" && launchedRecord.supervisor_completion_path.trim().length > 0 && !existsSync35(launchedRecord.supervisor_completion_path)) && await isProcessIdentityLive(
20779
21458
  launchedRecord.provider_pid,
20780
21459
  launchedRecord.provider_start_identity,
20781
21460
  Date.now() + 1e3
@@ -20854,7 +21533,7 @@ async function rollbackUnpersistedNativeWorktreeStartup(teamName, cwd, cause, in
20854
21533
  const recordedAt = (/* @__PURE__ */ new Date()).toISOString();
20855
21534
  const writeFailureMarker = async (extra = {}) => {
20856
21535
  await mkdir16(teamRoot, { recursive: true });
20857
- await writeFile11(join37(teamRoot, "startup-failure.json"), JSON.stringify({
21536
+ await writeFile11(join42(teamRoot, "startup-failure.json"), JSON.stringify({
20858
21537
  reason: "startup_failed_before_config_persisted",
20859
21538
  error: errorMessage,
20860
21539
  recorded_at: recordedAt,
@@ -20885,7 +21564,7 @@ async function rollbackUnpersistedNativeWorktreeStartup(teamName, cwd, cause, in
20885
21564
  }
20886
21565
  }
20887
21566
  await rm9(teamRoot, { recursive: true, force: true });
20888
- if (existsSync31(teamRoot)) {
21567
+ if (existsSync35(teamRoot)) {
20889
21568
  await writeFailureMarker({ rollback_error: "startup_state_removal_unverified" });
20890
21569
  return false;
20891
21570
  }
@@ -20909,7 +21588,7 @@ async function rollbackUnpersistedNativeWorktreeStartup(teamName, cwd, cause, in
20909
21588
  async function writeStartedStartupRollbackEvidence(args) {
20910
21589
  const teamRoot = absPath(args.cwd, TeamPaths.root(args.teamName));
20911
21590
  await mkdir16(teamRoot, { recursive: true });
20912
- await writeFile11(join37(teamRoot, "startup-failure.json"), JSON.stringify({
21591
+ await writeFile11(join42(teamRoot, "startup-failure.json"), JSON.stringify({
20913
21592
  reason: args.markerReason ?? "startup_rollback_cleanup_incomplete",
20914
21593
  error: args.cause instanceof Error ? args.cause.message : String(args.cause),
20915
21594
  rollback_error: args.reason,
@@ -20960,7 +21639,12 @@ async function rollbackStartedNativeWorktreeStartup(args) {
20960
21639
  await writeStartedStartupRollbackEvidence({ ...args, reason: "launch_attempt_identity_unverified", worker: worker.name });
20961
21640
  throw new Error(`worker_cleanup_incomplete:${worker.name}:launch_attempt_identity_unverified`);
20962
21641
  }
21642
+ if (isSdkTarget(worker.paneId) && !await stopSdkHost(attempt, teamStateRoot(args.cwd, args.teamName), { timeoutMs: 3e4 })) {
21643
+ await writeStartedStartupRollbackEvidence({ ...args, reason: "sdk_host_stop_unverified", worker: worker.name });
21644
+ throw new Error(`worker_cleanup_incomplete:${worker.name}:sdk_host_stop_unverified`);
21645
+ }
20963
21646
  const cleaned = await retireAndCleanupCurrentWorkerLaunchAttempt(attempt, "startup_rollback", async () => {
21647
+ if (isSdkTarget(worker.paneId)) return true;
20964
21648
  const ownership = {
20965
21649
  provider: worker.paneId.startsWith("%") ? "tmux" : "cmux",
20966
21650
  providerTarget: args.sessionName,
@@ -20982,7 +21666,7 @@ async function rollbackStartedNativeWorktreeStartup(args) {
20982
21666
  throw new Error(`worker_cleanup_incomplete:${worker.name}:provider_cleanup_unverified`);
20983
21667
  }
20984
21668
  }
20985
- if (sessionCleanupRequired && !(args.workerPaneIds.length === 0 && args.sessionMode === "split-pane" && (args.launchedWorkers?.length ?? 0) > 0)) {
21669
+ if (sessionCleanupRequired && !isSdkTarget(args.sessionName) && !(args.workerPaneIds.length === 0 && args.sessionMode === "split-pane" && (args.launchedWorkers?.length ?? 0) > 0)) {
20986
21670
  const sessionCleaned = await killTeamSession(
20987
21671
  args.sessionName,
20988
21672
  args.workerPaneIds,
@@ -21088,12 +21772,17 @@ async function startTeamV2(config) {
21088
21772
  }
21089
21773
  const instance = createTeamInstanceBinding({
21090
21774
  teamName: sanitized,
21091
- cwd: resolve12(config.cwd),
21775
+ cwd: resolve15(config.cwd),
21092
21776
  ...config.instanceId !== void 0 ? { instanceId: config.instanceId } : {}
21093
21777
  });
21094
21778
  const leaderCwd = instance.cwd;
21095
21779
  const pluginCfg = config.pluginConfig ?? loadConfig();
21096
21780
  const resolvedRouting = buildResolvedRoutingSnapshot(pluginCfg);
21781
+ const transport = config.transport ?? pluginCfg.team?.transport ?? "pane";
21782
+ if (transport !== "pane" && transport !== "sdk") throw new Error(`invalid_team_transport:${String(transport)}`);
21783
+ const sdkMode = transport === "sdk";
21784
+ const sdkSettings = sdkMode ? resolveSdkTeamSettings(pluginCfg) : null;
21785
+ if (sdkMode && config.autoMerge) throw new Error("sdk_transport_unsupported:auto_merge");
21097
21786
  let worktreeMode = normalizeTeamWorktreeMode(
21098
21787
  process.env.OMC_TEAM_WORKTREE_MODE ?? pluginCfg.team?.ops?.worktreeMode
21099
21788
  );
@@ -21159,21 +21848,33 @@ async function startTeamV2(config) {
21159
21848
  const workerName = workerNames[i];
21160
21849
  const taskIndex = startupByWorker.get(workerName);
21161
21850
  const fallbackAgent = agentTypes[i % agentTypes.length] ?? agentTypes[0] ?? "claude";
21162
- const resolvedAssignment = taskIndex === void 0 ? { agentType: fallbackAgent, model: "", reasoningEffort: void 0, role: void 0 } : resolveTaskAssignment(
21163
- config.tasks[taskIndex],
21164
- resolvedRouting,
21165
- pluginCfg.team?.roleRouting,
21166
- fallbackAgent
21167
- );
21851
+ const roleRoutingConfig = pluginCfg.team?.roleRouting;
21852
+ const task = taskIndex === void 0 ? void 0 : config.tasks[taskIndex];
21853
+ const resolvedAssignment = task === void 0 ? { agentType: fallbackAgent, model: "", reasoningEffort: void 0, role: void 0 } : resolveTaskAssignment(task, resolvedRouting, roleRoutingConfig, fallbackAgent);
21854
+ let role = resolvedAssignment.role ?? void 0;
21855
+ if (sdkMode && role && shouldInjectContract(role, resolvedAssignment.agentType) && task && !isExplicitTaskRoleAssignment(task, roleRoutingConfig, role)) {
21856
+ process.stderr.write(`[omg team] sdk transport: inferred role "${role}" for worker ${workerName} would require a verdict contract the sdk transport cannot process; running as a plain executor instead (an explicitly assigned contract role is still rejected)
21857
+ `);
21858
+ role = void 0;
21859
+ }
21168
21860
  const assignment = {
21169
21861
  agentType: resolvedAssignment.agentType,
21170
21862
  model: resolvedAssignment.model || resolveDefaultModel(resolvedAssignment.agentType),
21171
21863
  reasoningEffort: resolvedAssignment.reasoningEffort,
21172
- ...resolvedAssignment.role ? { role: resolvedAssignment.role } : {}
21864
+ ...role ? { role } : {}
21173
21865
  };
21174
21866
  startupAssignments.set(workerName, assignment);
21175
21867
  effectiveAgentTypes.add(assignment.agentType);
21176
21868
  }
21869
+ if (sdkMode && [...effectiveAgentTypes].some((agentType) => agentType !== "copilot")) {
21870
+ throw new Error(`sdk_transport_requires_copilot_workers:${[...effectiveAgentTypes].join(",")}`);
21871
+ }
21872
+ if (sdkMode) {
21873
+ const contractRoles = [...new Set([...startupAssignments.values()].flatMap((a) => a.role && shouldInjectContract(a.role, a.agentType) ? [a.role] : []))];
21874
+ if (contractRoles.length > 0) {
21875
+ throw new Error(`sdk_transport_unsupported:contract_roles:${contractRoles.join(",")} (${[...CONTRACT_ROLES].join("/")} workers emit verdict files the sdk transport does not process; use --transport pane for an explicitly assigned reviewer-style role, or stop assigning it explicitly to let it run as a plain executor)`);
21876
+ }
21877
+ }
21177
21878
  for (const agentType of effectiveAgentTypes) {
21178
21879
  try {
21179
21880
  resolvedBinaryPaths[agentType] = resolvePreflightBinaryPath(agentType).path;
@@ -21213,7 +21914,7 @@ async function startTeamV2(config) {
21213
21914
  try {
21214
21915
  const pendingConfig = buildTeamInstancePendingConfig(instance);
21215
21916
  const pendingConfigPath = absPath(leaderCwd, TeamPaths.config(sanitized));
21216
- await mkdir16(join37(pendingConfigPath, ".."), { recursive: true });
21917
+ await mkdir16(join42(pendingConfigPath, ".."), { recursive: true });
21217
21918
  await writeFile11(pendingConfigPath, JSON.stringify(pendingConfig, null, 2), "utf-8");
21218
21919
  } catch (error) {
21219
21920
  if (!await rollbackBeforeConfig(error)) throw startupCleanupIncompleteError(error);
@@ -21224,7 +21925,7 @@ async function startTeamV2(config) {
21224
21925
  try {
21225
21926
  await mkdir16(absPath(leaderCwd, TeamPaths.tasks(sanitized)), { recursive: true });
21226
21927
  await mkdir16(absPath(leaderCwd, TeamPaths.workers(sanitized)), { recursive: true });
21227
- await mkdir16(join37(getOmcRoot(leaderCwd), "state", "team", sanitized, "mailbox"), { recursive: true });
21928
+ await mkdir16(join42(getOmcRoot(leaderCwd), "state", "team", sanitized, "mailbox"), { recursive: true });
21228
21929
  for (let i = 0; i < config.tasks.length; i++) {
21229
21930
  const taskId = String(i + 1);
21230
21931
  const task = config.tasks[i];
@@ -21261,7 +21962,7 @@ async function startTeamV2(config) {
21261
21962
  const assignment = startupAssignments.get(workerName);
21262
21963
  if (!assignment) throw new Error(`Missing startup assignment for ${workerName}`);
21263
21964
  const worktree = workerWorktrees.get(workerName);
21264
- const verdictAssignmentId = taskIndex !== void 0 ? randomUUID16() : void 0;
21965
+ const verdictAssignmentId = taskIndex !== void 0 ? randomUUID17() : void 0;
21265
21966
  const outputFile = taskIndex !== void 0 && assignment.role && shouldInjectContract(assignment.role, assignment.agentType) ? cliWorkerOutputFilePath(teamStateRoot(leaderCwd, sanitized), workerName, {
21266
21967
  taskId: String(taskIndex + 1),
21267
21968
  assignmentId: verdictAssignmentId
@@ -21298,7 +21999,8 @@ async function startTeamV2(config) {
21298
21999
  if (!await rollbackBeforeConfig(error)) throw startupCleanupIncompleteError(error);
21299
22000
  throw error;
21300
22001
  }
21301
- for (const line of formatWorkerPermissionLines(preparedLaunches.values())) {
22002
+ const permissionLines = sdkSettings ? [`[omg team] copilot sdk workers (x${preparedLaunches.size}): no allow-all; host permission policy (writes: worktree + team state; shell: denylist, not a sandbox: all but team control/smoke/tmux/git push; no sub-agent tools); deny: ${[...sdkSettings.denyTools, ...sdkSettings.denyUrls.map((u) => `url(${u})`)].join(", ") || "(none)"}; credit cap ${sdkSettings.maxCreditsPerWorker}/worker`] : formatWorkerPermissionLines(preparedLaunches.values());
22003
+ for (const line of permissionLines) {
21302
22004
  process.stderr.write(`${line}
21303
22005
  `);
21304
22006
  }
@@ -21335,7 +22037,7 @@ async function startTeamV2(config) {
21335
22037
  }
21336
22038
  let session;
21337
22039
  try {
21338
- session = await createTeamSession(sanitized, 0, leaderCwd, {
22040
+ session = sdkMode ? { sessionName: sdkTeamTarget(sanitized), leaderPaneId: "", workerPaneIds: [], sessionMode: "split-pane" } : await createTeamSession(sanitized, 0, leaderCwd, {
21339
22041
  newWindow: Boolean(config.newWindow)
21340
22042
  });
21341
22043
  } catch (error) {
@@ -21355,6 +22057,7 @@ async function startTeamV2(config) {
21355
22057
  role: preparedLaunches.get(wName)?.role ?? config.workerRoles?.[i] ?? (agentTypes[i % agentTypes.length] ?? agentTypes[0] ?? "claude"),
21356
22058
  worker_cli: preparedLaunches.get(wName).descriptor.provider,
21357
22059
  launch_descriptor: preparedLaunches.get(wName).descriptor,
22060
+ ...sdkMode ? { transport: "sdk" } : {},
21358
22061
  assigned_tasks: [],
21359
22062
  working_dir: worktree?.path ?? leaderCwd,
21360
22063
  team_state_root: teamStateRoot(leaderCwd, sanitized),
@@ -21400,7 +22103,7 @@ async function startTeamV2(config) {
21400
22103
  service_descriptor: config.autoMerge ? {
21401
22104
  schema_version: 1,
21402
22105
  service_generation: 1,
21403
- service_attempt_id: randomUUID16(),
22106
+ service_attempt_id: randomUUID17(),
21404
22107
  auto_merge_enabled: true,
21405
22108
  workspace_root: leaderCwd,
21406
22109
  leader_branch: autoMergeLeaderBranch,
@@ -21408,7 +22111,7 @@ async function startTeamV2(config) {
21408
22111
  } : {
21409
22112
  schema_version: 1,
21410
22113
  service_generation: 1,
21411
- service_attempt_id: randomUUID16(),
22114
+ service_attempt_id: randomUUID17(),
21412
22115
  auto_merge_enabled: false,
21413
22116
  workspace_root: leaderCwd,
21414
22117
  cadence_policy: "disabled"
@@ -21496,7 +22199,7 @@ async function startTeamV2(config) {
21496
22199
  if (!prepared) continue;
21497
22200
  const workerInfo = workersInfo[workerIndex];
21498
22201
  if (!workerInfo) continue;
21499
- const workerLaunch = await spawnV2Worker({
22202
+ const spawnOptions = {
21500
22203
  sessionName: sessionName2,
21501
22204
  ...session.tmuxServerIdentity ? { tmuxServerIdentity: session.tmuxServerIdentity } : {},
21502
22205
  leaderPaneId,
@@ -21515,7 +22218,8 @@ async function startTeamV2(config) {
21515
22218
  autoMerge: Boolean(config.autoMerge),
21516
22219
  ...prepared.role ? { role: prepared.role } : {},
21517
22220
  ...prepared.verdictAssignmentId ? { verdictAssignmentId: prepared.verdictAssignmentId } : {}
21518
- });
22221
+ };
22222
+ const workerLaunch = sdkSettings ? await spawnSdkV2Worker(spawnOptions, sdkSettings) : await spawnV2Worker(spawnOptions);
21519
22223
  if (workerLaunch.paneId) {
21520
22224
  if (workerLaunch.startupAssigned) workerPaneIds.push(workerLaunch.paneId);
21521
22225
  launchedWorkers.push({
@@ -21680,7 +22384,7 @@ async function writeWatchdogFailedMarker(teamName, cwd, reason) {
21680
22384
  writtenBy: "runtime-v2"
21681
22385
  };
21682
22386
  const root = absPath(cwd, TeamPaths.root(sanitizeTeamName(teamName)));
21683
- const markerPath = join37(root, "watchdog-failed.json");
22387
+ const markerPath = join42(root, "watchdog-failed.json");
21684
22388
  await mkdir16(root, { recursive: true });
21685
22389
  await writeFile12(markerPath, JSON.stringify(marker, null, 2), "utf-8");
21686
22390
  }
@@ -21775,7 +22479,7 @@ async function processCliWorkerVerdictsUnderLock(teamName, cwd, expectedInstance
21775
22479
  "team.runtime-v2.processCliWorkerVerdicts teamMarkTaskCompleted failed"
21776
22480
  );
21777
22481
  const { rename: rename7 } = await import("fs/promises");
21778
- const { renameSync: renameSync6, readFileSync: readFileSync23, existsSync: fsExistsSync } = await import("fs");
22482
+ const { renameSync: renameSync6, readFileSync: readFileSync26, existsSync: fsExistsSync } = await import("fs");
21779
22483
  const { withFileLockSync: withFileLockSync2 } = await Promise.resolve().then(() => (init_file_lock(), file_lock_exports));
21780
22484
  const quarantineNonCursorVerdict = async (outputFile, artifactFingerprint, workerName, taskId, taskVersion, reason) => {
21781
22485
  const stalePath = nonCursorVerdictStalePath(outputFile, artifactFingerprint);
@@ -21808,7 +22512,7 @@ async function processCliWorkerVerdictsUnderLock(teamName, cwd, expectedInstance
21808
22512
  const outputFile = worker.output_file;
21809
22513
  if (!outputFile) continue;
21810
22514
  const paneOwnership = configuredPaneOwnership(config, worker);
21811
- const liveness = paneOwnership ? await getOwnedWorkerLiveness(paneOwnership) : "unknown";
22515
+ const liveness = isSdkTarget(worker.pane_id) ? await getWorkerProviderLiveness(sanitized, cwd, config.instance_id, worker) : paneOwnership ? await getOwnedWorkerLiveness(paneOwnership) : "unknown";
21812
22516
  const workerRole = normalizeDelegationRole(worker.role);
21813
22517
  const cursorReviewer = worker.worker_cli === "cursor" && CONTRACT_ROLES.has(workerRole);
21814
22518
  const liveCursorReviewer = liveness === "alive" && worker.worker_cli === "cursor" && CONTRACT_ROLES.has(workerRole);
@@ -21856,7 +22560,7 @@ async function processCliWorkerVerdictsUnderLock(teamName, cwd, expectedInstance
21856
22560
  return;
21857
22561
  }
21858
22562
  }
21859
- const raw = readFileSync23(outputFile, "utf-8");
22563
+ const raw = readFileSync26(outputFile, "utf-8");
21860
22564
  parseCliWorkerVerdict(raw);
21861
22565
  renameSync6(outputFile, processingOutputFile);
21862
22566
  verdictFile = processingOutputFile;
@@ -22020,7 +22724,7 @@ async function processCliWorkerVerdictsUnderLock(teamName, cwd, expectedInstance
22020
22724
  if (cursorReviewer && verdictFile === processingOutputFile) {
22021
22725
  const processedTaskPath = absPath(cwd, TeamPaths.taskFile(sanitized, payload.task_id));
22022
22726
  try {
22023
- const processedTask = JSON.parse(readFileSync23(processedTaskPath, "utf-8"));
22727
+ const processedTask = JSON.parse(readFileSync26(processedTaskPath, "utf-8"));
22024
22728
  const metadata = processedTask.metadata && typeof processedTask.metadata === "object" ? processedTask.metadata : void 0;
22025
22729
  const processedTaskRole = typeof processedTask.role === "string" ? normalizeDelegationRole(processedTask.role) : null;
22026
22730
  const taskAlreadyRecorded = processedTask.owner === worker.name && (processedTask.status === "completed" || processedTask.status === "failed") && (!cursorReviewer || processedTaskRole === workerRole) && metadata?.verdict_source === "cli_worker_output_contract" && (!cursorReviewer || metadata.verdict_claim_token === payload.claim_token && metadata.verdict_task_version === payload.task_version) && (worker.launch_attempt_id === void 0 || metadata.verdict_worker_launch_attempt_id === worker.launch_attempt_id) && metadata.verdict === payload.verdict;
@@ -22362,20 +23066,28 @@ async function monitorTeamV2(teamName, cwd, expectedInstanceId) {
22362
23066
  const workerScanStartMs = performance.now();
22363
23067
  const workerSignals = await Promise.all(
22364
23068
  config.workers.map(async (worker) => {
23069
+ const providerLiveness = await getWorkerProviderLiveness(sanitized, cwd, config.instance_id, worker);
23070
+ if (isSdkTarget(worker.pane_id)) {
23071
+ const sdkSession = readSdkSession(teamStateRoot(cwd, sanitized), worker.name);
23072
+ const [status2, heartbeat2] = await Promise.all([
23073
+ readWorkerStatus(sanitized, worker.name, cwd),
23074
+ readWorkerHeartbeat(sanitized, worker.name, cwd)
23075
+ ]);
23076
+ return { worker, alive: providerLiveness === "alive", liveness: providerLiveness, providerLiveness, status: status2, heartbeat: heartbeat2, paneCapture: "", sdkSession };
23077
+ }
22365
23078
  const ownership = configuredPaneOwnership(config, worker);
22366
23079
  const liveness = ownership ? await getOwnedWorkerLiveness(ownership) : "unknown";
22367
- const providerLiveness = await getWorkerProviderLiveness(sanitized, cwd, config.instance_id, worker);
22368
23080
  const paneAlive = liveness === "alive";
22369
23081
  const [status, heartbeat, paneCapture] = await Promise.all([
22370
23082
  readWorkerStatus(sanitized, worker.name, cwd),
22371
23083
  readWorkerHeartbeat(sanitized, worker.name, cwd),
22372
23084
  paneAlive && ownership ? captureOwnedTeamPane(ownership) : Promise.resolve("")
22373
23085
  ]);
22374
- return { worker, alive: paneAlive, liveness, providerLiveness, status, heartbeat, paneCapture };
23086
+ return { worker, alive: paneAlive, liveness, providerLiveness, status, heartbeat, paneCapture, sdkSession: null };
22375
23087
  })
22376
23088
  );
22377
23089
  const workerScanMs = performance.now() - workerScanStartMs;
22378
- for (const { worker: w, alive, liveness, providerLiveness, status, heartbeat, paneCapture } of workerSignals) {
23090
+ for (const { worker: w, alive, liveness, providerLiveness, status, heartbeat, paneCapture, sdkSession } of workerSignals) {
22379
23091
  const currentTask = status.current_task_id ? taskById.get(status.current_task_id) ?? null : null;
22380
23092
  const outstandingTask = currentTask ?? findOutstandingWorkerTask(w, taskById, inProgressByOwner);
22381
23093
  const expectedTaskId = status.current_task_id ?? outstandingTask?.id ?? w.assigned_tasks[0] ?? "";
@@ -22398,7 +23110,19 @@ async function monitorTeamV2(teamName, cwd, expectedInstanceId) {
22398
23110
  worktree_detached: w.worktree_detached,
22399
23111
  worktree_created: w.worktree_created,
22400
23112
  team_state_root: w.team_state_root,
22401
- turnsWithoutProgress
23113
+ turnsWithoutProgress,
23114
+ ...sdkSession ? { sdk: {
23115
+ state: sdkSession.state,
23116
+ turns: sdkSession.turns,
23117
+ queued: sdkSession.queued,
23118
+ last_event_type: sdkSession.last_event_type,
23119
+ last_event_at: sdkSession.last_event_at,
23120
+ last_error: sdkSession.last_error,
23121
+ session_id: sdkSession.session_id,
23122
+ model: sdkSession.model,
23123
+ credits: sdkSession.usage.credits,
23124
+ premium_requests: sdkSession.usage.shutdown_premium_requests ?? sdkSession.usage.premium_requests
23125
+ } } : {}
22402
23126
  });
22403
23127
  if (providerLiveness === "dead") {
22404
23128
  deadWorkers.push(w.name);
@@ -22407,13 +23131,16 @@ async function monitorTeamV2(teamName, cwd, expectedInstanceId) {
22407
23131
  recommendations.push(`Reassign task-${t.id} from dead ${w.name}`);
22408
23132
  }
22409
23133
  }
22410
- const paneSuggestsIdle = alive && paneLooksReady(paneCapture) && !paneHasActiveTask(paneCapture);
23134
+ const sdkCapped = Boolean(sdkSession && providerLiveness !== "dead" && sdkSession.state === "capped");
23135
+ const paneSuggestsIdle = sdkSession ? alive && (sdkSession.state === "idle" && sdkSession.queued === 0 || sdkCapped) : alive && paneLooksReady(paneCapture) && !paneHasActiveTask(paneCapture);
22411
23136
  const statusFresh = isFreshTimestamp(status.updated_at);
22412
23137
  const heartbeatFresh = isFreshTimestamp(heartbeat?.last_turn_at);
22413
23138
  const hasWorkStartEvidence = expectedTaskId !== "" && hasWorkerStatusProgress(status, expectedTaskId);
22414
23139
  const missingDependencyIds = outstandingTask ? getMissingDependencyIds(outstandingTask, taskById) : [];
22415
23140
  let stallReason = null;
22416
- if (paneSuggestsIdle && missingDependencyIds.length > 0) {
23141
+ if (sdkCapped) {
23142
+ stallReason = "sdk_credit_cap";
23143
+ } else if (paneSuggestsIdle && missingDependencyIds.length > 0) {
22417
23144
  stallReason = "missing_dependency";
22418
23145
  } else if (paneSuggestsIdle && expectedTaskId !== "" && !hasWorkStartEvidence) {
22419
23146
  stallReason = "no_work_start_evidence";
@@ -22424,7 +23151,15 @@ async function monitorTeamV2(teamName, cwd, expectedInstanceId) {
22424
23151
  }
22425
23152
  if (stallReason) {
22426
23153
  nonReportingWorkers.push(w.name);
22427
- if (stallReason === "missing_dependency") {
23154
+ if (stallReason === "sdk_credit_cap") {
23155
+ const cappedTasks = inProgressByOwner.get(w.name) ?? [];
23156
+ for (const t of cappedTasks) {
23157
+ recommendations.push(`Reassign task-${t.id} from ${w.name}: sdk credit cap reached (${sdkSession?.last_error ?? "capped"}); the worker takes no more prompts`);
23158
+ }
23159
+ if (cappedTasks.length === 0) {
23160
+ recommendations.push(`${w.name} reached its sdk credit cap and takes no more prompts; do not assign it new work`);
23161
+ }
23162
+ } else if (stallReason === "missing_dependency") {
22428
23163
  recommendations.push(
22429
23164
  `Investigate ${w.name}: task-${outstandingTask?.id ?? expectedTaskId} is blocked by missing task ids [${missingDependencyIds.join(", ")}]; pane is idle at prompt`
22430
23165
  );
@@ -22518,7 +23253,7 @@ async function cleanupStaleReservations(teamName, cwd) {
22518
23253
  cwd,
22519
23254
  TeamPaths.teamInstanceReservation(workspaceHash2, sanitized)
22520
23255
  );
22521
- if (!existsSync31(reservationPath2)) return;
23256
+ if (!existsSync35(reservationPath2)) return;
22522
23257
  const contentStr = await readFile16(reservationPath2, "utf-8");
22523
23258
  const reservation = JSON.parse(contentStr);
22524
23259
  if (!(reservation && typeof reservation === "object" && !Array.isArray(reservation) && "owner" in reservation && typeof reservation.owner === "object")) {
@@ -22528,6 +23263,7 @@ async function cleanupStaleReservations(teamName, cwd) {
22528
23263
  if (!(owner && typeof owner === "object" && !Array.isArray(owner) && "pid" in owner && "process_started_at" in owner)) {
22529
23264
  return;
22530
23265
  }
23266
+ if (reservation.phase === "active") return;
22531
23267
  const ownerRecord = owner;
22532
23268
  if (isProcessIdentityDead(ownerRecord)) {
22533
23269
  await unlink7(reservationPath2);
@@ -22544,7 +23280,7 @@ async function cleanupAbandonedTeamState(teamName, cwd) {
22544
23280
  cwd,
22545
23281
  TeamPaths.teamInstanceReservation(workspaceHash2, sanitized)
22546
23282
  );
22547
- if (existsSync31(reservationPath2)) {
23283
+ if (existsSync35(reservationPath2)) {
22548
23284
  try {
22549
23285
  const contentStr = await readFile16(reservationPath2, "utf-8");
22550
23286
  const reservation = JSON.parse(contentStr);
@@ -22560,7 +23296,7 @@ async function cleanupAbandonedTeamState(teamName, cwd) {
22560
23296
  }
22561
23297
  }
22562
23298
  const teamRoot = teamStateRoot(cwd, sanitized);
22563
- if (existsSync31(teamRoot)) {
23299
+ if (existsSync35(teamRoot)) {
22564
23300
  try {
22565
23301
  await rm9(teamRoot, { recursive: true, force: true });
22566
23302
  } catch (error) {
@@ -22657,7 +23393,7 @@ async function shutdownTeamV2(teamName, cwd, options = {}) {
22657
23393
  });
22658
23394
  instance = boundInstance;
22659
23395
  await assertTeamInstanceUnderLock(boundInstance);
22660
- if (!current.config.tmux_session || !current.config.tmux_session.startsWith("cmux:") && !isValidTmuxServerIdentity(current.config.tmux_server_identity)) {
23396
+ if (!current.config.tmux_session || !current.config.tmux_session.startsWith("cmux:") && !isSdkTarget(current.config.tmux_session) && !isValidTmuxServerIdentity(current.config.tmux_server_identity)) {
22661
23397
  throw new Error("tmux_server_identity_missing");
22662
23398
  }
22663
23399
  if (current.config.active_recovery) throw new Error(`shutdown_blocked:active_recovery:${current.config.active_recovery.recovery_id}`);
@@ -22688,7 +23424,7 @@ async function shutdownTeamV2(teamName, cwd, options = {}) {
22688
23424
  }
22689
23425
  const processStartedAt = currentProcessStartIdentity();
22690
23426
  if (!processStartedAt) throw new Error("process_start_identity_unavailable");
22691
- ownedShutdownNonce = randomUUID16();
23427
+ ownedShutdownNonce = randomUUID17();
22692
23428
  const nextRevision = current.stateRevision + 1;
22693
23429
  const next = {
22694
23430
  ...current.config,
@@ -22796,7 +23532,7 @@ async function shutdownTeamV2(teamName, cwd, options = {}) {
22796
23532
  };
22797
23533
  if (!config) {
22798
23534
  const cleanupSafety = inspectTeamWorktreeCleanupSafety(sanitized, cwd);
22799
- if (cleanupSafety.hasEvidence || existsSync31(absPath(cwd, TeamPaths.root(sanitized)))) {
23535
+ if (cleanupSafety.hasEvidence || existsSync35(absPath(cwd, TeamPaths.root(sanitized)))) {
22800
23536
  process.stderr.write("[team/runtime-v2] preserving team state because config is missing and worktree cleanup evidence remains\n");
22801
23537
  return { outcome: "preserved", reason: "config_missing_cleanup_evidence", workers: [] };
22802
23538
  }
@@ -22828,6 +23564,7 @@ Format: {"status":"accept","reason":"ok","updated_at":"<iso>"}
22828
23564
  Then exit your session.
22829
23565
  `;
22830
23566
  await writeWorkerInbox(sanitized, w.name, shutdownInbox, cwd);
23567
+ if (isSdkTarget(w.pane_id)) ringDoorbell(teamStateRoot(cwd, sanitized), w.name, { kind: "shutdown", from: "leader-fixed" });
22831
23568
  } catch (err) {
22832
23569
  process.stderr.write(`[team/runtime-v2] shutdown request failed for ${w.name}: ${err}
22833
23570
  `);
@@ -22868,6 +23605,30 @@ Then exit your session.
22868
23605
  const providerCleanupFailures = [];
22869
23606
  const paneCleanupAlive = [];
22870
23607
  const paneCleanupUnknown = [];
23608
+ const sdkStopTimeoutMs = Math.max(timeoutMs, SDK_HOST_STOP_FLOOR_MS);
23609
+ const sdkStops = /* @__PURE__ */ new Map();
23610
+ for (const worker of config.workers) {
23611
+ if (!isSdkTarget(worker.pane_id) || !worker.launch_attempt_id || !config.tmux_session) continue;
23612
+ const provider = worker.launch_descriptor?.provider ?? worker.worker_cli;
23613
+ if (!provider) continue;
23614
+ const attemptId = worker.launch_attempt_id;
23615
+ const paneId = worker.pane_id;
23616
+ sdkStops.set(worker.name, (async () => {
23617
+ const sdkAttempt = await loadWorkerLaunchAttempt({
23618
+ cwd,
23619
+ teamName: sanitized,
23620
+ instanceId: shutdownInstance.instance_id,
23621
+ workerName: worker.name,
23622
+ paneId,
23623
+ provider,
23624
+ attemptId,
23625
+ runtimeCliPath: resolveRuntimeCliPath()
23626
+ });
23627
+ if (!sdkAttempt) return false;
23628
+ if (!await stopSdkHost(sdkAttempt, teamStateRoot(cwd, sanitized), { timeoutMs: sdkStopTimeoutMs })) return false;
23629
+ return retireAndCleanupCurrentWorkerLaunchAttempt(sdkAttempt, "team_shutdown", async () => true);
23630
+ })().catch(() => false));
23631
+ }
22871
23632
  for (const worker of config.workers) {
22872
23633
  if (!worker.pane_id) {
22873
23634
  providerCleanupFailures.push(worker.name);
@@ -22882,6 +23643,10 @@ Then exit your session.
22882
23643
  providerCleanupFailures.push(worker.name);
22883
23644
  continue;
22884
23645
  }
23646
+ if (isSdkTarget(worker.pane_id)) {
23647
+ if (!await (sdkStops.get(worker.name) ?? Promise.resolve(false))) providerCleanupFailures.push(worker.name);
23648
+ continue;
23649
+ }
22885
23650
  const initialOwnership = configuredPaneOwnership(config, worker);
22886
23651
  const initialPaneLiveness = initialOwnership ? await getOwnedWorkerLiveness(initialOwnership) : "unknown";
22887
23652
  let paneOwnership = null;
@@ -22950,9 +23715,9 @@ Then exit your session.
22950
23715
  killTeamSession: killOwnedTeamSession
22951
23716
  } = await Promise.resolve().then(() => (init_tmux_session(), tmux_session_exports));
22952
23717
  const ownsWindow = config.tmux_window_owned === true;
22953
- const workerPaneIds = recordedWorkerPaneIds;
23718
+ const workerPaneIds = recordedWorkerPaneIds.filter((paneId) => !isSdkTarget(paneId));
22954
23719
  const splitPaneMode = Boolean(config.tmux_session && !ownsWindow && config.tmux_session.includes(":"));
22955
- if (!splitPaneMode && config.tmux_session) {
23720
+ if (!splitPaneMode && config.tmux_session && !isSdkTarget(config.tmux_session)) {
22956
23721
  if (!config.leader_pane_id) {
22957
23722
  if (!await rollbackShutdownForRetry()) await finalizeAutoMerge();
22958
23723
  return { outcome: "preserved", reason: "provider_cleanup_unverified", workers: ["leader-fixed"] };
@@ -23078,7 +23843,7 @@ async function resumeTeamV2(teamName, cwd) {
23078
23843
  const config = await readTeamConfig(sanitized, cwd);
23079
23844
  if (!config?.instance_id) return null;
23080
23845
  const sessionName2 = config.tmux_session || `omc-team-${sanitized}`;
23081
- if (sessionName2.startsWith("cmux:")) {
23846
+ if (sessionName2.startsWith("cmux:") || isSdkTarget(sessionName2)) {
23082
23847
  return {
23083
23848
  teamName: sanitized,
23084
23849
  sanitizedName: sanitized,
@@ -23113,8 +23878,8 @@ async function resumeTeamV2(teamName, cwd) {
23113
23878
  };
23114
23879
  }
23115
23880
  async function findActiveTeamsV2(cwd) {
23116
- const root = join37(getOmcRoot(cwd), "state", "team");
23117
- if (!existsSync31(root)) return [];
23881
+ const root = join42(getOmcRoot(cwd), "state", "team");
23882
+ if (!existsSync35(root)) return [];
23118
23883
  const entries = await readdir6(root, { withFileTypes: true });
23119
23884
  const active = [];
23120
23885
  for (const e of entries) {
@@ -23170,6 +23935,11 @@ var init_runtime_v2 = __esm({
23170
23935
  init_team_owner_epoch();
23171
23936
  init_worker_activation_gate();
23172
23937
  init_worker_launch_ack();
23938
+ init_sdk_transport();
23939
+ init_model_contract();
23940
+ init_copilot_sdk_driver();
23941
+ init_copilot_session_env();
23942
+ init_config_dir();
23173
23943
  init_process_utils();
23174
23944
  init_team_instance();
23175
23945
  init_runtime_flags();
@@ -23271,19 +24041,19 @@ var init_runtime_v2 = __esm({
23271
24041
  });
23272
24042
 
23273
24043
  // src/cli/team.ts
23274
- import { randomUUID as randomUUID17 } from "crypto";
23275
- import { spawn as spawn2 } from "child_process";
24044
+ import { randomUUID as randomUUID18 } from "crypto";
24045
+ import { spawn as spawn3 } from "child_process";
23276
24046
  import {
23277
- existsSync as existsSync34,
23278
- mkdirSync as mkdirSync8,
23279
- readFileSync as readFileSync22,
24047
+ existsSync as existsSync38,
24048
+ mkdirSync as mkdirSync10,
24049
+ readFileSync as readFileSync25,
23280
24050
  renameSync as renameSync5,
23281
24051
  unlinkSync as unlinkSync10,
23282
- writeFileSync as writeFileSync7
24052
+ writeFileSync as writeFileSync10
23283
24053
  } from "fs";
23284
24054
  import { readFile as readFile18 } from "fs/promises";
23285
- import { dirname as dirname30, join as join41, resolve as resolve13 } from "path";
23286
- import { fileURLToPath as fileURLToPath5 } from "url";
24055
+ import { dirname as dirname34, join as join46, resolve as resolve16 } from "path";
24056
+ import { fileURLToPath as fileURLToPath6 } from "url";
23287
24057
 
23288
24058
  // src/team/api-interop.ts
23289
24059
  init_worktree_paths();
@@ -23296,13 +24066,14 @@ init_dispatch_queue();
23296
24066
  init_mailbox_notification_guard();
23297
24067
  init_dispatch_queue();
23298
24068
  init_worker_bootstrap();
24069
+ init_sdk_transport();
23299
24070
  init_runtime_v2();
23300
24071
  init_recovery_request_store();
23301
24072
  init_git_worktree();
23302
24073
  init_swallowed_error();
23303
24074
  init_types();
23304
- import { existsSync as existsSync32, readFileSync as readFileSync20 } from "node:fs";
23305
- import { dirname as dirname29, join as join38, resolve as resolvePath } from "node:path";
24075
+ import { existsSync as existsSync36, readFileSync as readFileSync23 } from "node:fs";
24076
+ import { dirname as dirname33, join as join43, resolve as resolvePath } from "node:path";
23306
24077
  var TEAM_UPDATE_TASK_MUTABLE_FIELDS = /* @__PURE__ */ new Set(["subject", "description", "blocked_by", "requires_code_change", "delegation"]);
23307
24078
  var TEAM_UPDATE_TASK_REQUEST_FIELDS = /* @__PURE__ */ new Set(["team_name", "task_id", "workingDirectory", ...TEAM_UPDATE_TASK_MUTABLE_FIELDS]);
23308
24079
  var RECOVER_WORKER_REQUEST_FIELDS = /* @__PURE__ */ new Set(["team_name", "worker", "request_id", "timeout_ms"]);
@@ -23457,8 +24228,8 @@ function parseTaskDelegationPlan(value) {
23457
24228
  }
23458
24229
  function teamStateExists(teamName, candidateCwd) {
23459
24230
  if (!TEAM_NAME_SAFE_PATTERN.test(teamName)) return false;
23460
- const teamRoot = join38(getOmcRoot(candidateCwd), "state", "team", teamName);
23461
- return existsSync32(join38(teamRoot, "config.json")) || existsSync32(join38(teamRoot, "tasks")) || existsSync32(teamRoot);
24231
+ const teamRoot = join43(getOmcRoot(candidateCwd), "state", "team", teamName);
24232
+ return existsSync36(join43(teamRoot, "config.json")) || existsSync36(join43(teamRoot, "tasks")) || existsSync36(teamRoot);
23462
24233
  }
23463
24234
  function parseTeamWorkerEnv(raw) {
23464
24235
  if (typeof raw !== "string" || raw.trim() === "") return null;
@@ -23520,9 +24291,9 @@ async function executeTeamCleanupViaRuntime(teamName, cwd, options = {}) {
23520
24291
  if (shutdown.outcome !== "cleaned") throw new Error(`team_shutdown_${shutdown.outcome}:${shutdown.reason}`);
23521
24292
  }
23522
24293
  function readTeamStateRootFromFile(path5) {
23523
- if (!existsSync32(path5)) return null;
24294
+ if (!existsSync36(path5)) return null;
23524
24295
  try {
23525
- const parsed = JSON.parse(readFileSync20(path5, "utf8"));
24296
+ const parsed = JSON.parse(readFileSync23(path5, "utf8"));
23526
24297
  return typeof parsed.team_state_root === "string" && parsed.team_state_root.trim() !== "" ? parsed.team_state_root.trim() : null;
23527
24298
  } catch {
23528
24299
  return null;
@@ -23536,7 +24307,7 @@ function stateRootToWorkingDirectory(stateRoot2) {
23536
24307
  if (idx >= 0) {
23537
24308
  const workspaceRoot = absolute.slice(0, idx);
23538
24309
  if (workspaceRoot && workspaceRoot !== "/") return workspaceRoot;
23539
- return dirname29(dirname29(dirname29(dirname29(absolute))));
24310
+ return dirname33(dirname33(dirname33(dirname33(absolute))));
23540
24311
  }
23541
24312
  }
23542
24313
  for (const marker of ["/.omg/state", "/.omx/state"]) {
@@ -23544,22 +24315,22 @@ function stateRootToWorkingDirectory(stateRoot2) {
23544
24315
  if (idx >= 0) {
23545
24316
  const workspaceRoot = absolute.slice(0, idx);
23546
24317
  if (workspaceRoot && workspaceRoot !== "/") return workspaceRoot;
23547
- return dirname29(dirname29(absolute));
24318
+ return dirname33(dirname33(absolute));
23548
24319
  }
23549
24320
  }
23550
- return dirname29(dirname29(absolute));
24321
+ return dirname33(dirname33(absolute));
23551
24322
  }
23552
24323
  function resolveTeamWorkingDirectoryFromMetadata(teamName, candidateCwd, workerContext) {
23553
- const teamRoot = join38(getOmcRoot(candidateCwd), "state", "team", teamName);
23554
- if (!existsSync32(teamRoot)) return null;
24324
+ const teamRoot = join43(getOmcRoot(candidateCwd), "state", "team", teamName);
24325
+ if (!existsSync36(teamRoot)) return null;
23555
24326
  if (workerContext?.teamName === teamName) {
23556
- const workerRoot = readTeamStateRootFromFile(join38(teamRoot, "workers", workerContext.workerName, "identity.json"));
24327
+ const workerRoot = readTeamStateRootFromFile(join43(teamRoot, "workers", workerContext.workerName, "identity.json"));
23557
24328
  if (workerRoot) return stateRootToWorkingDirectory(workerRoot);
23558
24329
  }
23559
- const fromConfig = readTeamStateRootFromFile(join38(teamRoot, "config.json"));
24330
+ const fromConfig = readTeamStateRootFromFile(join43(teamRoot, "config.json"));
23560
24331
  if (fromConfig) return stateRootToWorkingDirectory(fromConfig);
23561
24332
  for (const manifestName of ["manifest.json", "manifest.v2.json"]) {
23562
- const fromManifest = readTeamStateRootFromFile(join38(teamRoot, manifestName));
24333
+ const fromManifest = readTeamStateRootFromFile(join43(teamRoot, manifestName));
23563
24334
  if (fromManifest) return stateRootToWorkingDirectory(fromManifest);
23564
24335
  }
23565
24336
  return null;
@@ -23590,7 +24361,7 @@ function resolveTeamWorkingDirectory(teamName, preferredCwd) {
23590
24361
  if (teamStateExists(normalizedTeamName, cursor)) {
23591
24362
  return resolveTeamWorkingDirectoryFromMetadata(normalizedTeamName, cursor, workerContext) ?? cursor;
23592
24363
  }
23593
- const parent = dirname29(cursor);
24364
+ const parent = dirname33(cursor);
23594
24365
  if (!parent || parent === cursor) break;
23595
24366
  cursor = parent;
23596
24367
  }
@@ -23622,9 +24393,9 @@ async function readMailboxGuardWithCanonicalLeaderTarget(input, cwd) {
23622
24393
  };
23623
24394
  return readCurrentMailboxNotificationGuard(input, cwd, {
23624
24395
  readConfig,
23625
- readStrictDispatchRequest: async (teamName, requestId, requestCwd) => {
24396
+ readStrictDispatchRequest: async (teamName, requestId, requestCwd2) => {
23626
24397
  const [dispatch, config] = await Promise.all([
23627
- readDispatchRequestStrict(teamName, requestId, requestCwd),
24398
+ readDispatchRequestStrict(teamName, requestId, requestCwd2),
23628
24399
  readConfig()
23629
24400
  ]);
23630
24401
  const canonicalLeaderPaneId = config?.leader_pane_id;
@@ -23638,6 +24409,11 @@ async function readMailboxGuardWithCanonicalLeaderTarget(input, cwd) {
23638
24409
  });
23639
24410
  }
23640
24411
  async function notifyMailboxTarget(params) {
24412
+ const recipient = (await teamReadConfig(params.teamName, params.cwd).catch(() => null))?.workers.find((worker) => worker.name === params.toWorker);
24413
+ if (isSdkTarget(recipient?.pane_id)) {
24414
+ ringDoorbell(teamStateRoot(params.cwd, params.teamName), params.toWorker, { kind: "prompt", text: params.triggerMessage, from: "mailbox" });
24415
+ return { ok: true, transport: "mailbox", reason: "sdk_doorbell_queued", request_id: params.requestId, message_id: params.messageId, to_worker: params.toWorker };
24416
+ }
23641
24417
  return runMailboxNotificationAttempt({
23642
24418
  teamName: params.teamName,
23643
24419
  recipient: params.toWorker,
@@ -24313,7 +25089,7 @@ init_tmux_session();
24313
25089
  init_state_paths();
24314
25090
  init_types();
24315
25091
  import { readFile as readFile17 } from "fs/promises";
24316
- import { join as join39 } from "path";
25092
+ import { join as join44 } from "path";
24317
25093
  function stateRoot(cwd, teamName) {
24318
25094
  validateTeamName2(teamName);
24319
25095
  return teamStateRoot(cwd, teamName);
@@ -24326,7 +25102,7 @@ async function readJsonSafe3(filePath) {
24326
25102
  }
24327
25103
  }
24328
25104
  function taskPath(root, taskId) {
24329
- return join39(root, "tasks", `${normalizeTaskFileStem(taskId)}.json`);
25105
+ return join44(root, "tasks", `${normalizeTaskFileStem(taskId)}.json`);
24330
25106
  }
24331
25107
  async function readTask(root, taskId) {
24332
25108
  return readJsonSafe3(taskPath(root, taskId));
@@ -24339,9 +25115,9 @@ async function monitorTeam(teamName, cwd, workerPaneIds) {
24339
25115
  const taskCounts = { pending: 0, inProgress: 0, completed: 0, failed: 0 };
24340
25116
  try {
24341
25117
  const { readdir: readdir7 } = await import("fs/promises");
24342
- const taskFiles = await readdir7(join39(root, "tasks"));
25118
+ const taskFiles = await readdir7(join44(root, "tasks"));
24343
25119
  for (const f of taskFiles.filter((f2) => f2.endsWith(".json"))) {
24344
- const task = await readJsonSafe3(join39(root, "tasks", f));
25120
+ const task = await readJsonSafe3(join44(root, "tasks", f));
24345
25121
  if (task?.status === "pending") taskCounts.pending++;
24346
25122
  else if (task?.status === "in_progress") taskCounts.inProgress++;
24347
25123
  else if (task?.status === "completed") taskCounts.completed++;
@@ -24357,7 +25133,7 @@ async function monitorTeam(teamName, cwd, workerPaneIds) {
24357
25133
  const wName = `worker-${i + 1}`;
24358
25134
  const paneId = workerPaneIds[i];
24359
25135
  const alive = await isWorkerAlive(paneId);
24360
- const heartbeatPath = join39(root, "workers", wName, "heartbeat.json");
25136
+ const heartbeatPath = join44(root, "workers", wName, "heartbeat.json");
24361
25137
  const heartbeat = await readJsonSafe3(heartbeatPath);
24362
25138
  let stalled = false;
24363
25139
  if (heartbeat?.updatedAt) {
@@ -24399,7 +25175,7 @@ async function monitorTeam(teamName, cwd, workerPaneIds) {
24399
25175
  }
24400
25176
  async function resumeTeam(teamName, cwd) {
24401
25177
  const root = stateRoot(cwd, teamName);
24402
- const configData = await readJsonSafe3(join39(root, "config.json"));
25178
+ const configData = await readJsonSafe3(join44(root, "config.json"));
24403
25179
  if (!configData || !isValidTeamInstanceId(configData.instance_id)) return null;
24404
25180
  const sName = configData.tmuxSession;
24405
25181
  const leaderPaneId = configData.leaderPaneId;
@@ -24494,14 +25270,14 @@ init_paths();
24494
25270
 
24495
25271
  // src/planning/artifacts.ts
24496
25272
  init_worktree_paths();
24497
- import { readdirSync as readdirSync12, readFileSync as readFileSync21, existsSync as existsSync33 } from "fs";
24498
- import { join as join40 } from "path";
25273
+ import { readdirSync as readdirSync14, readFileSync as readFileSync24, existsSync as existsSync37 } from "fs";
25274
+ import { join as join45 } from "path";
24499
25275
 
24500
25276
  // src/planning/artifact-names.ts
24501
- import { basename as basename15 } from "path";
25277
+ import { basename as basename16 } from "path";
24502
25278
  var PLANNING_ARTIFACT_TIMESTAMP_PATTERN = /^\d{8}T\d{6}Z$/;
24503
25279
  function legacyTestSpecSlug(fileNameOrPath) {
24504
- const match = basename15(fileNameOrPath).match(/^test-?spec-(?<slug>.+)\.md$/i);
25280
+ const match = basename16(fileNameOrPath).match(/^test-?spec-(?<slug>.+)\.md$/i);
24505
25281
  return match?.groups?.slug ?? null;
24506
25282
  }
24507
25283
  function requiredTimestampedTestSpecFileName(prdArtifact) {
@@ -24522,7 +25298,7 @@ function splitTimestampPrefix(rawSlug) {
24522
25298
  };
24523
25299
  }
24524
25300
  function parsePlanningArtifactFileName(fileNameOrPath) {
24525
- const fileName = basename15(fileNameOrPath);
25301
+ const fileName = basename16(fileNameOrPath);
24526
25302
  const autoresearchDeepInterviewMatch = fileName.match(
24527
25303
  /^deep-interview-autoresearch-(?<slug>.+)\.md$/i
24528
25304
  );
@@ -24586,7 +25362,7 @@ function selectMatchingTestSpecsForPrd(prdPath, testSpecPaths) {
24586
25362
  return [];
24587
25363
  }
24588
25364
  const requiredTimestampedFileName = requiredTimestampedTestSpecFileName(prdArtifact);
24589
- return (requiredTimestampedFileName ? testSpecPaths.filter((path5) => basename15(path5) === requiredTimestampedFileName) : testSpecPaths.filter((path5) => legacyTestSpecSlug(path5) === prdArtifact.slug)).sort(comparePlanningArtifactPaths);
25365
+ return (requiredTimestampedFileName ? testSpecPaths.filter((path5) => basename16(path5) === requiredTimestampedFileName) : testSpecPaths.filter((path5) => legacyTestSpecSlug(path5) === prdArtifact.slug)).sort(comparePlanningArtifactPaths);
24590
25366
  }
24591
25367
  function selectLatestPlanningArtifactPath(paths) {
24592
25368
  return [...paths].sort(comparePlanningArtifactPaths).at(-1) ?? null;
@@ -24595,7 +25371,7 @@ function selectLatestPlanningArtifactPath(paths) {
24595
25371
  // src/planning/artifacts.ts
24596
25372
  function readFileSafe(path5) {
24597
25373
  try {
24598
- return readFileSync21(path5, "utf-8");
25374
+ return readFileSync24(path5, "utf-8");
24599
25375
  } catch {
24600
25376
  return null;
24601
25377
  }
@@ -24622,7 +25398,7 @@ function hasRequiredSections(markdown, headings) {
24622
25398
  );
24623
25399
  }
24624
25400
  function getPlansDirCandidates(cwd) {
24625
- return [join40(getOmcRoot(cwd), "plans"), join40(cwd, ".omx", "plans")];
25401
+ return [join45(getOmcRoot(cwd), "plans"), join45(cwd, ".omx", "plans")];
24626
25402
  }
24627
25403
  function sortArtifactPathsDescending(paths) {
24628
25404
  return [...paths].sort((a, b) => comparePlanningArtifactPaths(b, a));
@@ -24649,19 +25425,19 @@ function readPlanningArtifacts(cwd) {
24649
25425
  const prdPaths = [];
24650
25426
  const testSpecPaths = [];
24651
25427
  for (const plansDir of getPlansDirCandidates(cwd)) {
24652
- if (!existsSync33(plansDir)) {
25428
+ if (!existsSync37(plansDir)) {
24653
25429
  continue;
24654
25430
  }
24655
25431
  try {
24656
- entries = readdirSync12(plansDir);
25432
+ entries = readdirSync14(plansDir);
24657
25433
  } catch {
24658
25434
  continue;
24659
25435
  }
24660
25436
  for (const entry of entries) {
24661
25437
  if (entry.startsWith("prd-") && entry.endsWith(".md")) {
24662
- prdPaths.push(join40(plansDir, entry));
25438
+ prdPaths.push(join45(plansDir, entry));
24663
25439
  } else if (entry.startsWith("test-spec-") && entry.endsWith(".md")) {
24664
- testSpecPaths.push(join40(plansDir, entry));
25440
+ testSpecPaths.push(join45(plansDir, entry));
24665
25441
  }
24666
25442
  }
24667
25443
  }
@@ -24836,22 +25612,22 @@ function resolveRuntimeCliPath2(env = process.env) {
24836
25612
  if (env.OMC_RUNTIME_CLI_PATH) {
24837
25613
  return env.OMC_RUNTIME_CLI_PATH;
24838
25614
  }
24839
- const moduleDir = dirname30(fileURLToPath5(import.meta.url));
24840
- return join41(moduleDir, "../../bridge/runtime-cli.cjs");
25615
+ const moduleDir = dirname34(fileURLToPath6(import.meta.url));
25616
+ return join46(moduleDir, "../../bridge/runtime-cli.cjs");
24841
25617
  }
24842
25618
  function ensureJobsDir(jobsDir) {
24843
- if (!existsSync34(jobsDir)) {
24844
- mkdirSync8(jobsDir, { recursive: true });
25619
+ if (!existsSync38(jobsDir)) {
25620
+ mkdirSync10(jobsDir, { recursive: true });
24845
25621
  }
24846
25622
  }
24847
25623
  function jobPath(jobsDir, jobId) {
24848
- return join41(jobsDir, `${jobId}.json`);
25624
+ return join46(jobsDir, `${jobId}.json`);
24849
25625
  }
24850
25626
  function resultArtifactPath(jobsDir, jobId) {
24851
- return join41(jobsDir, `${jobId}-result.json`);
25627
+ return join46(jobsDir, `${jobId}-result.json`);
24852
25628
  }
24853
25629
  function panesArtifactPath(jobsDir, jobId) {
24854
- return join41(jobsDir, `${jobId}-panes.json`);
25630
+ return join46(jobsDir, `${jobId}-panes.json`);
24855
25631
  }
24856
25632
  function validateJobId(jobId) {
24857
25633
  if (!JOB_ID_PATTERN.test(jobId)) {
@@ -24916,7 +25692,7 @@ async function readPaneArtifact(jobsDir, jobId, instanceId) {
24916
25692
  function resultArtifactIdentityError(jobsDir, jobId, instanceId) {
24917
25693
  let raw;
24918
25694
  try {
24919
- raw = readFileSync22(resultArtifactPath(jobsDir, jobId), "utf-8");
25695
+ raw = readFileSync25(resultArtifactPath(jobsDir, jobId), "utf-8");
24920
25696
  } catch (error) {
24921
25697
  if (error.code === "ENOENT") return null;
24922
25698
  return `cleanup_result_evidence_unreadable:${error instanceof Error ? error.message : String(error)}`;
@@ -24930,7 +25706,7 @@ function resultArtifactIdentityError(jobsDir, jobId, instanceId) {
24930
25706
  function readJobFromDisk(jobId, jobsDir) {
24931
25707
  let content;
24932
25708
  try {
24933
- content = readFileSync22(jobPath(jobsDir, jobId), "utf-8");
25709
+ content = readFileSync25(jobPath(jobsDir, jobId), "utf-8");
24934
25710
  } catch (error) {
24935
25711
  const code = error.code;
24936
25712
  if (code === "ENOENT") return { kind: "missing" };
@@ -24954,14 +25730,14 @@ function formatJobReadError(jobId, result) {
24954
25730
  }
24955
25731
  }
24956
25732
  function jobLockPath(jobsDir, jobId) {
24957
- return join41(jobsDir, `.${jobId}.lock`);
25733
+ return join46(jobsDir, `.${jobId}.lock`);
24958
25734
  }
24959
25735
  function writeJobToDiskUnlocked(jobId, job, jobsDir) {
24960
25736
  ensureJobsDir(jobsDir);
24961
25737
  const targetPath = jobPath(jobsDir, jobId);
24962
- const tempPath = `${targetPath}.tmp.${process.pid}.${randomUUID17()}`;
25738
+ const tempPath = `${targetPath}.tmp.${process.pid}.${randomUUID18()}`;
24963
25739
  try {
24964
- writeFileSync7(tempPath, JSON.stringify(job), { encoding: "utf-8", mode: 384 });
25740
+ writeFileSync10(tempPath, JSON.stringify(job), { encoding: "utf-8", mode: 384 });
24965
25741
  renameSync5(tempPath, targetPath);
24966
25742
  } finally {
24967
25743
  try {
@@ -25082,11 +25858,11 @@ function buildStatus(jobId, job) {
25082
25858
  };
25083
25859
  }
25084
25860
  function generateJobId(now = Date.now()) {
25085
- return `omc-${now.toString(36)}${randomUUID17().slice(0, 8)}`;
25861
+ return `omc-${now.toString(36)}${randomUUID18().slice(0, 8)}`;
25086
25862
  }
25087
25863
  function convergeWithResultArtifact(jobId, job, jobsDir) {
25088
25864
  try {
25089
- const artifactRaw = readFileSync22(resultArtifactPath(jobsDir, jobId), "utf-8");
25865
+ const artifactRaw = readFileSync25(resultArtifactPath(jobsDir, jobId), "utf-8");
25090
25866
  const artifactParsed = parseJsonSafe(artifactRaw);
25091
25867
  if (!artifactParsed) throw new Error("result_artifact_parse_failed");
25092
25868
  if (artifactParsed.status !== "completed" && artifactParsed.status !== "failed") {
@@ -25159,7 +25935,7 @@ async function startTeamJob(input) {
25159
25935
  if (typeof input.cwd !== "string" || input.cwd.trim().length === 0) {
25160
25936
  throw new Error("cwd must be a non-empty path");
25161
25937
  }
25162
- const cwd = resolve13(input.cwd);
25938
+ const cwd = resolve16(input.cwd);
25163
25939
  await assertTeamSpawnAllowed(cwd);
25164
25940
  if (!Array.isArray(input.agentTypes) || input.agentTypes.length === 0) {
25165
25941
  throw new Error("agentTypes must be a non-empty array");
@@ -25176,7 +25952,7 @@ async function startTeamJob(input) {
25176
25952
  const jobsDir = resolveJobsDir();
25177
25953
  const runtimeCliPath = resolveRuntimeCliPath2();
25178
25954
  const jobId = generateJobId();
25179
- const instanceId = randomUUID17();
25955
+ const instanceId = randomUUID18();
25180
25956
  const job = {
25181
25957
  status: "running",
25182
25958
  startedAt: Date.now(),
@@ -25187,7 +25963,7 @@ async function startTeamJob(input) {
25187
25963
  writeJobToDisk(jobId, job, jobsDir);
25188
25964
  let child;
25189
25965
  try {
25190
- child = spawn2(process.execPath, [runtimeCliPath], {
25966
+ child = spawn3(process.execPath, [runtimeCliPath], {
25191
25967
  env: {
25192
25968
  ...process.env,
25193
25969
  OMC_JOB_ID: jobId,
@@ -25291,7 +26067,7 @@ async function waitForTeamJob(jobId, options = {}) {
25291
26067
  if (status2.status !== "running") {
25292
26068
  return status2;
25293
26069
  }
25294
- await new Promise((resolve14) => setTimeout(resolve14, delayMs));
26070
+ await new Promise((resolve17) => setTimeout(resolve17, delayMs));
25295
26071
  delayMs = Math.min(Math.floor(delayMs * 1.5), 2e3);
25296
26072
  }
25297
26073
  const status = await getTeamJobStatus(jobId);