@sortedyuan/maybecode 0.3.2 → 0.5.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 (295) hide show
  1. package/README.md +166 -55
  2. package/README.zh-CN.md +267 -0
  3. package/dist/application.d.ts +40 -34
  4. package/dist/application.d.ts.map +1 -1
  5. package/dist/application.js +290 -170
  6. package/dist/application.js.map +1 -1
  7. package/dist/args.d.ts +2 -2
  8. package/dist/args.d.ts.map +1 -1
  9. package/dist/args.js +50 -27
  10. package/dist/args.js.map +1 -1
  11. package/dist/bin.js +82 -71
  12. package/dist/bin.js.map +4 -4
  13. package/dist/cli/chunk-3IORPKBL.js +3572 -0
  14. package/dist/cli/chunk-3IORPKBL.js.map +7 -0
  15. package/dist/cli/{chunk-LVTRXPDS.js → chunk-4B2Z6KW7.js} +1547 -1536
  16. package/dist/cli/chunk-4B2Z6KW7.js.map +7 -0
  17. package/dist/cli/{chunk-JT6VBKOM.js → chunk-4WG6JIJJ.js} +127 -33
  18. package/dist/cli/{chunk-JT6VBKOM.js.map → chunk-4WG6JIJJ.js.map} +3 -3
  19. package/dist/cli/{chunk-K5JWPNSY.js → chunk-5SLWALZK.js} +3521 -16164
  20. package/dist/cli/chunk-5SLWALZK.js.map +7 -0
  21. package/dist/cli/chunk-MNBYXL5Y.js +132 -0
  22. package/dist/cli/chunk-MNBYXL5Y.js.map +7 -0
  23. package/dist/cli/{chunk-F4XRPLUM.js → chunk-SLWLUEHQ.js} +226 -86
  24. package/dist/cli/chunk-SLWLUEHQ.js.map +7 -0
  25. package/dist/cli/chunk-UQDZ55LQ.js +199 -0
  26. package/dist/cli/chunk-UQDZ55LQ.js.map +7 -0
  27. package/dist/cli/{chunk-7ISOHFS7.js → chunk-WMSG5ZTR.js} +717 -388
  28. package/dist/cli/chunk-WMSG5ZTR.js.map +7 -0
  29. package/dist/cli/chunk-WVIRS76R.js +4057 -0
  30. package/dist/cli/chunk-WVIRS76R.js.map +7 -0
  31. package/dist/cli/{chunk-HOU5ITUK.js → chunk-XTEMRAQW.js} +1 -1
  32. package/dist/cli/chunk-XTEMRAQW.js.map +7 -0
  33. package/dist/cli/chunk-Z3BOPBVU.js +91 -0
  34. package/dist/cli/chunk-Z3BOPBVU.js.map +7 -0
  35. package/dist/cli/{configured-WHY3GGAJ.js → configured-ACNM6TRQ.js} +10 -9
  36. package/dist/cli/{file-type-R2T7TBHI.js → file-type-HLHPV7WC.js} +817 -13
  37. package/dist/cli/file-type-HLHPV7WC.js.map +7 -0
  38. package/dist/cli/mcp-auth-XD5U7WCV.js +74 -0
  39. package/dist/cli/mcp-auth-XD5U7WCV.js.map +7 -0
  40. package/dist/cli/onboarding-WQWCPYEO.js +530 -0
  41. package/dist/cli/onboarding-WQWCPYEO.js.map +7 -0
  42. package/dist/cli/onboarding-check-HRRI5OJ7.js +32 -0
  43. package/dist/cli/onboarding-check-HRRI5OJ7.js.map +7 -0
  44. package/dist/cli/{retained-tui-VJ3VX4R3.js → retained-tui-QF5VMYLC.js} +788 -332
  45. package/dist/cli/retained-tui-QF5VMYLC.js.map +7 -0
  46. package/dist/cli/{sixel-LWTCM76G.js → sixel-ISZ4FZ3U.js} +37 -37
  47. package/dist/cli/{sixel-LWTCM76G.js.map → sixel-ISZ4FZ3U.js.map} +1 -1
  48. package/dist/cli/{team-T7G7PPNN.js → team-O2I5BXHM.js} +7 -6
  49. package/dist/cli/{team-v2-JGBBQ7FR.js → team-v2-YYO2G7DJ.js} +816 -390
  50. package/dist/cli/team-v2-YYO2G7DJ.js.map +7 -0
  51. package/dist/cli/{web-server-FOMNPY7Q.js → web-server-SXMH6FGA.js} +55 -19
  52. package/dist/cli/web-server-SXMH6FGA.js.map +7 -0
  53. package/dist/cli/{web-ui-COB6PKC5.js → web-ui-UWQUFE4W.js} +7 -6
  54. package/dist/config-schema.json +337 -0
  55. package/dist/configured.d.ts +18 -11
  56. package/dist/configured.d.ts.map +1 -1
  57. package/dist/configured.js +213 -390
  58. package/dist/configured.js.map +1 -1
  59. package/dist/controller.d.ts +19 -18
  60. package/dist/controller.d.ts.map +1 -1
  61. package/dist/delegation-commands.d.ts +1 -1
  62. package/dist/delegation-commands.d.ts.map +1 -1
  63. package/dist/delegation-commands.js +8 -8
  64. package/dist/delegation-commands.js.map +1 -1
  65. package/dist/errors.d.ts +2 -1
  66. package/dist/errors.d.ts.map +1 -1
  67. package/dist/errors.js +2 -1
  68. package/dist/errors.js.map +1 -1
  69. package/dist/events.d.ts +8 -6
  70. package/dist/events.d.ts.map +1 -1
  71. package/dist/fork-picker.d.ts.map +1 -1
  72. package/dist/fork-picker.js +19 -5
  73. package/dist/fork-picker.js.map +1 -1
  74. package/dist/git-request.d.ts +6 -6
  75. package/dist/git-request.d.ts.map +1 -1
  76. package/dist/git-request.js +28 -15
  77. package/dist/git-request.js.map +1 -1
  78. package/dist/goal-commands.d.ts +1 -1
  79. package/dist/goal-commands.d.ts.map +1 -1
  80. package/dist/goal-commands.js +12 -5
  81. package/dist/goal-commands.js.map +1 -1
  82. package/dist/index.d.ts +5 -37
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +3 -36
  85. package/dist/index.js.map +1 -1
  86. package/dist/instructions.d.ts +2 -7
  87. package/dist/instructions.d.ts.map +1 -1
  88. package/dist/instructions.js +7 -15
  89. package/dist/instructions.js.map +1 -1
  90. package/dist/keymap.d.ts +2 -2
  91. package/dist/keymap.d.ts.map +1 -1
  92. package/dist/keymap.js +2 -2
  93. package/dist/keymap.js.map +1 -1
  94. package/dist/maybecode-config.schema.json +1765 -0
  95. package/dist/mcp-auth.d.ts +1 -1
  96. package/dist/mcp-auth.d.ts.map +1 -1
  97. package/dist/mcp-auth.js +11 -8
  98. package/dist/mcp-auth.js.map +1 -1
  99. package/dist/mcp-commands.d.ts.map +1 -1
  100. package/dist/mcp-commands.js +18 -4
  101. package/dist/mcp-commands.js.map +1 -1
  102. package/dist/mcp-interaction-ui.d.ts.map +1 -1
  103. package/dist/mcp-interaction-ui.js +11 -4
  104. package/dist/mcp-interaction-ui.js.map +1 -1
  105. package/dist/media-history.d.ts +1 -1
  106. package/dist/media-history.d.ts.map +1 -1
  107. package/dist/media-history.js +8 -2
  108. package/dist/media-history.js.map +1 -1
  109. package/dist/model-picker.d.ts.map +1 -1
  110. package/dist/model-picker.js +10 -11
  111. package/dist/model-picker.js.map +1 -1
  112. package/dist/model-transition.d.ts +11 -0
  113. package/dist/model-transition.d.ts.map +1 -0
  114. package/dist/model-transition.js +48 -0
  115. package/dist/model-transition.js.map +1 -0
  116. package/dist/model.d.ts +2 -2
  117. package/dist/model.d.ts.map +1 -1
  118. package/dist/model.js +8 -4
  119. package/dist/model.js.map +1 -1
  120. package/dist/onboarding-check.d.ts +3 -0
  121. package/dist/onboarding-check.d.ts.map +1 -0
  122. package/dist/onboarding-check.js +22 -0
  123. package/dist/onboarding-check.js.map +1 -0
  124. package/dist/onboarding.d.ts +6 -0
  125. package/dist/onboarding.d.ts.map +1 -0
  126. package/dist/onboarding.js +463 -0
  127. package/dist/onboarding.js.map +1 -0
  128. package/dist/plugins/application.d.ts +6 -4
  129. package/dist/plugins/application.d.ts.map +1 -1
  130. package/dist/plugins/application.js +106 -52
  131. package/dist/plugins/application.js.map +1 -1
  132. package/dist/plugins/instructions.d.ts +1 -1
  133. package/dist/plugins/instructions.d.ts.map +1 -1
  134. package/dist/plugins/instructions.js +24 -11
  135. package/dist/plugins/instructions.js.map +1 -1
  136. package/dist/plugins/resources.d.ts +2 -2
  137. package/dist/plugins/resources.d.ts.map +1 -1
  138. package/dist/plugins/resources.js +22 -12
  139. package/dist/plugins/resources.js.map +1 -1
  140. package/dist/policy.d.ts +1 -1
  141. package/dist/policy.d.ts.map +1 -1
  142. package/dist/policy.js +59 -11
  143. package/dist/policy.js.map +1 -1
  144. package/dist/run.d.ts +2 -0
  145. package/dist/run.d.ts.map +1 -1
  146. package/dist/run.js +38 -33
  147. package/dist/run.js.map +1 -1
  148. package/dist/runtime-instructions.d.ts +1 -1
  149. package/dist/runtime-instructions.d.ts.map +1 -1
  150. package/dist/runtime-instructions.js +15 -7
  151. package/dist/runtime-instructions.js.map +1 -1
  152. package/dist/session-navigation.d.ts +6 -0
  153. package/dist/session-navigation.d.ts.map +1 -0
  154. package/dist/session-navigation.js +64 -0
  155. package/dist/session-navigation.js.map +1 -0
  156. package/dist/session-picker.d.ts +1 -1
  157. package/dist/session-picker.d.ts.map +1 -1
  158. package/dist/session-picker.js +23 -32
  159. package/dist/session-picker.js.map +1 -1
  160. package/dist/settings.d.ts +718 -0
  161. package/dist/settings.d.ts.map +1 -0
  162. package/dist/settings.js +14 -0
  163. package/dist/settings.js.map +1 -0
  164. package/dist/skills.d.ts +1 -1
  165. package/dist/skills.d.ts.map +1 -1
  166. package/dist/skills.js +10 -12
  167. package/dist/skills.js.map +1 -1
  168. package/dist/slash-commands.d.ts +2 -2
  169. package/dist/slash-commands.d.ts.map +1 -1
  170. package/dist/slash-commands.js +149 -67
  171. package/dist/slash-commands.js.map +1 -1
  172. package/dist/team-execution.d.ts +10 -0
  173. package/dist/team-execution.d.ts.map +1 -0
  174. package/dist/team-execution.js +29 -0
  175. package/dist/team-execution.js.map +1 -0
  176. package/dist/team-patches.d.ts.map +1 -1
  177. package/dist/team-patches.js +149 -52
  178. package/dist/team-patches.js.map +1 -1
  179. package/dist/team-plan.d.ts +2 -2
  180. package/dist/team-plan.d.ts.map +1 -1
  181. package/dist/team-plan.js +115 -34
  182. package/dist/team-plan.js.map +1 -1
  183. package/dist/team-recovery.d.ts +1 -1
  184. package/dist/team-recovery.d.ts.map +1 -1
  185. package/dist/team-recovery.js +40 -10
  186. package/dist/team-recovery.js.map +1 -1
  187. package/dist/team-v2.d.ts.map +1 -1
  188. package/dist/team-v2.js +335 -104
  189. package/dist/team-v2.js.map +1 -1
  190. package/dist/team-verification.d.ts +4 -2
  191. package/dist/team-verification.d.ts.map +1 -1
  192. package/dist/team-verification.js +300 -97
  193. package/dist/team-verification.js.map +1 -1
  194. package/dist/team.d.ts +2 -2
  195. package/dist/team.d.ts.map +1 -1
  196. package/dist/team.js +172 -62
  197. package/dist/team.js.map +1 -1
  198. package/dist/terminal-web.d.ts +1 -0
  199. package/dist/terminal-web.d.ts.map +1 -1
  200. package/dist/terminal-web.js +28 -10
  201. package/dist/terminal-web.js.map +1 -1
  202. package/dist/ui/actions.d.ts.map +1 -1
  203. package/dist/ui/actions.js.map +1 -1
  204. package/dist/ui/retained-tui.d.ts.map +1 -1
  205. package/dist/ui/retained-tui.js +231 -173
  206. package/dist/ui/retained-tui.js.map +1 -1
  207. package/dist/ui/{prototype-view.d.ts → terminal-view.d.ts} +7 -7
  208. package/dist/ui/terminal-view.d.ts.map +1 -0
  209. package/dist/ui/{prototype-view.js → terminal-view.js} +185 -98
  210. package/dist/ui/terminal-view.js.map +1 -0
  211. package/dist/web-commands.d.ts.map +1 -1
  212. package/dist/web-commands.js +160 -57
  213. package/dist/web-commands.js.map +1 -1
  214. package/dist/web-extension.d.ts.map +1 -1
  215. package/dist/web-extension.js +14 -4
  216. package/dist/web-extension.js.map +1 -1
  217. package/dist/web-server.d.ts.map +1 -1
  218. package/dist/web-server.js +2 -1
  219. package/dist/web-server.js.map +1 -1
  220. package/dist/web-ui.d.ts.map +1 -1
  221. package/dist/web-ui.js +167 -40
  222. package/dist/web-ui.js.map +1 -1
  223. package/dist/workspace-configuration.d.ts +7 -0
  224. package/dist/workspace-configuration.d.ts.map +1 -0
  225. package/dist/workspace-configuration.js +134 -0
  226. package/dist/workspace-configuration.js.map +1 -0
  227. package/dist/workspace-state.d.ts +20 -0
  228. package/dist/workspace-state.d.ts.map +1 -0
  229. package/dist/workspace-state.js +2 -0
  230. package/dist/workspace-state.js.map +1 -0
  231. package/dist/workspace.d.ts +26 -43
  232. package/dist/workspace.d.ts.map +1 -1
  233. package/dist/workspace.js +261 -323
  234. package/dist/workspace.js.map +1 -1
  235. package/package.json +21 -31
  236. package/dist/cli/chunk-7ISOHFS7.js.map +0 -7
  237. package/dist/cli/chunk-F4XRPLUM.js.map +0 -7
  238. package/dist/cli/chunk-H7SNBFO4.js +0 -5522
  239. package/dist/cli/chunk-H7SNBFO4.js.map +0 -7
  240. package/dist/cli/chunk-HOU5ITUK.js.map +0 -7
  241. package/dist/cli/chunk-K5JWPNSY.js.map +0 -7
  242. package/dist/cli/chunk-LVTRXPDS.js.map +0 -7
  243. package/dist/cli/chunk-VAZMCNBB.js +0 -686
  244. package/dist/cli/chunk-VAZMCNBB.js.map +0 -7
  245. package/dist/cli/chunk-WOFEI42C.js +0 -7820
  246. package/dist/cli/chunk-WOFEI42C.js.map +0 -7
  247. package/dist/cli/file-type-R2T7TBHI.js.map +0 -7
  248. package/dist/cli/mcp-auth-UNRHSIKJ.js +0 -63
  249. package/dist/cli/mcp-auth-UNRHSIKJ.js.map +0 -7
  250. package/dist/cli/retained-tui-VJ3VX4R3.js.map +0 -7
  251. package/dist/cli/team-v2-JGBBQ7FR.js.map +0 -7
  252. package/dist/cli/tui-SA74DKMA.js +0 -1705
  253. package/dist/cli/tui-SA74DKMA.js.map +0 -7
  254. package/dist/cli/web-server-FOMNPY7Q.js.map +0 -7
  255. package/dist/delegation.d.ts +0 -2
  256. package/dist/delegation.d.ts.map +0 -1
  257. package/dist/delegation.js +0 -2
  258. package/dist/delegation.js.map +0 -1
  259. package/dist/history-memory.d.ts +0 -2
  260. package/dist/history-memory.d.ts.map +0 -1
  261. package/dist/history-memory.js +0 -2
  262. package/dist/history-memory.js.map +0 -1
  263. package/dist/subagent-budget.d.ts +0 -2
  264. package/dist/subagent-budget.d.ts.map +0 -1
  265. package/dist/subagent-budget.js +0 -2
  266. package/dist/subagent-budget.js.map +0 -1
  267. package/dist/subagent-files.d.ts +0 -2
  268. package/dist/subagent-files.d.ts.map +0 -1
  269. package/dist/subagent-files.js +0 -2
  270. package/dist/subagent-files.js.map +0 -1
  271. package/dist/subagent-host.d.ts +0 -2
  272. package/dist/subagent-host.d.ts.map +0 -1
  273. package/dist/subagent-host.js +0 -2
  274. package/dist/subagent-host.js.map +0 -1
  275. package/dist/subagent-instructions.d.ts +0 -2
  276. package/dist/subagent-instructions.d.ts.map +0 -1
  277. package/dist/subagent-instructions.js +0 -2
  278. package/dist/subagent-instructions.js.map +0 -1
  279. package/dist/subagents.d.ts +0 -2
  280. package/dist/subagents.d.ts.map +0 -1
  281. package/dist/subagents.js +0 -2
  282. package/dist/subagents.js.map +0 -1
  283. package/dist/summarizer.d.ts +0 -2
  284. package/dist/summarizer.d.ts.map +0 -1
  285. package/dist/summarizer.js +0 -2
  286. package/dist/summarizer.js.map +0 -1
  287. package/dist/tui.d.ts +0 -7
  288. package/dist/tui.d.ts.map +0 -1
  289. package/dist/tui.js +0 -1109
  290. package/dist/tui.js.map +0 -1
  291. package/dist/ui/prototype-view.d.ts.map +0 -1
  292. package/dist/ui/prototype-view.js.map +0 -1
  293. /package/dist/cli/{configured-WHY3GGAJ.js.map → configured-ACNM6TRQ.js.map} +0 -0
  294. /package/dist/cli/{team-T7G7PPNN.js.map → team-O2I5BXHM.js.map} +0 -0
  295. /package/dist/cli/{web-ui-COB6PKC5.js.map → web-ui-UWQUFE4W.js.map} +0 -0
@@ -1,17 +1,18 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
+ TeamExecutionEnvironments,
3
4
  createListTool
4
- } from "./chunk-F4XRPLUM.js";
5
+ } from "./chunk-SLWLUEHQ.js";
5
6
  import {
6
7
  createMaybeCodeModel,
7
8
  getDefaultMaybeCodeDataDirectory,
8
- loadMayConfig,
9
+ readMaybeCodeSettings,
10
+ resolveMaybeCodeRecording,
9
11
  selectMaybeCodeModel
10
- } from "./chunk-WOFEI42C.js";
11
- import "./chunk-H7SNBFO4.js";
12
- import "./chunk-VAZMCNBB.js";
12
+ } from "./chunk-3IORPKBL.js";
13
+ import "./chunk-MNBYXL5Y.js";
14
+ import "./chunk-WVIRS76R.js";
13
15
  import {
14
- AsyncStateSerializer,
15
16
  CoordinationRuntime,
16
17
  FileArtifactStore,
17
18
  FileCoordinationStore,
@@ -19,49 +20,60 @@ import {
19
20
  MaybeCodeUsageError,
20
21
  TaskWorkspaceManager,
21
22
  createApplicationAgent,
22
- createEditTool,
23
- createReadTool,
24
- createWriteTool,
25
- defineAgent,
23
+ require_lib,
26
24
  sharedBudgetTotals
27
- } from "./chunk-K5JWPNSY.js";
25
+ } from "./chunk-5SLWALZK.js";
26
+ import "./chunk-UQDZ55LQ.js";
28
27
  import "./chunk-BSBNNF34.js";
29
28
  import {
30
- __name
29
+ __name,
30
+ __toESM
31
31
  } from "./chunk-E732GDOI.js";
32
32
 
33
33
  // apps/maybecode/src/team-v2.ts
34
34
  import { randomUUID as randomUUID2 } from "node:crypto";
35
- import { mkdir as mkdir3, open as open5, readFile, realpath as realpath3, rename as rename2, stat } from "node:fs/promises";
35
+ import { mkdir as mkdir3, open as open5, readFile, realpath as realpath3, stat } from "node:fs/promises";
36
36
  import { dirname as dirname2, isAbsolute as isAbsolute3, join as join4, relative as relative3, resolve as resolve3, sep as sep3 } from "node:path";
37
- import { resolveRunBudget as resolveRunBudget2 } from "@sortedyuan/core";
38
- import { FileSessionStore as FileSessionStore2 } from "@sortedyuan/session/file-store";
39
- import { withFileAccess } from "@sortedyuan/session/file-access";
37
+ import { defineAgent } from "@sortedyuan/may";
38
+ import {
39
+ createEditTool,
40
+ createReadTool,
41
+ createWriteTool,
42
+ createGlobTool,
43
+ createGrepTool,
44
+ createFetchTool
45
+ } from "@sortedyuan/coding-tools";
46
+ import { loadMayConfig } from "@sortedyuan/may/config";
47
+ var import_write_file_atomic = __toESM(require_lib(), 1);
48
+ import { resolveRunBudget as resolveRunBudget2 } from "@sortedyuan/may/core";
49
+ import { FileSessionStore as FileSessionStore2 } from "@sortedyuan/may/session/file-store";
50
+ import { hasErrorCode as hasErrorCode3, withFileAccess } from "@sortedyuan/may/storage";
40
51
 
41
52
  // apps/maybecode/src/team-plan.ts
42
53
  import { open as open2 } from "node:fs/promises";
43
- import { resolveRunBudget } from "@sortedyuan/core";
54
+ import { omitUndefined, resolveRunBudget } from "@sortedyuan/may/core";
44
55
 
45
56
  // apps/maybecode/src/team-verification.ts
46
- import { acquireFileLock, releaseFileLock } from "@sortedyuan/session/file-store";
57
+ import { acquireFileLock, hasErrorCode } from "@sortedyuan/may/storage";
47
58
  import { createHash } from "node:crypto";
48
- import { spawn } from "node:child_process";
49
59
  import { constants } from "node:fs";
50
60
  import { lstat, mkdir, open, readdir, realpath } from "node:fs/promises";
51
61
  import { isAbsolute, join, relative, resolve, sep } from "node:path";
52
62
  import { isDeepStrictEqual } from "node:util";
63
+ import { AsyncStateSerializer } from "@sortedyuan/may/core";
64
+ import { openCodingExecutionEnvironment } from "@sortedyuan/coding-tools";
53
65
  var maxJournalBytes = 16777216;
54
66
  var TeamVerificationStore = class _TeamVerificationStore {
55
- constructor(file, lock, lockPath, checks) {
67
+ constructor(file, lock, checks, executionFor) {
56
68
  this.file = file;
57
69
  this.lock = lock;
58
- this.lockPath = lockPath;
59
70
  this.checks = checks;
71
+ this.executionFor = executionFor;
60
72
  }
61
73
  file;
62
74
  lock;
63
- lockPath;
64
75
  checks;
76
+ executionFor;
65
77
  static {
66
78
  __name(this, "TeamVerificationStore");
67
79
  }
@@ -76,14 +88,12 @@ var TeamVerificationStore = class _TeamVerificationStore {
76
88
  static async open(options) {
77
89
  const checks = parseTeamChecks(options.checks ?? []);
78
90
  await mkdir(options.directory, { recursive: true });
79
- if ((await lstat(options.directory)).isSymbolicLink()) throw new Error("Verification directory must not be a symbolic link");
91
+ if ((await lstat(options.directory)).isSymbolicLink())
92
+ throw new Error("Verification directory must not be a symbolic link");
80
93
  const path = join(await realpath(options.directory), "verification.jsonl");
81
- const lockPath = `${path}.lock`;
82
- const lock = await acquireFileLock(lockPath);
94
+ const lock = await acquireFileLock(`${path}.lock`);
83
95
  let file;
84
96
  try {
85
- await lock.writeFile(JSON.stringify({ pid: process.pid }));
86
- await lock.sync();
87
97
  await rejectLinkIfPresent(path);
88
98
  file = await open(path, constants.O_CREAT | constants.O_APPEND | constants.O_RDWR | noFollow(), 384);
89
99
  const { entries, committed, size } = await readJournal(file);
@@ -96,21 +106,33 @@ var TeamVerificationStore = class _TeamVerificationStore {
96
106
  await repair.close();
97
107
  }
98
108
  }
99
- const store = new _TeamVerificationStore(file, lock, lockPath, checks);
109
+ const store = new _TeamVerificationStore(file, lock, checks, options.executionFor);
100
110
  store.size = committed;
101
111
  for (const entry of entries) {
102
112
  store.apply(entry.event);
103
113
  store.sequence = entry.sequence;
104
114
  }
105
- if (entries.length && !isDeepStrictEqual(entries[0].event.checks, checks)) throw new Error("Verification checks changed on resume");
115
+ if (entries.length && !isDeepStrictEqual(entries[0].event.checks, checks))
116
+ throw new Error("Verification checks changed on resume");
106
117
  if (!entries.length) await store.append({ type: "config", checks });
107
- for (const result of store.results.values()) if (result.status === "pending") {
108
- await store.append({ type: "check", result: { ...result, status: "unknown", detail: "Interrupted check; inspect effects and reconcile before a new command." } });
109
- }
118
+ for (const result of store.results.values())
119
+ if (result.status === "pending") {
120
+ await store.append({
121
+ type: "check",
122
+ result: {
123
+ ...result,
124
+ status: "unknown",
125
+ detail: "Interrupted check; inspect effects and reconcile before a new command."
126
+ }
127
+ });
128
+ }
110
129
  return store;
111
130
  } catch (error) {
112
- await file?.close().catch(() => void 0);
113
- await releaseFileLock(lock, lockPath);
131
+ try {
132
+ await file?.close();
133
+ } finally {
134
+ await lock.release();
135
+ }
114
136
  throw error;
115
137
  }
116
138
  }
@@ -122,7 +144,7 @@ var TeamVerificationStore = class _TeamVerificationStore {
122
144
  try {
123
145
  file = await open(path, constants.O_RDONLY | noFollow());
124
146
  } catch (error) {
125
- if (isMissing(error)) return { reports: [], checks: [] };
147
+ if (hasErrorCode(error, "ENOENT")) return { reports: [], checks: [] };
126
148
  throw error;
127
149
  }
128
150
  try {
@@ -152,38 +174,72 @@ var TeamVerificationStore = class _TeamVerificationStore {
152
174
  if (!spec) throw new Error("Check is not configured for this task");
153
175
  return this.runCheck(commandId, spec, workspace, { ...options, ...extra, execution });
154
176
  }, "runCheck");
155
- const tools = /* @__PURE__ */ __name(() => [{
156
- name: "submit_report",
157
- permissionVersion: "team-verification-v1",
158
- description: "Store a structured report and file/line evidence. The host validates evidence bytes, not claim correctness. This never grants acceptance.",
159
- inputSchema: { type: "object", additionalProperties: false, required: ["summary", "claims"], properties: {
160
- summary: { type: "string" },
161
- claims: { type: "array", items: { type: "object", additionalProperties: false, required: ["text", "kind"], properties: {
162
- text: { type: "string" },
163
- kind: { type: "string", enum: ["finding", "proposal"] },
164
- evidence: { type: "array", items: { type: "object", additionalProperties: false, required: ["path", "startLine", "endLine"], properties: { path: { type: "string" }, startLine: { type: "integer" }, endLine: { type: "integer" }, quote: { type: "string" } } } }
165
- } } }
166
- } },
167
- parse: parseTeamReport,
168
- async execute(input, call) {
169
- call.signal.throwIfAborted();
170
- return submit(hash(call.idempotencyKey), input);
171
- }
172
- }, {
173
- name: "run_check",
174
- permissionVersion: "team-verification-v1",
175
- description: `Run one exact host-configured check by id; no model-supplied commands or arguments. Available: ${this.checks.filter((entry) => entry.taskId === identity.taskId).map((entry) => entry.id).join(", ") || "none"}. Command checks require explicit host authorization and are not sandboxed.`,
176
- inputSchema: { type: "object", additionalProperties: false, required: ["id"], properties: { id: { type: "string" } } },
177
- parse(value) {
178
- const input = fields(value, ["id"]);
179
- identifier(input.id, "check id");
180
- return { id: input.id };
177
+ const tools = /* @__PURE__ */ __name(() => [
178
+ {
179
+ name: "submit_report",
180
+ permissionVersion: "team-verification-v1",
181
+ description: "Store a structured report and file/line evidence. The host validates evidence bytes, not claim correctness. This never grants acceptance.",
182
+ inputSchema: {
183
+ type: "object",
184
+ additionalProperties: false,
185
+ required: ["summary", "claims"],
186
+ properties: {
187
+ summary: { type: "string" },
188
+ claims: {
189
+ type: "array",
190
+ items: {
191
+ type: "object",
192
+ additionalProperties: false,
193
+ required: ["text", "kind"],
194
+ properties: {
195
+ text: { type: "string" },
196
+ kind: { type: "string", enum: ["finding", "proposal"] },
197
+ evidence: {
198
+ type: "array",
199
+ items: {
200
+ type: "object",
201
+ additionalProperties: false,
202
+ required: ["path", "startLine", "endLine"],
203
+ properties: {
204
+ path: { type: "string" },
205
+ startLine: { type: "integer" },
206
+ endLine: { type: "integer" },
207
+ quote: { type: "string" }
208
+ }
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ }
215
+ },
216
+ parse: parseTeamReport,
217
+ async execute(input, call) {
218
+ call.signal.throwIfAborted();
219
+ return submit(hash(call.idempotencyKey), input);
220
+ }
181
221
  },
182
- async execute(input, call) {
183
- call.signal.throwIfAborted();
184
- return runCheck(hash(call.idempotencyKey), input.id, { signal: call.signal });
222
+ {
223
+ name: "run_check",
224
+ permissionVersion: "team-verification-v1",
225
+ description: `Run one exact host-configured check by id; no model-supplied commands or arguments. Available: ${this.checks.filter((entry) => entry.taskId === identity.taskId).map((entry) => entry.id).join(", ") || "none"}. Command checks require explicit host authorization and are not sandboxed.`,
226
+ inputSchema: {
227
+ type: "object",
228
+ additionalProperties: false,
229
+ required: ["id"],
230
+ properties: { id: { type: "string" } }
231
+ },
232
+ parse(value) {
233
+ const input = fields(value, ["id"]);
234
+ identifier(input.id, "check id");
235
+ return { id: input.id };
236
+ },
237
+ async execute(input, call) {
238
+ call.signal.throwIfAborted();
239
+ return runCheck(hash(call.idempotencyKey), input.id, { signal: call.signal });
240
+ }
185
241
  }
186
- }], "tools");
242
+ ], "tools");
187
243
  return { submit, runCheck, tools };
188
244
  }
189
245
  runCheck(commandId, input, workspace, options = {}) {
@@ -195,16 +251,19 @@ var TeamVerificationStore = class _TeamVerificationStore {
195
251
  /** Host reconciliation never invents a passing result and never executes a command. */
196
252
  async reconcile(commandId, outcome, evidence) {
197
253
  boundedString(evidence, "reconciliation evidence", 8192);
198
- if (outcome.status !== "failed" && outcome.status !== "cancelled") throw new Error("Reconciliation cannot grant acceptance");
254
+ if (outcome.status !== "failed" && outcome.status !== "cancelled")
255
+ throw new Error("Reconciliation cannot grant acceptance");
199
256
  return this.serial.run(async () => {
200
257
  this.assertOpen();
201
258
  const current = this.results.get(commandId);
202
259
  if (!current) throw new Error("Unknown check command");
203
260
  if (current.reconciliation) {
204
- if (current.status !== outcome.status || current.reconciliation !== evidence) throw new Error("Reconciliation already recorded differently");
261
+ if (current.status !== outcome.status || current.reconciliation !== evidence)
262
+ throw new Error("Reconciliation already recorded differently");
205
263
  return structuredClone(current);
206
264
  }
207
- if (current.status !== "unknown") throw new Error("Only an unknown check can be reconciled; an active pending check must first stop");
265
+ if (current.status !== "unknown")
266
+ throw new Error("Only an unknown check can be reconciled; an active pending check must first stop");
208
267
  const result = { ...current, status: outcome.status, reconciliation: evidence };
209
268
  await this.write({ type: "check", result });
210
269
  return structuredClone(result);
@@ -216,10 +275,17 @@ var TeamVerificationStore = class _TeamVerificationStore {
216
275
  const identity = execution ? taskIdentity(execution) : void 0;
217
276
  const report = state.reports.filter((entry) => entry.taskId === taskId && (!identity || sameIdentity(entry, identity))).at(-1);
218
277
  const checks = this.checks.filter((spec) => spec.taskId === taskId).map((spec) => {
219
- const result = state.checks.filter((entry) => entry.spec.id === spec.id && (!identity || entry.dispatchId === void 0 || sameIdentity(entry, identity))).at(-1);
278
+ const result = state.checks.filter(
279
+ (entry) => entry.spec.id === spec.id && (!identity || entry.dispatchId === void 0 || sameIdentity(entry, identity))
280
+ ).at(-1);
220
281
  if (!result) return { id: spec.id, status: "missing" };
221
282
  const stale = result.workspaceFingerprint !== fingerprint || result.afterFingerprint !== fingerprint;
222
- return { id: spec.id, status: stale && !["pending", "unknown"].includes(result.status) ? "stale" : result.status, commandId: result.commandId, ...result.detail ? { detail: result.detail } : {} };
283
+ return {
284
+ id: spec.id,
285
+ status: stale && !["pending", "unknown"].includes(result.status) ? "stale" : result.status,
286
+ commandId: result.commandId,
287
+ ...result.detail ? { detail: result.detail } : {}
288
+ };
223
289
  });
224
290
  const currentReport = report?.workspaceFingerprint === fingerprint;
225
291
  const badEvidence = currentReport && report.evidence.some((item) => !item.valid);
@@ -239,7 +305,7 @@ var TeamVerificationStore = class _TeamVerificationStore {
239
305
  try {
240
306
  await this.file.close();
241
307
  } finally {
242
- await releaseFileLock(this.lock, this.lockPath);
308
+ await this.lock.release();
243
309
  }
244
310
  })();
245
311
  }
@@ -250,32 +316,41 @@ var TeamVerificationStore = class _TeamVerificationStore {
250
316
  this.assertOpen();
251
317
  const old = this.reports.find((entry) => entry.commandId === commandId);
252
318
  if (old) {
253
- if (!sameIdentity(old, identity) || !isDeepStrictEqual(old.report, report)) throw new Error("Report command already used with different content or identity");
319
+ if (!sameIdentity(old, identity) || !isDeepStrictEqual(old.report, report))
320
+ throw new Error("Report command already used with different content or identity");
254
321
  return structuredClone(old);
255
322
  }
256
323
  if (this.reports.length >= 256) throw new Error("Report quota exceeded");
257
324
  const fingerprint = await workspaceFingerprint(workspace);
258
325
  const evidence = [];
259
- for (const claim of report.claims) for (const item of claim.evidence ?? []) {
260
- try {
261
- const bytes = await readWorkspaceFile(workspace, item.path);
262
- const lines2 = bytes.toString("utf8").replace(/\r\n/gu, "\n").split("\n");
263
- if (lines2.at(-1) === "") lines2.pop();
264
- const excerpt = lines2.slice(item.startLine - 1, item.endLine).join("\n");
265
- const valid = item.endLine <= lines2.length && (item.quote === void 0 || excerpt.includes(item.quote.replace(/\r\n/gu, "\n")));
266
- evidence.push({
267
- path: item.path,
268
- startLine: item.startLine,
269
- endLine: item.endLine,
270
- sha256: hash(bytes),
271
- valid,
272
- ...!valid ? { detail: "Line range or quote does not match the file" } : {}
273
- });
274
- } catch (error) {
275
- evidence.push({ path: item.path, startLine: item.startLine, endLine: item.endLine, valid: false, detail: message(error) });
326
+ for (const claim of report.claims)
327
+ for (const item of claim.evidence ?? []) {
328
+ try {
329
+ const bytes = await readWorkspaceFile(workspace, item.path);
330
+ const lines2 = bytes.toString("utf8").replace(/\r\n/gu, "\n").split("\n");
331
+ if (lines2.at(-1) === "") lines2.pop();
332
+ const excerpt = lines2.slice(item.startLine - 1, item.endLine).join("\n");
333
+ const valid = item.endLine <= lines2.length && (item.quote === void 0 || excerpt.includes(item.quote.replace(/\r\n/gu, "\n")));
334
+ evidence.push({
335
+ path: item.path,
336
+ startLine: item.startLine,
337
+ endLine: item.endLine,
338
+ sha256: hash(bytes),
339
+ valid,
340
+ ...!valid ? { detail: "Line range or quote does not match the file" } : {}
341
+ });
342
+ } catch (error) {
343
+ evidence.push({
344
+ path: item.path,
345
+ startLine: item.startLine,
346
+ endLine: item.endLine,
347
+ valid: false,
348
+ detail: message(error)
349
+ });
350
+ }
276
351
  }
277
- }
278
- if (await workspaceFingerprint(workspace) !== fingerprint) throw new Error("Workspace changed while validating report evidence");
352
+ if (await workspaceFingerprint(workspace) !== fingerprint)
353
+ throw new Error("Workspace changed while validating report evidence");
279
354
  const stored = { ...identity, commandId, report, workspaceFingerprint: fingerprint, evidence };
280
355
  await this.write({ type: "report", report: stored });
281
356
  return structuredClone(stored);
@@ -293,14 +368,25 @@ var TeamVerificationStore = class _TeamVerificationStore {
293
368
  this.assertOpen();
294
369
  const old = this.results.get(commandId);
295
370
  if (old) {
296
- if (!isDeepStrictEqual(old.spec, spec) || !sameIdentity(old, identity)) throw new Error("Check command already used with different specification or identity");
371
+ if (!isDeepStrictEqual(old.spec, spec) || !sameIdentity(old, identity))
372
+ throw new Error("Check command already used with different specification or identity");
297
373
  return structuredClone(old);
298
374
  }
299
375
  if (this.results.size >= 512) throw new Error("Check quota exceeded");
300
- if ([...this.results.values()].some((entry) => entry.taskId === spec.taskId && ["unknown", "pending"].includes(entry.status))) throw new Error("Task has a pending or unknown check; inspect and reconcile before another check");
301
- if (spec.type === "command" && options.allowCommands !== true) throw new Error("Command checks require explicit --allow-checks authorization");
376
+ if ([...this.results.values()].some(
377
+ (entry) => entry.taskId === spec.taskId && ["unknown", "pending"].includes(entry.status)
378
+ ))
379
+ throw new Error("Task has a pending or unknown check; inspect and reconcile before another check");
380
+ if (spec.type === "command" && options.allowCommands !== true)
381
+ throw new Error("Command checks require explicit --allow-checks authorization");
302
382
  options.signal?.throwIfAborted();
303
- const result2 = { ...identity, commandId, spec, workspaceFingerprint: await workspaceFingerprint(workspace), status: "pending" };
383
+ const result2 = {
384
+ ...identity,
385
+ commandId,
386
+ spec,
387
+ workspaceFingerprint: await workspaceFingerprint(workspace),
388
+ status: "pending"
389
+ };
304
390
  await this.write({ type: "check", result: result2 });
305
391
  fresh = true;
306
392
  return result2;
@@ -308,12 +394,15 @@ var TeamVerificationStore = class _TeamVerificationStore {
308
394
  if (!fresh) return pending;
309
395
  let outcome;
310
396
  try {
311
- if (spec.type === "command") outcome = await runCommand(spec, workspace, options.signal);
397
+ if (spec.type === "command") outcome = await runCommand(spec, workspace, options.signal, this.executionFor);
312
398
  else {
313
399
  options.signal?.throwIfAborted();
314
400
  const bytes = await readWorkspaceFile(workspace, spec.path);
315
401
  const passed = spec.type === "file-sha256" ? hash(bytes) === spec.sha256 : bytes.toString("utf8").includes(spec.text);
316
- outcome = { status: passed ? "passed" : "failed", detail: passed ? "Exact configured file check passed" : "Configured file predicate did not match" };
402
+ outcome = {
403
+ status: passed ? "passed" : "failed",
404
+ detail: passed ? "Exact configured file check passed" : "Configured file predicate did not match"
405
+ };
317
406
  }
318
407
  } catch (error) {
319
408
  outcome = { status: spec.type === "command" ? "unknown" : "failed", detail: message(error) };
@@ -322,7 +411,11 @@ var TeamVerificationStore = class _TeamVerificationStore {
322
411
  try {
323
412
  afterFingerprint = await workspaceFingerprint(workspace);
324
413
  } catch (error) {
325
- outcome = { ...outcome, status: spec.type === "command" ? "unknown" : "failed", detail: `Cannot inspect workspace after check: ${message(error)}` };
414
+ outcome = {
415
+ ...outcome,
416
+ status: spec.type === "command" ? "unknown" : "failed",
417
+ detail: `Cannot inspect workspace after check: ${message(error)}`
418
+ };
326
419
  }
327
420
  const result = { ...pending, ...outcome, ...afterFingerprint ? { afterFingerprint } : {} };
328
421
  await this.append({ type: "check", result });
@@ -357,7 +450,18 @@ var TeamVerificationStore = class _TeamVerificationStore {
357
450
  }
358
451
  };
359
452
  function parseTeamCheck(value) {
360
- const raw = fields(value, ["id", "taskId", "type", "path", "text", "sha256", "command", "args", "timeoutMs", "maxOutputBytes"]);
453
+ const raw = fields(value, [
454
+ "id",
455
+ "taskId",
456
+ "type",
457
+ "path",
458
+ "text",
459
+ "sha256",
460
+ "command",
461
+ "args",
462
+ "timeoutMs",
463
+ "maxOutputBytes"
464
+ ]);
361
465
  identifier(raw.id, "check id");
362
466
  identifier(raw.taskId, "check taskId");
363
467
  if (raw.type === "file-contains") {
@@ -371,7 +475,8 @@ function parseTeamCheck(value) {
371
475
  } else if (raw.type === "command") {
372
476
  fields(raw, ["id", "taskId", "type", "command", "args", "timeoutMs", "maxOutputBytes"]);
373
477
  boundedString(raw.command, "check command", 4096);
374
- if (/[\u0000\r\n]/u.test(raw.command) || !Array.isArray(raw.args) || raw.args.length > 64 || raw.args.some((arg) => typeof arg !== "string" || arg.length > 8192 || arg.includes("\0"))) throw new Error("Invalid check command arguments");
478
+ if (/[\u0000\r\n]/u.test(raw.command) || !Array.isArray(raw.args) || raw.args.length > 64 || raw.args.some((arg) => typeof arg !== "string" || arg.length > 8192 || arg.includes("\0")))
479
+ throw new Error("Invalid check command arguments");
375
480
  if (raw.timeoutMs !== void 0) integer(raw.timeoutMs, 1, 12e4, "check timeoutMs");
376
481
  if (raw.maxOutputBytes !== void 0) integer(raw.maxOutputBytes, 1, 1048576, "check maxOutputBytes");
377
482
  } else throw new Error("Unknown check type");
@@ -388,7 +493,8 @@ __name(parseTeamChecks, "parseTeamChecks");
388
493
  function parseTeamReport(value) {
389
494
  const report = fields(value, ["summary", "claims"]);
390
495
  boundedString(report.summary, "report summary", 8192);
391
- if (!Array.isArray(report.claims) || report.claims.length > 64) throw new Error("Report claims must be an array of at most 64 entries");
496
+ if (!Array.isArray(report.claims) || report.claims.length > 64)
497
+ throw new Error("Report claims must be an array of at most 64 entries");
392
498
  for (const value2 of report.claims) {
393
499
  const claim = fields(value2, ["text", "kind", "evidence"]);
394
500
  boundedString(claim.text, "claim text", 4096);
@@ -400,7 +506,8 @@ function parseTeamReport(value) {
400
506
  safeRelative(evidence.path);
401
507
  integer(evidence.startLine, 1, 1e6, "evidence startLine");
402
508
  integer(evidence.endLine, evidence.startLine, 1e6, "evidence endLine");
403
- if (evidence.endLine - evidence.startLine > 1e3) throw new Error("Evidence range exceeds 1001 lines");
509
+ if (evidence.endLine - evidence.startLine > 1e3)
510
+ throw new Error("Evidence range exceeds 1001 lines");
404
511
  if (evidence.quote !== void 0) boundedString(evidence.quote, "evidence quote", 8192);
405
512
  }
406
513
  }
@@ -421,7 +528,8 @@ async function workspaceFingerprint(directory) {
421
528
  const child = join(path, name);
422
529
  const stat2 = await lstat(child);
423
530
  const nameInRoot = relative(root, child).split(sep).join("/");
424
- if (++files > 1e4 || stat2.isSymbolicLink()) throw new Error("Workspace exceeds 10000 entries or contains a symbolic link");
531
+ if (++files > 1e4 || stat2.isSymbolicLink())
532
+ throw new Error("Workspace exceeds 10000 entries or contains a symbolic link");
425
533
  if (stat2.isDirectory()) {
426
534
  entries.push([nameInRoot, "directory"]);
427
535
  await visit(child);
@@ -447,13 +555,15 @@ async function readWorkspaceFile(directory, path) {
447
555
  }
448
556
  const canonical = await realpath(target);
449
557
  const rel = relative(root, canonical);
450
- if (!rel || rel.startsWith(`..${sep}`) || rel === ".." || isAbsolute(rel)) throw new Error("Evidence/check path escapes workspace");
558
+ if (!rel || rel.startsWith(`..${sep}`) || rel === ".." || isAbsolute(rel))
559
+ throw new Error("Evidence/check path escapes workspace");
451
560
  const before = await lstat(target);
452
561
  if (!before.isFile() || before.size > 67108864) throw new Error("Evidence/check file is invalid or exceeds 64 MiB");
453
562
  const file = await open(target, constants.O_RDONLY | noFollow());
454
563
  try {
455
564
  const current = await file.stat();
456
- if (!current.isFile() || current.dev !== before.dev || current.ino !== before.ino || current.size !== before.size) throw new Error("File changed while opening");
565
+ if (!current.isFile() || current.dev !== before.dev || current.ino !== before.ino || current.size !== before.size)
566
+ throw new Error("File changed while opening");
457
567
  const buffer = Buffer.alloc(before.size + 1);
458
568
  let length = 0;
459
569
  while (length < buffer.length) {
@@ -462,43 +572,79 @@ async function readWorkspaceFile(directory, path) {
462
572
  length += chunk.bytesRead;
463
573
  }
464
574
  const after = await file.stat();
465
- if (length !== before.size || after.size !== current.size || after.mtimeMs !== current.mtimeMs) throw new Error("File changed while reading");
575
+ if (length !== before.size || after.size !== current.size || after.mtimeMs !== current.mtimeMs)
576
+ throw new Error("File changed while reading");
466
577
  return buffer.subarray(0, length);
467
578
  } finally {
468
579
  await file.close();
469
580
  }
470
581
  }
471
582
  __name(readWorkspaceFile, "readWorkspaceFile");
472
- async function runCommand(spec, workspace, signal) {
583
+ async function runCommand(spec, workspace, signal, executionFor) {
584
+ const environment = executionFor ? await executionFor(workspace) : await openCodingExecutionEnvironment({ workspace, isolation: { mode: "host" } });
585
+ try {
586
+ return await runEnvironmentCommand(spec, workspace, environment, signal);
587
+ } finally {
588
+ if (!executionFor) await environment.close();
589
+ }
590
+ }
591
+ __name(runCommand, "runCommand");
592
+ async function runEnvironmentCommand(spec, workspace, environment, signal) {
473
593
  signal?.throwIfAborted();
474
- if (process.platform === "win32" && /\.(?:cmd|bat)$/iu.test(spec.command)) return { status: "failed", detail: "Command checks execute native programs directly. Use node.exe with the package manager JavaScript entry point, not .cmd/.bat." };
594
+ if (process.platform === "win32" && /\.(?:cmd|bat)$/iu.test(spec.command))
595
+ return {
596
+ status: "failed",
597
+ detail: "Command checks execute native programs directly. Use node.exe with the package manager JavaScript entry point, not .cmd/.bat."
598
+ };
475
599
  const cwd = await realpath(workspace);
476
600
  const env = {};
477
- for (const key of ["PATH", "Path", "PATHEXT", "SystemRoot", "WINDIR", "COMSPEC", "TEMP", "TMP", "TMPDIR", "LANG", "LC_ALL"]) if (process.env[key] !== void 0) env[key] = process.env[key];
601
+ for (const key of [
602
+ "PATH",
603
+ "Path",
604
+ "PATHEXT",
605
+ "SystemRoot",
606
+ "WINDIR",
607
+ "COMSPEC",
608
+ "TEMP",
609
+ "TMP",
610
+ "TMPDIR",
611
+ "LANG",
612
+ "LC_ALL"
613
+ ])
614
+ if (environment.isolation.mode === "host" && process.env[key] !== void 0) env[key] = process.env[key];
478
615
  env.CI = "1";
479
- return new Promise((resolveResult) => {
616
+ return new Promise((resolveResult, rejectResult) => {
617
+ const cancellation = new AbortController();
480
618
  let output = Buffer.alloc(0);
481
619
  let reason;
482
620
  let settled = false;
483
- const child = spawn(spec.command, [...spec.args], { cwd, env, shell: false, windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
621
+ const child = environment.spawn(spec.command, spec.args, {
622
+ cwd,
623
+ env,
624
+ signal: cancellation.signal
625
+ });
626
+ const stdout = child.stdout;
627
+ const stderr = child.stderr;
628
+ if (!stdout || !stderr) {
629
+ rejectResult(new Error("Execution environment must provide command output pipes"));
630
+ return;
631
+ }
484
632
  const finish = /* @__PURE__ */ __name((status, exitCode, detail) => {
485
633
  if (settled) return;
486
634
  settled = true;
487
635
  clearTimeout(timer);
488
- clearTimeout(killWait);
489
636
  signal?.removeEventListener("abort", abort);
490
- resolveResult({ status, ...exitCode !== void 0 ? { exitCode } : {}, ...detail ? { detail } : {}, output: boundedOutput(output, spec.maxOutputBytes ?? 65536) });
637
+ resolveResult({
638
+ status,
639
+ ...exitCode !== void 0 ? { exitCode } : {},
640
+ ...detail ? { detail } : {},
641
+ output: boundedOutput(output, spec.maxOutputBytes ?? 65536)
642
+ });
491
643
  }, "finish");
492
- let killWait;
493
644
  const stop = /* @__PURE__ */ __name((detail) => {
494
645
  if (reason) return;
495
646
  reason = detail;
496
- child.kill("SIGKILL");
497
- killWait = setTimeout(() => {
498
- child.stdout.destroy();
499
- child.stderr.destroy();
500
- finish("unknown", void 0, `${detail}; child effects require inspection`);
501
- }, 1e3);
647
+ cancellation.abort();
502
648
  }, "stop");
503
649
  const abort = /* @__PURE__ */ __name(() => stop("Check interrupted"), "abort");
504
650
  const timer = setTimeout(() => stop("Check timed out"), spec.timeoutMs ?? 3e4);
@@ -509,18 +655,24 @@ async function runCommand(spec, workspace, signal) {
509
655
  stop("Check output limit exceeded");
510
656
  } else output = Buffer.concat([output, chunk]);
511
657
  }, "collect");
512
- child.stdout.on("data", collect);
513
- child.stderr.on("data", collect);
658
+ stdout.on("data", collect);
659
+ stderr.on("data", collect);
514
660
  child.on("error", (error) => finish(child.pid === void 0 ? "failed" : "unknown", void 0, message(error)));
515
661
  child.on("close", (code, terminationSignal) => {
516
- if (reason || terminationSignal || code === null) finish("unknown", void 0, reason ?? `Check ended by ${terminationSignal ?? "unknown termination"}`);
517
- else finish(code === 0 ? "passed" : "failed", code, code === 0 ? "Configured command exited successfully" : "Configured command exited unsuccessfully");
662
+ if (reason || terminationSignal || code === null)
663
+ finish("unknown", void 0, reason ?? `Check ended by ${terminationSignal ?? "unknown termination"}`);
664
+ else
665
+ finish(
666
+ code === 0 ? "passed" : "failed",
667
+ code,
668
+ code === 0 ? "Configured command exited successfully" : "Configured command exited unsuccessfully"
669
+ );
518
670
  });
519
671
  signal?.addEventListener("abort", abort, { once: true });
520
672
  if (signal?.aborted) abort();
521
673
  });
522
674
  }
523
- __name(runCommand, "runCommand");
675
+ __name(runEnvironmentCommand, "runEnvironmentCommand");
524
676
  async function readJournal(file) {
525
677
  const stat2 = await file.stat();
526
678
  if (!stat2.isFile() || stat2.size > maxJournalBytes) throw new Error("Invalid verification journal type or size");
@@ -538,7 +690,8 @@ async function readJournal(file) {
538
690
  let specs = [];
539
691
  for (const line of bytes.subarray(0, committed).toString("utf8").split("\n").slice(0, -1)) {
540
692
  const entry = JSON.parse(line);
541
- if (!entry || entry.sequence !== entries.length + 1 || !entry.event) throw new Error("Invalid verification journal sequence");
693
+ if (!entry || entry.sequence !== entries.length + 1 || !entry.event)
694
+ throw new Error("Invalid verification journal sequence");
542
695
  const event = entry.event;
543
696
  if (event.type === "config") {
544
697
  if (entries.length !== 0) throw new Error("Duplicate verification config");
@@ -547,24 +700,32 @@ async function readJournal(file) {
547
700
  else if (event.type === "report") {
548
701
  parseTeamReport(event.report.report);
549
702
  validateStored(event.report);
550
- if (reportIds.size >= 256 || reportIds.has(event.report.commandId) || !Array.isArray(event.report.evidence)) throw new Error("Invalid stored report history");
703
+ if (reportIds.size >= 256 || reportIds.has(event.report.commandId) || !Array.isArray(event.report.evidence))
704
+ throw new Error("Invalid stored report history");
551
705
  for (const item of event.report.evidence) {
552
706
  safeRelative(item.path);
553
707
  integer(item.startLine, 1, 1e6, "stored evidence startLine");
554
708
  integer(item.endLine, item.startLine, 1e6, "stored evidence endLine");
555
- if (typeof item.valid !== "boolean" || item.valid && !/^[a-f0-9]{64}$/u.test(item.sha256 ?? "")) throw new Error("Invalid stored evidence");
709
+ if (typeof item.valid !== "boolean" || item.valid && !/^[a-f0-9]{64}$/u.test(item.sha256 ?? ""))
710
+ throw new Error("Invalid stored evidence");
556
711
  }
557
712
  reportIds.add(event.report.commandId);
558
713
  } else if (event.type === "check") {
559
714
  const result = event.result;
560
715
  parseTeamCheck(result.spec);
561
716
  validateStored(result);
562
- if (!isDeepStrictEqual(specs.find((entry2) => entry2.id === result.spec.id), result.spec) || result.taskId !== result.spec.taskId || !["pending", "passed", "failed", "unknown", "cancelled"].includes(result.status) || result.afterFingerprint !== void 0 && !/^[a-f0-9]{64}$/u.test(result.afterFingerprint)) throw new Error("Invalid check record");
717
+ if (!isDeepStrictEqual(
718
+ specs.find((entry2) => entry2.id === result.spec.id),
719
+ result.spec
720
+ ) || result.taskId !== result.spec.taskId || !["pending", "passed", "failed", "unknown", "cancelled"].includes(result.status) || result.afterFingerprint !== void 0 && !/^[a-f0-9]{64}$/u.test(result.afterFingerprint))
721
+ throw new Error("Invalid check record");
563
722
  const old = checkResults.get(result.commandId);
564
723
  if (!old) {
565
- if (checkResults.size >= 512 || result.status !== "pending") throw new Error("Check result has no pending intent");
724
+ if (checkResults.size >= 512 || result.status !== "pending")
725
+ throw new Error("Check result has no pending intent");
566
726
  } else {
567
- if (!sameIdentity(old, result) || !isDeepStrictEqual(old.spec, result.spec) || old.workspaceFingerprint !== result.workspaceFingerprint || old.status !== "pending" && old.status !== "unknown" || result.status === "pending" || old.status === "unknown" && (!["failed", "cancelled"].includes(result.status) || !result.reconciliation)) throw new Error("Invalid check history transition");
727
+ if (!sameIdentity(old, result) || !isDeepStrictEqual(old.spec, result.spec) || old.workspaceFingerprint !== result.workspaceFingerprint || old.status !== "pending" && old.status !== "unknown" || result.status === "pending" || old.status === "unknown" && (!["failed", "cancelled"].includes(result.status) || !result.reconciliation))
728
+ throw new Error("Invalid check history transition");
568
729
  }
569
730
  checkResults.set(result.commandId, result);
570
731
  } else throw new Error("Unknown verification journal record");
@@ -580,7 +741,12 @@ function validateStored(value) {
580
741
  }
581
742
  __name(validateStored, "validateStored");
582
743
  function taskIdentity(execution) {
583
- return { taskId: execution.task.id, coordinationId: execution.coordinationId, dispatchId: execution.task.dispatchId, turn: execution.task.turn ?? 0 };
744
+ return {
745
+ taskId: execution.task.id,
746
+ coordinationId: execution.coordinationId,
747
+ dispatchId: execution.task.dispatchId,
748
+ turn: execution.task.turn ?? 0
749
+ };
584
750
  }
585
751
  __name(taskIdentity, "taskIdentity");
586
752
  function sameIdentity(a, b) {
@@ -588,39 +754,40 @@ function sameIdentity(a, b) {
588
754
  }
589
755
  __name(sameIdentity, "sameIdentity");
590
756
  function fields(value, allowed) {
591
- if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !allowed.includes(key))) throw new Error("Invalid verification fields");
757
+ if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !allowed.includes(key)))
758
+ throw new Error("Invalid verification fields");
592
759
  return value;
593
760
  }
594
761
  __name(fields, "fields");
595
762
  function identifier(value, label) {
596
- if (typeof value !== "string" || !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,255}$/u.test(value)) throw new Error(`Invalid ${label}`);
763
+ if (typeof value !== "string" || !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,255}$/u.test(value))
764
+ throw new Error(`Invalid ${label}`);
597
765
  }
598
766
  __name(identifier, "identifier");
599
767
  function boundedString(value, label, max) {
600
- if (typeof value !== "string" || value.length < 1 || Buffer.byteLength(value) > max || value.includes("\0")) throw new Error(`Invalid ${label}`);
768
+ if (typeof value !== "string" || value.length < 1 || Buffer.byteLength(value) > max || value.includes("\0"))
769
+ throw new Error(`Invalid ${label}`);
601
770
  }
602
771
  __name(boundedString, "boundedString");
603
772
  function integer(value, min, max, label) {
604
- if (!Number.isSafeInteger(value) || value < min || value > max) throw new Error(`Invalid ${label}`);
773
+ if (!Number.isSafeInteger(value) || value < min || value > max)
774
+ throw new Error(`Invalid ${label}`);
605
775
  }
606
776
  __name(integer, "integer");
607
777
  function safeRelative(value) {
608
778
  boundedString(value, "workspace relative path", 2048);
609
- if (isAbsolute(value) || /[:\u0000-\u001f]/u.test(value) || value.replace(/\\/gu, "/").split("/").some((part) => !part || part === "." || part === "..")) throw new Error("Unsafe workspace relative path");
779
+ if (isAbsolute(value) || /[:\u0000-\u001f]/u.test(value) || value.replace(/\\/gu, "/").split("/").some((part) => !part || part === "." || part === ".."))
780
+ throw new Error("Unsafe workspace relative path");
610
781
  }
611
782
  __name(safeRelative, "safeRelative");
612
783
  async function rejectLinkIfPresent(path) {
613
784
  try {
614
785
  if ((await lstat(path)).isSymbolicLink()) throw new Error("Verification file must not be a symbolic link");
615
786
  } catch (error) {
616
- if (!isMissing(error)) throw error;
787
+ if (!hasErrorCode(error, "ENOENT")) throw error;
617
788
  }
618
789
  }
619
790
  __name(rejectLinkIfPresent, "rejectLinkIfPresent");
620
- function isMissing(error) {
621
- return error instanceof Error && "code" in error && error.code === "ENOENT";
622
- }
623
- __name(isMissing, "isMissing");
624
791
  function noFollow() {
625
792
  return process.platform === "win32" ? 0 : constants.O_NOFOLLOW;
626
793
  }
@@ -649,8 +816,17 @@ __name(boundedOutput, "boundedOutput");
649
816
 
650
817
  // apps/maybecode/src/team-plan.ts
651
818
  var MAX_PLAN_BYTES = 1048576;
652
- var READ_TOOLS = ["read", "list_files", "publish_artifact", "read_artifact", "submit_report", "run_check"];
653
- var ALL_TOOLS = [...READ_TOOLS, "write", "edit"];
819
+ var READ_TOOLS = [
820
+ "read",
821
+ "glob",
822
+ "grep",
823
+ "list_files",
824
+ "publish_artifact",
825
+ "read_artifact",
826
+ "submit_report",
827
+ "run_check"
828
+ ];
829
+ var ALL_TOOLS = [...READ_TOOLS, "fetch", "write", "edit"];
654
830
  var LIMIT_CAPS = {
655
831
  maxConcurrent: 8,
656
832
  maxTasks: 128,
@@ -672,36 +848,48 @@ function parseTeamPlan(value, options = {}) {
672
848
  if (plan.format !== 1) fail("plan.format must be 1");
673
849
  const name = plan.name === void 0 ? void 0 : text(plan.name, "plan.name", 128);
674
850
  const roleValues = object(plan.roles, "plan.roles");
675
- if (Object.keys(roleValues).length < 1 || Object.keys(roleValues).length > 16) fail("plan.roles must contain 1-16 roles");
851
+ if (Object.keys(roleValues).length < 1 || Object.keys(roleValues).length > 16)
852
+ fail("plan.roles must contain 1-16 roles");
676
853
  const roles = {};
677
854
  for (const [id, value2] of Object.entries(roleValues)) {
678
855
  identifier2(id, "role id");
679
- const role = object(value2, `role ${id}`, ["model", "instructions", "tools", "delegateTo", "messaging", "runBudget"]);
856
+ const role = object(value2, `role ${id}`, [
857
+ "model",
858
+ "instructions",
859
+ "tools",
860
+ "delegateTo",
861
+ "messaging",
862
+ "runBudget"
863
+ ]);
680
864
  const model = role.model === void 0 ? void 0 : text(role.model, `role ${id}.model`, 128);
681
865
  const instructions2 = role.instructions === void 0 ? void 0 : text(role.instructions, `role ${id}.instructions`, 16384);
682
866
  const tools = role.tools === void 0 ? [...READ_TOOLS] : stringArray(role.tools, `role ${id}.tools`, ALL_TOOLS.length);
683
867
  for (const tool of tools) {
684
868
  if (!ALL_TOOLS.includes(tool)) fail(`Unknown tool in role ${id}: ${tool}`);
685
- if (mode === "read-only" && (tool === "write" || tool === "edit")) fail(`Tool ${tool} in role ${id} requires --mode coding`);
869
+ if (mode === "read-only" && (tool === "write" || tool === "edit"))
870
+ fail(`Tool ${tool} in role ${id} requires --mode coding`);
686
871
  }
687
872
  const delegateTo = role.delegateTo === void 0 ? [] : stringArray(role.delegateTo, `role ${id}.delegateTo`, 16);
688
873
  delegateTo.forEach((target) => identifier2(target, `role ${id}.delegateTo`));
689
- if (role.messaging !== void 0 && typeof role.messaging !== "boolean") fail(`role ${id}.messaging must be boolean`);
874
+ if (role.messaging !== void 0 && typeof role.messaging !== "boolean")
875
+ fail(`role ${id}.messaging must be boolean`);
690
876
  const runBudget = role.runBudget === void 0 ? void 0 : budget(role.runBudget, `role ${id}.runBudget`);
691
- roles[id] = {
692
- ...model === void 0 ? {} : { model },
693
- ...instructions2 === void 0 ? {} : { instructions: instructions2 },
877
+ roles[id] = omitUndefined({
878
+ model,
879
+ instructions: instructions2,
694
880
  tools,
695
881
  delegateTo,
696
882
  messaging: role.messaging ?? false,
697
- ...runBudget === void 0 ? {} : { runBudget }
698
- };
883
+ runBudget
884
+ });
699
885
  }
700
886
  for (const [id, role] of Object.entries(roles)) {
701
- for (const target of role.delegateTo) if (!Object.hasOwn(roles, target)) fail(`Unknown delegated role ${target} in role ${id}`);
887
+ for (const target of role.delegateTo)
888
+ if (!Object.hasOwn(roles, target)) fail(`Unknown delegated role ${target} in role ${id}`);
702
889
  }
703
890
  const limits = plan.limits === void 0 ? void 0 : parseLimits(plan.limits);
704
- if (!Array.isArray(plan.tasks) || plan.tasks.length < 1 || plan.tasks.length > (limits?.maxTasks ?? 128)) fail("plan.tasks exceeds its task quota or is empty");
891
+ if (!Array.isArray(plan.tasks) || plan.tasks.length < 1 || plan.tasks.length > (limits?.maxTasks ?? 128))
892
+ fail("plan.tasks exceeds its task quota or is empty");
705
893
  const tasks = plan.tasks.map((value2, index) => {
706
894
  const task = object(value2, `task ${index}`, ["id", "agent", "input", "dependsOn"]);
707
895
  const id = identifier2(task.id, "task id");
@@ -721,16 +909,10 @@ function parseTeamPlan(value, options = {}) {
721
909
  } catch (error) {
722
910
  fail(`plan.checks: ${error instanceof Error ? error.message : "Invalid checks"}`);
723
911
  }
724
- for (const check of checks) if (!tasks.some((task) => task.id === check.taskId)) fail(`Check ${check.id} references unknown task ${check.taskId}`);
725
- const result = {
726
- format: 1,
727
- ...name === void 0 ? {} : { name },
728
- roles,
729
- tasks,
730
- resultTaskId,
731
- ...limits === void 0 ? {} : { limits },
732
- checks
733
- };
912
+ for (const check of checks)
913
+ if (!tasks.some((task) => task.id === check.taskId))
914
+ fail(`Check ${check.id} references unknown task ${check.taskId}`);
915
+ const result = omitUndefined({ format: 1, name, roles, tasks, resultTaskId, limits, checks });
734
916
  if (Buffer.byteLength(JSON.stringify(result), "utf8") > MAX_PLAN_BYTES) fail("Team plan exceeds 1 MiB");
735
917
  return freeze(result);
736
918
  }
@@ -750,7 +932,9 @@ async function loadTeamPlan(path, options = {}) {
750
932
  if (length > MAX_PLAN_BYTES) fail("Team plan exceeds 1 MiB");
751
933
  let value;
752
934
  try {
753
- value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(buffer.subarray(0, length)).replace(/^\uFEFF/u, ""));
935
+ value = JSON.parse(
936
+ new TextDecoder("utf-8", { fatal: true }).decode(buffer.subarray(0, length)).replace(/^\uFEFF/u, "")
937
+ );
754
938
  } catch {
755
939
  fail("Team plan must contain valid UTF-8 JSON");
756
940
  }
@@ -765,55 +949,75 @@ function createTeamPreset(preset, prompt, options = {}) {
765
949
  text(prompt, "team prompt", 32768);
766
950
  const coding = options.mode === "coding";
767
951
  const worker = {
768
- ...options.model === void 0 ? {} : { model: options.model },
952
+ ...omitUndefined({ model: options.model }),
769
953
  tools: coding ? [...READ_TOOLS, "write", "edit"] : READ_TOOLS,
770
954
  instructions: coding ? "Implement a bounded change in your own workspace copy. Run only configured checks. Submit evidence and a report; never claim source changes have been applied." : "Investigate independently using workspace evidence. Do not change files or claim unperformed tests. Submit findings, evidence, and limitations."
771
955
  };
772
956
  const final = {
773
- ...options.model === void 0 ? {} : { model: options.model },
957
+ ...omitUndefined({ model: options.model }),
774
958
  tools: READ_TOOLS,
775
959
  delegateTo: preset === "supervisor" ? ["worker"] : [],
776
960
  instructions: "Synthesize the dependency reports, identify each task's contribution, and distinguish verified evidence from unverified claims. Dependency workspaces are not automatically merged. Do not wait for unsolicited messages."
777
961
  };
778
962
  const restriction = coding ? "Work only in your isolated copy; source application requires later human confirmation." : "Do not change files.";
779
963
  const tasks = preset === "pipeline" ? [
780
- { id: "analysis", agent: "worker", input: `Inspect the request and produce evidence and a concrete ${coding ? "implementation" : "investigation"}. ${restriction}
964
+ {
965
+ id: "analysis",
966
+ agent: "worker",
967
+ input: `Inspect the request and produce evidence and a concrete ${coding ? "implementation" : "investigation"}. ${restriction}
781
968
 
782
969
  User task:
783
- ${prompt}` },
784
- { id: "review", agent: "worker", dependsOn: ["analysis"], input: `Review the analysis report for correctness, edge cases, and verification gaps. Your workspace is an independent baseline; no prior edits are present. ${restriction}
970
+ ${prompt}`
971
+ },
972
+ {
973
+ id: "review",
974
+ agent: "worker",
975
+ dependsOn: ["analysis"],
976
+ input: `Review the analysis report for correctness, edge cases, and verification gaps. Your workspace is an independent baseline; no prior edits are present. ${restriction}
785
977
 
786
978
  User task:
787
- ${prompt}` },
979
+ ${prompt}`
980
+ },
788
981
  { id: "summary", agent: "supervisor", dependsOn: ["analysis", "review"], input: prompt }
789
982
  ] : [
790
- { id: "analysis", agent: "worker", input: `Investigate the user's task independently. Inspect relevant files and identify a concrete approach with evidence. ${restriction}
983
+ {
984
+ id: "analysis",
985
+ agent: "worker",
986
+ input: `Investigate the user's task independently. Inspect relevant files and identify a concrete approach with evidence. ${restriction}
791
987
 
792
988
  User task:
793
- ${prompt}` },
794
- { id: "review", agent: "worker", input: `Independently review risks, edge cases, and validation needs. Inspect files and provide evidence. ${restriction}
989
+ ${prompt}`
990
+ },
991
+ {
992
+ id: "review",
993
+ agent: "worker",
994
+ input: `Independently review risks, edge cases, and validation needs. Inspect files and provide evidence. ${restriction}
795
995
 
796
996
  User task:
797
- ${prompt}` },
997
+ ${prompt}`
998
+ },
798
999
  { id: "summary", agent: "supervisor", dependsOn: ["analysis", "review"], input: prompt }
799
1000
  ];
800
- return parseTeamPlan({
801
- format: 1,
802
- name: preset,
803
- roles: { worker, supervisor: final },
804
- tasks,
805
- resultTaskId: "summary",
806
- limits: {
807
- maxConcurrent: 2,
808
- maxTasks: 8,
809
- maxDepth: 2,
810
- maxTaskTurns: 4,
811
- maxDurationMs: 6e5,
812
- maxOutputBytes: 65536,
813
- maxMessages: 24,
814
- maxMessageBytes: 8192
815
- }
816
- }, { mode: options.mode ?? "read-only" });
1001
+ return parseTeamPlan(
1002
+ {
1003
+ format: 1,
1004
+ name: preset,
1005
+ roles: { worker, supervisor: final },
1006
+ tasks,
1007
+ resultTaskId: "summary",
1008
+ limits: {
1009
+ maxConcurrent: 2,
1010
+ maxTasks: 8,
1011
+ maxDepth: 2,
1012
+ maxTaskTurns: 4,
1013
+ maxDurationMs: 6e5,
1014
+ maxOutputBytes: 65536,
1015
+ maxMessages: 24,
1016
+ maxMessageBytes: 8192
1017
+ }
1018
+ },
1019
+ { mode: options.mode ?? "read-only" }
1020
+ );
817
1021
  }
818
1022
  __name(createTeamPreset, "createTeamPreset");
819
1023
  function parseLimits(value) {
@@ -825,7 +1029,8 @@ function parseLimits(value) {
825
1029
  continue;
826
1030
  }
827
1031
  const cap = LIMIT_CAPS[key];
828
- if (typeof value2 !== "number" || !Number.isSafeInteger(value2) || value2 < 1 || value2 > cap) fail(`plan.limits.${key} must be an integer from 1 to ${cap}`);
1032
+ if (typeof value2 !== "number" || !Number.isSafeInteger(value2) || value2 < 1 || value2 > cap)
1033
+ fail(`plan.limits.${key} must be an integer from 1 to ${cap}`);
829
1034
  result[key] = value2;
830
1035
  }
831
1036
  return result;
@@ -843,7 +1048,8 @@ __name(budget, "budget");
843
1048
  function validateGraph(tasks) {
844
1049
  const pending = new Map(tasks.map((task) => [task.id, task]));
845
1050
  if (pending.size !== tasks.length) fail("Duplicate task id");
846
- for (const task of tasks) for (const id of task.dependsOn ?? []) if (!pending.has(id)) fail(`Unknown dependency ${id} in task ${task.id}`);
1051
+ for (const task of tasks)
1052
+ for (const id of task.dependsOn ?? []) if (!pending.has(id)) fail(`Unknown dependency ${id} in task ${task.id}`);
847
1053
  while (pending.size) {
848
1054
  let progress = false;
849
1055
  for (const [id, task] of pending) {
@@ -856,7 +1062,8 @@ function validateGraph(tasks) {
856
1062
  }
857
1063
  __name(validateGraph, "validateGraph");
858
1064
  function object(value, label, keys) {
859
- if (!value || typeof value !== "object" || Array.isArray(value) || ![null, Object.prototype].includes(Object.getPrototypeOf(value))) fail(`${label} must be an object`);
1065
+ if (!value || typeof value !== "object" || Array.isArray(value) || ![null, Object.prototype].includes(Object.getPrototypeOf(value)))
1066
+ fail(`${label} must be an object`);
860
1067
  const record = value;
861
1068
  if (keys) {
862
1069
  for (const key of Object.keys(record)) if (!keys.includes(key)) fail(`Unknown ${label} field: ${key}`);
@@ -865,17 +1072,20 @@ function object(value, label, keys) {
865
1072
  }
866
1073
  __name(object, "object");
867
1074
  function identifier2(value, label) {
868
- if (typeof value !== "string" || !/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$/u.test(value) || ["__proto__", "constructor", "prototype"].includes(value)) fail(`${label} must be a non-reserved 1-128 character ASCII identifier`);
1075
+ if (typeof value !== "string" || !/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$/u.test(value) || ["__proto__", "constructor", "prototype"].includes(value))
1076
+ fail(`${label} must be a non-reserved 1-128 character ASCII identifier`);
869
1077
  return value;
870
1078
  }
871
1079
  __name(identifier2, "identifier");
872
1080
  function text(value, label, maxBytes) {
873
- if (typeof value !== "string" || !value.trim() || value.includes("\0") || Buffer.byteLength(value, "utf8") > maxBytes) fail(`${label} must be nonempty text of at most ${maxBytes} bytes without NUL`);
1081
+ if (typeof value !== "string" || !value.trim() || value.includes("\0") || Buffer.byteLength(value, "utf8") > maxBytes)
1082
+ fail(`${label} must be nonempty text of at most ${maxBytes} bytes without NUL`);
874
1083
  return value;
875
1084
  }
876
1085
  __name(text, "text");
877
1086
  function stringArray(value, label, max) {
878
- if (!Array.isArray(value) || value.length > max || value.some((item) => typeof item !== "string") || new Set(value).size !== value.length) fail(`${label} must be an array of at most ${max} unique strings`);
1087
+ if (!Array.isArray(value) || value.length > max || value.some((item) => typeof item !== "string") || new Set(value).size !== value.length)
1088
+ fail(`${label} must be an array of at most ${max} unique strings`);
879
1089
  return [...value];
880
1090
  }
881
1091
  __name(stringArray, "stringArray");
@@ -896,12 +1106,13 @@ __name(fail, "fail");
896
1106
  import { createHash as createHash2 } from "node:crypto";
897
1107
  import { open as open3 } from "node:fs/promises";
898
1108
  import { join as join2 } from "node:path";
899
- import { FileSessionStore } from "@sortedyuan/session/file-store";
1109
+ import { FileSessionStore } from "@sortedyuan/may/session/file-store";
900
1110
  async function readTeamResolution(path) {
901
1111
  const file = await open3(path, "r");
902
1112
  let value;
903
1113
  try {
904
- if (!(await file.stat()).isFile() || (await file.stat()).size > 32768) throw new Error("Resolution file exceeds 32768 bytes");
1114
+ if (!(await file.stat()).isFile() || (await file.stat()).size > 32768)
1115
+ throw new Error("Resolution file exceeds 32768 bytes");
905
1116
  const bytes = await file.readFile();
906
1117
  if (bytes.length > 32768) throw new Error("Resolution file exceeds 32768 bytes");
907
1118
  value = JSON.parse(bytes.toString("utf8"));
@@ -910,22 +1121,28 @@ async function readTeamResolution(path) {
910
1121
  }
911
1122
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Resolution must be an object");
912
1123
  const input = value;
913
- if (input.format !== 1 || !["task", "budget", "check"].includes(input.kind) || typeof input.finding !== "string" || !input.finding.trim() || input.finding.length > (input.kind === "budget" ? 256 : 8192) || /[\u0000-\u001f]/u.test(input.finding)) throw new Error("Resolution requires format 1, a supported kind, and bounded verified finding");
1124
+ if (input.format !== 1 || !["task", "budget", "check"].includes(input.kind) || typeof input.finding !== "string" || !input.finding.trim() || input.finding.length > (input.kind === "budget" ? 256 : 8192) || /[\u0000-\u001f]/u.test(input.finding))
1125
+ throw new Error("Resolution requires format 1, a supported kind, and bounded verified finding");
914
1126
  const keys = input.kind === "budget" ? ["callId", "usage"] : [input.kind === "task" ? "taskId" : "commandId", "outcome"];
915
- if (Object.keys(input).some((key) => !["format", "kind", "finding", ...keys].includes(key))) throw new Error("Unknown resolution field");
1127
+ if (Object.keys(input).some((key) => !["format", "kind", "finding", ...keys].includes(key)))
1128
+ throw new Error("Unknown resolution field");
916
1129
  const id = input[keys[0]];
917
- if (typeof id !== "string" || !id.length || id.length > 256 || /[\u0000-\u001f]/u.test(id)) throw new Error("Invalid resolution identity");
1130
+ if (typeof id !== "string" || !id.length || id.length > 256 || /[\u0000-\u001f]/u.test(id))
1131
+ throw new Error("Invalid resolution identity");
918
1132
  if (input.kind === "budget") {
919
1133
  const usage = input.usage;
920
- if (!usage || typeof usage !== "object" || Array.isArray(usage) || Object.keys(usage).some((key) => !["inputTokens", "outputTokens", "totalTokens"].includes(key)) || !Object.keys(usage).length || Object.values(usage).some((n) => !Number.isSafeInteger(n) || n < 0) || usage.totalTokens === void 0 && (usage.inputTokens === void 0 || usage.outputTokens === void 0)) throw new Error("Supply verified non-negative token usage; do not estimate unknown usage as zero");
921
- } else if (!["failed", "cancelled"].includes(input.outcome)) throw new Error("Reconciliation cannot manufacture a successful answer/check");
1134
+ if (!usage || typeof usage !== "object" || Array.isArray(usage) || Object.keys(usage).some((key) => !["inputTokens", "outputTokens", "totalTokens"].includes(key)) || !Object.keys(usage).length || Object.values(usage).some((n) => !Number.isSafeInteger(n) || n < 0) || usage.totalTokens === void 0 && (usage.inputTokens === void 0 || usage.outputTokens === void 0))
1135
+ throw new Error("Supply verified non-negative token usage; do not estimate unknown usage as zero");
1136
+ } else if (!["failed", "cancelled"].includes(input.outcome))
1137
+ throw new Error("Reconciliation cannot manufacture a successful answer/check");
922
1138
  return input;
923
1139
  }
924
1140
  __name(readTeamResolution, "readTeamResolution");
925
1141
  function teamReviewDigest(value) {
926
1142
  const canonical = /* @__PURE__ */ __name((value2) => {
927
1143
  if (Array.isArray(value2)) return `[${value2.map(canonical).join(",")}]`;
928
- if (value2 && typeof value2 === "object") return `{${Object.entries(value2).filter(([, v]) => v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${canonical(v)}`).join(",")}}`;
1144
+ if (value2 && typeof value2 === "object")
1145
+ return `{${Object.entries(value2).filter(([, v]) => v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${canonical(v)}`).join(",")}}`;
929
1146
  return JSON.stringify(value2);
930
1147
  }, "canonical");
931
1148
  return createHash2("sha256").update(canonical(value)).digest("hex");
@@ -938,10 +1155,11 @@ function retryImpact(state, taskId, finding) {
938
1155
  const affected = /* @__PURE__ */ new Set([taskId]);
939
1156
  for (let changed = true; changed; ) {
940
1157
  changed = false;
941
- for (const candidate of state.tasks) if (!affected.has(candidate.id) && candidate.dependsOn.some((id) => affected.has(id))) {
942
- affected.add(candidate.id);
943
- changed = true;
944
- }
1158
+ for (const candidate of state.tasks)
1159
+ if (!affected.has(candidate.id) && candidate.dependsOn.some((id) => affected.has(id))) {
1160
+ affected.add(candidate.id);
1161
+ changed = true;
1162
+ }
945
1163
  }
946
1164
  return {
947
1165
  taskId,
@@ -967,23 +1185,31 @@ async function inspectTeam(directory, id, limits) {
967
1185
  for (const task of state.tasks) {
968
1186
  lines2.push(`${task.id}: ${task.status}; attempt ${task.attempt ?? 0}; session ${task.sessionId}`);
969
1187
  if (task.detail) lines2.push(` Reason: ${task.detail}`);
970
- const blocked = task.dependsOn.filter((id2) => state.tasks.find((candidate) => candidate.id === id2)?.status !== "completed");
1188
+ const blocked = task.dependsOn.filter(
1189
+ (id2) => state.tasks.find((candidate) => candidate.id === id2)?.status !== "completed"
1190
+ );
971
1191
  if (blocked.length) lines2.push(` Unsuccessful dependencies: ${blocked.join(", ")}`);
972
1192
  if (["failed", "cancelled", "recovery-required", "cancelling"].includes(task.status)) {
973
1193
  const events = await sessions.read(task.sessionId);
974
1194
  const pending = /* @__PURE__ */ new Map();
975
1195
  for (const event of events) {
976
- if (event.type === "tool.started") pending.set(`${event.runId}:${event.step}:${event.call.id}`, event.call.name);
977
- if (event.type === "tool.completed" || event.type === "tool.failed" && !/CANCEL|ABORT|UNKNOWN/iu.test(`${event.error.name} ${event.error.code ?? ""}`)) pending.delete(`${event.runId}:${event.step}:${event.call.id}`);
1196
+ if (event.type === "tool.started")
1197
+ pending.set(`${event.runId}:${event.step}:${event.call.id}`, event.call.name);
1198
+ if (event.type === "tool.completed" || event.type === "tool.failed" && !/CANCEL|ABORT|UNKNOWN/iu.test(`${event.error.name} ${event.error.code ?? ""}`))
1199
+ pending.delete(`${event.runId}:${event.step}:${event.call.id}`);
978
1200
  }
979
- for (const [key, name] of pending) lines2.push(` Unsettled tool evidence: ${key} (${name}); inspect Session before reconciling task`);
1201
+ for (const [key, name] of pending)
1202
+ lines2.push(` Unsettled tool evidence: ${key} (${name}); inspect Session before reconciling task`);
980
1203
  }
981
1204
  }
982
1205
  }
983
1206
  if (budget2) lines2.push(...budgetStatus(budget2));
984
1207
  if (verification) {
985
1208
  lines2.push(`Structured reports: ${verification.reports.length}; checks: ${verification.checks.length}`);
986
- for (const check of verification.checks) lines2.push(` Check ${check.spec.id} (${check.taskId}): ${check.status}; command ${check.commandId}${check.detail ? `; ${check.detail}` : ""}`);
1209
+ for (const check of verification.checks)
1210
+ lines2.push(
1211
+ ` Check ${check.spec.id} (${check.taskId}): ${check.status}; command ${check.commandId}${check.detail ? `; ${check.detail}` : ""}`
1212
+ );
987
1213
  }
988
1214
  lines2.push(
989
1215
  "Recovery does not steal locks, erase unknown effects, reset budgets, or execute agents.",
@@ -994,7 +1220,12 @@ async function inspectTeam(directory, id, limits) {
994
1220
  }
995
1221
  __name(inspectTeam, "inspectTeam");
996
1222
  function budgetStatus(budget2) {
997
- return [`Shared budget: ${JSON.stringify(sharedBudgetTotals(budget2))}`, ...budget2.calls.filter((call) => call.status !== "settled" || call.exceededReservation).map((call) => ` Budget call ${call.id}: ${call.status}${call.exceededReservation ? ", exceeded reservation" : ""}; reserved ${call.reservation.totalTokens} tokens`)];
1223
+ return [
1224
+ `Shared budget: ${JSON.stringify(sharedBudgetTotals(budget2))}`,
1225
+ ...budget2.calls.filter((call) => call.status !== "settled" || call.exceededReservation).map(
1226
+ (call) => ` Budget call ${call.id}: ${call.status}${call.exceededReservation ? ", exceeded reservation" : ""}; reserved ${call.reservation.totalTokens} tokens`
1227
+ )
1228
+ ];
998
1229
  }
999
1230
  __name(budgetStatus, "budgetStatus");
1000
1231
  async function optional(read) {
@@ -1008,7 +1239,7 @@ async function optional(read) {
1008
1239
  __name(optional, "optional");
1009
1240
 
1010
1241
  // apps/maybecode/src/team-patches.ts
1011
- import { acquireFileLock as acquireFileLock2, releaseFileLock as releaseFileLock2 } from "@sortedyuan/session/file-store";
1242
+ import { acquireFileLock as acquireFileLock2, hasErrorCode as hasErrorCode2 } from "@sortedyuan/may/storage";
1012
1243
  import { createHash as createHash3, randomUUID } from "node:crypto";
1013
1244
  import { constants as constants2 } from "node:fs";
1014
1245
  import { lstat as lstat2, mkdir as mkdir2, open as open4, realpath as realpath2, rename, unlink } from "node:fs/promises";
@@ -1020,15 +1251,17 @@ var MAX_FILE_BYTES = 262144;
1020
1251
  var MAX_TOTAL_BYTES = 2097152;
1021
1252
  async function createTeamPatch(options) {
1022
1253
  const bundle = bundleFrom(await options.workspaces.snapshotPatch(options.taskIds));
1023
- if (inside(bundle.sourceDirectory, resolve2(options.directory))) throw new Error("Patch storage must be outside the source workspace");
1254
+ if (inside(bundle.sourceDirectory, resolve2(options.directory)))
1255
+ throw new Error("Patch storage must be outside the source workspace");
1024
1256
  const patches = await privateDirectory(join3(resolve2(options.directory), "patches"));
1025
1257
  const path = join3(patches, `${bundle.id}.json`);
1026
1258
  try {
1027
1259
  await durableFile(path, `${JSON.stringify(bundle, null, 2)}
1028
1260
  `, "wx");
1029
1261
  } catch (error) {
1030
- if (!hasCode(error, "EEXIST")) throw error;
1031
- if (!isDeepStrictEqual2(await readTeamPatch(options.directory, bundle.id), bundle)) throw new Error("Patch id already exists with different content");
1262
+ if (!hasErrorCode2(error, "EEXIST")) throw error;
1263
+ if (!isDeepStrictEqual2(await readTeamPatch(options.directory, bundle.id), bundle))
1264
+ throw new Error("Patch id already exists with different content");
1032
1265
  }
1033
1266
  return bundle;
1034
1267
  }
@@ -1045,11 +1278,16 @@ async function readTeamPatch(directory, patchId) {
1045
1278
  __name(readTeamPatch, "readTeamPatch");
1046
1279
  function renderTeamPatchDiff(bundle) {
1047
1280
  validateBundle(bundle, bundle.id);
1048
- const sections = [`Patch ${bundle.id}`, `Confirm digest: ${bundle.digest}`, `Tasks: ${bundle.taskSnapshots.map((task) => task.taskId).join(", ")}`];
1281
+ const sections = [
1282
+ `Patch ${bundle.id}`,
1283
+ `Confirm digest: ${bundle.digest}`,
1284
+ `Tasks: ${bundle.taskSnapshots.map((task) => task.taskId).join(", ")}`
1285
+ ];
1049
1286
  for (const file of bundle.files) sections.push(fileDiff(file));
1050
1287
  for (const conflict of bundle.conflicts) {
1051
1288
  sections.push(`CONFLICT ${conflict.path}: different task results; apply is blocked.`);
1052
- for (const file of conflict.candidates) sections.push(`Candidate tasks: ${file.taskIds.join(", ")}
1289
+ for (const file of conflict.candidates)
1290
+ sections.push(`Candidate tasks: ${file.taskIds.join(", ")}
1053
1291
  ${fileDiff(file)}`);
1054
1292
  }
1055
1293
  if (bundle.files.length === 0 && bundle.conflicts.length === 0) sections.push("No source changes.");
@@ -1059,8 +1297,10 @@ ${fileDiff(file)}`);
1059
1297
  __name(renderTeamPatchDiff, "renderTeamPatchDiff");
1060
1298
  async function applyTeamPatch(options) {
1061
1299
  const bundle = await readTeamPatch(options.directory, options.patchId);
1062
- if (options.confirmDigest !== bundle.digest) throw new Error("Apply requires the exact digest from the reviewed patch");
1063
- if (bundle.conflicts.length > 0) throw new Error("Patch has conflicting task results; choose a non-conflicting task set");
1300
+ if (options.confirmDigest !== bundle.digest)
1301
+ throw new Error("Apply requires the exact digest from the reviewed patch");
1302
+ if (bundle.conflicts.length > 0)
1303
+ throw new Error("Patch has conflicting task results; choose a non-conflicting task set");
1064
1304
  const existing = await readTeamPatchApplication(options.directory, bundle.id);
1065
1305
  if (existing) return { ...existing, ...existing.status === "applied" ? { alreadyApplied: true } : {} };
1066
1306
  const source = await safeRoot(bundle.sourceDirectory);
@@ -1068,16 +1308,17 @@ async function applyTeamPatch(options) {
1068
1308
  const taskIds = bundle.taskSnapshots.map((task) => task.taskId);
1069
1309
  const checkTasks = /* @__PURE__ */ __name(async () => {
1070
1310
  const current = bundleFrom(await options.workspaces.snapshotPatch(taskIds));
1071
- if (current.digest !== bundle.digest) throw new Error("Task or baseline snapshot changed since review; create a new patch");
1311
+ if (current.digest !== bundle.digest)
1312
+ throw new Error("Task or baseline snapshot changed since review; create a new patch");
1072
1313
  }, "checkTasks");
1073
1314
  await checkTasks();
1074
1315
  await preflight(source, bundle.files);
1075
1316
  const lockDirectory = join3(homedir(), ".may", "maybecode", "apply-locks");
1076
- if (inside(source, resolve2(lockDirectory))) throw new Error("Apply lock directory must be outside the source workspace");
1317
+ if (inside(source, resolve2(lockDirectory)))
1318
+ throw new Error("Apply lock directory must be outside the source workspace");
1077
1319
  const locks = await privateDirectory(lockDirectory);
1078
1320
  if (inside(source, locks)) throw new Error("Apply lock directory must be outside the source workspace");
1079
- const lockPath = join3(locks, `${hash2(source)}.lock`);
1080
- const lock = await acquireFileLock2(lockPath);
1321
+ const lock = await acquireFileLock2(join3(locks, `${hash2(source)}.lock`));
1081
1322
  let journal;
1082
1323
  let sequence = 0;
1083
1324
  const appliedPaths = [];
@@ -1091,9 +1332,6 @@ async function applyTeamPatch(options) {
1091
1332
  sequence++;
1092
1333
  }, "append");
1093
1334
  try {
1094
- await lock.writeFile(`${JSON.stringify({ pid: process.pid, patchId: bundle.id, source })}
1095
- `);
1096
- await lock.sync();
1097
1335
  const prior = await readTeamPatchApplication(options.directory, bundle.id);
1098
1336
  if (prior) return { ...prior, ...prior.status === "applied" ? { alreadyApplied: true } : {} };
1099
1337
  await checkTasks();
@@ -1157,18 +1395,30 @@ async function applyTeamPatch(options) {
1157
1395
  }
1158
1396
  await syncDirectory(dirname(target));
1159
1397
  const after = await safeRead(source, target, MAX_FILE_BYTES);
1160
- if (file.afterSha256 === void 0 ? after !== void 0 : after === void 0 || hash2(after) !== file.afterSha256) throw new Error("Source changed before the patch result was acknowledged");
1398
+ if (file.afterSha256 === void 0 ? after !== void 0 : after === void 0 || hash2(after) !== file.afterSha256)
1399
+ throw new Error("Source changed before the patch result was acknowledged");
1161
1400
  await append({ type: "applied", path: file.path });
1162
1401
  appliedPaths.push(file.path);
1163
1402
  options.onProgress?.({ type: "file.applied", path: file.path });
1164
1403
  }
1165
1404
  await append({ type: "completed" });
1166
- return { status: "applied", patchId: bundle.id, digest: bundle.digest, appliedPaths, uncertainPaths: [], journalPath };
1405
+ return {
1406
+ status: "applied",
1407
+ patchId: bundle.id,
1408
+ digest: bundle.digest,
1409
+ appliedPaths,
1410
+ uncertainPaths: [],
1411
+ journalPath
1412
+ };
1167
1413
  } catch (error) {
1168
1414
  if (!begun) throw error;
1169
1415
  try {
1170
1416
  await append({ type: "unknown" });
1171
- } catch {
1417
+ } catch (appendError) {
1418
+ throw new AggregateError(
1419
+ [error, appendError],
1420
+ "Patch application failed and its unknown outcome could not be recorded"
1421
+ );
1172
1422
  }
1173
1423
  return {
1174
1424
  status: "unknown",
@@ -1183,7 +1433,7 @@ async function applyTeamPatch(options) {
1183
1433
  try {
1184
1434
  await journal?.close();
1185
1435
  } finally {
1186
- await releaseFileLock2(lock, lockPath);
1436
+ await lock.release();
1187
1437
  }
1188
1438
  }
1189
1439
  }
@@ -1203,9 +1453,11 @@ async function readTeamPatchApplication(directory, patchId) {
1203
1453
  for (const line of bytes.toString("utf8").split("\n").slice(0, -1)) {
1204
1454
  try {
1205
1455
  const entry = JSON.parse(line);
1206
- if (entry.revision !== ++revision || entry.digest !== bundle.digest || !["started", "intent", "applied", "completed", "unknown"].includes(entry.type) || (revision === 1 ? entry.type !== "started" : entry.type === "started") || ["completed", "unknown"].includes(last ?? "")) throw new Error("Invalid application sequence");
1456
+ if (entry.revision !== ++revision || entry.digest !== bundle.digest || !["started", "intent", "applied", "completed", "unknown"].includes(entry.type) || (revision === 1 ? entry.type !== "started" : entry.type === "started") || ["completed", "unknown"].includes(last ?? ""))
1457
+ throw new Error("Invalid application sequence");
1207
1458
  if (entry.type === "intent") {
1208
- if (!bundle.files.some((file) => file.path === entry.path) || pending.has(entry.path) || appliedPaths.includes(entry.path)) throw new Error("Invalid application intent");
1459
+ if (!bundle.files.some((file) => file.path === entry.path) || pending.has(entry.path) || appliedPaths.includes(entry.path))
1460
+ throw new Error("Invalid application intent");
1209
1461
  pending.add(entry.path);
1210
1462
  }
1211
1463
  if (entry.type === "applied") {
@@ -1213,7 +1465,8 @@ async function readTeamPatchApplication(directory, patchId) {
1213
1465
  appliedPaths.push(entry.path);
1214
1466
  }
1215
1467
  if (entry.type === "completed") {
1216
- if (pending.size || appliedPaths.length !== bundle.files.length) throw new Error("Application completed before all files");
1468
+ if (pending.size || appliedPaths.length !== bundle.files.length)
1469
+ throw new Error("Application completed before all files");
1217
1470
  completed = true;
1218
1471
  }
1219
1472
  last = entry.type;
@@ -1239,7 +1492,9 @@ function bundleFrom(snapshot) {
1239
1492
  for (const { taskId, ...change } of snapshot.changes) {
1240
1493
  assertRelativePath(change.path);
1241
1494
  const group = groups.get(change.path) ?? [];
1242
- const identical = group.find((file) => isDeepStrictEqual2({ ...file, taskIds: void 0 }, { ...change, taskIds: void 0 }));
1495
+ const identical = group.find(
1496
+ (file) => isDeepStrictEqual2({ ...file, taskIds: void 0 }, { ...change, taskIds: void 0 })
1497
+ );
1243
1498
  if (identical) group[group.indexOf(identical)] = { ...identical, taskIds: [...identical.taskIds, taskId].sort() };
1244
1499
  else group.push({ ...change, taskIds: [taskId] });
1245
1500
  groups.set(change.path, group);
@@ -1271,12 +1526,14 @@ function bundleFrom(snapshot) {
1271
1526
  __name(bundleFrom, "bundleFrom");
1272
1527
  function validateBundle(bundle, expectedId) {
1273
1528
  assertPatchId(expectedId);
1274
- if (!bundle || bundle.format !== 1 || bundle.id !== expectedId || bundle.id !== `patch-${bundle.digest}` || !isAbsolute2(bundle.sourceDirectory) || !/^[a-f0-9]{64}$/u.test(bundle.baselineDigest) || !Array.isArray(bundle.taskSnapshots) || !bundle.taskSnapshots.length || !Array.isArray(bundle.files) || !Array.isArray(bundle.conflicts)) throw new Error("Invalid patch bundle");
1529
+ if (!bundle || bundle.format !== 1 || bundle.id !== expectedId || bundle.id !== `patch-${bundle.digest}` || !isAbsolute2(bundle.sourceDirectory) || !/^[a-f0-9]{64}$/u.test(bundle.baselineDigest) || !Array.isArray(bundle.taskSnapshots) || !bundle.taskSnapshots.length || !Array.isArray(bundle.files) || !Array.isArray(bundle.conflicts))
1530
+ throw new Error("Invalid patch bundle");
1275
1531
  const { id: _id, digest, ...body } = bundle;
1276
1532
  if (hash2(JSON.stringify(body)) !== digest) throw new Error("Patch digest does not match its content");
1277
1533
  const ids = /* @__PURE__ */ new Set();
1278
1534
  for (const task of bundle.taskSnapshots) {
1279
- if (typeof task.taskId !== "string" || !task.taskId || ids.has(task.taskId) || !/^[a-f0-9]{64}$/u.test(task.digest)) throw new Error("Invalid patch task identity");
1535
+ if (typeof task.taskId !== "string" || !task.taskId || ids.has(task.taskId) || !/^[a-f0-9]{64}$/u.test(task.digest))
1536
+ throw new Error("Invalid patch task identity");
1280
1537
  ids.add(task.taskId);
1281
1538
  }
1282
1539
  let total = 0;
@@ -1284,12 +1541,14 @@ function validateBundle(bundle, expectedId) {
1284
1541
  if (records.length > 128) throw new Error("Patch has too many file records");
1285
1542
  for (const file of records) {
1286
1543
  assertRelativePath(file.path);
1287
- if (!["added", "modified", "deleted"].includes(file.kind) || !Array.isArray(file.taskIds) || !file.taskIds.length || file.taskIds.some((id) => typeof id !== "string" || !ids.has(id))) throw new Error("Invalid patch file ownership");
1544
+ if (!["added", "modified", "deleted"].includes(file.kind) || !Array.isArray(file.taskIds) || !file.taskIds.length || file.taskIds.some((id) => typeof id !== "string" || !ids.has(id)))
1545
+ throw new Error("Invalid patch file ownership");
1288
1546
  for (const prefix of ["before", "after"]) {
1289
1547
  const text2 = file[`${prefix}Text`];
1290
1548
  const sha = file[`${prefix}Sha256`];
1291
1549
  const expected = prefix === "before" ? file.kind !== "added" : file.kind !== "deleted";
1292
- if (expected ? typeof text2 !== "string" || sha !== hash2(text2) || /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u.test(text2) : text2 !== void 0 || sha !== void 0) throw new Error("Invalid patch file content/hash or unsafe display controls");
1550
+ if (expected ? typeof text2 !== "string" || sha !== hash2(text2) || /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u.test(text2) : text2 !== void 0 || sha !== void 0)
1551
+ throw new Error("Invalid patch file content/hash or unsafe display controls");
1293
1552
  if (text2 !== void 0) {
1294
1553
  const bytes = Buffer.byteLength(text2);
1295
1554
  if (bytes > MAX_FILE_BYTES) throw new Error("Patch file exceeds its byte limit");
@@ -1309,7 +1568,10 @@ function fileDiff(file) {
1309
1568
  `+++ ${file.afterText === void 0 ? "/dev/null" : `b/${file.path}`}`,
1310
1569
  `@@ -${old.length ? 1 : 0},${old.length} +${next.length ? 1 : 0},${next.length} @@`
1311
1570
  ];
1312
- for (const [prefix, entries, text2] of [["-", old, file.beforeText], ["+", next, file.afterText]]) {
1571
+ for (const [prefix, entries, text2] of [
1572
+ ["-", old, file.beforeText],
1573
+ ["+", next, file.afterText]
1574
+ ]) {
1313
1575
  for (const line of entries) rendered.push(`${prefix}${line}`);
1314
1576
  if (entries.length && !text2.endsWith("\n")) rendered.push("\");
1315
1577
  }
@@ -1326,7 +1588,9 @@ __name(lines, "lines");
1326
1588
  async function preflight(source, files) {
1327
1589
  const originals = /* @__PURE__ */ new Map();
1328
1590
  const paths = files.map((file) => file.path);
1329
- for (const path of paths) if (paths.some((other) => other !== path && other.startsWith(`${path}/`))) throw new Error("Patch contains overlapping file and directory paths");
1591
+ for (const path of paths)
1592
+ if (paths.some((other) => other !== path && other.startsWith(`${path}/`)))
1593
+ throw new Error("Patch contains overlapping file and directory paths");
1330
1594
  for (const file of files) {
1331
1595
  const target = checkedPath(source, file.path);
1332
1596
  const current = await safeRead(source, target, MAX_FILE_BYTES);
@@ -1338,7 +1602,8 @@ async function preflight(source, files) {
1338
1602
  }
1339
1603
  __name(preflight, "preflight");
1340
1604
  function assertBefore(file, current) {
1341
- if (file.beforeSha256 === void 0 ? current !== void 0 : current === void 0 || hash2(current) !== file.beforeSha256) throw new Error(`Source changed since the baseline: ${file.path}`);
1605
+ if (file.beforeSha256 === void 0 ? current !== void 0 : current === void 0 || hash2(current) !== file.beforeSha256)
1606
+ throw new Error(`Source changed since the baseline: ${file.path}`);
1342
1607
  }
1343
1608
  __name(assertBefore, "assertBefore");
1344
1609
  async function safeRead(root, path, maxBytes) {
@@ -1347,14 +1612,16 @@ async function safeRead(root, path, maxBytes) {
1347
1612
  try {
1348
1613
  before = await lstat2(path);
1349
1614
  } catch (error) {
1350
- if (hasCode(error, "ENOENT")) return void 0;
1615
+ if (hasErrorCode2(error, "ENOENT")) return void 0;
1351
1616
  throw error;
1352
1617
  }
1353
- if (!before.isFile() || before.isSymbolicLink() || before.nlink > 1 || before.size > maxBytes) throw new Error("Patch file is unsafe or exceeds its byte limit");
1618
+ if (!before.isFile() || before.isSymbolicLink() || before.nlink > 1 || before.size > maxBytes)
1619
+ throw new Error("Patch file is unsafe or exceeds its byte limit");
1354
1620
  const file = await open4(path, constants2.O_RDONLY | (process.platform === "win32" ? 0 : constants2.O_NOFOLLOW));
1355
1621
  try {
1356
1622
  const stat2 = await file.stat();
1357
- if (!stat2.isFile() || stat2.ino !== before.ino || stat2.dev !== before.dev || stat2.size !== before.size || stat2.nlink > 1) throw new Error("Patch file changed while opening");
1623
+ if (!stat2.isFile() || stat2.ino !== before.ino || stat2.dev !== before.dev || stat2.size !== before.size || stat2.nlink > 1)
1624
+ throw new Error("Patch file changed while opening");
1358
1625
  const bytes = Buffer.alloc(before.size + 1);
1359
1626
  let position = 0;
1360
1627
  while (position < bytes.length) {
@@ -1363,7 +1630,8 @@ async function safeRead(root, path, maxBytes) {
1363
1630
  position += result.bytesRead;
1364
1631
  }
1365
1632
  const after = await file.stat();
1366
- if (position !== before.size || after.size !== before.size || after.mtimeMs !== stat2.mtimeMs) throw new Error("Patch file changed while reading");
1633
+ if (position !== before.size || after.size !== before.size || after.mtimeMs !== stat2.mtimeMs)
1634
+ throw new Error("Patch file changed while reading");
1367
1635
  await assertParents(root, path);
1368
1636
  return bytes.subarray(0, position);
1369
1637
  } finally {
@@ -1381,7 +1649,7 @@ async function assertParents(root, path) {
1381
1649
  const info = await lstat2(cursor);
1382
1650
  if (!info.isDirectory() || info.isSymbolicLink()) throw new Error("Patch parent is not a safe directory");
1383
1651
  } catch (error) {
1384
- if (hasCode(error, "ENOENT")) return;
1652
+ if (hasErrorCode2(error, "ENOENT")) return;
1385
1653
  throw error;
1386
1654
  }
1387
1655
  }
@@ -1397,7 +1665,7 @@ async function missingDirectories(root, path) {
1397
1665
  const info = await lstat2(cursor);
1398
1666
  if (!info.isDirectory() || info.isSymbolicLink()) throw new Error("Patch parent is unsafe");
1399
1667
  } catch (error) {
1400
- if (!hasCode(error, "ENOENT")) throw error;
1668
+ if (!hasErrorCode2(error, "ENOENT")) throw error;
1401
1669
  missing.push(cursor);
1402
1670
  }
1403
1671
  }
@@ -1426,7 +1694,7 @@ async function privateDirectory(path) {
1426
1694
  await safeRoot(parent);
1427
1695
  break;
1428
1696
  } catch (error) {
1429
- if (!hasCode(error, "ENOENT")) throw error;
1697
+ if (!hasErrorCode2(error, "ENOENT")) throw error;
1430
1698
  missing.unshift(parent);
1431
1699
  parent = dirname(parent);
1432
1700
  }
@@ -1435,7 +1703,7 @@ async function privateDirectory(path) {
1435
1703
  try {
1436
1704
  await mkdir2(directory, { mode: 448 });
1437
1705
  } catch (error) {
1438
- if (!hasCode(error, "EEXIST")) throw error;
1706
+ if (!hasErrorCode2(error, "EEXIST")) throw error;
1439
1707
  }
1440
1708
  await safeRoot(directory);
1441
1709
  }
@@ -1458,7 +1726,8 @@ async function syncDirectory(path) {
1458
1726
  directory = await open4(path, "r");
1459
1727
  await directory.sync();
1460
1728
  } catch (error) {
1461
- if (process.platform !== "win32" || !["EPERM", "EACCES", "EINVAL", "EISDIR"].some((code) => hasCode(error, code))) throw error;
1729
+ if (process.platform !== "win32" || !["EPERM", "EACCES", "EINVAL", "EISDIR"].some((code) => hasErrorCode2(error, code)))
1730
+ throw error;
1462
1731
  } finally {
1463
1732
  await directory?.close();
1464
1733
  }
@@ -1472,7 +1741,10 @@ function checkedPath(root, path) {
1472
1741
  }
1473
1742
  __name(checkedPath, "checkedPath");
1474
1743
  function assertRelativePath(path) {
1475
- if (typeof path !== "string" || !path || isAbsolute2(path) || /[\\:\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u.test(path) || path.split("/").some((part) => !part || part === "." || part === ".." || /[. ]$/u.test(part) || /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/iu.test(part))) throw new Error("Unsafe or nonportable patch path");
1744
+ if (typeof path !== "string" || !path || isAbsolute2(path) || /[\\:\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u.test(path) || path.split("/").some(
1745
+ (part) => !part || part === "." || part === ".." || /[. ]$/u.test(part) || /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/iu.test(part)
1746
+ ))
1747
+ throw new Error("Unsafe or nonportable patch path");
1476
1748
  }
1477
1749
  __name(assertRelativePath, "assertRelativePath");
1478
1750
  function assertPatchId(id) {
@@ -1488,10 +1760,6 @@ function hash2(value) {
1488
1760
  return createHash3("sha256").update(value).digest("hex");
1489
1761
  }
1490
1762
  __name(hash2, "hash");
1491
- function hasCode(error, code) {
1492
- return typeof error === "object" && error !== null && "code" in error && error.code === code;
1493
- }
1494
- __name(hasCode, "hasCode");
1495
1763
 
1496
1764
  // apps/maybecode/src/team-v2.ts
1497
1765
  var VERSION = "maybecode-team-v2";
@@ -1500,26 +1768,38 @@ var DEFAULT_RUN_BUDGET = { maxSteps: 10, maxModelCalls: 10, maxToolCalls: 24, ma
1500
1768
  async function runTeamV2Command(command, dependencies) {
1501
1769
  const id = command.action === "run" ? randomUUID2() : command.value;
1502
1770
  if (!/^[A-Za-z0-9_-]{1,128}$/u.test(id)) throw new Error("Invalid team id");
1503
- const directory = await canonicalPotentialPath(join4(resolve3(command.dataDirectory ?? getDefaultMaybeCodeDataDirectory()), "teams", id));
1771
+ const directory = await canonicalPotentialPath(
1772
+ join4(resolve3(command.dataDirectory ?? getDefaultMaybeCodeDataDirectory()), "teams", id)
1773
+ );
1504
1774
  const write = /* @__PURE__ */ __name((text2) => dependencies.write(safeTerminal(text2)), "write");
1505
1775
  let config;
1506
1776
  let manifest;
1507
1777
  if (command.action === "run") {
1508
- if (!command.value.trim() || Buffer.byteLength(command.value) > 32768) throw new Error("Team prompt must contain 1-32768 bytes");
1778
+ if (!command.value.trim() || Buffer.byteLength(command.value) > 32768)
1779
+ throw new Error("Team prompt must contain 1-32768 bytes");
1509
1780
  const workspace = await realpath3(resolve3(command.workspace ?? process.cwd()));
1510
- if (!(await stat(workspace)).isDirectory() || inside2(workspace, directory) || inside2(directory, workspace)) throw new Error("Team data directory must be outside and not overlap the source workspace");
1781
+ if (!(await stat(workspace)).isDirectory() || inside2(workspace, directory) || inside2(directory, workspace))
1782
+ throw new Error("Team data directory must be outside and not overlap the source workspace");
1511
1783
  const mode = command.mode ?? "read-only";
1512
- const plan = command.planPath ? await loadTeamPlan(command.planPath, { mode }) : createTeamPreset(command.preset ?? "supervisor", command.value, { mode, ...command.model ? { model: command.model } : {} });
1784
+ const plan = command.planPath ? await loadTeamPlan(command.planPath, { mode }) : createTeamPreset(command.preset ?? "supervisor", command.value, {
1785
+ mode,
1786
+ ...command.model ? { model: command.model } : {}
1787
+ });
1513
1788
  config = await (dependencies.loadConfig ?? loadMayConfig)(command.configPath ? { path: command.configPath } : {});
1514
1789
  const fallback = command.model ?? (Object.values(plan.roles).every((role) => role.model !== void 0) ? Object.values(plan.roles)[0].model : void 0);
1515
1790
  const defaultModel = selectMaybeCodeModel(config, fallback ? { model: fallback } : {});
1516
1791
  const roleModels = {};
1517
1792
  for (const [name, role] of Object.entries(plan.roles)) {
1518
1793
  const selected = selectMaybeCodeModel(config, { model: role.model ?? defaultModel.profile });
1519
- const runBudget = resolveRunBudget2(resolveRunBudget2(config.apps?.maybecode?.runBudget, DEFAULT_RUN_BUDGET), role.runBudget);
1794
+ const runBudget = resolveRunBudget2(
1795
+ resolveRunBudget2(readMaybeCodeSettings(config).runBudget, DEFAULT_RUN_BUDGET),
1796
+ role.runBudget
1797
+ );
1520
1798
  roleModels[name] = { profile: selected.profile, fingerprint: modelFingerprint(selected), runBudget };
1521
1799
  }
1522
1800
  manifest = {
1801
+ execution: readMaybeCodeSettings(config).execution ?? { mode: "host" },
1802
+ fetch: readMaybeCodeSettings(config).fetch ?? {},
1523
1803
  format: 1,
1524
1804
  version: VERSION,
1525
1805
  id,
@@ -1540,7 +1820,8 @@ async function runTeamV2Command(command, dependencies) {
1540
1820
  await mkdir3(directory, { recursive: true, mode: 448 });
1541
1821
  await writeJson(join4(directory, "manifest.json"), manifest, true);
1542
1822
  } else manifest = await readManifest(directory, id);
1543
- if (inside2(manifest.workspace, directory) || inside2(directory, manifest.workspace)) throw new Error("Team data and source directories overlap");
1823
+ if (inside2(manifest.workspace, directory) || inside2(directory, manifest.workspace))
1824
+ throw new Error("Team data and source directories overlap");
1544
1825
  const authorityVersion = `${VERSION}-${teamReviewDigest({ mode: manifest.mode, allowChecks: manifest.allowChecks, plan: manifest.plan, roleModels: manifest.roleModels })}`;
1545
1826
  const budgetLimits = { maxModelCalls: manifest.maxModelCalls, maxTotalTokens: manifest.maxTotalTokens };
1546
1827
  if (command.action === "status") {
@@ -1551,10 +1832,12 @@ Records: ${directory}
1551
1832
  write(await inspectTeam(directory, id, budgetLimits));
1552
1833
  const path = join4(directory, "acceptance.json");
1553
1834
  try {
1554
- write(`Last acceptance projection (may be stale): ${await withFileAccess(path, "shared", () => readFile(path, "utf8"))}
1555
- `);
1835
+ write(
1836
+ `Last acceptance projection (may be stale): ${await withFileAccess(path, "shared", () => readFile(path, "utf8"))}
1837
+ `
1838
+ );
1556
1839
  } catch (error) {
1557
- if (!isMissing2(error)) throw error;
1840
+ if (!hasErrorCode3(error, "ENOENT")) throw error;
1558
1841
  }
1559
1842
  return 0;
1560
1843
  }
@@ -1566,15 +1849,25 @@ Records: ${directory}
1566
1849
  }
1567
1850
  const executes = command.action === "run" || command.action === "resume";
1568
1851
  const selections = /* @__PURE__ */ new Map();
1852
+ let recording;
1569
1853
  if (executes) {
1570
1854
  config ??= await (dependencies.loadConfig ?? loadMayConfig)({ path: manifest.configPath });
1855
+ recording = resolveMaybeCodeRecording(config);
1571
1856
  for (const [name, binding] of Object.entries(manifest.roleModels)) {
1572
1857
  const selected = selectMaybeCodeModel(config, { model: binding.profile });
1573
- if (modelFingerprint(selected) !== binding.fingerprint) throw new Error(`Model configuration changed for role ${name}; restore it before resuming`);
1858
+ if (modelFingerprint(selected) !== binding.fingerprint)
1859
+ throw new Error(`Model configuration changed for role ${name}; restore it before resuming`);
1574
1860
  selections.set(name, selected);
1575
1861
  }
1576
1862
  }
1577
1863
  const ledger = await FileSharedBudget.open(join4(directory, "budget"), id, budgetLimits);
1864
+ const settings = readMaybeCodeSettings({
1865
+ providers: {},
1866
+ models: {},
1867
+ path: manifest.configPath,
1868
+ apps: { maybecode: { execution: manifest.execution ?? { mode: "host" }, fetch: manifest.fetch ?? {} } }
1869
+ });
1870
+ const executionEnvironments = new TeamExecutionEnvironments(settings.execution);
1578
1871
  let workspaces;
1579
1872
  let artifacts;
1580
1873
  let verification;
@@ -1583,9 +1876,31 @@ Records: ${directory}
1583
1876
  let timer;
1584
1877
  let cancelling;
1585
1878
  let retryAuthorized = false;
1879
+ const backgroundTasks = /* @__PURE__ */ new Set();
1880
+ const backgroundErrors = [];
1881
+ let failBackground;
1882
+ const backgroundFailed = new Promise((resolve4) => {
1883
+ failBackground = resolve4;
1884
+ });
1885
+ const trackBackground = /* @__PURE__ */ __name((operation) => {
1886
+ const task = operation.then(
1887
+ () => {
1888
+ backgroundTasks.delete(task);
1889
+ },
1890
+ (error) => {
1891
+ backgroundTasks.delete(task);
1892
+ backgroundErrors.push(error);
1893
+ failBackground(error);
1894
+ cancel();
1895
+ }
1896
+ );
1897
+ backgroundTasks.add(task);
1898
+ }, "trackBackground");
1586
1899
  const cancel = /* @__PURE__ */ __name(() => {
1587
- if (runtime) cancelling ??= runtime.cancel(`cancel-${id}`);
1588
- void cancelling?.catch(() => void 0);
1900
+ if (runtime && !cancelling) {
1901
+ cancelling = runtime.cancel(`cancel-${id}`);
1902
+ trackBackground(cancelling);
1903
+ }
1589
1904
  }, "cancel");
1590
1905
  try {
1591
1906
  artifacts = await FileArtifactStore.open(join4(directory, "artifacts"), id, {
@@ -1595,8 +1910,15 @@ Records: ${directory}
1595
1910
  maxArtifactBytes: 262144,
1596
1911
  maxTotalBytes: 16777216
1597
1912
  });
1598
- workspaces = await TaskWorkspaceManager.open({ sourceDirectory: manifest.workspace, directory: join4(directory, "workspaces") });
1599
- verification = await TeamVerificationStore.open({ directory: join4(directory, "verification"), checks: manifest.plan.checks });
1913
+ workspaces = await TaskWorkspaceManager.open({
1914
+ sourceDirectory: manifest.workspace,
1915
+ directory: join4(directory, "workspaces")
1916
+ });
1917
+ verification = await TeamVerificationStore.open({
1918
+ directory: join4(directory, "verification"),
1919
+ checks: manifest.plan.checks,
1920
+ executionFor: /* @__PURE__ */ __name((workspace) => executionEnvironments.get(workspace), "executionFor")
1921
+ });
1600
1922
  const sessionStore = new FileSessionStore2(join4(directory, "sessions"));
1601
1923
  const models = /* @__PURE__ */ new Map();
1602
1924
  const modelFor = /* @__PURE__ */ __name((name) => {
@@ -1607,68 +1929,97 @@ Records: ${directory}
1607
1929
  const maxOutputTokens = Math.min(
1608
1930
  4096,
1609
1931
  selected.limits?.maxOutputTokens ?? 4096,
1610
- ...[selected.options.maxTokens, selected.options.maxOutputTokens].filter((n) => typeof n === "number" && n > 0 && Number.isSafeInteger(n))
1932
+ ...[selected.options.maxTokens, selected.options.maxOutputTokens].filter(
1933
+ (n) => typeof n === "number" && n > 0 && Number.isSafeInteger(n)
1934
+ )
1611
1935
  );
1612
1936
  const selection = {
1613
1937
  ...selected,
1614
1938
  options: { ...selected.options, maxTokens: maxOutputTokens, maxOutputTokens },
1615
1939
  limits: { ...selected.limits, maxOutputTokens }
1616
1940
  };
1617
- model = ledger.wrapModel((dependencies.createModel ?? createMaybeCodeModel)(selection), { reservation: { totalTokens: RESERVATION } });
1941
+ model = ledger.wrapModel((dependencies.createModel ?? createMaybeCodeModel)(selection), {
1942
+ reservation: { totalTokens: RESERVATION }
1943
+ });
1618
1944
  models.set(name, model);
1619
1945
  }
1620
1946
  return model;
1621
1947
  }, "modelFor");
1622
1948
  const agents = {};
1623
1949
  for (const [name, role] of Object.entries(manifest.plan.roles)) {
1624
- const scoped = /* @__PURE__ */ __name((execution, workspace) => createApplicationAgent({
1625
- version: authorityVersion,
1626
- store: sessionStore,
1627
- delegation: role.delegateTo.length > 0,
1628
- messaging: role.messaging,
1629
- definition: /* @__PURE__ */ __name(({ tools }) => {
1630
- const available = [
1631
- createReadTool({ cwd: workspace, maxBytes: 262144, maxLines: 160 }),
1632
- createListTool(workspace),
1633
- ...artifacts.forTask(execution.task.id).tools(),
1634
- ...verification.forTask(execution, workspace, { allowCommands: manifest.allowChecks }).tools(),
1635
- ...manifest.mode === "coding" ? [createWriteTool({ cwd: workspace, maxBytes: 262144 }), createEditTool({ cwd: workspace, maxBytes: 262144 })] : []
1636
- ];
1637
- const selectedTools = available.filter((tool) => role.tools.includes(tool.name)).map((tool) => {
1638
- if (!["write", "edit"].includes(tool.name)) return tool;
1639
- return { ...tool, async execute(input, context) {
1640
- if ((await verification.snapshot()).checks.some((check) => check.status === "unknown" || check.taskId === execution.task.id && check.status === "pending")) throw new Error("Pending or unknown check effects block editing; stop and reconcile uncertain processes first");
1641
- return tool.execute(input, context);
1642
- } };
1643
- });
1644
- const allowed = new Set([...selectedTools, ...tools].map((tool) => tool.name));
1645
- const roleBudget = manifest.roleModels[name].runBudget;
1646
- const budget2 = config ? resolveRunBudget2(roleBudget, config.apps?.maybecode?.runBudget) : roleBudget;
1647
- return defineAgent({
1648
- model: modelFor(name),
1649
- tools: [...selectedTools, ...tools],
1650
- runBudget: budget2,
1651
- instructions: instructions(manifest, name, role),
1652
- toolScope: { workspaceId: workspace },
1653
- permissionPolicy: /* @__PURE__ */ __name((check) => allowed.has(check.tool.name) ? "allow" : "deny", "permissionPolicy")
1654
- });
1655
- }, "definition")
1656
- }), "scoped");
1950
+ const scoped = /* @__PURE__ */ __name(async (execution, workspace) => {
1951
+ const environment = await executionEnvironments.get(workspace);
1952
+ return createApplicationAgent({
1953
+ version: authorityVersion,
1954
+ store: sessionStore,
1955
+ delegation: role.delegateTo.length > 0,
1956
+ messaging: role.messaging,
1957
+ definition: /* @__PURE__ */ __name(({ tools }) => {
1958
+ const available = [
1959
+ createReadTool({ cwd: workspace, maxBytes: 262144, maxLines: 160 }),
1960
+ createGlobTool({ cwd: workspace, execution: environment }),
1961
+ createGrepTool({ cwd: workspace, execution: environment }),
1962
+ createFetchTool(settings?.fetch ?? {}),
1963
+ createListTool(workspace),
1964
+ ...artifacts.forTask(execution.task.id).tools(),
1965
+ ...verification.forTask(execution, workspace, { allowCommands: manifest.allowChecks }).tools(),
1966
+ ...manifest.mode === "coding" ? [
1967
+ createWriteTool({ cwd: workspace, maxBytes: 262144 }),
1968
+ createEditTool({ cwd: workspace, maxBytes: 262144 })
1969
+ ] : []
1970
+ ];
1971
+ const selectedTools = available.filter((tool) => role.tools.includes(tool.name)).map((tool) => {
1972
+ if (!["write", "edit"].includes(tool.name)) return tool;
1973
+ return {
1974
+ ...tool,
1975
+ async execute(input, context) {
1976
+ if ((await verification.snapshot()).checks.some(
1977
+ (check) => check.status === "unknown" || check.taskId === execution.task.id && check.status === "pending"
1978
+ ))
1979
+ throw new Error(
1980
+ "Pending or unknown check effects block editing; stop and reconcile uncertain processes first"
1981
+ );
1982
+ return tool.execute(input, context);
1983
+ }
1984
+ };
1985
+ });
1986
+ const allowed = new Set([...selectedTools, ...tools].map((tool) => tool.name));
1987
+ const roleBudget = manifest.roleModels[name].runBudget;
1988
+ const budget2 = config ? resolveRunBudget2(roleBudget, readMaybeCodeSettings(config).runBudget) : roleBudget;
1989
+ if (!recording) throw new Error("A host control command cannot start a model");
1990
+ return defineAgent({
1991
+ ...recording,
1992
+ model: modelFor(name),
1993
+ tools: [...selectedTools, ...tools],
1994
+ runBudget: budget2,
1995
+ instructions: instructions(manifest, name, role),
1996
+ toolScope: { workspaceId: workspace },
1997
+ permissionPolicy: /* @__PURE__ */ __name((check) => allowed.has(check.tool.name) ? "allow" : "deny", "permissionPolicy")
1998
+ });
1999
+ }, "definition")
2000
+ });
2001
+ }, "scoped");
1657
2002
  const publish = /* @__PURE__ */ __name(async (execution, output) => {
1658
- await artifacts.forTask(execution.task.id).publish(
1659
- `${execution.task.dispatchId}-${execution.task.turn ?? 0}-final`,
1660
- { name: `${execution.task.id.slice(0, 100)}-result.md`, text: output.text, mimeType: "text/markdown" }
1661
- );
2003
+ await artifacts.forTask(execution.task.id).publish(`${execution.task.dispatchId}-${execution.task.turn ?? 0}-final`, {
2004
+ name: `${execution.task.id.slice(0, 100)}-result.md`,
2005
+ text: output.text,
2006
+ mimeType: "text/markdown"
2007
+ });
1662
2008
  }, "publish");
1663
2009
  agents[name] = {
1664
2010
  version: authorityVersion,
1665
2011
  async execute(execution, context) {
1666
- if ((await verification.snapshot()).checks.some((check) => check.status === "unknown")) throw new Error("Unknown check effects block a new Agent Run; reconcile before retrying");
2012
+ if ((await verification.snapshot()).checks.some((check) => check.status === "unknown"))
2013
+ throw new Error("Unknown check effects block a new Agent Run; reconcile before retrying");
1667
2014
  const isolated = await workspaces.prepare(execution.task.id);
1668
2015
  const dependencyResults = [];
1669
2016
  for (const dependency of execution.dependencies) {
1670
2017
  const source = await workspaces.prepare(dependency.taskId);
1671
- const acceptance2 = await verification.acceptance(dependency.taskId, source.directory, executionOf(runtime.snapshot(), dependency.taskId));
2018
+ const acceptance2 = await verification.acceptance(
2019
+ dependency.taskId,
2020
+ source.directory,
2021
+ executionOf(runtime.snapshot(), dependency.taskId)
2022
+ );
1672
2023
  const record = {
1673
2024
  taskId: dependency.taskId,
1674
2025
  status: acceptance2.status,
@@ -1678,26 +2029,36 @@ Records: ${directory}
1678
2029
  evidenceValid: acceptance2.report?.evidence.every((item) => item.valid) ?? false,
1679
2030
  detail: acceptance2.detail
1680
2031
  };
1681
- dependencyResults.push({ ...dependency, output: {
1682
- ...dependency.output,
1683
- text: `${dependency.output.text}
2032
+ dependencyResults.push({
2033
+ ...dependency,
2034
+ output: {
2035
+ ...dependency.output,
2036
+ text: `${dependency.output.text}
1684
2037
 
1685
2038
  Host verification record (scoped to that task's private workspace, not the source checkout or every claim):
1686
2039
  ${JSON.stringify(record)}`
1687
- } });
2040
+ }
2041
+ });
1688
2042
  }
1689
2043
  const submitted = { ...execution, dependencies: dependencyResults };
1690
- const output = await scoped(submitted, isolated.directory).execute(submitted, context);
2044
+ const output = await (await scoped(submitted, isolated.directory)).execute(submitted, context);
1691
2045
  if (!("yielded" in output)) {
1692
2046
  await publish(execution, output);
1693
- for (const check of manifest.plan.checks.filter((check2) => check2.taskId === execution.task.id && check2.type !== "command")) {
1694
- await verification.runCheck(teamReviewDigest({ auto: execution.task.dispatchId, turn: execution.task.turn ?? 0, check: check.id }), check, isolated.directory, { execution, signal: context.signal });
2047
+ for (const check of manifest.plan.checks.filter(
2048
+ (check2) => check2.taskId === execution.task.id && check2.type !== "command"
2049
+ )) {
2050
+ await verification.runCheck(
2051
+ teamReviewDigest({ auto: execution.task.dispatchId, turn: execution.task.turn ?? 0, check: check.id }),
2052
+ check,
2053
+ isolated.directory,
2054
+ { execution, signal: context.signal }
2055
+ );
1695
2056
  }
1696
2057
  }
1697
2058
  return output;
1698
2059
  },
1699
2060
  async recover(execution) {
1700
- const output = await scoped(execution, manifest.workspace).recover(execution);
2061
+ const output = await (await scoped(execution, manifest.workspace)).recover(execution);
1701
2062
  if (output.status === "completed") await publish(execution, output.output);
1702
2063
  return output;
1703
2064
  }
@@ -1716,7 +2077,8 @@ ${JSON.stringify(record)}`
1716
2077
  if (retryAuthorized) return true;
1717
2078
  const state = runtime?.snapshot(), current = state?.tasks.find((entry) => entry.id === task.id);
1718
2079
  const previous = current?.attempts?.at(-1);
1719
- if (current?.status !== "queued" || !previous || previous.task.dispatchId !== task.dispatchId || previous.task.sessionId !== task.sessionId || previous.finding !== finding || !/^retry-[a-f0-9]{64}$/u.test(previous.commandId)) return false;
2080
+ if (current?.status !== "queued" || !previous || previous.task.dispatchId !== task.dispatchId || previous.task.sessionId !== task.sessionId || previous.finding !== finding || !/^retry-[a-f0-9]{64}$/u.test(previous.commandId))
2081
+ return false;
1720
2082
  const receipt = state?.commands[previous.commandId];
1721
2083
  if (!receipt) return false;
1722
2084
  const value = JSON.parse(receipt);
@@ -1739,26 +2101,31 @@ ${JSON.stringify(record)}`
1739
2101
  maxConcurrent: manifest.maxConcurrent
1740
2102
  }
1741
2103
  }) : await CoordinationRuntime.resume(options);
1742
- write(`Team ${id}
2104
+ write(
2105
+ `Team ${id}
1743
2106
  Mode: ${manifest.mode}; source application requires a separate reviewed patch confirmation.
1744
2107
  Records: ${directory}
1745
- `);
1746
- if (manifest.allowChecks) write("Configured test processes explicitly authorized; no OS sandbox or automatic dependency installation.\n");
2108
+ `
2109
+ );
2110
+ if (manifest.allowChecks)
2111
+ write("Configured test processes explicitly authorized; no OS sandbox or automatic dependency installation.\n");
1747
2112
  relay = (async () => {
1748
2113
  const statuses = /* @__PURE__ */ new Map();
1749
2114
  for await (const event of runtime.events) {
1750
2115
  if (event.type === "state.changed") {
1751
- for (const task of event.snapshot.tasks) if (statuses.get(task.id) !== task.status) {
1752
- statuses.set(task.id, task.status);
1753
- write(`[${task.id}] ${task.status}${task.detail ? `: ${task.detail}` : ""}
2116
+ for (const task of event.snapshot.tasks)
2117
+ if (statuses.get(task.id) !== task.status) {
2118
+ statuses.set(task.id, task.status);
2119
+ write(`[${task.id}] ${task.status}${task.detail ? `: ${task.detail}` : ""}
1754
2120
  `);
1755
- }
1756
- } else if (event.type === "agent.event" && event.event.type === "run.event" && event.event.event.type === "tool.started") write(`[${event.taskId}] tool ${event.event.event.call.name}
2121
+ }
2122
+ } else if (event.type === "agent.event" && event.event.type === "run.event" && event.event.event.type === "tool.started")
2123
+ write(`[${event.taskId}] tool ${event.event.event.call.name}
1757
2124
  `);
1758
2125
  else if (event.type === "runtime.failed") write("Team runtime failed; inspect recovery records.\n");
1759
2126
  }
1760
2127
  })();
1761
- void relay.catch(cancel);
2128
+ trackBackground(relay);
1762
2129
  if (command.action === "retry" || command.action === "reconcile") {
1763
2130
  const state = runtime.snapshot(), budget2 = await ledger.snapshot(), checks = await verification.snapshot();
1764
2131
  const operation = command.action === "retry" ? retryImpact(state, command.task, command.finding) : await readTeamResolution(command.resolutionPath);
@@ -1768,58 +2135,85 @@ Records: ${directory}
1768
2135
  Review digest: ${digest}
1769
2136
  `);
1770
2137
  if (!command.confirm) {
1771
- write("Preview only. Verify recorded effects/usage, then repeat with --confirm and this digest. No agent has executed.\n");
2138
+ write(
2139
+ "Preview only. Verify recorded effects/usage, then repeat with --confirm and this digest. No agent has executed.\n"
2140
+ );
1772
2141
  return 0;
1773
2142
  }
1774
2143
  if (command.confirm !== digest) throw new Error("Review digest changed or mismatched; inspect a fresh preview");
1775
2144
  if (command.action === "retry") {
1776
- if ((await ledger.totals()).blocked || checks.checks.some((check) => ["unknown", "pending"].includes(check.status))) throw new Error("Reconcile unknown usage/check effects before retrying; no reset or replay is allowed");
2145
+ if ((await ledger.totals()).blocked || checks.checks.some((check) => ["unknown", "pending"].includes(check.status)))
2146
+ throw new Error("Reconcile unknown usage/check effects before retrying; no reset or replay is allowed");
1777
2147
  retryAuthorized = true;
1778
2148
  await runtime.retryTask(`retry-${digest}`, command.task, command.finding);
1779
2149
  } else {
1780
2150
  const resolution = operation;
1781
- if (resolution.kind === "budget") await ledger.reconcile(resolution.callId, resolution.usage, resolution.finding);
1782
- else if (resolution.kind === "check") await verification.reconcile(resolution.commandId, { status: resolution.outcome }, resolution.finding);
1783
- else await runtime.resolveRecovery(`resolve-${digest}`, resolution.taskId, resolution.finding, { status: resolution.outcome, detail: resolution.finding });
2151
+ if (resolution.kind === "budget")
2152
+ await ledger.reconcile(resolution.callId, resolution.usage, resolution.finding);
2153
+ else if (resolution.kind === "check")
2154
+ await verification.reconcile(resolution.commandId, { status: resolution.outcome }, resolution.finding);
2155
+ else
2156
+ await runtime.resolveRecovery(`resolve-${digest}`, resolution.taskId, resolution.finding, {
2157
+ status: resolution.outcome,
2158
+ detail: resolution.finding
2159
+ });
1784
2160
  }
1785
2161
  write("Recorded. No agents or checks executed. Use team resume explicitly when ready.\n");
1786
2162
  return 0;
1787
2163
  }
1788
2164
  if (command.action === "diff" || command.action === "apply") {
1789
- if (manifest.mode !== "coding") throw new Error("Patch controls require a team explicitly created with --mode coding");
2165
+ if (manifest.mode !== "coding")
2166
+ throw new Error("Patch controls require a team explicitly created with --mode coding");
1790
2167
  const state = runtime.snapshot();
1791
- if (state.tasks.some((task) => !["completed", "failed", "cancelled"].includes(task.status))) throw new Error("Settle all active/unknown team work before reviewing or applying a patch");
2168
+ if (state.tasks.some((task) => !["completed", "failed", "cancelled"].includes(task.status)))
2169
+ throw new Error("Settle all active/unknown team work before reviewing or applying a patch");
1792
2170
  if (command.action === "diff") {
1793
2171
  const taskIds = command.tasks.split(",");
1794
- if (!taskIds.length || new Set(taskIds).size !== taskIds.length || taskIds.some((id2) => state.tasks.find((task) => task.id === id2)?.status !== "completed")) throw new Error("Select distinct completed task ids for review");
2172
+ if (!taskIds.length || new Set(taskIds).size !== taskIds.length || taskIds.some((id2) => state.tasks.find((task) => task.id === id2)?.status !== "completed"))
2173
+ throw new Error("Select distinct completed task ids for review");
1795
2174
  const patch2 = await createTeamPatch({ directory, workspaces, taskIds });
1796
2175
  write(renderTeamPatchDiff(patch2));
1797
- write(`
2176
+ write(
2177
+ `
1798
2178
  Patch: ${patch2.id}
1799
2179
  Review digest: ${patch2.digest}
1800
2180
  Only use team apply after reviewing the diff and current acceptance.
1801
- `);
2181
+ `
2182
+ );
1802
2183
  return 0;
1803
2184
  }
1804
2185
  const patch = await readTeamPatch(directory, command.patch);
1805
2186
  const uncheckedTasks = patch.taskSnapshots.map((task) => task.taskId).filter((taskId) => !manifest.plan.checks.some((check) => check.taskId === taskId));
1806
- if (uncheckedTasks.length) write(`Unverified patch tasks (human review only): ${uncheckedTasks.join(", ")}. Other tasks' passing checks do not verify these edits.
1807
- `);
1808
- if ((await ledger.totals()).blocked || (await verification.snapshot()).checks.some((check) => ["pending", "unknown"].includes(check.status))) throw new Error("Reconcile unknown team effects before applying source changes");
2187
+ if (uncheckedTasks.length)
2188
+ write(
2189
+ `Unverified patch tasks (human review only): ${uncheckedTasks.join(", ")}. Other tasks' passing checks do not verify these edits.
2190
+ `
2191
+ );
2192
+ if ((await ledger.totals()).blocked || (await verification.snapshot()).checks.some((check) => ["pending", "unknown"].includes(check.status)))
2193
+ throw new Error("Reconcile unknown team effects before applying source changes");
1809
2194
  for (const checkTaskId of new Set(manifest.plan.checks.map((check) => check.taskId))) {
1810
2195
  const task = state.tasks.find((task2) => task2.id === checkTaskId);
1811
- if (task?.status !== "completed") throw new Error("All configured acceptance tasks must complete before source application");
2196
+ if (task?.status !== "completed")
2197
+ throw new Error("All configured acceptance tasks must complete before source application");
1812
2198
  const workspace = await workspaces.prepare(checkTaskId);
1813
- if ((await verification.acceptance(checkTaskId, workspace.directory, executionOf(state, checkTaskId))).status !== "passed") throw new Error(`Acceptance is not passed/current for ${checkTaskId}; use team verify and inspect reports`);
2199
+ if ((await verification.acceptance(checkTaskId, workspace.directory, executionOf(state, checkTaskId))).status !== "passed")
2200
+ throw new Error(`Acceptance is not passed/current for ${checkTaskId}; use team verify and inspect reports`);
1814
2201
  }
1815
- if (!manifest.plan.checks.length) write("No configured acceptance checks: this is an explicit human-reviewed, unverified source application.\n");
1816
- const result2 = await applyTeamPatch({ directory, workspaces, patchId: patch.id, confirmDigest: command.confirm });
2202
+ if (!manifest.plan.checks.length)
2203
+ write("No configured acceptance checks: this is an explicit human-reviewed, unverified source application.\n");
2204
+ const result2 = await applyTeamPatch({
2205
+ directory,
2206
+ workspaces,
2207
+ patchId: patch.id,
2208
+ confirmDigest: command.confirm
2209
+ });
1817
2210
  write(`${JSON.stringify(result2, null, 2)}
1818
2211
  `);
1819
2212
  return result2.status === "applied" ? 0 : 1;
1820
2213
  }
1821
2214
  if (command.action === "verify") {
1822
- if ((await verification.snapshot()).checks.some((check) => ["unknown", "pending"].includes(check.status))) throw new Error("Reconcile unknown check effects before running new verification");
2215
+ if ((await verification.snapshot()).checks.some((check) => ["unknown", "pending"].includes(check.status)))
2216
+ throw new Error("Reconcile unknown check effects before running new verification");
1823
2217
  const controller = new AbortController();
1824
2218
  const signal = AbortSignal.any([controller.signal, ...dependencies.signal ? [dependencies.signal] : []]);
1825
2219
  const observeCancellation = /* @__PURE__ */ __name(async () => {
@@ -1828,7 +2222,7 @@ Only use team apply after reviewing the diff and current acceptance.
1828
2222
  await withFileAccess(path, "shared", () => stat(path));
1829
2223
  controller.abort("Team verification cancelled");
1830
2224
  } catch (error) {
1831
- if (!isMissing2(error)) {
2225
+ if (!hasErrorCode3(error, "ENOENT")) {
1832
2226
  controller.abort("Cannot establish cancellation state");
1833
2227
  throw error;
1834
2228
  }
@@ -1836,7 +2230,7 @@ Only use team apply after reviewing the diff and current acceptance.
1836
2230
  }, "observeCancellation");
1837
2231
  await observeCancellation();
1838
2232
  timer = setInterval(() => {
1839
- void observeCancellation().catch(() => controller.abort("Cancellation monitoring failed"));
2233
+ trackBackground(observeCancellation());
1840
2234
  }, 300);
1841
2235
  const state = runtime.snapshot();
1842
2236
  for (const check of manifest.plan.checks) {
@@ -1850,12 +2244,11 @@ Only use team apply after reviewing the diff and current acceptance.
1850
2244
  continue;
1851
2245
  }
1852
2246
  const workspace = await workspaces.prepare(check.taskId);
1853
- const result2 = await verification.runCheck(
1854
- `host-${randomUUID2()}`,
1855
- check,
1856
- workspace.directory,
1857
- { allowCommands: manifest.allowChecks, signal, execution: executionOf(state, check.taskId) }
1858
- );
2247
+ const result2 = await verification.runCheck(`host-${randomUUID2()}`, check, workspace.directory, {
2248
+ allowCommands: manifest.allowChecks,
2249
+ signal,
2250
+ execution: executionOf(state, check.taskId)
2251
+ });
1859
2252
  write(`Check ${check.id}: ${result2.status}${result2.detail ? ` (${result2.detail})` : ""}
1860
2253
  `);
1861
2254
  }
@@ -1870,7 +2263,7 @@ Only use team apply after reviewing the diff and current acceptance.
1870
2263
  await withFileAccess(path, "shared", () => stat(path));
1871
2264
  cancel();
1872
2265
  } catch (error) {
1873
- if (!isMissing2(error)) {
2266
+ if (!hasErrorCode3(error, "ENOENT")) {
1874
2267
  cancel();
1875
2268
  throw error;
1876
2269
  }
@@ -1880,14 +2273,21 @@ Only use team apply after reviewing the diff and current acceptance.
1880
2273
  await checkCancellation();
1881
2274
  if (dependencies.signal?.aborted) cancel();
1882
2275
  timer = setInterval(() => {
1883
- void checkCancellation().catch(cancel);
2276
+ trackBackground(checkCancellation());
1884
2277
  }, 300);
1885
2278
  await cancelling;
1886
2279
  if ((await ledger.totals()).blocked || (await verification.snapshot()).checks.some((check) => check.status === "unknown")) {
1887
- write("Unknown usage/check effects or exceeded budget block execution. No new Run started; inspect and reconcile explicitly.\n");
2280
+ write(
2281
+ "Unknown usage/check effects or exceeded budget block execution. No new Run started; inspect and reconcile explicitly.\n"
2282
+ );
1888
2283
  return 1;
1889
2284
  }
1890
- const result = await runtime.wait();
2285
+ const result = await Promise.race([
2286
+ runtime.wait(),
2287
+ backgroundFailed.then((error) => {
2288
+ throw error;
2289
+ })
2290
+ ]);
1891
2291
  await cancelling;
1892
2292
  const final = result.tasks.find((task) => task.id === manifest.plan.resultTaskId);
1893
2293
  if (final?.output?.text) write(`
@@ -1900,9 +2300,11 @@ Team ${complete ? "completed" : "stopped with unfinished or failed tasks"}.
1900
2300
  for (const task of result.tasks) write(` ${task.id}: ${task.status}
1901
2301
  `);
1902
2302
  const acceptance = await summarizeAcceptance(directory, result, manifest, workspaces, verification);
1903
- write(`Acceptance: ${acceptance.status}. Completion is not a correctness guarantee.
2303
+ write(
2304
+ `Acceptance: ${acceptance.status}. Completion is not a correctness guarantee.
1904
2305
  Shared budget: ${JSON.stringify(await ledger.totals())}
1905
- `);
2306
+ `
2307
+ );
1906
2308
  for (const ref of await artifacts.snapshot()) write(`Artifact [${ref.ownerTaskId}]: ${JSON.stringify(ref)}
1907
2309
  `);
1908
2310
  if (!complete) write(`Inspect: team status ${id}; use explicit reconciliation/retry controls before resume.
@@ -1912,10 +2314,23 @@ Shared budget: ${JSON.stringify(await ledger.totals())}
1912
2314
  if (timer) clearInterval(timer);
1913
2315
  dependencies.signal?.removeEventListener("abort", cancel);
1914
2316
  try {
1915
- await runtime?.close();
1916
- await relay;
2317
+ const results = await Promise.allSettled([...runtime ? [runtime.close()] : [], ...relay ? [relay] : []]);
2318
+ while (backgroundTasks.size) await Promise.all(backgroundTasks);
2319
+ const failures = [
2320
+ .../* @__PURE__ */ new Set([
2321
+ ...backgroundErrors,
2322
+ ...results.flatMap((result) => result.status === "rejected" ? [result.reason] : [])
2323
+ ])
2324
+ ];
2325
+ if (failures.length) throw new AggregateError(failures, "Team background operations failed");
1917
2326
  } finally {
1918
- await Promise.all([verification?.close(), workspaces?.close(), artifacts?.close(), ledger.close()]);
2327
+ await Promise.all([
2328
+ verification?.close(),
2329
+ workspaces?.close(),
2330
+ artifacts?.close(),
2331
+ ledger.close(),
2332
+ executionEnvironments.close()
2333
+ ]);
1919
2334
  }
1920
2335
  }
1921
2336
  }
@@ -1936,15 +2351,26 @@ function executionOf(state, taskId) {
1936
2351
  __name(executionOf, "executionOf");
1937
2352
  async function summarizeAcceptance(directory, state, manifest, workspaces, verification) {
1938
2353
  const tasks = {};
1939
- for (const task of state.tasks) if (task.status === "completed") {
1940
- const workspace = await workspaces.prepare(task.id);
1941
- const { report: _report, ...acceptance } = await verification.acceptance(task.id, workspace.directory, executionOf(state, task.id));
1942
- tasks[task.id] = acceptance;
1943
- }
2354
+ for (const task of state.tasks)
2355
+ if (task.status === "completed") {
2356
+ const workspace = await workspaces.prepare(task.id);
2357
+ const { report: _report, ...acceptance } = await verification.acceptance(
2358
+ task.id,
2359
+ workspace.directory,
2360
+ executionOf(state, task.id)
2361
+ );
2362
+ tasks[task.id] = acceptance;
2363
+ }
1944
2364
  const required = [...new Set(manifest.plan.checks.map((check) => check.taskId))];
1945
2365
  const failed = Object.values(tasks).some((task) => task.status === "failed");
1946
2366
  const status = failed ? "failed" : required.length && state.tasks.every((task) => task.status === "completed") && required.every((id) => tasks[id]?.status === "passed") ? "passed" : "unverified";
1947
- const result = { format: 1, revision: state.revision, status, tasks, note: "Scoped configured checks only, not proof of every natural-language claim. Verify rechecks exact workspace fingerprints." };
2367
+ const result = {
2368
+ format: 1,
2369
+ revision: state.revision,
2370
+ status,
2371
+ tasks,
2372
+ note: "Scoped configured checks only, not proof of every natural-language claim. Verify rechecks exact workspace fingerprints."
2373
+ };
1948
2374
  await writeJson(join4(directory, "acceptance.json"), result);
1949
2375
  return result;
1950
2376
  }
@@ -1972,29 +2398,33 @@ async function readManifest(directory, id) {
1972
2398
  }
1973
2399
  __name(readManifest, "readManifest");
1974
2400
  function validateManifest(value, id) {
1975
- if (!value || value.format !== 1 || value.version !== VERSION || value.id !== id || !isAbsolute3(value.workspace) || !isAbsolute3(value.configPath) || typeof value.prompt !== "string" || typeof value.model !== "string" || !["coding", "read-only"].includes(value.mode) || typeof value.allowChecks !== "boolean") throw new Error("Invalid v2 team manifest");
2401
+ if (!value || value.format !== 1 || value.version !== VERSION || value.id !== id || !isAbsolute3(value.workspace) || !isAbsolute3(value.configPath) || typeof value.prompt !== "string" || typeof value.model !== "string" || !["coding", "read-only"].includes(value.mode) || typeof value.allowChecks !== "boolean")
2402
+ throw new Error("Invalid v2 team manifest");
1976
2403
  parseTeamPlan(value.plan, { mode: value.mode });
1977
- if (![value.maxModelCalls, value.maxTotalTokens, value.maxConcurrent].every((n) => Number.isSafeInteger(n) && n > 0) || value.maxModelCalls > 1e4 || value.maxConcurrent > 8 || value.maxTotalTokens < RESERVATION) throw new Error("Invalid team limits; token budget must hold at least 32768 tokens");
1978
- if (!value.roleModels || Object.keys(value.roleModels).length !== Object.keys(value.plan.roles).length) throw new Error("Invalid role model bindings");
2404
+ if (![value.maxModelCalls, value.maxTotalTokens, value.maxConcurrent].every((n) => Number.isSafeInteger(n) && n > 0) || value.maxModelCalls > 1e4 || value.maxConcurrent > 8 || value.maxTotalTokens < RESERVATION)
2405
+ throw new Error("Invalid team limits; token budget must hold at least 32768 tokens");
2406
+ if (!value.roleModels || Object.keys(value.roleModels).length !== Object.keys(value.plan.roles).length)
2407
+ throw new Error("Invalid role model bindings");
1979
2408
  for (const name of Object.keys(value.plan.roles)) {
1980
2409
  const model = value.roleModels[name];
1981
- if (!model || typeof model.profile !== "string" || !/^[a-f0-9]{64}$/u.test(model.fingerprint)) throw new Error("Invalid role model binding");
2410
+ if (!model || typeof model.profile !== "string" || !/^[a-f0-9]{64}$/u.test(model.fingerprint))
2411
+ throw new Error("Invalid role model binding");
1982
2412
  resolveRunBudget2(model.runBudget);
1983
2413
  }
1984
2414
  }
1985
2415
  __name(validateManifest, "validateManifest");
1986
2416
  async function writeJson(path, value, exclusive = false) {
2417
+ const contents = `${JSON.stringify(value, null, 2)}
2418
+ `;
1987
2419
  await withFileAccess(path, "exclusive", async () => {
1988
- const target = exclusive ? path : `${path}.${randomUUID2()}.tmp`;
1989
- const file = await open5(target, "wx", 384);
2420
+ if (!exclusive) return (0, import_write_file_atomic.default)(path, contents, { mode: 384 });
2421
+ const file = await open5(path, "wx", 384);
1990
2422
  try {
1991
- await file.writeFile(`${JSON.stringify(value, null, 2)}
1992
- `);
2423
+ await file.writeFile(contents);
1993
2424
  await file.sync();
1994
2425
  } finally {
1995
2426
  await file.close();
1996
2427
  }
1997
- if (!exclusive) await rename2(target, path);
1998
2428
  });
1999
2429
  }
2000
2430
  __name(writeJson, "writeJson");
@@ -2007,7 +2437,7 @@ async function canonicalPotentialPath(path) {
2007
2437
  try {
2008
2438
  return await realpath3(path);
2009
2439
  } catch (error) {
2010
- if (!isMissing2(error)) throw error;
2440
+ if (!hasErrorCode3(error, "ENOENT")) throw error;
2011
2441
  const parent = dirname2(path);
2012
2442
  if (parent === path) throw error;
2013
2443
  return join4(await canonicalPotentialPath(parent), relative3(parent, path));
@@ -2018,11 +2448,7 @@ function safeTerminal(text2) {
2018
2448
  return text2.replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/gu, "");
2019
2449
  }
2020
2450
  __name(safeTerminal, "safeTerminal");
2021
- function isMissing2(error) {
2022
- return !!error && typeof error === "object" && "code" in error && error.code === "ENOENT";
2023
- }
2024
- __name(isMissing2, "isMissing");
2025
2451
  export {
2026
2452
  runTeamV2Command
2027
2453
  };
2028
- //# sourceMappingURL=team-v2-JGBBQ7FR.js.map
2454
+ //# sourceMappingURL=team-v2-YYO2G7DJ.js.map