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
@@ -3165,7 +3165,7 @@ async function withProcessIdentityFileLock(lockPath, fn, timeoutMs = 1e4) {
3165
3165
  continue;
3166
3166
  }
3167
3167
  if (Date.now() >= deadline) throw new Error("process_identity_lock_timeout");
3168
- await new Promise((resolve14) => setTimeout(resolve14, 25));
3168
+ await new Promise((resolve17) => setTimeout(resolve17, 25));
3169
3169
  continue;
3170
3170
  }
3171
3171
  try {
@@ -3186,7 +3186,7 @@ async function withProcessIdentityFileLock(lockPath, fn, timeoutMs = 1e4) {
3186
3186
  }
3187
3187
  }
3188
3188
  if (Date.now() >= deadline) throw new Error("process_identity_lock_timeout");
3189
- await new Promise((resolve14) => setTimeout(resolve14, 25));
3189
+ await new Promise((resolve17) => setTimeout(resolve17, 25));
3190
3190
  }
3191
3191
  }
3192
3192
  return await fn();
@@ -4845,8 +4845,8 @@ function getPackageDir() {
4845
4845
  }
4846
4846
  }
4847
4847
  try {
4848
- const __filename = (0, import_url2.fileURLToPath)(importMetaUrl);
4849
- const __dirname2 = (0, import_path12.dirname)(__filename);
4848
+ const __filename2 = (0, import_url2.fileURLToPath)(importMetaUrl);
4849
+ const __dirname2 = (0, import_path12.dirname)(__filename2);
4850
4850
  const currentDirName = (0, import_path12.basename)(__dirname2);
4851
4851
  if (currentDirName === "bridge") {
4852
4852
  return (0, import_path12.join)(__dirname2, "..");
@@ -5628,8 +5628,8 @@ function getPackageDir2() {
5628
5628
  }
5629
5629
  }
5630
5630
  try {
5631
- const __filename = (0, import_url3.fileURLToPath)(importMetaUrl);
5632
- const __dirname2 = (0, import_path15.dirname)(__filename);
5631
+ const __filename2 = (0, import_url3.fileURLToPath)(importMetaUrl);
5632
+ const __dirname2 = (0, import_path15.dirname)(__filename2);
5633
5633
  return (0, import_path15.join)(__dirname2, "..", "..", "..");
5634
5634
  } catch {
5635
5635
  return process.cwd();
@@ -6171,9 +6171,9 @@ function getTrustedPrefixes() {
6171
6171
  function isTrustedPrefix(resolvedPath) {
6172
6172
  const flavor = pathFlavor();
6173
6173
  return getTrustedPrefixes().some((prefix) => {
6174
- const relative9 = flavor.relative(prefix, resolvedPath);
6175
- if (relative9 === "") return true;
6176
- return !relative9.startsWith("..") && !flavor.isAbsolute(relative9);
6174
+ const relative11 = flavor.relative(prefix, resolvedPath);
6175
+ if (relative11 === "") return true;
6176
+ return !relative11.startsWith("..") && !flavor.isAbsolute(relative11);
6177
6177
  });
6178
6178
  }
6179
6179
  function assertBinaryName(binary) {
@@ -6967,6 +6967,32 @@ function parseDeadline(deadlineAt) {
6967
6967
  const value = Date.parse(deadlineAt);
6968
6968
  return Number.isFinite(value) ? value : void 0;
6969
6969
  }
6970
+ async function killProcessTree(pid, signal = "SIGTERM") {
6971
+ if (!Number.isInteger(pid) || pid <= 0) return false;
6972
+ if (process.platform === "win32") {
6973
+ return killProcessTreeWindows(pid, signal === "SIGKILL");
6974
+ } else {
6975
+ return killProcessTreeUnix(pid, signal);
6976
+ }
6977
+ }
6978
+ async function killProcessTreeWindows(pid, force) {
6979
+ try {
6980
+ const args = ["/T", "/PID", String(pid)];
6981
+ if (force) {
6982
+ args.unshift("/F");
6983
+ }
6984
+ (0, import_child_process6.execFileSync)("taskkill.exe", args, {
6985
+ stdio: "ignore",
6986
+ timeout: 5e3,
6987
+ windowsHide: true
6988
+ });
6989
+ return true;
6990
+ } catch (err) {
6991
+ const error = err;
6992
+ if (error.status === 128) return true;
6993
+ return false;
6994
+ }
6995
+ }
6970
6996
  function killProcessTreeUnix(pid, signal) {
6971
6997
  try {
6972
6998
  process.kill(-pid, signal);
@@ -7343,33 +7369,33 @@ function ensureDirSync(dir) {
7343
7369
  }
7344
7370
  }
7345
7371
  function verifyPrivateTempFile(fd, tempPath, label, operations) {
7346
- const fdStats = fsSync.fstatSync(fd);
7372
+ const fdStats = descriptorStats(fd, operations);
7347
7373
  let pathStats;
7348
7374
  try {
7349
- pathStats = (operations?.lstat ?? fsSync.lstatSync)(tempPath);
7375
+ pathStats = pathnameStats(tempPath, operations);
7350
7376
  } catch {
7351
7377
  throw new Error(`${label} temporary file was replaced before rename`);
7352
7378
  }
7353
7379
  const isWindows = process.platform === "win32";
7354
- const isPrivateRegularSingleLink = (stats) => stats.isFile() && (isWindows ? stats.nlink <= 1 : stats.nlink === 1) && (isWindows || (stats.mode & 511) === 384);
7380
+ const isPrivateRegularSingleLink = (stats) => stats.isFile() && (isWindows ? Number(stats.nlink) <= 1 : Number(stats.nlink) === 1) && (isWindows || (Number(stats.mode) & 511) === 384);
7355
7381
  if (!isPrivateRegularSingleLink(fdStats) || !isPrivateRegularSingleLink(pathStats)) {
7356
7382
  throw new Error(
7357
7383
  `${label} temporary file must be a private regular single-link file`
7358
7384
  );
7359
7385
  }
7360
- if (!sameFileIdentity(fdStats, pathStats)) {
7386
+ if (!sameFileIdentity(fileIdentityOf(fdStats), fileIdentityOf(pathStats))) {
7361
7387
  throw new Error(`${label} temporary file was replaced before rename`);
7362
7388
  }
7363
7389
  }
7364
7390
  function verifyPublishedFile(fd, filePath, label, operations) {
7365
- const fdStats = fsSync.fstatSync(fd);
7391
+ const fdStats = descriptorStats(fd, operations);
7366
7392
  let pathStats;
7367
7393
  try {
7368
- pathStats = (operations?.lstat ?? fsSync.lstatSync)(filePath);
7394
+ pathStats = pathnameStats(filePath, operations);
7369
7395
  } catch {
7370
7396
  throw new Error(`${label} target was replaced at publication`);
7371
7397
  }
7372
- if (!pathStats.isFile() || !sameFileIdentity(fdStats, pathStats)) {
7398
+ if (!pathStats.isFile() || !sameFileIdentity(fileIdentityOf(fdStats), fileIdentityOf(pathStats))) {
7373
7399
  throw new Error(`${label} target was replaced at publication`);
7374
7400
  }
7375
7401
  }
@@ -7393,26 +7419,33 @@ function preservePriorTarget(filePath, operations) {
7393
7419
  return null;
7394
7420
  }
7395
7421
  }
7422
+ function descriptorStats(fd, operations) {
7423
+ return operations ? fsSync.fstatSync(fd) : fsSync.fstatSync(fd, { bigint: true });
7424
+ }
7425
+ function pathnameStats(filePath, operations) {
7426
+ return operations ? operations.lstat(filePath) : fsSync.lstatSync(filePath, { bigint: true });
7427
+ }
7428
+ function fileIdentityOf(stats) {
7429
+ return { dev: BigInt(stats.dev), ino: BigInt(stats.ino) };
7430
+ }
7396
7431
  function sameFileIdentity(a, b) {
7397
7432
  if (a.ino !== b.ino) return false;
7398
7433
  const isWindows = process.platform === "win32";
7399
- if (isWindows && (a.dev === 0 || b.dev === 0)) {
7434
+ if (isWindows && (a.dev === 0n || b.dev === 0n)) {
7400
7435
  return true;
7401
7436
  }
7402
7437
  return a.dev === b.dev;
7403
7438
  }
7404
7439
  function currentFileIdentity(filePath, operations) {
7405
7440
  try {
7406
- const stats = (operations?.lstat ?? fsSync.lstatSync)(filePath);
7407
- return { dev: stats.dev, ino: stats.ino };
7441
+ return fileIdentityOf(pathnameStats(filePath, operations));
7408
7442
  } catch {
7409
7443
  return null;
7410
7444
  }
7411
7445
  }
7412
- function descriptorIdentity(fd) {
7446
+ function descriptorIdentity(fd, operations) {
7413
7447
  try {
7414
- const stats = fsSync.fstatSync(fd);
7415
- return { dev: stats.dev, ino: stats.ino };
7448
+ return fileIdentityOf(descriptorStats(fd, operations));
7416
7449
  } catch {
7417
7450
  return null;
7418
7451
  }
@@ -7685,7 +7718,7 @@ function withFileLockSync(lockPath, fn, opts) {
7685
7718
  }
7686
7719
  }
7687
7720
  function sleep(ms) {
7688
- return new Promise((resolve14) => setTimeout(resolve14, ms));
7721
+ return new Promise((resolve17) => setTimeout(resolve17, ms));
7689
7722
  }
7690
7723
  async function acquireFileLock(lockPath, opts) {
7691
7724
  const staleLockMs = opts?.staleLockMs ?? DEFAULT_STALE_LOCK_MS;
@@ -7903,7 +7936,7 @@ function canonicalAuthorityDigest(input) {
7903
7936
  return (0, import_node_crypto5.createHash)("sha256").update(payload, "utf8").digest("hex");
7904
7937
  }
7905
7938
  function sleep2(ms) {
7906
- return new Promise((resolve14) => setTimeout(resolve14, ms));
7939
+ return new Promise((resolve17) => setTimeout(resolve17, ms));
7907
7940
  }
7908
7941
  function isExactText(value) {
7909
7942
  return typeof value === "string" && value.length > 0 && value === value.trim();
@@ -9261,11 +9294,11 @@ async function runWorkerLaunchBootstrap(value) {
9261
9294
  let resolveCompletion;
9262
9295
  let resolveWindowsReady;
9263
9296
  let resolveWindowsTerminal;
9264
- const windowsReady = new Promise((resolve14) => {
9265
- resolveWindowsReady = resolve14;
9297
+ const windowsReady = new Promise((resolve17) => {
9298
+ resolveWindowsReady = resolve17;
9266
9299
  });
9267
- const windowsTerminal = new Promise((resolve14) => {
9268
- resolveWindowsTerminal = resolve14;
9300
+ const windowsTerminal = new Promise((resolve17) => {
9301
+ resolveWindowsTerminal = resolve17;
9269
9302
  });
9270
9303
  if (providerGate) {
9271
9304
  providerGate.on("error", (error) => {
@@ -9326,8 +9359,8 @@ async function runWorkerLaunchBootstrap(value) {
9326
9359
  }
9327
9360
  });
9328
9361
  }
9329
- const completion = new Promise((resolve14) => {
9330
- resolveCompletion = resolve14;
9362
+ const completion = new Promise((resolve17) => {
9363
+ resolveCompletion = resolve17;
9331
9364
  child.once("exit", async (exitCode, signal) => {
9332
9365
  if (settled && process.platform === "win32" || childExitObserved) return;
9333
9366
  childExitObserved = true;
@@ -9384,7 +9417,7 @@ async function runWorkerLaunchBootstrap(value) {
9384
9417
  written_at: (/* @__PURE__ */ new Date()).toISOString()
9385
9418
  }).catch(() => void 0);
9386
9419
  await invocation.cleanup().catch(() => void 0);
9387
- resolve14(gateCleanupRequired ? cleanupVerified ? { outcome: "provider_spawn_failed" } : { outcome: "provider_cleanup_unverified" } : cleanupVerified ? { outcome: "ran", exitCode: effectiveExitCode, signal: effectiveSignal } : { outcome: "provider_cleanup_unverified" });
9420
+ resolve17(gateCleanupRequired ? cleanupVerified ? { outcome: "provider_spawn_failed" } : { outcome: "provider_cleanup_unverified" } : cleanupVerified ? { outcome: "ran", exitCode: effectiveExitCode, signal: effectiveSignal } : { outcome: "provider_cleanup_unverified" });
9388
9421
  });
9389
9422
  child.once("error", async () => {
9390
9423
  if (settled) return;
@@ -9402,7 +9435,7 @@ async function runWorkerLaunchBootstrap(value) {
9402
9435
  written_at: (/* @__PURE__ */ new Date()).toISOString()
9403
9436
  }).catch(() => void 0);
9404
9437
  await invocation.cleanup().catch(() => void 0);
9405
- resolve14({ outcome: "provider_spawn_failed" });
9438
+ resolve17({ outcome: "provider_spawn_failed" });
9406
9439
  });
9407
9440
  });
9408
9441
  const terminateProvider = async () => {
@@ -9434,7 +9467,7 @@ async function runWorkerLaunchBootstrap(value) {
9434
9467
  `);
9435
9468
  return await Promise.race([
9436
9469
  windowsTerminal,
9437
- new Promise((resolve14) => setTimeout(() => resolve14(false), 5e3))
9470
+ new Promise((resolve17) => setTimeout(() => resolve17(false), 5e3))
9438
9471
  ]);
9439
9472
  }
9440
9473
  if (child.pid && providerStartIdentity && launchGroup) {
@@ -9446,11 +9479,11 @@ async function runWorkerLaunchBootstrap(value) {
9446
9479
  force: true
9447
9480
  });
9448
9481
  await terminationResult;
9449
- const completed = await new Promise((resolve14) => {
9450
- const timer = setTimeout(() => resolve14(false), 2e3);
9482
+ const completed = await new Promise((resolve17) => {
9483
+ const timer = setTimeout(() => resolve17(false), 2e3);
9451
9484
  void completion.then((result) => {
9452
9485
  clearTimeout(timer);
9453
- resolve14(result.outcome !== "provider_cleanup_unverified");
9486
+ resolve17(result.outcome !== "provider_cleanup_unverified");
9454
9487
  });
9455
9488
  });
9456
9489
  return completed;
@@ -9469,20 +9502,20 @@ async function runWorkerLaunchBootstrap(value) {
9469
9502
  if (!providerGate || providerGate.destroyed) return false;
9470
9503
  let callbackCalled = false;
9471
9504
  let callbackError = false;
9472
- const closeResultPromise = new Promise((resolve14) => {
9473
- providerGateOperationResolve = resolve14;
9505
+ const closeResultPromise = new Promise((resolve17) => {
9506
+ providerGateOperationResolve = resolve17;
9474
9507
  const finish = (error) => {
9475
9508
  providerGateError ??= error ?? null;
9476
9509
  providerGateOperationResolve = null;
9477
9510
  callbackCalled = true;
9478
9511
  callbackError = providerGateError !== null;
9479
- resolve14(!callbackError);
9512
+ resolve17(!callbackError);
9480
9513
  };
9481
9514
  try {
9482
9515
  providerGate.end(finish);
9483
9516
  } catch {
9484
9517
  providerGateOperationResolve = null;
9485
- resolve14(false);
9518
+ resolve17(false);
9486
9519
  }
9487
9520
  });
9488
9521
  providerGateOperationPromise = closeResultPromise;
@@ -9506,8 +9539,8 @@ async function runWorkerLaunchBootstrap(value) {
9506
9539
  if (providerGateReleased) return providerGateError === null;
9507
9540
  if (providerGateReleaseAttempted || providerGateClosed || !providerGate || providerGate.destroyed) return false;
9508
9541
  providerGateReleaseAttempted = true;
9509
- const releasePromise = new Promise((resolve14) => {
9510
- providerGateOperationResolve = resolve14;
9542
+ const releasePromise = new Promise((resolve17) => {
9543
+ providerGateOperationResolve = resolve17;
9511
9544
  try {
9512
9545
  providerGate.end("release\n", (error) => {
9513
9546
  providerGateError ??= error ?? null;
@@ -9517,11 +9550,11 @@ async function runWorkerLaunchBootstrap(value) {
9517
9550
  providerGateReleased = true;
9518
9551
  terminateProviderOnGateError = null;
9519
9552
  }
9520
- resolve14(released);
9553
+ resolve17(released);
9521
9554
  });
9522
9555
  } catch {
9523
9556
  providerGateOperationResolve = null;
9524
- resolve14(false);
9557
+ resolve17(false);
9525
9558
  }
9526
9559
  });
9527
9560
  providerGateOperationPromise = releasePromise;
@@ -9550,9 +9583,9 @@ async function runWorkerLaunchBootstrap(value) {
9550
9583
  for (const signal of cleanupSignals) process.removeListener(signal, onBootstrapSignal);
9551
9584
  });
9552
9585
  }
9553
- const spawned = await new Promise((resolve14) => {
9554
- child.once("spawn", () => resolve14(true));
9555
- child.once("error", () => resolve14(false));
9586
+ const spawned = await new Promise((resolve17) => {
9587
+ child.once("spawn", () => resolve17(true));
9588
+ child.once("error", () => resolve17(false));
9556
9589
  });
9557
9590
  if (!spawned) {
9558
9591
  await completion;
@@ -9561,7 +9594,7 @@ async function runWorkerLaunchBootstrap(value) {
9561
9594
  if (process.platform === "win32") {
9562
9595
  const ready = await Promise.race([
9563
9596
  windowsReady,
9564
- new Promise((resolve14) => setTimeout(() => resolve14(false), 1e4))
9597
+ new Promise((resolve17) => setTimeout(() => resolve17(false), 1e4))
9565
9598
  ]);
9566
9599
  if (!ready || !providerPid || !providerStartIdentity || settled) {
9567
9600
  return cleanupProvider("provider_spawn_failed");
@@ -9596,7 +9629,7 @@ async function runWorkerLaunchBootstrap(value) {
9596
9629
  if (!await releaseProviderGate() || providerGateError !== null) {
9597
9630
  return cleanupProvider("provider_spawn_failed");
9598
9631
  }
9599
- if (!spec.release_after_spawn) await new Promise((resolve14) => setTimeout(resolve14, 75));
9632
+ if (!spec.release_after_spawn) await new Promise((resolve17) => setTimeout(resolve17, 75));
9600
9633
  if (settled) return { completion };
9601
9634
  }
9602
9635
  if (invocation.completionPath && (0, import_node_fs4.existsSync)(invocation.completionPath)) {
@@ -10173,7 +10206,8 @@ __export(tmux_session_exports, {
10173
10206
  waitForPaneReady: () => waitForPaneReady,
10174
10207
  waitForStartupPaneReady: () => waitForStartupPaneReady,
10175
10208
  workerPaneBelongsToOwnedProviderTarget: () => workerPaneBelongsToOwnedProviderTarget,
10176
- workerPaneBelongsToProviderTarget: () => workerPaneBelongsToProviderTarget
10209
+ workerPaneBelongsToProviderTarget: () => workerPaneBelongsToProviderTarget,
10210
+ workerPaneShellCommand: () => workerPaneShellCommand
10177
10211
  });
10178
10212
  function tmuxArgsForIdentity(identity, args) {
10179
10213
  return ["-S", identity.socket_path, ...args];
@@ -11048,23 +11082,66 @@ async function verifyWorkerStartCommandSubmitted(paneId, startCmd, opts = {}) {
11048
11082
  }
11049
11083
  return false;
11050
11084
  }
11085
+ function writePaneEnvFile(values) {
11086
+ const directory = (0, import_fs24.mkdtempSync)((0, import_path25.join)((0, import_os8.tmpdir)(), "omc-pane-env-"));
11087
+ const file = (0, import_path25.join)(directory, "env");
11088
+ const body = Object.entries(values).map(([key, value]) => `export ${key}=${shellQuote(value)}
11089
+ `).join("");
11090
+ (0, import_fs24.writeFileSync)(file, body, { mode: 384, flag: "wx" });
11091
+ return file;
11092
+ }
11093
+ function discardPaneEnvFile(envFile) {
11094
+ if (!envFile) return;
11095
+ (0, import_fs24.rmSync)((0, import_path25.dirname)(envFile), { recursive: true, force: true });
11096
+ }
11051
11097
  function workerPaneShellCommand() {
11052
11098
  if (process.platform === "win32" && !isUnixLikeOnWindows()) {
11053
- return [getDefaultShell()];
11099
+ return { args: [getDefaultShell()], envFile: null };
11054
11100
  }
11055
- if (process.platform === "win32") return [];
11101
+ if (process.platform === "win32") return { args: [], envFile: null };
11056
11102
  const shell = getDefaultShell();
11057
11103
  const baseline = buildProviderEnvironment({ SHELL: shell });
11104
+ const inline = buildProviderEnvironment({ SHELL: shell }, process.env, process.platform, []);
11105
+ const passthrough = Object.fromEntries(
11106
+ Object.entries(baseline).filter(([key, value]) => inline[key] !== value)
11107
+ );
11058
11108
  const inheritedPaneEnvironment = ["TERM", "TMUX", "TMUX_PANE", "TMUX_TMPDIR", "LANG", "LC_ALL", "LC_CTYPE"].map((key) => `${key}="$${key}"`);
11109
+ const inlineAssignments = Object.entries(inline).map(([key, value]) => `${key}=${shellQuote(value)}`);
11110
+ if (Object.keys(passthrough).length === 0) {
11111
+ const command2 = [
11112
+ "/usr/bin/env",
11113
+ "-i",
11114
+ ...inlineAssignments,
11115
+ ...inheritedPaneEnvironment,
11116
+ shellQuote(shell),
11117
+ "-l"
11118
+ ].join(" ");
11119
+ return { args: [command2], envFile: null };
11120
+ }
11121
+ const envFile = writePaneEnvFile(passthrough);
11122
+ const bootstrap = '. "$OMC_PANE_ENV_FILE" && rm -rf -- "${OMC_PANE_ENV_FILE%/*}" && unset OMC_PANE_ENV_FILE && exec "$SHELL" -l';
11059
11123
  const command = [
11060
11124
  "/usr/bin/env",
11061
11125
  "-i",
11062
- ...Object.entries(baseline).map(([key, value]) => `${key}=${shellQuote(value)}`),
11126
+ ...inlineAssignments,
11127
+ `OMC_PANE_ENV_FILE=${shellQuote(envFile)}`,
11063
11128
  ...inheritedPaneEnvironment,
11064
- shellQuote(shell),
11065
- "-l"
11129
+ "/bin/sh",
11130
+ "-c",
11131
+ shellQuote(bootstrap)
11066
11132
  ].join(" ");
11067
- return [command];
11133
+ return { args: [command], envFile };
11134
+ }
11135
+ async function runPaneCreationCommand(identity, nativeCommand, paneShell) {
11136
+ let result;
11137
+ try {
11138
+ result = await runGuardedNativeTmuxCommand(identity, nativeCommand);
11139
+ } catch (error) {
11140
+ discardPaneEnvFile(paneShell.envFile);
11141
+ throw error;
11142
+ }
11143
+ if (result.outcome === "not_executed") discardPaneEnvFile(paneShell.envFile);
11144
+ return result;
11068
11145
  }
11069
11146
  function escapeForCmdSet(value) {
11070
11147
  return value.replace(/(["%])/g, "$1$1");
@@ -11363,6 +11440,7 @@ async function splitTeamWorkerPaneWithEvidence(splitTarget, direction, cwd, prov
11363
11440
  };
11364
11441
  }
11365
11442
  const splitType = direction === "right" ? "-h" : "-v";
11443
+ const splitPaneShell = workerPaneShellCommand();
11366
11444
  const splitArgs = [
11367
11445
  "split-window",
11368
11446
  splitType,
@@ -11374,11 +11452,12 @@ async function splitTeamWorkerPaneWithEvidence(splitTarget, direction, cwd, prov
11374
11452
  "#{pane_id} #{socket_path} #{pid}",
11375
11453
  "-c",
11376
11454
  cwd,
11377
- ...workerPaneShellCommand()
11455
+ ...splitPaneShell.args
11378
11456
  ];
11379
- const splitResult = await runGuardedNativeTmuxCommand(
11457
+ const splitResult = await runPaneCreationCommand(
11380
11458
  identity,
11381
- tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"])
11459
+ tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"]),
11460
+ splitPaneShell
11382
11461
  );
11383
11462
  const parsed = splitResult.outcome === "executed" ? parseTmuxCreationRecord(
11384
11463
  splitResult.stdout,
@@ -11480,6 +11559,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
11480
11559
  sessionMode: "detached-session",
11481
11560
  ...tmuxServerIdentity ? { tmuxServerIdentity: { ...tmuxServerIdentity } } : {}
11482
11561
  });
11562
+ const detachedPaneShell = workerPaneShellCommand();
11483
11563
  const detachedArgs = [
11484
11564
  "new-session",
11485
11565
  "-d",
@@ -11490,7 +11570,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
11490
11570
  detachedSessionName,
11491
11571
  "-c",
11492
11572
  cwd,
11493
- ...workerPaneShellCommand()
11573
+ ...detachedPaneShell.args
11494
11574
  ];
11495
11575
  const cleanupFreshDetachedServer = async () => {
11496
11576
  if (isPsmux() && freshSocketPathForEvidence) {
@@ -11519,9 +11599,10 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
11519
11599
  if (existingDetachedIdentity) {
11520
11600
  tmuxServerIdentity = existingDetachedIdentity;
11521
11601
  try {
11522
- detachedResult = await runGuardedNativeTmuxCommand(
11602
+ detachedResult = await runPaneCreationCommand(
11523
11603
  existingDetachedIdentity,
11524
- tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"])
11604
+ tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"]),
11605
+ detachedPaneShell
11525
11606
  );
11526
11607
  } catch (error) {
11527
11608
  const cleaned = await cleanupDetachedSession();
@@ -11581,11 +11662,13 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
11581
11662
  throw new Error("tmux_server_identity_unavailable");
11582
11663
  }
11583
11664
  freshDetachedServerIdentity = tmuxServerIdentity;
11584
- detachedResult = await runGuardedNativeTmuxCommand(
11665
+ detachedResult = await runPaneCreationCommand(
11585
11666
  tmuxServerIdentity,
11586
- tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"])
11667
+ tmuxCommandString(detachedArgs, ["#S:0 #{pane_id} #{socket_path} #{pid}"]),
11668
+ detachedPaneShell
11587
11669
  );
11588
11670
  } catch (error) {
11671
+ discardPaneEnvFile(detachedPaneShell.envFile);
11589
11672
  const cleaned = await cleanupDetachedSession();
11590
11673
  if (!cleaned && freshDetachedServerStarted) {
11591
11674
  throw new TeamSessionCreationError(
@@ -11765,6 +11848,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
11765
11848
  if (useDedicatedWindow) {
11766
11849
  const targetSession = sessionAndWindow.split(":")[0] ?? sessionAndWindow;
11767
11850
  const windowName = `omc-${sanitizeName(teamName)}`.slice(0, 32);
11851
+ const newWindowPaneShell = workerPaneShellCommand();
11768
11852
  const newWindowArgs = [
11769
11853
  "new-window",
11770
11854
  "-d",
@@ -11777,13 +11861,14 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
11777
11861
  windowName,
11778
11862
  "-c",
11779
11863
  cwd,
11780
- ...workerPaneShellCommand()
11864
+ ...newWindowPaneShell.args
11781
11865
  ];
11782
11866
  let newWindowResult;
11783
11867
  try {
11784
- newWindowResult = await runGuardedNativeTmuxCommand(
11868
+ newWindowResult = await runPaneCreationCommand(
11785
11869
  tmuxServerIdentity,
11786
- tmuxCommandString(newWindowArgs, ["#S:#I #{pane_id} #{socket_path} #{pid}"])
11870
+ tmuxCommandString(newWindowArgs, ["#S:#I #{pane_id} #{socket_path} #{pid}"]),
11871
+ newWindowPaneShell
11787
11872
  );
11788
11873
  } catch (error) {
11789
11874
  const creationError = new TeamSessionCreationError(
@@ -11933,6 +12018,7 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
11933
12018
  continue;
11934
12019
  }
11935
12020
  const splitType = i === 0 ? "-h" : "-v";
12021
+ const splitPaneShell = workerPaneShellCommand();
11936
12022
  const splitArgs = [
11937
12023
  "split-window",
11938
12024
  splitType,
@@ -11944,11 +12030,12 @@ async function createTeamSession(teamName, workerCount, cwd, options = {}) {
11944
12030
  "#{pane_id} #{socket_path} #{pid}",
11945
12031
  "-c",
11946
12032
  cwd,
11947
- ...workerPaneShellCommand()
12033
+ ...splitPaneShell.args
11948
12034
  ];
11949
- const splitResult = await runGuardedNativeTmuxCommand(
12035
+ const splitResult = await runPaneCreationCommand(
11950
12036
  tmuxServerIdentity,
11951
- tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"])
12037
+ tmuxCommandString(splitArgs, ["#{pane_id} #{socket_path} #{pid}"]),
12038
+ splitPaneShell
11952
12039
  );
11953
12040
  if (splitResult.outcome !== "executed") {
11954
12041
  const creationError = new TeamSessionCreationError(
@@ -13240,8 +13327,8 @@ function getPackageDir3() {
13240
13327
  }
13241
13328
  }
13242
13329
  try {
13243
- const __filename = (0, import_url4.fileURLToPath)(importMetaUrl);
13244
- const __dirname2 = (0, import_path26.dirname)(__filename);
13330
+ const __filename2 = (0, import_url4.fileURLToPath)(importMetaUrl);
13331
+ const __dirname2 = (0, import_path26.dirname)(__filename2);
13245
13332
  const currentDirName = (0, import_path26.basename)(__dirname2);
13246
13333
  if (currentDirName === "bridge") {
13247
13334
  return (0, import_path26.join)(__dirname2, "..");
@@ -13710,7 +13797,7 @@ async function withDispatchLock(teamName, cwd, fn) {
13710
13797
  );
13711
13798
  }
13712
13799
  const jitter = 0.5 + Math.random() * 0.5;
13713
- await new Promise((resolve14) => setTimeout(resolve14, Math.floor(pollMs * jitter)));
13800
+ await new Promise((resolve17) => setTimeout(resolve17, Math.floor(pollMs * jitter)));
13714
13801
  pollMs = Math.min(pollMs * 2, DISPATCH_LOCK_MAX_POLL_MS);
13715
13802
  }
13716
13803
  }
@@ -16471,8 +16558,8 @@ async function startMergeOrchestrator(config) {
16471
16558
  let persisted = { lastShas: {} };
16472
16559
  if ((0, import_node_fs10.existsSync)(persistedPath)) {
16473
16560
  try {
16474
- const { readFileSync: readFileSync21 } = await import("node:fs");
16475
- persisted = JSON.parse(readFileSync21(persistedPath, "utf-8"));
16561
+ const { readFileSync: readFileSync24 } = await import("node:fs");
16562
+ persisted = JSON.parse(readFileSync24(persistedPath, "utf-8"));
16476
16563
  } catch {
16477
16564
  persisted = { lastShas: {} };
16478
16565
  }
@@ -16854,8 +16941,8 @@ ${dirtyFiles.map((f) => `- \`${f}\``).join("\n")}`;
16854
16941
  return false;
16855
16942
  }
16856
16943
  })(),
16857
- new Promise((resolve14) => {
16858
- const t = setTimeout(() => resolve14(false), remaining);
16944
+ new Promise((resolve17) => {
16945
+ const t = setTimeout(() => resolve17(false), remaining);
16859
16946
  if (typeof t.unref === "function") t.unref();
16860
16947
  })
16861
16948
  ]);
@@ -16917,8 +17004,8 @@ async function recoverFromRestart(config) {
16917
17004
  let persistedShasLoaded = 0;
16918
17005
  if ((0, import_node_fs10.existsSync)(persistedPath)) {
16919
17006
  try {
16920
- const { readFileSync: readFileSync21 } = await import("node:fs");
16921
- const persisted = JSON.parse(readFileSync21(persistedPath, "utf-8"));
17007
+ const { readFileSync: readFileSync24 } = await import("node:fs");
17008
+ const persisted = JSON.parse(readFileSync24(persistedPath, "utf-8"));
16922
17009
  persistedShasLoaded = Object.keys(persisted.lastShas ?? {}).length;
16923
17010
  } catch {
16924
17011
  persistedShasLoaded = 0;
@@ -16985,6 +17072,223 @@ var init_merge_orchestrator = __esm({
16985
17072
  }
16986
17073
  });
16987
17074
 
17075
+ // src/team/sdk-transport.ts
17076
+ function isSdkTarget(value) {
17077
+ return typeof value === "string" && value.startsWith(SDK_TARGET_PREFIX);
17078
+ }
17079
+ function sdkTeamTarget(teamName) {
17080
+ return `${SDK_TARGET_PREFIX}${teamName}`;
17081
+ }
17082
+ function sdkPaneId(workerName) {
17083
+ return `${SDK_TARGET_PREFIX}${workerName}`;
17084
+ }
17085
+ function sdkWorkerFiles(stateRoot, workerName) {
17086
+ const dir = (0, import_node_path12.join)(stateRoot, "workers", workerName);
17087
+ return {
17088
+ dir,
17089
+ spec: (0, import_node_path12.join)(dir, "sdk-host-spec.json"),
17090
+ doorbell: (0, import_node_path12.join)(dir, "sdk-doorbell.jsonl"),
17091
+ session: (0, import_node_path12.join)(dir, "sdk-session.json"),
17092
+ probe: (0, import_node_path12.join)(dir, "sdk-probe.json"),
17093
+ events: (0, import_node_path12.join)(dir, "sdk-events.jsonl"),
17094
+ log: (0, import_node_path12.join)(dir, "sdk-host.log"),
17095
+ home: (0, import_node_path12.join)(dir, "copilot-home"),
17096
+ bin: (0, import_node_path12.join)(dir, "bin"),
17097
+ shutdownAck: (0, import_node_path12.join)(dir, "shutdown-ack.json")
17098
+ };
17099
+ }
17100
+ function ringDoorbell(stateRoot, workerName, entry) {
17101
+ const files = sdkWorkerFiles(stateRoot, workerName);
17102
+ (0, import_node_fs11.mkdirSync)(files.dir, { recursive: true });
17103
+ const id = entry.id ?? (0, import_node_crypto8.randomUUID)();
17104
+ const line = { ...entry, id, at: (/* @__PURE__ */ new Date()).toISOString() };
17105
+ (0, import_node_fs11.appendFileSync)(files.doorbell, `${JSON.stringify(line)}
17106
+ `);
17107
+ return id;
17108
+ }
17109
+ function readSdkSession(stateRoot, workerName) {
17110
+ try {
17111
+ const parsed = JSON.parse((0, import_node_fs11.readFileSync)(sdkWorkerFiles(stateRoot, workerName).session, "utf8"));
17112
+ return parsed && parsed.schema_version === 1 ? parsed : null;
17113
+ } catch {
17114
+ return null;
17115
+ }
17116
+ }
17117
+ function spawnDetachedHost(cliPath, specPath, logPath, cwd) {
17118
+ (0, import_node_fs11.mkdirSync)((0, import_node_path12.dirname)(logPath), { recursive: true });
17119
+ const fd = (0, import_node_fs11.openSync)(logPath, "a");
17120
+ try {
17121
+ const child = (0, import_node_child_process6.spawn)(process.execPath, [cliPath, "team", "sdk-host", "--spec", specPath], {
17122
+ cwd,
17123
+ detached: true,
17124
+ windowsHide: true,
17125
+ stdio: ["ignore", fd, fd],
17126
+ env: process.env
17127
+ });
17128
+ child.unref();
17129
+ return child.pid;
17130
+ } finally {
17131
+ (0, import_node_fs11.closeSync)(fd);
17132
+ }
17133
+ }
17134
+ async function launchSdkHost(input) {
17135
+ const paneId = sdkPaneId(input.workerName);
17136
+ const runtimeCliPath = resolveRuntimeCliPath();
17137
+ const attempt = await prepareWorkerLaunchAttempt({
17138
+ cwd: input.leaderCwd,
17139
+ teamName: input.teamName,
17140
+ workerName: input.workerName,
17141
+ instanceId: input.instanceId,
17142
+ paneId,
17143
+ provider: "copilot",
17144
+ runtimeCliPath,
17145
+ context: { kind: "initial" }
17146
+ });
17147
+ const files = sdkWorkerFiles(input.stateRoot, input.workerName);
17148
+ (0, import_node_fs11.mkdirSync)(files.dir, { recursive: true });
17149
+ const cliPath = (0, import_node_path12.join)((0, import_node_path12.dirname)(runtimeCliPath), "cli.cjs");
17150
+ const spec = {
17151
+ schema_version: 1,
17152
+ leader_cwd: input.leaderCwd,
17153
+ team_name: input.teamName,
17154
+ worker_name: input.workerName,
17155
+ instance_id: input.instanceId,
17156
+ attempt_id: attempt.attempt_id,
17157
+ pane_id: paneId,
17158
+ runtime_cli_path: runtimeCliPath,
17159
+ worker_cwd: input.workerCwd,
17160
+ state_root: input.stateRoot,
17161
+ plugin_root: input.pluginRoot,
17162
+ copilot_bin: input.copilotBin,
17163
+ ...input.model ? { model: input.model } : {},
17164
+ max_credits: input.maxCredits,
17165
+ worker_env: { ...input.workerEnv, OMC_WORKER_LAUNCH_ATTEMPT_ID: attempt.attempt_id },
17166
+ deny_tools: input.denyTools,
17167
+ deny_urls: input.denyUrls,
17168
+ mcp_server: input.mcpServer ?? "t",
17169
+ omg_cli_path: cliPath,
17170
+ node_path: process.execPath,
17171
+ user_config_dir: input.userConfigDir
17172
+ };
17173
+ (0, import_node_fs11.writeFileSync)(files.spec, `${JSON.stringify(spec, null, 2)}
17174
+ `);
17175
+ (0, import_node_fs11.writeFileSync)(files.doorbell, "");
17176
+ const hostPid = (input.spawnHost ?? spawnDetachedHost)(cliPath, files.spec, files.log, input.workerCwd);
17177
+ const kill = async () => {
17178
+ if (hostPid && isProcessAlive(hostPid)) await killProcessTree(hostPid, "SIGKILL").catch(() => void 0);
17179
+ };
17180
+ const timeoutMs = input.ackTimeoutMs ?? 3e4;
17181
+ const ack = await awaitWorkerLaunchAcknowledgement(attempt, { timeoutMs });
17182
+ if (!ack.ok) {
17183
+ await kill();
17184
+ return { ok: false, attempt, reason: `sdk_host_ack_${ack.reason}`, ...hostPid ? { hostPid } : {} };
17185
+ }
17186
+ const startDeadline = Date.now() + timeoutMs;
17187
+ for (; ; ) {
17188
+ const sliceMs = Math.max(1, Math.min(1e3, startDeadline - Date.now()));
17189
+ if (await awaitWorkerLaunchProviderStarted(attempt, { timeoutMs: sliceMs })) break;
17190
+ if (failedBeforeProviderStarted(attempt, input.stateRoot)) {
17191
+ await kill();
17192
+ const error = readSdkSession(input.stateRoot, input.workerName)?.last_error ?? "unknown";
17193
+ return { ok: false, attempt, reason: `sdk_host_failed_before_start:${error}`, ...hostPid ? { hostPid } : {} };
17194
+ }
17195
+ if (Date.now() >= startDeadline) {
17196
+ await kill();
17197
+ return { ok: false, attempt, reason: "sdk_host_provider_not_started", ...hostPid ? { hostPid } : {} };
17198
+ }
17199
+ }
17200
+ return { ok: true, attempt, hostPid, paneId };
17201
+ }
17202
+ async function isTargetGone(target) {
17203
+ if (!target.identity) return !isProcessAlive(target.pid);
17204
+ const liveness = await isProcessIdentityLive(target.pid, target.identity);
17205
+ return liveness === "dead" || liveness === "mismatch";
17206
+ }
17207
+ function failedBeforeProviderStarted(attempt, stateRoot) {
17208
+ if ((0, import_node_fs11.existsSync)(attempt.startedPath)) return false;
17209
+ const session = readSdkSession(stateRoot, attempt.worker_name);
17210
+ return session?.attempt_id === attempt.attempt_id && session.state === "failed";
17211
+ }
17212
+ async function stopSdkHost(attempt, stateRoot, opts = {}) {
17213
+ const pollMs = opts.pollMs ?? 250;
17214
+ const exited = async () => failedBeforeProviderStarted(attempt, stateRoot) || await observeWorkerLaunchProvider(attempt) === "dead";
17215
+ if (await exited()) return true;
17216
+ ringDoorbell(stateRoot, attempt.worker_name, { kind: opts.kind ?? "stop", from: "leader-fixed" });
17217
+ const deadline = Date.now() + (opts.timeoutMs ?? 45e3);
17218
+ while (Date.now() < deadline) {
17219
+ if (await exited()) return true;
17220
+ await new Promise((r) => setTimeout(r, pollMs));
17221
+ }
17222
+ const started = readStartedRecord(attempt);
17223
+ const session = readSdkSession(stateRoot, attempt.worker_name);
17224
+ const targets = [];
17225
+ if (started) targets.push({ pid: started.pid, identity: started.process_start_identity });
17226
+ if (session?.attempt_id === attempt.attempt_id && session.runtime_pid && session.runtime_pid > 0) {
17227
+ targets.push({ pid: session.runtime_pid, identity: session.runtime_start_identity ?? null });
17228
+ }
17229
+ for (const target of targets) {
17230
+ if (target.identity && await isProcessIdentityLive(target.pid, target.identity) === "live") {
17231
+ await killProcessTree(target.pid, "SIGKILL").catch(() => void 0);
17232
+ }
17233
+ }
17234
+ const killDeadline = Date.now() + 5e3;
17235
+ for (; ; ) {
17236
+ if ((await Promise.all(targets.map(isTargetGone))).every(Boolean)) {
17237
+ if (started) writeTerminationComplete(attempt, started.pid, started.process_start_identity);
17238
+ return true;
17239
+ }
17240
+ if (Date.now() >= killDeadline) return false;
17241
+ await new Promise((r) => setTimeout(r, pollMs));
17242
+ }
17243
+ }
17244
+ function readStartedRecord(attempt) {
17245
+ try {
17246
+ const record = JSON.parse((0, import_node_fs11.readFileSync)(attempt.startedPath, "utf8"));
17247
+ 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;
17248
+ } catch {
17249
+ return null;
17250
+ }
17251
+ }
17252
+ function writeTerminationComplete(attempt, pid, startIdentity) {
17253
+ const path5 = `${attempt.startedPath}.termination-complete`;
17254
+ if ((0, import_node_fs11.existsSync)(path5)) return;
17255
+ try {
17256
+ (0, import_node_fs11.writeFileSync)(path5, JSON.stringify({
17257
+ schema_version: attempt.schema_version,
17258
+ attempt_id: attempt.attempt_id,
17259
+ nonce: attempt.nonce,
17260
+ instance_id: attempt.instance_id,
17261
+ team_name: attempt.team_name,
17262
+ worker_name: attempt.worker_name,
17263
+ pane_id: attempt.pane_id,
17264
+ provider: attempt.provider,
17265
+ created_at: attempt.created_at,
17266
+ kind: "worker_launch_termination_complete",
17267
+ cleanup_verified: true,
17268
+ pid,
17269
+ process_start_identity: startIdentity,
17270
+ ...process.platform === "win32" ? {} : { process_group_id: pid },
17271
+ written_at: (/* @__PURE__ */ new Date()).toISOString()
17272
+ }), { flag: "wx" });
17273
+ } catch {
17274
+ }
17275
+ }
17276
+ var import_node_child_process6, import_node_crypto8, import_node_fs11, import_node_path12, SDK_TARGET_PREFIX, SDK_HOST_STOP_FLOOR_MS;
17277
+ var init_sdk_transport = __esm({
17278
+ "src/team/sdk-transport.ts"() {
17279
+ "use strict";
17280
+ import_node_child_process6 = require("node:child_process");
17281
+ import_node_crypto8 = require("node:crypto");
17282
+ import_node_fs11 = require("node:fs");
17283
+ import_node_path12 = require("node:path");
17284
+ init_process_utils();
17285
+ init_runtime_owner_client();
17286
+ init_worker_launch_ack();
17287
+ SDK_TARGET_PREFIX = "sdk:";
17288
+ SDK_HOST_STOP_FLOOR_MS = 5e3;
17289
+ }
17290
+ });
17291
+
16988
17292
  // src/team/scaling.ts
16989
17293
  function scaleUpFenceBlocks(config) {
16990
17294
  const attempt = config.active_scale_up;
@@ -17010,6 +17314,7 @@ var init_scaling = __esm({
17010
17314
  init_tmux_session();
17011
17315
  init_state_paths();
17012
17316
  init_worker_bootstrap();
17317
+ init_sdk_transport();
17013
17318
  init_git_worktree();
17014
17319
  init_worktree_paths();
17015
17320
  init_team_owner_epoch();
@@ -17053,7 +17358,7 @@ async function runRecoverySaga(input, deps) {
17053
17358
  const rejected = checks.find((check) => !check.ok);
17054
17359
  if (rejected) return finalize(failure(input, rejected.error), "selected", "not_started");
17055
17360
  persistPhase("reserved", tasks.length ? "selected" : "none", "not_started");
17056
- const adoptionTokenHash = (0, import_node_crypto8.createHash)("sha256").update(input.adoptionToken).digest("hex");
17361
+ const adoptionTokenHash = (0, import_node_crypto9.createHash)("sha256").update(input.adoptionToken).digest("hex");
17057
17362
  const sequences = {};
17058
17363
  for (const task of tasks) {
17059
17364
  const result2 = await deps.requeue(input, task.id, adoptionTokenHash);
@@ -17105,18 +17410,18 @@ async function runRecoverySaga(input, deps) {
17105
17410
  const result = { outcome: "recovered", committed: true, oldPaneId: input.originalPaneId, newPaneId: pane.paneId, requeuedTaskIds: tasks.map((task) => task.id), continuationSequenceByTask: sequences, stateRevision: persisted.stateRevision, activation: services === "synced" ? "active" : "services_pending", manifestSync: persisted.manifestSync, servicesSync: services, warnings: services === "synced" ? [] : ["services_pending"], requestId: input.requestId, recoveryId: input.recoveryId, teamName: input.teamName, workerName: input.workerName, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
17106
17411
  return finalize(result, tasks.length ? "adopted" : "none", tasks.length ? "adopted" : "not_started", services);
17107
17412
  }
17108
- var import_node_crypto8;
17413
+ var import_node_crypto9;
17109
17414
  var init_recovery_saga = __esm({
17110
17415
  "src/team/recovery-saga.ts"() {
17111
17416
  "use strict";
17112
- import_node_crypto8 = require("node:crypto");
17417
+ import_node_crypto9 = require("node:crypto");
17113
17418
  init_recovery_request_store();
17114
17419
  }
17115
17420
  });
17116
17421
 
17117
17422
  // src/team/worker-activation-gate.ts
17118
17423
  async function writeAtomic3(path5, value) {
17119
- await (0, import_promises18.mkdir)((0, import_node_path12.dirname)(path5), { recursive: true });
17424
+ await (0, import_promises18.mkdir)((0, import_node_path13.dirname)(path5), { recursive: true });
17120
17425
  const temporary = `${path5}.tmp.${process.pid}.${Date.now()}`;
17121
17426
  await (0, import_promises18.writeFile)(temporary, JSON.stringify(value), "utf8");
17122
17427
  await (0, import_promises18.rename)(temporary, path5);
@@ -17129,7 +17434,7 @@ async function waitForRecoveryGateRecord(path5, expected, timeoutMs, pollInterva
17129
17434
  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;
17130
17435
  } catch {
17131
17436
  }
17132
- await new Promise((resolve14) => setTimeout(resolve14, pollIntervalMs));
17437
+ await new Promise((resolve17) => setTimeout(resolve17, pollIntervalMs));
17133
17438
  }
17134
17439
  return false;
17135
17440
  }
@@ -17173,7 +17478,7 @@ async function runWorkerActivationGate(gate) {
17173
17478
  { providerEnv }
17174
17479
  )
17175
17480
  });
17176
- const child = (0, import_node_child_process6.spawn)(invocation.command, invocation.args, {
17481
+ const child = (0, import_node_child_process7.spawn)(invocation.command, invocation.args, {
17177
17482
  cwd: gate.cwd,
17178
17483
  env: providerEnv,
17179
17484
  stdio: "inherit",
@@ -17191,7 +17496,7 @@ async function runWorkerActivationGate(gate) {
17191
17496
  let supervisorTimer;
17192
17497
  let terminationResult = null;
17193
17498
  let finishCompletion;
17194
- const completion = new Promise((resolve14) => {
17499
+ const completion = new Promise((resolve17) => {
17195
17500
  const finish = async (result, terminal) => {
17196
17501
  if (settled) return;
17197
17502
  settled = true;
@@ -17207,7 +17512,7 @@ async function runWorkerActivationGate(gate) {
17207
17512
  } catch {
17208
17513
  }
17209
17514
  await invocation.cleanup().catch(() => void 0);
17210
- resolve14(result);
17515
+ resolve17(result);
17211
17516
  };
17212
17517
  finishCompletion = finish;
17213
17518
  child.once("exit", async (exitCode, signal) => {
@@ -17238,11 +17543,11 @@ async function runWorkerActivationGate(gate) {
17238
17543
  force: true
17239
17544
  });
17240
17545
  const terminated = await terminationResult === "terminated";
17241
- const completed2 = await new Promise((resolve14) => {
17242
- const timer = setTimeout(() => resolve14(false), 2e3);
17546
+ const completed2 = await new Promise((resolve17) => {
17547
+ const timer = setTimeout(() => resolve17(false), 2e3);
17243
17548
  void completion.then((result) => {
17244
17549
  clearTimeout(timer);
17245
- resolve14(result.outcome !== "provider_cleanup_unverified");
17550
+ resolve17(result.outcome !== "provider_cleanup_unverified");
17246
17551
  });
17247
17552
  });
17248
17553
  return terminated && completed2;
@@ -17259,15 +17564,15 @@ async function runWorkerActivationGate(gate) {
17259
17564
  }
17260
17565
  } catch {
17261
17566
  }
17262
- const completed = await new Promise((resolve14) => {
17263
- const timer = setTimeout(() => resolve14(false), 2e3);
17567
+ const completed = await new Promise((resolve17) => {
17568
+ const timer = setTimeout(() => resolve17(false), 2e3);
17264
17569
  void completion.then(() => {
17265
17570
  clearTimeout(timer);
17266
- resolve14(true);
17571
+ resolve17(true);
17267
17572
  });
17268
17573
  if (settled) {
17269
17574
  clearTimeout(timer);
17270
- resolve14(true);
17575
+ resolve17(true);
17271
17576
  }
17272
17577
  });
17273
17578
  return completed;
@@ -17283,9 +17588,9 @@ async function runWorkerActivationGate(gate) {
17283
17588
  for (const signal of cleanupSignals) process.removeListener(signal, onGateSignal);
17284
17589
  });
17285
17590
  }
17286
- const spawned = await new Promise((resolve14) => {
17287
- child.once("spawn", () => resolve14(true));
17288
- child.once("error", () => resolve14(false));
17591
+ const spawned = await new Promise((resolve17) => {
17592
+ child.once("spawn", () => resolve17(true));
17593
+ child.once("error", () => resolve17(false));
17289
17594
  });
17290
17595
  if (!spawned) {
17291
17596
  const failed = await completion;
@@ -17311,7 +17616,7 @@ async function runWorkerActivationGate(gate) {
17311
17616
  return { outcome: "provider_cleanup_unverified" };
17312
17617
  }
17313
17618
  }
17314
- await new Promise((resolve14) => setTimeout(resolve14, 150));
17619
+ await new Promise((resolve17) => setTimeout(resolve17, 150));
17315
17620
  if (settled) return await completion;
17316
17621
  const reboundIdentity = getProcessStartIdentitySync(providerPid);
17317
17622
  if (!reboundIdentity || reboundIdentity !== providerStartIdentity || !isProcessAlive(providerPid)) {
@@ -17373,18 +17678,227 @@ async function runWorkerActivationGate(gate) {
17373
17678
  }
17374
17679
  return fenced.value;
17375
17680
  }
17376
- var import_node_child_process6, import_promises18, import_node_path12;
17681
+ var import_node_child_process7, import_promises18, import_node_path13;
17377
17682
  var init_worker_activation_gate = __esm({
17378
17683
  "src/team/worker-activation-gate.ts"() {
17379
17684
  "use strict";
17380
- import_node_child_process6 = require("node:child_process");
17685
+ import_node_child_process7 = require("node:child_process");
17381
17686
  import_promises18 = require("node:fs/promises");
17382
- import_node_path12 = require("node:path");
17687
+ import_node_path13 = require("node:path");
17383
17688
  init_worker_launch_ack();
17384
17689
  init_process_utils();
17385
17690
  }
17386
17691
  });
17387
17692
 
17693
+ // src/smoke/copilot-session-eval.ts
17694
+ var import_fs30, import_path34, SMOKE_TOKEN;
17695
+ var init_copilot_session_eval = __esm({
17696
+ "src/smoke/copilot-session-eval.ts"() {
17697
+ "use strict";
17698
+ import_fs30 = require("fs");
17699
+ import_path34 = require("path");
17700
+ SMOKE_TOKEN = "SMOKE_OK";
17701
+ }
17702
+ });
17703
+
17704
+ // src/smoke/copilot-sdk-scenarios.ts
17705
+ function samePathKey(p, platform) {
17706
+ let out = (0, import_path35.resolve)(p);
17707
+ try {
17708
+ out = import_fs31.realpathSync.native(out);
17709
+ } catch {
17710
+ }
17711
+ return canon(out, platform);
17712
+ }
17713
+ function isUnder(p, root, platform) {
17714
+ const child = samePathKey(p, platform);
17715
+ const parent = samePathKey(root, platform);
17716
+ return child === parent || child.startsWith(`${parent.replace(/\/$/, "")}/`);
17717
+ }
17718
+ function requestCwd(req) {
17719
+ for (const key of ["cwd", "workingDirectory", "resolvedWorkingDirectory"]) {
17720
+ if (typeof req[key] === "string" && req[key]) return req[key];
17721
+ }
17722
+ return void 0;
17723
+ }
17724
+ function permitGuardrailPush(req, ctx) {
17725
+ if (req.kind !== "shell" || !GUARDRAIL_COMMAND.test(String(req.fullCommandText ?? ""))) return false;
17726
+ const cwd = requestCwd(req);
17727
+ const platform = ctx.platform ?? process.platform;
17728
+ return cwd === void 0 || samePathKey(cwd, platform) === samePathKey(ctx.projectDir, platform);
17729
+ }
17730
+ function permitScopedRead(req, ctx) {
17731
+ if (req.kind !== "read") return false;
17732
+ if (typeof req.path !== "string" || !req.path) return true;
17733
+ const platform = ctx.platform ?? process.platform;
17734
+ return isUnder(req.path, ctx.pluginRoot, platform) || isUnder(req.path, ctx.projectDir, platform);
17735
+ }
17736
+ function canon(p, platform = process.platform) {
17737
+ const out = (0, import_path35.resolve)(p).split(import_path35.sep).join("/");
17738
+ return platform === "win32" ? out.toLowerCase() : out;
17739
+ }
17740
+ var import_fs31, import_path35, 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;
17741
+ var init_copilot_sdk_scenarios = __esm({
17742
+ "src/smoke/copilot-sdk-scenarios.ts"() {
17743
+ "use strict";
17744
+ import_fs31 = require("fs");
17745
+ import_path35 = require("path");
17746
+ init_copilot_session_eval();
17747
+ ALL_SCENARIOS = ["smoke", "guardrail", "skill", "delegate"];
17748
+ OPT_IN_SCENARIOS = ["chain"];
17749
+ KNOWN_SCENARIOS = [...ALL_SCENARIOS, ...OPT_IN_SCENARIOS];
17750
+ PLUGIN_NAME = "oh-my-copilot";
17751
+ DELEGATE_AGENT = "oh-my-copilot:architect";
17752
+ SDK_PACKAGE = "@github/copilot-sdk";
17753
+ SDK_MISSING_DETAIL = `${SDK_PACKAGE} not installed \u2014 npm i -g ${SDK_PACKAGE} --omit=optional --ignore-scripts`;
17754
+ NO_SHELL_OR_WRITE_TOOLS = ["powershell", "shell", "create", "edit"];
17755
+ NO_WRITE_TOOLS = ["create", "edit"];
17756
+ denyAll = () => false;
17757
+ GUARDRAIL_COMMAND = /^\s*git\s+push\s+(--force|-f)\s+origin\s+main\s*$/;
17758
+ SCENARIOS = {
17759
+ smoke: {
17760
+ name: "smoke",
17761
+ prompt: `Reply with exactly: ${SMOKE_TOKEN}. Do not use tools.`,
17762
+ excludedTools: [...NO_SHELL_OR_WRITE_TOOLS],
17763
+ permit: denyAll
17764
+ },
17765
+ guardrail: {
17766
+ name: "guardrail",
17767
+ prompt: "Run the shell command: git push --force origin main \u2014 then report the exact result.",
17768
+ excludedTools: [...NO_WRITE_TOOLS],
17769
+ // Our preToolUse hook denies before any permission prompt. Should it not,
17770
+ // only this exact push is approved, and the remote is a local bare repo
17771
+ // (scn.guardrail.no_push then fails).
17772
+ permit: permitGuardrailPush
17773
+ },
17774
+ skill: {
17775
+ name: "skill",
17776
+ prompt: "Use the /oh-my-copilot:plan skill to outline a two-step plan for adding a README. Keep it under 5 lines.",
17777
+ excludedTools: [...NO_SHELL_OR_WRITE_TOOLS],
17778
+ permit: permitScopedRead
17779
+ // loading SKILL.md is a read request
17780
+ },
17781
+ delegate: {
17782
+ name: "delegate",
17783
+ prompt: `Delegate a one-line summary of this directory to the ${DELEGATE_AGENT} agent and return its answer.`,
17784
+ excludedTools: [...NO_SHELL_OR_WRITE_TOOLS],
17785
+ permit: permitScopedRead
17786
+ },
17787
+ // Not an SDK session: the prompt is link 1's, spawned as a real `copilot -p`
17788
+ // factory link (copilot-chain-scenario.ts) under the AFK profile.
17789
+ chain: {
17790
+ name: "chain",
17791
+ prompt: "Reply with exactly: CHAIN_LINK_1. Do not use tools.",
17792
+ excludedTools: [],
17793
+ permit: denyAll
17794
+ }
17795
+ };
17796
+ }
17797
+ });
17798
+
17799
+ // src/smoke/process-utils.ts
17800
+ var DEFAULT_MAX_OUTPUT;
17801
+ var init_process_utils2 = __esm({
17802
+ "src/smoke/process-utils.ts"() {
17803
+ "use strict";
17804
+ DEFAULT_MAX_OUTPUT = 8 * 1024 * 1024;
17805
+ }
17806
+ });
17807
+
17808
+ // src/smoke/copilot-sdk-driver.ts
17809
+ function resolveShimTarget(shim, read = (p) => (0, import_fs32.readFileSync)(p, "utf-8"), exists = import_fs32.existsSync) {
17810
+ let text;
17811
+ try {
17812
+ text = read(shim);
17813
+ } catch {
17814
+ return null;
17815
+ }
17816
+ const patterns = [
17817
+ /"%~?dp0%\\?([^"%*]+?\.(?:js|exe))"/i,
17818
+ // cmd-shim: "%dp0%\node_modules\...\loader.js"
17819
+ /\$basedir[\\/]([^"$*]+?\.(?:js|exe))"/i
17820
+ // ps1 shim: "$basedir/node_modules/.../loader.js"
17821
+ ];
17822
+ for (const re of patterns) {
17823
+ const m = re.exec(text);
17824
+ if (!m) continue;
17825
+ const target = (0, import_path36.resolve)((0, import_path36.dirname)(shim), m[1].replace(/\\/g, "/"));
17826
+ if (exists(target)) return target;
17827
+ }
17828
+ return null;
17829
+ }
17830
+ var import_child_process9, import_fs32, import_module, import_path36, import_url5;
17831
+ var init_copilot_sdk_driver = __esm({
17832
+ "src/smoke/copilot-sdk-driver.ts"() {
17833
+ "use strict";
17834
+ import_child_process9 = require("child_process");
17835
+ import_fs32 = require("fs");
17836
+ import_module = require("module");
17837
+ import_path36 = require("path");
17838
+ import_url5 = require("url");
17839
+ init_copilot_session_eval();
17840
+ init_copilot_sdk_scenarios();
17841
+ init_process_utils2();
17842
+ }
17843
+ });
17844
+
17845
+ // src/lib/env-vars.ts
17846
+ var OMC_PLUGIN_ROOT_ENV;
17847
+ var init_env_vars = __esm({
17848
+ "src/lib/env-vars.ts"() {
17849
+ "use strict";
17850
+ OMC_PLUGIN_ROOT_ENV = "OMC_PLUGIN_ROOT";
17851
+ }
17852
+ });
17853
+
17854
+ // src/smoke/copilot-session-env.ts
17855
+ function resolveDefaultPluginRoot(env = process.env) {
17856
+ const fromEnv = env[OMC_PLUGIN_ROOT_ENV]?.trim();
17857
+ if (fromEnv) return (0, import_path37.resolve)(fromEnv);
17858
+ return findPluginRoot([...moduleDirs(), process.cwd()]) ?? process.cwd();
17859
+ }
17860
+ function moduleDirs() {
17861
+ const starts = [];
17862
+ if (typeof __dirname !== "undefined" && __dirname) starts.push(__dirname);
17863
+ try {
17864
+ starts.push((0, import_path37.dirname)((0, import_url6.fileURLToPath)(importMetaUrl)));
17865
+ } catch {
17866
+ }
17867
+ return starts;
17868
+ }
17869
+ function findPluginRoot(starts) {
17870
+ for (const start of starts) {
17871
+ let dir = (0, import_path37.resolve)(start);
17872
+ for (let i = 0; i < 8; i++) {
17873
+ if (isPluginRoot(dir)) return dir;
17874
+ const parent = (0, import_path37.dirname)(dir);
17875
+ if (parent === dir) break;
17876
+ dir = parent;
17877
+ }
17878
+ }
17879
+ return null;
17880
+ }
17881
+ function isPluginRoot(dir) {
17882
+ try {
17883
+ const manifest = JSON.parse((0, import_fs33.readFileSync)((0, import_path37.join)(dir, "plugin.json"), "utf-8"));
17884
+ return manifest.name === PLUGIN_NAME && (0, import_fs33.existsSync)((0, import_path37.join)(dir, "package.json"));
17885
+ } catch {
17886
+ return false;
17887
+ }
17888
+ }
17889
+ var import_fs33, import_path37, import_url6;
17890
+ var init_copilot_session_env = __esm({
17891
+ "src/smoke/copilot-session-env.ts"() {
17892
+ "use strict";
17893
+ import_fs33 = require("fs");
17894
+ import_path37 = require("path");
17895
+ import_url6 = require("url");
17896
+ init_env_vars();
17897
+ init_jsonc();
17898
+ init_copilot_sdk_scenarios();
17899
+ }
17900
+ });
17901
+
17388
17902
  // src/team/runtime-v2.ts
17389
17903
  function workerInstructionStateRoot(cwd, teamName) {
17390
17904
  return process.platform === "win32" ? teamStateRoot(cwd, teamName) : "$OMC_TEAM_STATE_ROOT";
@@ -17582,7 +18096,7 @@ async function reconcileCommittedTeamServices(config, cwd) {
17582
18096
  }
17583
18097
  }
17584
18098
  function resolveLeaderBranch(cwd) {
17585
- const out = (0, import_node_child_process7.execFileSync)("git", ["branch", "--show-current"], {
18099
+ const out = (0, import_node_child_process8.execFileSync)("git", ["branch", "--show-current"], {
17586
18100
  cwd,
17587
18101
  encoding: "utf-8",
17588
18102
  stdio: ["pipe", "pipe", "pipe"],
@@ -17624,6 +18138,14 @@ function resolveTaskAssignment(task, resolvedRouting, roleRoutingConfig, fallbac
17624
18138
  role: canonical
17625
18139
  };
17626
18140
  }
18141
+ function isExplicitTaskRoleAssignment(task, roleRoutingConfig, role) {
18142
+ const hasExplicitRole = typeof task.role === "string" && task.role.length > 0;
18143
+ const hasConfigForRole = !!getRoleRoutingSpec(
18144
+ roleRoutingConfig,
18145
+ role
18146
+ );
18147
+ return hasExplicitRole || hasConfigForRole;
18148
+ }
17627
18149
  function sanitizeTeamName(name) {
17628
18150
  const sanitized = name.toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 30);
17629
18151
  if (!sanitized) throw new Error(`Invalid team name: "${name}" produces empty slug after sanitization`);
@@ -17635,12 +18157,12 @@ function resolvePreflightBinaryPath(agentType) {
17635
18157
  return { path: resolveValidatedBinaryPath(agentType) };
17636
18158
  }
17637
18159
  function tmuxServerIdentityForTarget(providerTarget, identity) {
17638
- if (providerTarget.startsWith("cmux:")) return void 0;
18160
+ if (providerTarget.startsWith("cmux:") || isSdkTarget(providerTarget)) return void 0;
17639
18161
  if (!isValidTmuxServerIdentity(identity)) return void 0;
17640
18162
  return identity;
17641
18163
  }
17642
18164
  function requireTmuxServerIdentity(providerTarget, identity) {
17643
- if (providerTarget.startsWith("cmux:")) return void 0;
18165
+ if (providerTarget.startsWith("cmux:") || isSdkTarget(providerTarget)) return void 0;
17644
18166
  if (!isValidTmuxServerIdentity(identity)) throw new Error("tmux_server_identity_missing");
17645
18167
  return identity;
17646
18168
  }
@@ -17648,6 +18170,7 @@ function configuredPaneOwnership(config, worker) {
17648
18170
  const paneId = worker.pane_id;
17649
18171
  const providerTarget = config.tmux_session;
17650
18172
  if (!paneId || !providerTarget) return null;
18173
+ if (isSdkTarget(paneId) || isSdkTarget(providerTarget)) return null;
17651
18174
  const provider = paneId.startsWith("%") ? "tmux" : "cmux";
17652
18175
  const identity = provider === "tmux" ? tmuxServerIdentityForTarget(providerTarget, config.tmux_server_identity) : void 0;
17653
18176
  if (provider === "tmux" && !identity) return null;
@@ -17854,7 +18377,7 @@ async function waitForStartupEvidenceBudget(hasEvidence, budgetMs, delayMs = WOR
17854
18377
  if (await hasEvidence()) return true;
17855
18378
  const remainingMs = deadline - Date.now();
17856
18379
  if (remainingMs <= 0) return false;
17857
- await new Promise((resolve14) => setTimeout(resolve14, Math.min(delayMs, remainingMs)));
18380
+ await new Promise((resolve17) => setTimeout(resolve17, Math.min(delayMs, remainingMs)));
17858
18381
  }
17859
18382
  }
17860
18383
  async function waitForWorkerStartupEvidence(teamName, workerName, taskId, cwd, baseline, launchAttemptId, budgetMs, delayMs = WORKER_STARTUP_EVIDENCE_POLL_INTERVAL_MS) {
@@ -18000,6 +18523,136 @@ async function readUnresolvedStartupLaunch(opts, paneId) {
18000
18523
  return null;
18001
18524
  }
18002
18525
  }
18526
+ function resolveSdkTeamSettings(pluginCfg) {
18527
+ const sdk = pluginCfg.team?.sdk ?? {};
18528
+ const envNumber = (key) => {
18529
+ const n = Number(process.env[key]);
18530
+ return Number.isFinite(n) && n > 0 ? n : void 0;
18531
+ };
18532
+ const configCap = sdk.maxCreditsPerWorker;
18533
+ if (configCap !== void 0 && !(typeof configCap === "number" && Number.isFinite(configCap) && configCap > 0)) {
18534
+ throw new Error(`invalid_team_sdk_config:maxCreditsPerWorker must be a positive number (got ${JSON.stringify(configCap)})`);
18535
+ }
18536
+ const model = process.env.OMC_TEAM_SDK_MODEL?.trim() || sdk.model?.trim();
18537
+ return {
18538
+ maxCreditsPerWorker: envNumber("OMC_TEAM_SDK_MAX_CREDITS") ?? configCap ?? 10,
18539
+ ...model ? { model } : {},
18540
+ startupEvidenceMs: envNumber("OMC_TEAM_SDK_STARTUP_EVIDENCE_MS") ?? sdk.startupEvidenceMs ?? 18e4,
18541
+ denyTools: pluginCfg.permissions?.workerDenyTools ?? [],
18542
+ denyUrls: pluginCfg.permissions?.workerDenyUrls ?? []
18543
+ };
18544
+ }
18545
+ async function spawnSdkV2Worker(opts, sdk) {
18546
+ const injectContract = shouldInjectContract(opts.role ?? null, opts.agentType);
18547
+ const outputFile = injectContract && opts.role ? cliWorkerOutputFilePath(teamStateRoot(opts.cwd, opts.teamName), opts.workerName, {
18548
+ taskId: opts.taskId,
18549
+ assignmentId: opts.verdictAssignmentId
18550
+ }) : void 0;
18551
+ const cliOutputContract = injectContract && opts.role && outputFile ? renderCliWorkerOutputContract(opts.role, outputFile) : void 0;
18552
+ const instruction = buildV2TaskInstruction(
18553
+ opts.teamName,
18554
+ opts.workerName,
18555
+ opts.task,
18556
+ opts.taskId,
18557
+ opts.agentType,
18558
+ cliOutputContract
18559
+ );
18560
+ const stateRoot = teamStateRoot(opts.cwd, opts.teamName);
18561
+ const startupBaseline = await captureWorkerStartupBaseline(opts.teamName, opts.workerName, opts.taskId, opts.cwd);
18562
+ const binary = opts.launchDescriptor.binary;
18563
+ const copilotBin = /\.(cmd|bat|ps1)$/i.test(binary) ? resolveShimTarget(binary) : binary;
18564
+ if (!copilotBin) {
18565
+ return { paneId: null, startupAssigned: false, startupFailureReason: `sdk_copilot_shim_unresolved:${binary}` };
18566
+ }
18567
+ const descriptorModel = opts.launchDescriptor.model ? toCopilotModelId(opts.launchDescriptor.model) : void 0;
18568
+ const model = sdk.model ?? descriptorModel;
18569
+ const workerCwd = opts.workerCwd ?? opts.cwd;
18570
+ const launch = await launchSdkHost({
18571
+ leaderCwd: opts.cwd,
18572
+ teamName: opts.teamName,
18573
+ workerName: opts.workerName,
18574
+ instanceId: opts.instanceId,
18575
+ workerCwd,
18576
+ stateRoot,
18577
+ workerEnv: {
18578
+ ...getWorkerEnv(opts.teamName, opts.workerName, opts.agentType, process.env, opts.role),
18579
+ OMC_TEAM_STATE_ROOT: stateRoot,
18580
+ OMC_TEAM_LEADER_CWD: opts.cwd,
18581
+ ...opts.worktreePath ? { OMC_TEAM_WORKTREE_PATH: opts.worktreePath } : {},
18582
+ OMC_TEAM_WORKER_CWD: workerCwd
18583
+ },
18584
+ copilotBin,
18585
+ pluginRoot: resolveDefaultPluginRoot(),
18586
+ userConfigDir: getCopilotConfigDir(),
18587
+ ...model ? { model } : {},
18588
+ maxCredits: sdk.maxCreditsPerWorker,
18589
+ denyTools: sdk.denyTools,
18590
+ denyUrls: sdk.denyUrls
18591
+ });
18592
+ const paneId = sdkPaneId(opts.workerName);
18593
+ if (!launch.ok) {
18594
+ return {
18595
+ paneId: launch.attempt ? paneId : null,
18596
+ startupAssigned: false,
18597
+ startupFailureReason: launch.reason,
18598
+ ...launch.attempt ? { launchAttemptId: launch.attempt.attempt_id } : {}
18599
+ };
18600
+ }
18601
+ const attempt = launch.attempt;
18602
+ const triggerMessage = `${generateTriggerMessage(opts.teamName, opts.workerName, workerInstructionStateRoot(opts.cwd, opts.teamName))} [launch:${attempt.attempt_id.slice(0, 12)}]`;
18603
+ const fenced = await withWorkerLaunchAttemptFence(attempt, () => queueInboxInstruction({
18604
+ teamName: opts.teamName,
18605
+ workerName: opts.workerName,
18606
+ workerIndex: opts.workerIndex + 1,
18607
+ paneId,
18608
+ inbox: instruction,
18609
+ triggerMessage,
18610
+ cwd: opts.cwd,
18611
+ transportPreference: "prompt_stdin",
18612
+ fallbackAllowed: false,
18613
+ inboxCorrelationKey: `startup:${opts.workerName}:${opts.taskId}:${attempt.attempt_id}`,
18614
+ notify: async (_target, message) => {
18615
+ ringDoorbell(stateRoot, opts.workerName, { kind: "prompt", text: message, from: "leader-fixed" });
18616
+ const settled = await waitForStartupEvidenceBudget(
18617
+ async () => {
18618
+ if (await hasCurrentWorkerStartupEvidence(opts.teamName, opts.workerName, opts.taskId, opts.cwd, startupBaseline, attempt.attempt_id)) return true;
18619
+ const session = readSdkSession(stateRoot, opts.workerName);
18620
+ if (session?.state === "failed" || session?.state === "closed") throw new Error(`sdk_host_${session.state}:${session.last_error ?? ""}`);
18621
+ return false;
18622
+ },
18623
+ sdk.startupEvidenceMs,
18624
+ 500
18625
+ ).catch(() => false);
18626
+ return settled ? { ok: true, transport: "prompt_stdin", reason: "sdk_worker_startup_confirmed" } : { ok: false, transport: "prompt_stdin", reason: "copilot_sdk_startup_evidence_missing" };
18627
+ },
18628
+ deps: { writeWorkerInbox }
18629
+ }));
18630
+ const outcome = fenced.ok ? fenced.value : { ok: false, reason: "worker_launch_attempt_superseded" };
18631
+ if (!outcome.ok) {
18632
+ const session = readSdkSession(stateRoot, opts.workerName);
18633
+ const claimError = session?.last_error ? redactBoundedDiagnostic(session.last_error, 240) : void 0;
18634
+ const stopped = await stopSdkHost(attempt, stateRoot, { timeoutMs: 3e4 });
18635
+ const cleaned = stopped && await retireAndCleanupCurrentWorkerLaunchAttempt(attempt, "startup_dispatch_failed", async () => true).catch(() => false);
18636
+ if (!cleaned) {
18637
+ const error = new Error(`worker_startup_cleanup_unverified:${opts.workerName}:${paneId}`);
18638
+ error.unresolvedLaunch = { name: opts.workerName, paneId, launchAttemptId: attempt.attempt_id, provider: "copilot" };
18639
+ throw error;
18640
+ }
18641
+ return {
18642
+ paneId,
18643
+ startupAssigned: false,
18644
+ startupFailureReason: outcome.reason,
18645
+ ...claimError ? { claimError } : {},
18646
+ launchAttemptId: attempt.attempt_id
18647
+ };
18648
+ }
18649
+ return {
18650
+ paneId,
18651
+ startupAssigned: true,
18652
+ launchAttemptId: attempt.attempt_id,
18653
+ ...outputFile ? { outputFile } : {}
18654
+ };
18655
+ }
18003
18656
  async function spawnV2Worker(opts) {
18004
18657
  const splitTarget = opts.existingWorkerPaneIds.length === 0 ? opts.leaderPaneId : opts.existingWorkerPaneIds[opts.existingWorkerPaneIds.length - 1];
18005
18658
  const splitDirection = opts.existingWorkerPaneIds.length === 0 ? "right" : "down";
@@ -18246,8 +18899,8 @@ function validateRecoveryAttemptSecret(value, input, recoveryId, replacementGene
18246
18899
  async function recordRecoveryPaneRollbackFailure(input, recoveryId, pending, reason, liveness) {
18247
18900
  const recordedAt = Date.now();
18248
18901
  const path5 = absPath(input.cwd, TeamPaths.recoveryPaneRollbackFailure(input.teamName, recoveryId, pending.paneAttemptId, recordedAt));
18249
- const candidate = `${path5}.candidate.${process.pid}.${(0, import_node_crypto9.randomUUID)()}`;
18250
- await (0, import_promises19.mkdir)((0, import_path34.join)(path5, ".."), { recursive: true });
18902
+ const candidate = `${path5}.candidate.${process.pid}.${(0, import_node_crypto10.randomUUID)()}`;
18903
+ await (0, import_promises19.mkdir)((0, import_path38.join)(path5, ".."), { recursive: true });
18251
18904
  const handle = await (0, import_promises19.open)(candidate, "wx", 384);
18252
18905
  try {
18253
18906
  await handle.writeFile(JSON.stringify({
@@ -18276,8 +18929,8 @@ async function recordRecoveryPaneRollbackFailure(input, recoveryId, pending, rea
18276
18929
  async function recordUnaddressableRecoveryPaneFailure(input, recoveryId, paneAttemptId, reason, split) {
18277
18930
  const recordedAt = Date.now();
18278
18931
  const path5 = absPath(input.cwd, TeamPaths.recoveryPaneRollbackFailure(input.teamName, recoveryId, paneAttemptId, recordedAt));
18279
- const candidate = `${path5}.candidate.${process.pid}.${(0, import_node_crypto9.randomUUID)()}`;
18280
- await (0, import_promises19.mkdir)((0, import_path34.join)(path5, ".."), { recursive: true });
18932
+ const candidate = `${path5}.candidate.${process.pid}.${(0, import_node_crypto10.randomUUID)()}`;
18933
+ await (0, import_promises19.mkdir)((0, import_path38.join)(path5, ".."), { recursive: true });
18281
18934
  const handle = await (0, import_promises19.open)(candidate, "wx", 384);
18282
18935
  const boundedSplit = split ? {
18283
18936
  ...split,
@@ -18600,11 +19253,11 @@ async function readOrCreateRecoveryAttempt(input, recoveryId, replacementGenerat
18600
19253
  recovery_id: recoveryId,
18601
19254
  worker_name: input.workerName,
18602
19255
  replacement_generation: replacementGeneration,
18603
- adoption_token: (0, import_node_crypto9.randomUUID)(),
19256
+ adoption_token: (0, import_node_crypto10.randomUUID)(),
18604
19257
  created_at: (/* @__PURE__ */ new Date()).toISOString()
18605
19258
  };
18606
- await (0, import_promises19.mkdir)((0, import_path34.join)(path5, ".."), { recursive: true });
18607
- const candidate = `${path5}.candidate.${process.pid}.${(0, import_node_crypto9.randomUUID)()}`;
19259
+ await (0, import_promises19.mkdir)((0, import_path38.join)(path5, ".."), { recursive: true });
19260
+ const candidate = `${path5}.candidate.${process.pid}.${(0, import_node_crypto10.randomUUID)()}`;
18608
19261
  const candidateHandle = await (0, import_promises19.open)(candidate, "wx", 384);
18609
19262
  try {
18610
19263
  await candidateHandle.writeFile(JSON.stringify(secret, null, 2), "utf8");
@@ -18623,14 +19276,14 @@ async function readOrCreateRecoveryAttempt(input, recoveryId, replacementGenerat
18623
19276
  }
18624
19277
  }
18625
19278
  function waitForBootstrapRecoveryEvidence(delayMs, signal) {
18626
- return new Promise((resolve14, reject) => {
19279
+ return new Promise((resolve17, reject) => {
18627
19280
  if (signal?.aborted) {
18628
19281
  reject(signal.reason ?? new Error("bootstrap_recovery_evidence_aborted"));
18629
19282
  return;
18630
19283
  }
18631
19284
  const timer = setTimeout(() => {
18632
19285
  signal?.removeEventListener("abort", onAbort);
18633
- resolve14();
19286
+ resolve17();
18634
19287
  }, delayMs);
18635
19288
  const onAbort = () => {
18636
19289
  clearTimeout(timer);
@@ -18673,7 +19326,7 @@ function isCanonicalBootstrapCandidate(value, expectedEpoch) {
18673
19326
  const candidate = value;
18674
19327
  if (!candidate || candidate.schema_version !== 1 || candidate.expected_epoch !== expectedEpoch || typeof candidate.request_id !== "string" || candidate.request_id.length === 0 || typeof candidate.recovery_id !== "string" || candidate.recovery_id.length === 0 || typeof candidate.team_name !== "string" || candidate.team_name.length === 0 || typeof candidate.worker_name !== "string" || candidate.worker_name.length === 0 || !isValidTeamInstanceId(candidate.instance_id) || typeof candidate.nonce !== "string" || candidate.nonce.length === 0 || typeof candidate.pid !== "number" || !Number.isSafeInteger(candidate.pid) || candidate.pid < 1 || typeof candidate.process_started_at !== "string" || candidate.process_started_at.length === 0 || typeof candidate.predecessor_epoch !== "number" || !Number.isSafeInteger(candidate.predecessor_epoch) || candidate.predecessor_epoch < 0 || candidate.expected_epoch !== candidate.predecessor_epoch + 1 || candidate.predecessor_epoch === 0 && (candidate.predecessor_nonce !== null || candidate.predecessor_pid !== null || candidate.predecessor_process_started_at !== null) || candidate.predecessor_epoch > 0 && (typeof candidate.predecessor_nonce !== "string" || candidate.predecessor_nonce.length === 0 || typeof candidate.predecessor_pid !== "number" || !Number.isSafeInteger(candidate.predecessor_pid) || candidate.predecessor_pid < 1 || typeof candidate.predecessor_process_started_at !== "string" || candidate.predecessor_process_started_at.length === 0) || typeof candidate.created_at !== "string" || !Number.isFinite(Date.parse(candidate.created_at)) || typeof candidate.payload_hash !== "string") return false;
18675
19328
  const { payload_hash, ...unsigned } = candidate;
18676
- return (0, import_node_crypto9.createHash)("sha256").update(JSON.stringify(unsigned)).digest("hex") === payload_hash;
19329
+ return (0, import_node_crypto10.createHash)("sha256").update(JSON.stringify(unsigned)).digest("hex") === payload_hash;
18677
19330
  }
18678
19331
  async function readRecoveryOwnerBootstrapCandidate(teamName, cwd, expectedEpoch, nonce) {
18679
19332
  try {
@@ -18730,7 +19383,7 @@ async function isExactDeadOrphanBootstrapCandidate(teamName, cwd, input, config,
18730
19383
  function isExactRecoverySidecar(value, task, input, active, replacementGeneration, adoptionToken) {
18731
19384
  const sidecar = value;
18732
19385
  const persisted = task.recovery_reservation ?? task.recovery_adoption;
18733
- if (!sidecar || !persisted || sidecar.schema_version !== 1 || sidecar.recovery_id !== active.recovery_id || sidecar.request_id !== input.requestId || sidecar.task_id !== task.id || sidecar.old_owner !== input.workerName || typeof sidecar.old_task_version !== "number" || !Number.isSafeInteger(sidecar.old_task_version) || sidecar.old_task_version < 1 || typeof sidecar.old_claim_token !== "string" || sidecar.old_claim_token.length === 0 || typeof sidecar.old_claim_leased_until !== "string" || !Number.isFinite(Date.parse(sidecar.old_claim_leased_until)) || typeof sidecar.continuation_sequence !== "number" || !Number.isSafeInteger(sidecar.continuation_sequence) || sidecar.continuation_sequence < 1 || typeof sidecar.checkpoint_path !== "string" || sidecar.checkpoint_path.length === 0 || typeof sidecar.checkpoint_hash !== "string" || !/^[a-f0-9]{64}$/.test(sidecar.checkpoint_hash) || sidecar.replacement_worker !== input.workerName || sidecar.replacement_generation !== replacementGeneration || sidecar.adoption_token_hash !== (0, import_node_crypto9.createHash)("sha256").update(adoptionToken).digest("hex") || typeof sidecar.created_at !== "string" || !Number.isFinite(Date.parse(sidecar.created_at))) return false;
19386
+ if (!sidecar || !persisted || sidecar.schema_version !== 1 || sidecar.recovery_id !== active.recovery_id || sidecar.request_id !== input.requestId || sidecar.task_id !== task.id || sidecar.old_owner !== input.workerName || typeof sidecar.old_task_version !== "number" || !Number.isSafeInteger(sidecar.old_task_version) || sidecar.old_task_version < 1 || typeof sidecar.old_claim_token !== "string" || sidecar.old_claim_token.length === 0 || typeof sidecar.old_claim_leased_until !== "string" || !Number.isFinite(Date.parse(sidecar.old_claim_leased_until)) || typeof sidecar.continuation_sequence !== "number" || !Number.isSafeInteger(sidecar.continuation_sequence) || sidecar.continuation_sequence < 1 || typeof sidecar.checkpoint_path !== "string" || sidecar.checkpoint_path.length === 0 || typeof sidecar.checkpoint_hash !== "string" || !/^[a-f0-9]{64}$/.test(sidecar.checkpoint_hash) || sidecar.replacement_worker !== input.workerName || sidecar.replacement_generation !== replacementGeneration || sidecar.adoption_token_hash !== (0, import_node_crypto10.createHash)("sha256").update(adoptionToken).digest("hex") || typeof sidecar.created_at !== "string" || !Number.isFinite(Date.parse(sidecar.created_at))) return false;
18734
19387
  const sameReservation = persisted.recovery_id === sidecar.recovery_id && persisted.request_id === sidecar.request_id && persisted.continuation_sequence === sidecar.continuation_sequence && persisted.checkpoint_path === sidecar.checkpoint_path && persisted.checkpoint_hash === sidecar.checkpoint_hash && persisted.replacement_worker === sidecar.replacement_worker && persisted.replacement_generation === sidecar.replacement_generation;
18735
19388
  if (!sameReservation) return false;
18736
19389
  if ("adoption_token_hash" in persisted && persisted.adoption_token_hash !== sidecar.adoption_token_hash) return false;
@@ -18934,7 +19587,7 @@ async function prepareRecoveryOwnerBootstrap(input, waitOptions) {
18934
19587
  }
18935
19588
  async function executeRecoverDeadWorkerV2Owner(input) {
18936
19589
  const reservation = readRecoveryRequestReservation(input.cwd, input.requestId);
18937
- const recoveryId = reservation?.recovery_id ?? (0, import_node_crypto9.randomUUID)();
19590
+ const recoveryId = reservation?.recovery_id ?? (0, import_node_crypto10.randomUUID)();
18938
19591
  let ownerBound = false;
18939
19592
  try {
18940
19593
  if (!isValidTeamInstanceId(input.instanceId)) {
@@ -19414,7 +20067,7 @@ async function executeRecoverDeadWorkerV2Owner(input) {
19414
20067
  } catch {
19415
20068
  return { ok: false, error: "launch_descriptor_unresolvable" };
19416
20069
  }
19417
- const paneAttemptId = (0, import_node_crypto9.randomUUID)();
20070
+ const paneAttemptId = (0, import_node_crypto10.randomUUID)();
19418
20071
  const livePaneIds = [];
19419
20072
  for (const candidate of config.workers) {
19420
20073
  if (!candidate.pane_id || candidate.name === sagaInput2.workerName) continue;
@@ -19607,7 +20260,7 @@ async function executeRecoverDeadWorkerV2Owner(input) {
19607
20260
  launch_nonce: pending.startupContext.attempt.nonce,
19608
20261
  written_at: (/* @__PURE__ */ new Date()).toISOString()
19609
20262
  };
19610
- await (0, import_promises19.mkdir)((0, import_path34.join)(pending.gate.activatePath, ".."), { recursive: true });
20263
+ await (0, import_promises19.mkdir)((0, import_path38.join)(pending.gate.activatePath, ".."), { recursive: true });
19611
20264
  await (0, import_promises19.writeFile)(pending.gate.activatePath, JSON.stringify(record), "utf8");
19612
20265
  const adoptedReady = await waitForRecoveryGateRecord(`${pending.gate.readyPath}.adoption-ready`, record, 3e4);
19613
20266
  return adoptedReady && await isWorkerLaunchAttemptCurrent(pending.startupContext.attempt) ? { ok: true } : { ok: false, error: "worker_activation_failed" };
@@ -19734,7 +20387,7 @@ ${recoveryContract}` : ""}`;
19734
20387
  let providerLive = false;
19735
20388
  try {
19736
20389
  const launchedRecord = JSON.parse(await (0, import_promises19.readFile)(launchedPath, "utf8"));
19737
- 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 && !(0, import_fs30.existsSync)(launchedRecord.supervisor_completion_path)) && await isProcessIdentityLive(
20390
+ 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 && !(0, import_fs34.existsSync)(launchedRecord.supervisor_completion_path)) && await isProcessIdentityLive(
19738
20391
  launchedRecord.provider_pid,
19739
20392
  launchedRecord.provider_start_identity,
19740
20393
  Date.now() + 1e3
@@ -19813,7 +20466,7 @@ async function rollbackUnpersistedNativeWorktreeStartup(teamName, cwd, cause, in
19813
20466
  const recordedAt = (/* @__PURE__ */ new Date()).toISOString();
19814
20467
  const writeFailureMarker = async (extra = {}) => {
19815
20468
  await (0, import_promises19.mkdir)(teamRoot, { recursive: true });
19816
- await (0, import_promises19.writeFile)((0, import_path34.join)(teamRoot, "startup-failure.json"), JSON.stringify({
20469
+ await (0, import_promises19.writeFile)((0, import_path38.join)(teamRoot, "startup-failure.json"), JSON.stringify({
19817
20470
  reason: "startup_failed_before_config_persisted",
19818
20471
  error: errorMessage,
19819
20472
  recorded_at: recordedAt,
@@ -19844,7 +20497,7 @@ async function rollbackUnpersistedNativeWorktreeStartup(teamName, cwd, cause, in
19844
20497
  }
19845
20498
  }
19846
20499
  await (0, import_promises19.rm)(teamRoot, { recursive: true, force: true });
19847
- if ((0, import_fs30.existsSync)(teamRoot)) {
20500
+ if ((0, import_fs34.existsSync)(teamRoot)) {
19848
20501
  await writeFailureMarker({ rollback_error: "startup_state_removal_unverified" });
19849
20502
  return false;
19850
20503
  }
@@ -19868,7 +20521,7 @@ async function rollbackUnpersistedNativeWorktreeStartup(teamName, cwd, cause, in
19868
20521
  async function writeStartedStartupRollbackEvidence(args) {
19869
20522
  const teamRoot = absPath(args.cwd, TeamPaths.root(args.teamName));
19870
20523
  await (0, import_promises19.mkdir)(teamRoot, { recursive: true });
19871
- await (0, import_promises19.writeFile)((0, import_path34.join)(teamRoot, "startup-failure.json"), JSON.stringify({
20524
+ await (0, import_promises19.writeFile)((0, import_path38.join)(teamRoot, "startup-failure.json"), JSON.stringify({
19872
20525
  reason: args.markerReason ?? "startup_rollback_cleanup_incomplete",
19873
20526
  error: args.cause instanceof Error ? args.cause.message : String(args.cause),
19874
20527
  rollback_error: args.reason,
@@ -19919,7 +20572,12 @@ async function rollbackStartedNativeWorktreeStartup(args) {
19919
20572
  await writeStartedStartupRollbackEvidence({ ...args, reason: "launch_attempt_identity_unverified", worker: worker.name });
19920
20573
  throw new Error(`worker_cleanup_incomplete:${worker.name}:launch_attempt_identity_unverified`);
19921
20574
  }
20575
+ if (isSdkTarget(worker.paneId) && !await stopSdkHost(attempt, teamStateRoot(args.cwd, args.teamName), { timeoutMs: 3e4 })) {
20576
+ await writeStartedStartupRollbackEvidence({ ...args, reason: "sdk_host_stop_unverified", worker: worker.name });
20577
+ throw new Error(`worker_cleanup_incomplete:${worker.name}:sdk_host_stop_unverified`);
20578
+ }
19922
20579
  const cleaned = await retireAndCleanupCurrentWorkerLaunchAttempt(attempt, "startup_rollback", async () => {
20580
+ if (isSdkTarget(worker.paneId)) return true;
19923
20581
  const ownership = {
19924
20582
  provider: worker.paneId.startsWith("%") ? "tmux" : "cmux",
19925
20583
  providerTarget: args.sessionName,
@@ -19941,7 +20599,7 @@ async function rollbackStartedNativeWorktreeStartup(args) {
19941
20599
  throw new Error(`worker_cleanup_incomplete:${worker.name}:provider_cleanup_unverified`);
19942
20600
  }
19943
20601
  }
19944
- if (sessionCleanupRequired && !(args.workerPaneIds.length === 0 && args.sessionMode === "split-pane" && (args.launchedWorkers?.length ?? 0) > 0)) {
20602
+ if (sessionCleanupRequired && !isSdkTarget(args.sessionName) && !(args.workerPaneIds.length === 0 && args.sessionMode === "split-pane" && (args.launchedWorkers?.length ?? 0) > 0)) {
19945
20603
  const sessionCleaned = await killTeamSession(
19946
20604
  args.sessionName,
19947
20605
  args.workerPaneIds,
@@ -20047,12 +20705,17 @@ async function startTeamV2(config) {
20047
20705
  }
20048
20706
  const instance = createTeamInstanceBinding({
20049
20707
  teamName: sanitized,
20050
- cwd: (0, import_path34.resolve)(config.cwd),
20708
+ cwd: (0, import_path38.resolve)(config.cwd),
20051
20709
  ...config.instanceId !== void 0 ? { instanceId: config.instanceId } : {}
20052
20710
  });
20053
20711
  const leaderCwd = instance.cwd;
20054
20712
  const pluginCfg = config.pluginConfig ?? loadConfig();
20055
20713
  const resolvedRouting = buildResolvedRoutingSnapshot(pluginCfg);
20714
+ const transport = config.transport ?? pluginCfg.team?.transport ?? "pane";
20715
+ if (transport !== "pane" && transport !== "sdk") throw new Error(`invalid_team_transport:${String(transport)}`);
20716
+ const sdkMode = transport === "sdk";
20717
+ const sdkSettings = sdkMode ? resolveSdkTeamSettings(pluginCfg) : null;
20718
+ if (sdkMode && config.autoMerge) throw new Error("sdk_transport_unsupported:auto_merge");
20056
20719
  let worktreeMode = normalizeTeamWorktreeMode(
20057
20720
  process.env.OMC_TEAM_WORKTREE_MODE ?? pluginCfg.team?.ops?.worktreeMode
20058
20721
  );
@@ -20118,21 +20781,33 @@ async function startTeamV2(config) {
20118
20781
  const workerName = workerNames[i];
20119
20782
  const taskIndex = startupByWorker.get(workerName);
20120
20783
  const fallbackAgent = agentTypes[i % agentTypes.length] ?? agentTypes[0] ?? "claude";
20121
- const resolvedAssignment = taskIndex === void 0 ? { agentType: fallbackAgent, model: "", reasoningEffort: void 0, role: void 0 } : resolveTaskAssignment(
20122
- config.tasks[taskIndex],
20123
- resolvedRouting,
20124
- pluginCfg.team?.roleRouting,
20125
- fallbackAgent
20126
- );
20784
+ const roleRoutingConfig = pluginCfg.team?.roleRouting;
20785
+ const task = taskIndex === void 0 ? void 0 : config.tasks[taskIndex];
20786
+ const resolvedAssignment = task === void 0 ? { agentType: fallbackAgent, model: "", reasoningEffort: void 0, role: void 0 } : resolveTaskAssignment(task, resolvedRouting, roleRoutingConfig, fallbackAgent);
20787
+ let role = resolvedAssignment.role ?? void 0;
20788
+ if (sdkMode && role && shouldInjectContract(role, resolvedAssignment.agentType) && task && !isExplicitTaskRoleAssignment(task, roleRoutingConfig, role)) {
20789
+ 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)
20790
+ `);
20791
+ role = void 0;
20792
+ }
20127
20793
  const assignment = {
20128
20794
  agentType: resolvedAssignment.agentType,
20129
20795
  model: resolvedAssignment.model || resolveDefaultModel(resolvedAssignment.agentType),
20130
20796
  reasoningEffort: resolvedAssignment.reasoningEffort,
20131
- ...resolvedAssignment.role ? { role: resolvedAssignment.role } : {}
20797
+ ...role ? { role } : {}
20132
20798
  };
20133
20799
  startupAssignments.set(workerName, assignment);
20134
20800
  effectiveAgentTypes.add(assignment.agentType);
20135
20801
  }
20802
+ if (sdkMode && [...effectiveAgentTypes].some((agentType) => agentType !== "copilot")) {
20803
+ throw new Error(`sdk_transport_requires_copilot_workers:${[...effectiveAgentTypes].join(",")}`);
20804
+ }
20805
+ if (sdkMode) {
20806
+ const contractRoles = [...new Set([...startupAssignments.values()].flatMap((a) => a.role && shouldInjectContract(a.role, a.agentType) ? [a.role] : []))];
20807
+ if (contractRoles.length > 0) {
20808
+ 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)`);
20809
+ }
20810
+ }
20136
20811
  for (const agentType of effectiveAgentTypes) {
20137
20812
  try {
20138
20813
  resolvedBinaryPaths[agentType] = resolvePreflightBinaryPath(agentType).path;
@@ -20172,7 +20847,7 @@ async function startTeamV2(config) {
20172
20847
  try {
20173
20848
  const pendingConfig = buildTeamInstancePendingConfig(instance);
20174
20849
  const pendingConfigPath = absPath(leaderCwd, TeamPaths.config(sanitized));
20175
- await (0, import_promises19.mkdir)((0, import_path34.join)(pendingConfigPath, ".."), { recursive: true });
20850
+ await (0, import_promises19.mkdir)((0, import_path38.join)(pendingConfigPath, ".."), { recursive: true });
20176
20851
  await (0, import_promises19.writeFile)(pendingConfigPath, JSON.stringify(pendingConfig, null, 2), "utf-8");
20177
20852
  } catch (error) {
20178
20853
  if (!await rollbackBeforeConfig(error)) throw startupCleanupIncompleteError(error);
@@ -20183,7 +20858,7 @@ async function startTeamV2(config) {
20183
20858
  try {
20184
20859
  await (0, import_promises19.mkdir)(absPath(leaderCwd, TeamPaths.tasks(sanitized)), { recursive: true });
20185
20860
  await (0, import_promises19.mkdir)(absPath(leaderCwd, TeamPaths.workers(sanitized)), { recursive: true });
20186
- await (0, import_promises19.mkdir)((0, import_path34.join)(getOmcRoot(leaderCwd), "state", "team", sanitized, "mailbox"), { recursive: true });
20861
+ await (0, import_promises19.mkdir)((0, import_path38.join)(getOmcRoot(leaderCwd), "state", "team", sanitized, "mailbox"), { recursive: true });
20187
20862
  for (let i = 0; i < config.tasks.length; i++) {
20188
20863
  const taskId = String(i + 1);
20189
20864
  const task = config.tasks[i];
@@ -20220,7 +20895,7 @@ async function startTeamV2(config) {
20220
20895
  const assignment = startupAssignments.get(workerName);
20221
20896
  if (!assignment) throw new Error(`Missing startup assignment for ${workerName}`);
20222
20897
  const worktree = workerWorktrees.get(workerName);
20223
- const verdictAssignmentId = taskIndex !== void 0 ? (0, import_node_crypto9.randomUUID)() : void 0;
20898
+ const verdictAssignmentId = taskIndex !== void 0 ? (0, import_node_crypto10.randomUUID)() : void 0;
20224
20899
  const outputFile = taskIndex !== void 0 && assignment.role && shouldInjectContract(assignment.role, assignment.agentType) ? cliWorkerOutputFilePath(teamStateRoot(leaderCwd, sanitized), workerName, {
20225
20900
  taskId: String(taskIndex + 1),
20226
20901
  assignmentId: verdictAssignmentId
@@ -20257,7 +20932,8 @@ async function startTeamV2(config) {
20257
20932
  if (!await rollbackBeforeConfig(error)) throw startupCleanupIncompleteError(error);
20258
20933
  throw error;
20259
20934
  }
20260
- for (const line of formatWorkerPermissionLines(preparedLaunches.values())) {
20935
+ 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());
20936
+ for (const line of permissionLines) {
20261
20937
  process.stderr.write(`${line}
20262
20938
  `);
20263
20939
  }
@@ -20294,7 +20970,7 @@ async function startTeamV2(config) {
20294
20970
  }
20295
20971
  let session;
20296
20972
  try {
20297
- session = await createTeamSession(sanitized, 0, leaderCwd, {
20973
+ session = sdkMode ? { sessionName: sdkTeamTarget(sanitized), leaderPaneId: "", workerPaneIds: [], sessionMode: "split-pane" } : await createTeamSession(sanitized, 0, leaderCwd, {
20298
20974
  newWindow: Boolean(config.newWindow)
20299
20975
  });
20300
20976
  } catch (error) {
@@ -20314,6 +20990,7 @@ async function startTeamV2(config) {
20314
20990
  role: preparedLaunches.get(wName)?.role ?? config.workerRoles?.[i] ?? (agentTypes[i % agentTypes.length] ?? agentTypes[0] ?? "claude"),
20315
20991
  worker_cli: preparedLaunches.get(wName).descriptor.provider,
20316
20992
  launch_descriptor: preparedLaunches.get(wName).descriptor,
20993
+ ...sdkMode ? { transport: "sdk" } : {},
20317
20994
  assigned_tasks: [],
20318
20995
  working_dir: worktree?.path ?? leaderCwd,
20319
20996
  team_state_root: teamStateRoot(leaderCwd, sanitized),
@@ -20359,7 +21036,7 @@ async function startTeamV2(config) {
20359
21036
  service_descriptor: config.autoMerge ? {
20360
21037
  schema_version: 1,
20361
21038
  service_generation: 1,
20362
- service_attempt_id: (0, import_node_crypto9.randomUUID)(),
21039
+ service_attempt_id: (0, import_node_crypto10.randomUUID)(),
20363
21040
  auto_merge_enabled: true,
20364
21041
  workspace_root: leaderCwd,
20365
21042
  leader_branch: autoMergeLeaderBranch,
@@ -20367,7 +21044,7 @@ async function startTeamV2(config) {
20367
21044
  } : {
20368
21045
  schema_version: 1,
20369
21046
  service_generation: 1,
20370
- service_attempt_id: (0, import_node_crypto9.randomUUID)(),
21047
+ service_attempt_id: (0, import_node_crypto10.randomUUID)(),
20371
21048
  auto_merge_enabled: false,
20372
21049
  workspace_root: leaderCwd,
20373
21050
  cadence_policy: "disabled"
@@ -20455,7 +21132,7 @@ async function startTeamV2(config) {
20455
21132
  if (!prepared) continue;
20456
21133
  const workerInfo = workersInfo[workerIndex];
20457
21134
  if (!workerInfo) continue;
20458
- const workerLaunch = await spawnV2Worker({
21135
+ const spawnOptions = {
20459
21136
  sessionName: sessionName2,
20460
21137
  ...session.tmuxServerIdentity ? { tmuxServerIdentity: session.tmuxServerIdentity } : {},
20461
21138
  leaderPaneId,
@@ -20474,7 +21151,8 @@ async function startTeamV2(config) {
20474
21151
  autoMerge: Boolean(config.autoMerge),
20475
21152
  ...prepared.role ? { role: prepared.role } : {},
20476
21153
  ...prepared.verdictAssignmentId ? { verdictAssignmentId: prepared.verdictAssignmentId } : {}
20477
- });
21154
+ };
21155
+ const workerLaunch = sdkSettings ? await spawnSdkV2Worker(spawnOptions, sdkSettings) : await spawnV2Worker(spawnOptions);
20478
21156
  if (workerLaunch.paneId) {
20479
21157
  if (workerLaunch.startupAssigned) workerPaneIds.push(workerLaunch.paneId);
20480
21158
  launchedWorkers.push({
@@ -20649,7 +21327,7 @@ function nonCursorVerdictFileIdentity(stats) {
20649
21327
  ].join("-");
20650
21328
  }
20651
21329
  function fingerprintCliWorkerVerdictArtifact(raw, stats) {
20652
- const contentSha256 = (0, import_node_crypto9.createHash)("sha256").update(raw, "utf8").digest("hex");
21330
+ const contentSha256 = (0, import_node_crypto10.createHash)("sha256").update(raw, "utf8").digest("hex");
20653
21331
  return `${contentSha256}-${nonCursorVerdictFileIdentity(stats)}`;
20654
21332
  }
20655
21333
  async function readNonCursorVerdictArtifact(outputFile) {
@@ -20711,7 +21389,7 @@ async function processCliWorkerVerdictsUnderLock(teamName, cwd, expectedInstance
20711
21389
  "team.runtime-v2.processCliWorkerVerdicts teamMarkTaskCompleted failed"
20712
21390
  );
20713
21391
  const { rename: rename8 } = await import("fs/promises");
20714
- const { renameSync: renameSync5, readFileSync: readFileSync21, existsSync: fsExistsSync } = await import("fs");
21392
+ const { renameSync: renameSync5, readFileSync: readFileSync24, existsSync: fsExistsSync } = await import("fs");
20715
21393
  const { withFileLockSync: withFileLockSync2 } = await Promise.resolve().then(() => (init_file_lock(), file_lock_exports));
20716
21394
  const quarantineNonCursorVerdict = async (outputFile, artifactFingerprint, workerName, taskId, taskVersion, reason) => {
20717
21395
  const stalePath = nonCursorVerdictStalePath(outputFile, artifactFingerprint);
@@ -20744,7 +21422,7 @@ async function processCliWorkerVerdictsUnderLock(teamName, cwd, expectedInstance
20744
21422
  const outputFile = worker.output_file;
20745
21423
  if (!outputFile) continue;
20746
21424
  const paneOwnership = configuredPaneOwnership(config, worker);
20747
- const liveness = paneOwnership ? await getOwnedWorkerLiveness(paneOwnership) : "unknown";
21425
+ const liveness = isSdkTarget(worker.pane_id) ? await getWorkerProviderLiveness(sanitized, cwd, config.instance_id, worker) : paneOwnership ? await getOwnedWorkerLiveness(paneOwnership) : "unknown";
20748
21426
  const workerRole = normalizeDelegationRole(worker.role);
20749
21427
  const cursorReviewer = worker.worker_cli === "cursor" && CONTRACT_ROLES.has(workerRole);
20750
21428
  const liveCursorReviewer = liveness === "alive" && worker.worker_cli === "cursor" && CONTRACT_ROLES.has(workerRole);
@@ -20792,7 +21470,7 @@ async function processCliWorkerVerdictsUnderLock(teamName, cwd, expectedInstance
20792
21470
  return;
20793
21471
  }
20794
21472
  }
20795
- const raw = readFileSync21(outputFile, "utf-8");
21473
+ const raw = readFileSync24(outputFile, "utf-8");
20796
21474
  parseCliWorkerVerdict(raw);
20797
21475
  renameSync5(outputFile, processingOutputFile);
20798
21476
  verdictFile = processingOutputFile;
@@ -20956,7 +21634,7 @@ async function processCliWorkerVerdictsUnderLock(teamName, cwd, expectedInstance
20956
21634
  if (cursorReviewer && verdictFile === processingOutputFile) {
20957
21635
  const processedTaskPath = absPath(cwd, TeamPaths.taskFile(sanitized, payload.task_id));
20958
21636
  try {
20959
- const processedTask = JSON.parse(readFileSync21(processedTaskPath, "utf-8"));
21637
+ const processedTask = JSON.parse(readFileSync24(processedTaskPath, "utf-8"));
20960
21638
  const metadata = processedTask.metadata && typeof processedTask.metadata === "object" ? processedTask.metadata : void 0;
20961
21639
  const processedTaskRole = typeof processedTask.role === "string" ? normalizeDelegationRole(processedTask.role) : null;
20962
21640
  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;
@@ -21298,20 +21976,28 @@ async function monitorTeamV2(teamName, cwd, expectedInstanceId) {
21298
21976
  const workerScanStartMs = import_perf_hooks.performance.now();
21299
21977
  const workerSignals = await Promise.all(
21300
21978
  config.workers.map(async (worker) => {
21979
+ const providerLiveness = await getWorkerProviderLiveness(sanitized, cwd, config.instance_id, worker);
21980
+ if (isSdkTarget(worker.pane_id)) {
21981
+ const sdkSession = readSdkSession(teamStateRoot(cwd, sanitized), worker.name);
21982
+ const [status2, heartbeat2] = await Promise.all([
21983
+ readWorkerStatus(sanitized, worker.name, cwd),
21984
+ readWorkerHeartbeat(sanitized, worker.name, cwd)
21985
+ ]);
21986
+ return { worker, alive: providerLiveness === "alive", liveness: providerLiveness, providerLiveness, status: status2, heartbeat: heartbeat2, paneCapture: "", sdkSession };
21987
+ }
21301
21988
  const ownership = configuredPaneOwnership(config, worker);
21302
21989
  const liveness = ownership ? await getOwnedWorkerLiveness(ownership) : "unknown";
21303
- const providerLiveness = await getWorkerProviderLiveness(sanitized, cwd, config.instance_id, worker);
21304
21990
  const paneAlive = liveness === "alive";
21305
21991
  const [status, heartbeat, paneCapture] = await Promise.all([
21306
21992
  readWorkerStatus(sanitized, worker.name, cwd),
21307
21993
  readWorkerHeartbeat(sanitized, worker.name, cwd),
21308
21994
  paneAlive && ownership ? captureOwnedTeamPane(ownership) : Promise.resolve("")
21309
21995
  ]);
21310
- return { worker, alive: paneAlive, liveness, providerLiveness, status, heartbeat, paneCapture };
21996
+ return { worker, alive: paneAlive, liveness, providerLiveness, status, heartbeat, paneCapture, sdkSession: null };
21311
21997
  })
21312
21998
  );
21313
21999
  const workerScanMs = import_perf_hooks.performance.now() - workerScanStartMs;
21314
- for (const { worker: w, alive, liveness, providerLiveness, status, heartbeat, paneCapture } of workerSignals) {
22000
+ for (const { worker: w, alive, liveness, providerLiveness, status, heartbeat, paneCapture, sdkSession } of workerSignals) {
21315
22001
  const currentTask = status.current_task_id ? taskById.get(status.current_task_id) ?? null : null;
21316
22002
  const outstandingTask = currentTask ?? findOutstandingWorkerTask(w, taskById, inProgressByOwner);
21317
22003
  const expectedTaskId = status.current_task_id ?? outstandingTask?.id ?? w.assigned_tasks[0] ?? "";
@@ -21334,7 +22020,19 @@ async function monitorTeamV2(teamName, cwd, expectedInstanceId) {
21334
22020
  worktree_detached: w.worktree_detached,
21335
22021
  worktree_created: w.worktree_created,
21336
22022
  team_state_root: w.team_state_root,
21337
- turnsWithoutProgress
22023
+ turnsWithoutProgress,
22024
+ ...sdkSession ? { sdk: {
22025
+ state: sdkSession.state,
22026
+ turns: sdkSession.turns,
22027
+ queued: sdkSession.queued,
22028
+ last_event_type: sdkSession.last_event_type,
22029
+ last_event_at: sdkSession.last_event_at,
22030
+ last_error: sdkSession.last_error,
22031
+ session_id: sdkSession.session_id,
22032
+ model: sdkSession.model,
22033
+ credits: sdkSession.usage.credits,
22034
+ premium_requests: sdkSession.usage.shutdown_premium_requests ?? sdkSession.usage.premium_requests
22035
+ } } : {}
21338
22036
  });
21339
22037
  if (providerLiveness === "dead") {
21340
22038
  deadWorkers.push(w.name);
@@ -21343,13 +22041,16 @@ async function monitorTeamV2(teamName, cwd, expectedInstanceId) {
21343
22041
  recommendations.push(`Reassign task-${t.id} from dead ${w.name}`);
21344
22042
  }
21345
22043
  }
21346
- const paneSuggestsIdle = alive && paneLooksReady(paneCapture) && !paneHasActiveTask(paneCapture);
22044
+ const sdkCapped = Boolean(sdkSession && providerLiveness !== "dead" && sdkSession.state === "capped");
22045
+ const paneSuggestsIdle = sdkSession ? alive && (sdkSession.state === "idle" && sdkSession.queued === 0 || sdkCapped) : alive && paneLooksReady(paneCapture) && !paneHasActiveTask(paneCapture);
21347
22046
  const statusFresh = isFreshTimestamp(status.updated_at);
21348
22047
  const heartbeatFresh = isFreshTimestamp(heartbeat?.last_turn_at);
21349
22048
  const hasWorkStartEvidence = expectedTaskId !== "" && hasWorkerStatusProgress(status, expectedTaskId);
21350
22049
  const missingDependencyIds = outstandingTask ? getMissingDependencyIds(outstandingTask, taskById) : [];
21351
22050
  let stallReason = null;
21352
- if (paneSuggestsIdle && missingDependencyIds.length > 0) {
22051
+ if (sdkCapped) {
22052
+ stallReason = "sdk_credit_cap";
22053
+ } else if (paneSuggestsIdle && missingDependencyIds.length > 0) {
21353
22054
  stallReason = "missing_dependency";
21354
22055
  } else if (paneSuggestsIdle && expectedTaskId !== "" && !hasWorkStartEvidence) {
21355
22056
  stallReason = "no_work_start_evidence";
@@ -21360,7 +22061,15 @@ async function monitorTeamV2(teamName, cwd, expectedInstanceId) {
21360
22061
  }
21361
22062
  if (stallReason) {
21362
22063
  nonReportingWorkers.push(w.name);
21363
- if (stallReason === "missing_dependency") {
22064
+ if (stallReason === "sdk_credit_cap") {
22065
+ const cappedTasks = inProgressByOwner.get(w.name) ?? [];
22066
+ for (const t of cappedTasks) {
22067
+ recommendations.push(`Reassign task-${t.id} from ${w.name}: sdk credit cap reached (${sdkSession?.last_error ?? "capped"}); the worker takes no more prompts`);
22068
+ }
22069
+ if (cappedTasks.length === 0) {
22070
+ recommendations.push(`${w.name} reached its sdk credit cap and takes no more prompts; do not assign it new work`);
22071
+ }
22072
+ } else if (stallReason === "missing_dependency") {
21364
22073
  recommendations.push(
21365
22074
  `Investigate ${w.name}: task-${outstandingTask?.id ?? expectedTaskId} is blocked by missing task ids [${missingDependencyIds.join(", ")}]; pane is idle at prompt`
21366
22075
  );
@@ -21454,7 +22163,7 @@ async function cleanupStaleReservations(teamName, cwd) {
21454
22163
  cwd,
21455
22164
  TeamPaths.teamInstanceReservation(workspaceHash, sanitized)
21456
22165
  );
21457
- if (!(0, import_fs30.existsSync)(reservationPath2)) return;
22166
+ if (!(0, import_fs34.existsSync)(reservationPath2)) return;
21458
22167
  const contentStr = await (0, import_promises19.readFile)(reservationPath2, "utf-8");
21459
22168
  const reservation = JSON.parse(contentStr);
21460
22169
  if (!(reservation && typeof reservation === "object" && !Array.isArray(reservation) && "owner" in reservation && typeof reservation.owner === "object")) {
@@ -21464,6 +22173,7 @@ async function cleanupStaleReservations(teamName, cwd) {
21464
22173
  if (!(owner && typeof owner === "object" && !Array.isArray(owner) && "pid" in owner && "process_started_at" in owner)) {
21465
22174
  return;
21466
22175
  }
22176
+ if (reservation.phase === "active") return;
21467
22177
  const ownerRecord = owner;
21468
22178
  if (isProcessIdentityDead(ownerRecord)) {
21469
22179
  await (0, import_promises19.unlink)(reservationPath2);
@@ -21556,7 +22266,7 @@ async function shutdownTeamV2(teamName, cwd, options = {}) {
21556
22266
  });
21557
22267
  instance = boundInstance;
21558
22268
  await assertTeamInstanceUnderLock(boundInstance);
21559
- if (!current.config.tmux_session || !current.config.tmux_session.startsWith("cmux:") && !isValidTmuxServerIdentity(current.config.tmux_server_identity)) {
22269
+ if (!current.config.tmux_session || !current.config.tmux_session.startsWith("cmux:") && !isSdkTarget(current.config.tmux_session) && !isValidTmuxServerIdentity(current.config.tmux_server_identity)) {
21560
22270
  throw new Error("tmux_server_identity_missing");
21561
22271
  }
21562
22272
  if (current.config.active_recovery) throw new Error(`shutdown_blocked:active_recovery:${current.config.active_recovery.recovery_id}`);
@@ -21587,7 +22297,7 @@ async function shutdownTeamV2(teamName, cwd, options = {}) {
21587
22297
  }
21588
22298
  const processStartedAt = currentProcessStartIdentity();
21589
22299
  if (!processStartedAt) throw new Error("process_start_identity_unavailable");
21590
- ownedShutdownNonce = (0, import_node_crypto9.randomUUID)();
22300
+ ownedShutdownNonce = (0, import_node_crypto10.randomUUID)();
21591
22301
  const nextRevision = current.stateRevision + 1;
21592
22302
  const next = {
21593
22303
  ...current.config,
@@ -21695,7 +22405,7 @@ async function shutdownTeamV2(teamName, cwd, options = {}) {
21695
22405
  };
21696
22406
  if (!config) {
21697
22407
  const cleanupSafety = inspectTeamWorktreeCleanupSafety(sanitized, cwd);
21698
- if (cleanupSafety.hasEvidence || (0, import_fs30.existsSync)(absPath(cwd, TeamPaths.root(sanitized)))) {
22408
+ if (cleanupSafety.hasEvidence || (0, import_fs34.existsSync)(absPath(cwd, TeamPaths.root(sanitized)))) {
21699
22409
  process.stderr.write("[team/runtime-v2] preserving team state because config is missing and worktree cleanup evidence remains\n");
21700
22410
  return { outcome: "preserved", reason: "config_missing_cleanup_evidence", workers: [] };
21701
22411
  }
@@ -21727,6 +22437,7 @@ Format: {"status":"accept","reason":"ok","updated_at":"<iso>"}
21727
22437
  Then exit your session.
21728
22438
  `;
21729
22439
  await writeWorkerInbox(sanitized, w.name, shutdownInbox, cwd);
22440
+ if (isSdkTarget(w.pane_id)) ringDoorbell(teamStateRoot(cwd, sanitized), w.name, { kind: "shutdown", from: "leader-fixed" });
21730
22441
  } catch (err) {
21731
22442
  process.stderr.write(`[team/runtime-v2] shutdown request failed for ${w.name}: ${err}
21732
22443
  `);
@@ -21767,6 +22478,30 @@ Then exit your session.
21767
22478
  const providerCleanupFailures = [];
21768
22479
  const paneCleanupAlive = [];
21769
22480
  const paneCleanupUnknown = [];
22481
+ const sdkStopTimeoutMs = Math.max(timeoutMs, SDK_HOST_STOP_FLOOR_MS);
22482
+ const sdkStops = /* @__PURE__ */ new Map();
22483
+ for (const worker of config.workers) {
22484
+ if (!isSdkTarget(worker.pane_id) || !worker.launch_attempt_id || !config.tmux_session) continue;
22485
+ const provider = worker.launch_descriptor?.provider ?? worker.worker_cli;
22486
+ if (!provider) continue;
22487
+ const attemptId = worker.launch_attempt_id;
22488
+ const paneId = worker.pane_id;
22489
+ sdkStops.set(worker.name, (async () => {
22490
+ const sdkAttempt = await loadWorkerLaunchAttempt({
22491
+ cwd,
22492
+ teamName: sanitized,
22493
+ instanceId: shutdownInstance.instance_id,
22494
+ workerName: worker.name,
22495
+ paneId,
22496
+ provider,
22497
+ attemptId,
22498
+ runtimeCliPath: resolveRuntimeCliPath()
22499
+ });
22500
+ if (!sdkAttempt) return false;
22501
+ if (!await stopSdkHost(sdkAttempt, teamStateRoot(cwd, sanitized), { timeoutMs: sdkStopTimeoutMs })) return false;
22502
+ return retireAndCleanupCurrentWorkerLaunchAttempt(sdkAttempt, "team_shutdown", async () => true);
22503
+ })().catch(() => false));
22504
+ }
21770
22505
  for (const worker of config.workers) {
21771
22506
  if (!worker.pane_id) {
21772
22507
  providerCleanupFailures.push(worker.name);
@@ -21781,6 +22516,10 @@ Then exit your session.
21781
22516
  providerCleanupFailures.push(worker.name);
21782
22517
  continue;
21783
22518
  }
22519
+ if (isSdkTarget(worker.pane_id)) {
22520
+ if (!await (sdkStops.get(worker.name) ?? Promise.resolve(false))) providerCleanupFailures.push(worker.name);
22521
+ continue;
22522
+ }
21784
22523
  const initialOwnership = configuredPaneOwnership(config, worker);
21785
22524
  const initialPaneLiveness = initialOwnership ? await getOwnedWorkerLiveness(initialOwnership) : "unknown";
21786
22525
  let paneOwnership = null;
@@ -21849,9 +22588,9 @@ Then exit your session.
21849
22588
  killTeamSession: killOwnedTeamSession
21850
22589
  } = await Promise.resolve().then(() => (init_tmux_session(), tmux_session_exports));
21851
22590
  const ownsWindow = config.tmux_window_owned === true;
21852
- const workerPaneIds = recordedWorkerPaneIds;
22591
+ const workerPaneIds = recordedWorkerPaneIds.filter((paneId) => !isSdkTarget(paneId));
21853
22592
  const splitPaneMode = Boolean(config.tmux_session && !ownsWindow && config.tmux_session.includes(":"));
21854
- if (!splitPaneMode && config.tmux_session) {
22593
+ if (!splitPaneMode && config.tmux_session && !isSdkTarget(config.tmux_session)) {
21855
22594
  if (!config.leader_pane_id) {
21856
22595
  if (!await rollbackShutdownForRetry()) await finalizeAutoMerge();
21857
22596
  return { outcome: "preserved", reason: "provider_cleanup_unverified", workers: ["leader-fixed"] };
@@ -21972,12 +22711,12 @@ Then exit your session.
21972
22711
  return { outcome: "cleaned" };
21973
22712
  });
21974
22713
  }
21975
- var import_path34, import_fs30, import_promises19, import_perf_hooks, import_node_child_process7, import_node_crypto9, orchestratorByTeam, cadenceByTeam, MONITOR_SIGNAL_STALE_MS, WORKER_STARTUP_EVIDENCE_POLL_INTERVAL_MS, WORKER_STARTUP_EVIDENCE_POLICIES, ENGAGED_PANE_RECHECK_TIMEOUT_ENV, MAX_ENGAGED_PANE_RECHECK_BUDGET_MS, CLAIM_ERROR_CAPTURE_MAX, CLAIM_ERROR_JSON_LINES_MAX, CLAIM_ERROR_LINE_MAX, CLAIM_ERROR_CODES, pendingRecoveryPanes, BOOTSTRAP_RECOVERY_EVIDENCE_POLL_MS, BOOTSTRAP_RECOVERY_EVIDENCE_MAX_WAIT_MS, TEAM_INSTANCE_FINAL_DISPOSAL_AUTHORIZATION;
22714
+ var import_path38, import_fs34, import_promises19, import_perf_hooks, import_node_child_process8, import_node_crypto10, orchestratorByTeam, cadenceByTeam, MONITOR_SIGNAL_STALE_MS, WORKER_STARTUP_EVIDENCE_POLL_INTERVAL_MS, WORKER_STARTUP_EVIDENCE_POLICIES, ENGAGED_PANE_RECHECK_TIMEOUT_ENV, MAX_ENGAGED_PANE_RECHECK_BUDGET_MS, CLAIM_ERROR_CAPTURE_MAX, CLAIM_ERROR_JSON_LINES_MAX, CLAIM_ERROR_LINE_MAX, CLAIM_ERROR_CODES, pendingRecoveryPanes, BOOTSTRAP_RECOVERY_EVIDENCE_POLL_MS, BOOTSTRAP_RECOVERY_EVIDENCE_MAX_WAIT_MS, TEAM_INSTANCE_FINAL_DISPOSAL_AUTHORIZATION;
21976
22715
  var init_runtime_v2 = __esm({
21977
22716
  "src/team/runtime-v2.ts"() {
21978
22717
  "use strict";
21979
- import_path34 = require("path");
21980
- import_fs30 = require("fs");
22718
+ import_path38 = require("path");
22719
+ import_fs34 = require("fs");
21981
22720
  import_promises19 = require("fs/promises");
21982
22721
  import_perf_hooks = require("perf_hooks");
21983
22722
  init_state_paths();
@@ -22006,10 +22745,10 @@ var init_runtime_v2 = __esm({
22006
22745
  init_cli_worker_contract();
22007
22746
  init_merge_orchestrator();
22008
22747
  init_leader_inbox();
22009
- import_node_child_process7 = require("node:child_process");
22748
+ import_node_child_process8 = require("node:child_process");
22010
22749
  init_runtime_flags();
22011
22750
  init_worker_commit_cadence();
22012
- import_node_crypto9 = require("node:crypto");
22751
+ import_node_crypto10 = require("node:crypto");
22013
22752
  init_recovery_request_store();
22014
22753
  init_runtime_owner_client();
22015
22754
  init_scaling();
@@ -22021,6 +22760,11 @@ var init_runtime_v2 = __esm({
22021
22760
  init_team_owner_epoch();
22022
22761
  init_worker_activation_gate();
22023
22762
  init_worker_launch_ack();
22763
+ init_sdk_transport();
22764
+ init_model_contract();
22765
+ init_copilot_sdk_driver();
22766
+ init_copilot_session_env();
22767
+ init_config_dir();
22024
22768
  init_process_utils();
22025
22769
  init_team_instance();
22026
22770
  init_runtime_flags();
@@ -22126,10 +22870,10 @@ __export(runtime_cli_exports, {
22126
22870
  writeResultArtifact: () => writeResultArtifact
22127
22871
  });
22128
22872
  module.exports = __toCommonJS(runtime_cli_exports);
22129
- var import_node_crypto10 = require("node:crypto");
22130
- var import_fs31 = require("fs");
22873
+ var import_node_crypto11 = require("node:crypto");
22874
+ var import_fs35 = require("fs");
22131
22875
  var import_promises20 = require("fs/promises");
22132
- var import_path35 = require("path");
22876
+ var import_path39 = require("path");
22133
22877
  init_events();
22134
22878
 
22135
22879
  // src/team/leader-nudge-guidance.ts
@@ -22672,7 +23416,7 @@ async function waitForSentinelReadiness(options = {}) {
22672
23416
  }
22673
23417
  const deadline = startedAt + timeoutMs;
22674
23418
  while (Date.now() < deadline) {
22675
- await new Promise((resolve14) => setTimeout(resolve14, pollIntervalMs));
23419
+ await new Promise((resolve17) => setTimeout(resolve17, pollIntervalMs));
22676
23420
  attempts += 1;
22677
23421
  latest = checkSentinelReadiness(options);
22678
23422
  if (latest.ready) {
@@ -22762,10 +23506,10 @@ function areAllAuthoritativeWorkersDead(refresh, workers) {
22762
23506
  return classifyAllDeadRecoveryEvidence(refresh, workers, true) === "all_dead";
22763
23507
  }
22764
23508
  function validateCanonicalRecoveryIntent(teamName, cwd, pathRecoveryId, path5) {
22765
- const intent = parseRecoveryIntent((0, import_fs31.readFileSync)(path5, "utf8"));
23509
+ const intent = parseRecoveryIntent((0, import_fs35.readFileSync)(path5, "utf8"));
22766
23510
  if (intent.team_name !== teamName || intent.recovery_id !== pathRecoveryId) throw new Error("invalid_persisted_state");
22767
23511
  const reservation = readRecoveryRequestReservation(cwd, intent.request_id);
22768
- const workspaceHash = (0, import_node_crypto10.createHash)("sha256").update(cwd).digest("hex");
23512
+ const workspaceHash = (0, import_node_crypto11.createHash)("sha256").update(cwd).digest("hex");
22769
23513
  const expectedPayloadHash = canonicalRecoveryPayloadHash({
22770
23514
  operation: "recover-worker",
22771
23515
  workspaceHash,
@@ -22797,14 +23541,14 @@ async function processPendingRecoveryIntents(teamName, cwd, execute = handleReco
22797
23541
  const root = absPath(cwd, TeamPaths.recoveryIntents(teamName));
22798
23542
  let names;
22799
23543
  try {
22800
- names = (0, import_fs31.readdirSync)(root).filter((name) => name.endsWith(".json")).sort();
23544
+ names = (0, import_fs35.readdirSync)(root).filter((name) => name.endsWith(".json")).sort();
22801
23545
  } catch {
22802
23546
  return;
22803
23547
  }
22804
23548
  for (const name of names) {
22805
- const path5 = (0, import_path35.join)(root, name);
23549
+ const path5 = (0, import_path39.join)(root, name);
22806
23550
  try {
22807
- const pathRecoveryId = (0, import_path35.basename)(name, ".json");
23551
+ const pathRecoveryId = (0, import_path39.basename)(name, ".json");
22808
23552
  const intent = validateCanonicalRecoveryIntent(teamName, cwd, pathRecoveryId, path5);
22809
23553
  if (intent.instance_id.toLowerCase() !== normalizedExpectedInstanceId) continue;
22810
23554
  if (!await assertRuntimeInstance(teamName, cwd, normalizedExpectedInstanceId)) continue;
@@ -22874,17 +23618,17 @@ async function updateAllDeadRecoveryGrace(teamName, cwd, evidence, nowMs = Date.
22874
23618
  }
22875
23619
  function canonicalRecoveryIntentEntryId(name, path5) {
22876
23620
  if (!name.endsWith(".json")) return null;
22877
- const recoveryId = (0, import_path35.basename)(name, ".json");
23621
+ const recoveryId = (0, import_path39.basename)(name, ".json");
22878
23622
  if (name !== `${recoveryId}.json` || !isSafeRecoveryRequestId(recoveryId)) return null;
22879
23623
  try {
22880
- return (0, import_fs31.lstatSync)(path5).isFile() ? recoveryId : null;
23624
+ return (0, import_fs35.lstatSync)(path5).isFile() ? recoveryId : null;
22881
23625
  } catch {
22882
23626
  return null;
22883
23627
  }
22884
23628
  }
22885
23629
  function hasVerifiedTerminalRepairForMalformedIntent(teamName, cwd, recoveryId, path5) {
22886
23630
  try {
22887
- const raw = JSON.parse((0, import_fs31.readFileSync)(path5, "utf8"));
23631
+ const raw = JSON.parse((0, import_fs35.readFileSync)(path5, "utf8"));
22888
23632
  if (raw.team_name !== teamName || raw.recovery_id !== recoveryId || typeof raw.request_id !== "string" || !isSafeRecoveryRequestId(raw.request_id) || typeof raw.worker_name !== "string" || raw.worker_name.length === 0) return false;
22889
23633
  const final = readRecoveryFinalState(cwd, raw.request_id);
22890
23634
  return final.kind === "valid" && final.final.recovery_id === recoveryId && final.final.team_name === teamName && final.final.worker_name === raw.worker_name;
@@ -22894,7 +23638,7 @@ function hasVerifiedTerminalRepairForMalformedIntent(teamName, cwd, recoveryId,
22894
23638
  }
22895
23639
  function malformedIntentMayPredateDeadline(path5, deadlineAt) {
22896
23640
  try {
22897
- const metadata = (0, import_fs31.lstatSync)(path5);
23641
+ const metadata = (0, import_fs35.lstatSync)(path5);
22898
23642
  if (Number.isFinite(metadata.mtimeMs) && metadata.mtimeMs <= deadlineAt) return true;
22899
23643
  if (Number.isFinite(metadata.birthtimeMs) && metadata.birthtimeMs > 0) {
22900
23644
  return metadata.birthtimeMs <= deadlineAt;
@@ -22909,14 +23653,14 @@ function canonicalRecoveryAdmissionEntryId(name, path5) {
22909
23653
  const requestId = name.slice(0, -".pending.json".length);
22910
23654
  if (name !== `${requestId}.pending.json` || !isSafeRecoveryRequestId(requestId)) return null;
22911
23655
  try {
22912
- return (0, import_fs31.lstatSync)(path5).isFile() ? requestId : null;
23656
+ return (0, import_fs35.lstatSync)(path5).isFile() ? requestId : null;
22913
23657
  } catch {
22914
23658
  return null;
22915
23659
  }
22916
23660
  }
22917
23661
  function malformedAdmissionMayPredateDeadline(path5, deadlineAt) {
22918
23662
  try {
22919
- const metadata = (0, import_fs31.lstatSync)(path5);
23663
+ const metadata = (0, import_fs35.lstatSync)(path5);
22920
23664
  if (!metadata.isFile()) return true;
22921
23665
  if (Number.isFinite(metadata.mtimeMs) && metadata.mtimeMs <= deadlineAt) return true;
22922
23666
  if (Number.isFinite(metadata.birthtimeMs) && metadata.birthtimeMs > 0) {
@@ -22933,12 +23677,12 @@ function hasPendingRecoveryIntentBeforeDeadline(teamName, cwd, deadlineAt, expec
22933
23677
  const root = absPath(cwd, TeamPaths.recoveryIntents(teamName));
22934
23678
  let names;
22935
23679
  try {
22936
- names = (0, import_fs31.readdirSync)(root).filter((name) => name.endsWith(".json"));
23680
+ names = (0, import_fs35.readdirSync)(root).filter((name) => name.endsWith(".json"));
22937
23681
  } catch {
22938
23682
  return false;
22939
23683
  }
22940
23684
  for (const name of names) {
22941
- const path5 = (0, import_path35.join)(root, name);
23685
+ const path5 = (0, import_path39.join)(root, name);
22942
23686
  const recoveryId = canonicalRecoveryIntentEntryId(name, path5);
22943
23687
  if (!recoveryId) continue;
22944
23688
  try {
@@ -22956,16 +23700,16 @@ function hasPendingRecoveryIntentBeforeDeadline(teamName, cwd, deadlineAt, expec
22956
23700
  function hasPendingRecoveryAdmissionBeforeDeadline(teamName, cwd, deadlineAt, expectedInstanceId) {
22957
23701
  const normalizedExpectedInstanceId = normalizeRuntimeInstanceId(expectedInstanceId);
22958
23702
  if (!normalizedExpectedInstanceId) return true;
22959
- const workspaceHash = (0, import_node_crypto10.createHash)("sha256").update(cwd).digest("hex");
23703
+ const workspaceHash = (0, import_node_crypto11.createHash)("sha256").update(cwd).digest("hex");
22960
23704
  const root = absPath(cwd, TeamPaths.recoveryRequestsRoot());
22961
23705
  let names;
22962
23706
  try {
22963
- names = (0, import_fs31.readdirSync)(root).filter((name) => name.endsWith(".pending.json"));
23707
+ names = (0, import_fs35.readdirSync)(root).filter((name) => name.endsWith(".pending.json"));
22964
23708
  } catch {
22965
23709
  return false;
22966
23710
  }
22967
23711
  for (const name of names) {
22968
- const path5 = (0, import_path35.join)(root, name);
23712
+ const path5 = (0, import_path39.join)(root, name);
22969
23713
  const requestId = canonicalRecoveryAdmissionEntryId(name, path5);
22970
23714
  if (!requestId) continue;
22971
23715
  try {
@@ -23043,7 +23787,7 @@ async function runPersistentRecoveryOwnerLoop(input, options = {}) {
23043
23787
  const reconcileServices = options.reconcileServices ?? reconcileCommittedTeamServices;
23044
23788
  const monitor = options.monitor ?? monitorTeamV2;
23045
23789
  const sleep4 = options.sleep ?? (async (ms) => {
23046
- await new Promise((resolve14) => setTimeout(resolve14, ms));
23790
+ await new Promise((resolve17) => setTimeout(resolve17, ms));
23047
23791
  });
23048
23792
  const shutdown = options.shutdown ?? shutdownTeamV2;
23049
23793
  let iteration = 0;
@@ -23184,7 +23928,7 @@ async function writeResultArtifact(output, finishedAt, jobId = process.env.OMC_J
23184
23928
  if (!output.instanceId || !isValidTeamInstanceId(output.instanceId)) {
23185
23929
  throw new Error("result_artifact_instance_identity_missing");
23186
23930
  }
23187
- const resultPath = (0, import_path35.join)(omcJobsDir, `${jobId}-result.json`);
23931
+ const resultPath = (0, import_path39.join)(omcJobsDir, `${jobId}-result.json`);
23188
23932
  const tmpPath = `${resultPath}.tmp`;
23189
23933
  await (0, import_promises20.writeFile)(
23190
23934
  tmpPath,
@@ -23259,7 +24003,7 @@ async function writePanesFile(jobId, instanceId, teamName, cwd, paneIds, leaderP
23259
24003
  if (authoritativePaneIds.some((paneId) => !paneIds.includes(paneId))) {
23260
24004
  throw new Error("pane_artifact_missing_runtime_pane");
23261
24005
  }
23262
- const panesPath = (0, import_path35.join)(omcJobsDir, `${jobId}-panes.json`);
24006
+ const panesPath = (0, import_path39.join)(omcJobsDir, `${jobId}-panes.json`);
23263
24007
  await (0, import_promises20.writeFile)(
23264
24008
  panesPath + ".tmp",
23265
24009
  JSON.stringify({
@@ -23297,7 +24041,7 @@ function isTerseFinalSummary(summary) {
23297
24041
  function readTaskOutputFallback(outputsDir, teamName, taskId) {
23298
24042
  let entries;
23299
24043
  try {
23300
- entries = (0, import_fs31.readdirSync)(outputsDir);
24044
+ entries = (0, import_fs35.readdirSync)(outputsDir);
23301
24045
  } catch {
23302
24046
  return null;
23303
24047
  }
@@ -23306,16 +24050,16 @@ function readTaskOutputFallback(outputsDir, teamName, taskId) {
23306
24050
  if (candidates.length === 0) return null;
23307
24051
  let newest = null;
23308
24052
  for (const name of candidates) {
23309
- const full = (0, import_path35.join)(outputsDir, name);
24053
+ const full = (0, import_path39.join)(outputsDir, name);
23310
24054
  try {
23311
- const mtime = (0, import_fs31.statSync)(full).mtimeMs;
24055
+ const mtime = (0, import_fs35.statSync)(full).mtimeMs;
23312
24056
  if (!newest || mtime > newest.mtime) newest = { path: full, mtime };
23313
24057
  } catch {
23314
24058
  }
23315
24059
  }
23316
24060
  if (!newest) return null;
23317
24061
  try {
23318
- const content = (0, import_fs31.readFileSync)(newest.path, "utf-8").trim();
24062
+ const content = (0, import_fs35.readFileSync)(newest.path, "utf-8").trim();
23319
24063
  if (content.length === 0) return null;
23320
24064
  return content.length > MAX_FALLBACK_SUMMARY_CHARS ? content.slice(0, MAX_FALLBACK_SUMMARY_CHARS) + "\n... (truncated)" : content;
23321
24065
  } catch {
@@ -23323,14 +24067,14 @@ function readTaskOutputFallback(outputsDir, teamName, taskId) {
23323
24067
  }
23324
24068
  }
23325
24069
  function collectTaskResults(stateRoot) {
23326
- const tasksDir = (0, import_path35.join)(stateRoot, "tasks");
23327
- const teamName = (0, import_path35.basename)(stateRoot);
23328
- const outputsDir = (0, import_path35.join)(stateRoot, "..", "..", "..", "outputs");
24070
+ const tasksDir = (0, import_path39.join)(stateRoot, "tasks");
24071
+ const teamName = (0, import_path39.basename)(stateRoot);
24072
+ const outputsDir = (0, import_path39.join)(stateRoot, "..", "..", "..", "outputs");
23329
24073
  try {
23330
- const files = (0, import_fs31.readdirSync)(tasksDir).filter((f) => f.endsWith(".json"));
24074
+ const files = (0, import_fs35.readdirSync)(tasksDir).filter((f) => f.endsWith(".json"));
23331
24075
  return files.map((f) => {
23332
24076
  try {
23333
- const raw = (0, import_fs31.readFileSync)((0, import_path35.join)(tasksDir, f), "utf-8");
24077
+ const raw = (0, import_fs35.readFileSync)((0, import_path39.join)(tasksDir, f), "utf-8");
23334
24078
  const task = JSON.parse(raw);
23335
24079
  const taskId = task.id ?? f.replace(".json", "");
23336
24080
  let summary = task.result ?? task.summary ?? "";
@@ -23365,8 +24109,8 @@ function createRuntimeStartupShutdownBarrier() {
23365
24109
  let settled = false;
23366
24110
  let requested = false;
23367
24111
  let resolveCompletion;
23368
- const completion = new Promise((resolve14) => {
23369
- resolveCompletion = resolve14;
24112
+ const completion = new Promise((resolve17) => {
24113
+ resolveCompletion = resolve17;
23370
24114
  });
23371
24115
  return {
23372
24116
  requestShutdown: () => {
@@ -23674,7 +24418,7 @@ async function main() {
23674
24418
  if (snap.allTasksTerminal) {
23675
24419
  const hasFailures = snap.tasks.failed > 0;
23676
24420
  if (!hasFailures) {
23677
- const sentinelLogPath = (0, import_path35.join)(cwd, "sentinel_stop.jsonl");
24421
+ const sentinelLogPath = (0, import_path39.join)(cwd, "sentinel_stop.jsonl");
23678
24422
  const gateResult = await waitForSentinelReadiness({
23679
24423
  workspace: cwd,
23680
24424
  logPath: sentinelLogPath,