@fitlab-ai/agent-infra 0.9.9 → 0.9.11

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 (309) hide show
  1. package/README.md +13 -3
  2. package/README.zh-CN.md +13 -3
  3. package/bin/cli.ts +17 -4
  4. package/dist/bin/cli.js +19 -4
  5. package/dist/bin/internal-cli.js +55 -4
  6. package/dist/lib/agent-client.js +0 -1
  7. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +17 -10
  8. package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-context.js +11 -31
  9. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +15 -33
  10. package/dist/lib/agent-clients/adapters/codex-sandbox.js +72 -11
  11. package/dist/lib/agent-clients/adapters/index.js +3 -1
  12. package/dist/lib/agent-clients/adapters/opencode-sandbox.js +0 -4
  13. package/dist/lib/agent-clients/adapters/traecli.js +65 -0
  14. package/dist/lib/agent-clients/config.js +14 -99
  15. package/dist/lib/agent-clients/reconcile.js +1 -11
  16. package/dist/lib/agent-clients/schema.js +5 -4
  17. package/dist/lib/agent-clients/tokens.js +7 -17
  18. package/dist/lib/agent-clients/types.js +2 -1
  19. package/dist/lib/decide.js +14 -30
  20. package/dist/lib/defaults.json +9 -0
  21. package/dist/lib/init.js +2 -2
  22. package/dist/lib/internal/codex-lifecycle.js +2 -2
  23. package/dist/lib/internal/codex-sandbox-controller.js +4 -3
  24. package/dist/lib/internal/release-workflow.js +0 -1
  25. package/dist/lib/internal/sandbox-control.js +2 -2
  26. package/dist/lib/internal/task-finalization.js +19 -9
  27. package/dist/lib/internal/task-ledger.js +8 -2
  28. package/dist/lib/internal/task-lifecycle.js +17 -93
  29. package/dist/lib/internal/task-orchestration.js +30 -216
  30. package/dist/lib/{task/commands/validate.js → internal/task-validate.js} +77 -43
  31. package/dist/lib/merge.js +205 -103
  32. package/dist/lib/process-data/normalize.js +2 -9
  33. package/dist/lib/run/host.js +46 -16
  34. package/dist/lib/run/tui.js +5 -2
  35. package/dist/lib/sandbox/agent-client-reconciler.js +4 -12
  36. package/dist/lib/sandbox/commands/create.js +3 -3
  37. package/dist/lib/sandbox/commands/enter.js +18 -4
  38. package/dist/lib/sandbox/config.js +3 -12
  39. package/dist/lib/sandbox/control/controller-registration.js +4 -2
  40. package/dist/lib/sandbox/control/executor.js +135 -40
  41. package/dist/lib/sandbox/control/lifecycle.js +29 -20
  42. package/dist/lib/sandbox/control/server.js +18 -16
  43. package/dist/lib/sandbox/mounts.js +3 -2
  44. package/dist/lib/sandbox/recovery.js +123 -22
  45. package/dist/lib/sandbox/workspace-identity.js +14 -0
  46. package/dist/lib/sandbox/workspace-view.js +8 -9
  47. package/dist/lib/self-update.js +278 -0
  48. package/dist/lib/server/protocol.js +5 -5
  49. package/dist/lib/task/activity-log.js +4 -1
  50. package/dist/lib/task/artifact-lifecycle.js +4 -2
  51. package/dist/lib/task/codex-orchestration.js +32 -35
  52. package/dist/lib/task/command-options.js +1 -3
  53. package/dist/lib/task/commands/cat.js +0 -5
  54. package/dist/lib/task/commands/decisions.js +76 -92
  55. package/dist/lib/task/commands/files.js +6 -6
  56. package/dist/lib/task/commands/grep.js +25 -61
  57. package/dist/lib/task/commands/issue-body.js +6 -6
  58. package/dist/lib/task/commands/log.js +25 -10
  59. package/dist/lib/task/commands/show.js +5 -6
  60. package/dist/lib/task/commands/status.js +8 -8
  61. package/dist/lib/task/commit-operation.js +21 -25
  62. package/dist/lib/task/commit-policy.js +1 -1
  63. package/dist/lib/task/control-authority.js +431 -0
  64. package/dist/lib/task/create.js +6 -1
  65. package/dist/lib/task/current-contract.js +35 -0
  66. package/dist/lib/task/decision-details.js +263 -0
  67. package/dist/lib/task/decision-intents.js +5 -2
  68. package/dist/lib/task/delegation-receipts.js +8 -7
  69. package/dist/lib/task/events.js +11 -5
  70. package/dist/lib/task/finalization.js +72 -46
  71. package/dist/lib/task/index.js +19 -29
  72. package/dist/lib/task/ledger-intents.js +8 -9
  73. package/dist/lib/task/ledger.js +13 -6
  74. package/dist/lib/task/lifecycle.js +16 -0
  75. package/dist/lib/task/orchestration.js +51 -14
  76. package/dist/lib/task/review-artifacts.js +31 -12
  77. package/dist/lib/task/review-finalization.js +19 -6
  78. package/dist/lib/task/verification-engine.js +38 -18
  79. package/dist/lib/task/verification-review.js +1 -1
  80. package/dist/lib/task/workspace-snapshot.js +5 -11
  81. package/dist/lib/task/write.js +11 -1
  82. package/dist/lib/update.js +6 -37
  83. package/dist/lib/version.js +5 -1
  84. package/dist/lifecycle-build-manifest.json +3 -3
  85. package/lib/agent-client.ts +0 -1
  86. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +25 -10
  87. package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +16 -33
  88. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +16 -35
  89. package/lib/agent-clients/adapters/codex-sandbox.ts +89 -14
  90. package/lib/agent-clients/adapters/index.ts +3 -1
  91. package/lib/agent-clients/adapters/opencode-sandbox.ts +0 -5
  92. package/lib/agent-clients/adapters/traecli.ts +66 -0
  93. package/lib/agent-clients/config.ts +14 -144
  94. package/lib/agent-clients/reconcile.ts +1 -12
  95. package/lib/agent-clients/schema.ts +5 -4
  96. package/lib/agent-clients/tokens.ts +7 -20
  97. package/lib/agent-clients/types.ts +2 -1
  98. package/lib/decide.ts +12 -22
  99. package/lib/defaults.json +9 -0
  100. package/lib/init.ts +2 -2
  101. package/lib/internal/codex-lifecycle.ts +2 -2
  102. package/lib/internal/codex-sandbox-controller.ts +4 -3
  103. package/lib/internal/release-workflow.ts +0 -1
  104. package/lib/internal/sandbox-control.ts +2 -2
  105. package/lib/internal/task-finalization.ts +27 -13
  106. package/lib/internal/task-ledger.ts +8 -2
  107. package/lib/internal/task-lifecycle.ts +33 -76
  108. package/lib/internal/task-orchestration.ts +33 -190
  109. package/lib/{task/commands/validate.ts → internal/task-validate.ts} +77 -41
  110. package/lib/merge.ts +236 -120
  111. package/lib/process-data/normalize.ts +2 -8
  112. package/lib/run/host.ts +63 -14
  113. package/lib/run/tui.ts +5 -3
  114. package/lib/sandbox/agent-client-reconciler.ts +5 -15
  115. package/lib/sandbox/commands/create.ts +4 -4
  116. package/lib/sandbox/commands/enter.ts +24 -4
  117. package/lib/sandbox/config.ts +2 -14
  118. package/lib/sandbox/control/container-identity.ts +2 -2
  119. package/lib/sandbox/control/controller-registration.ts +8 -3
  120. package/lib/sandbox/control/executor.ts +156 -53
  121. package/lib/sandbox/control/lifecycle.ts +34 -28
  122. package/lib/sandbox/control/protocol.ts +1 -3
  123. package/lib/sandbox/control/server.ts +15 -12
  124. package/lib/sandbox/control/state.ts +7 -7
  125. package/lib/sandbox/mounts.ts +4 -3
  126. package/lib/sandbox/recovery.ts +162 -34
  127. package/lib/sandbox/tools.ts +1 -1
  128. package/lib/sandbox/workspace-identity.ts +28 -0
  129. package/lib/sandbox/workspace-view.ts +14 -10
  130. package/lib/self-update.ts +341 -0
  131. package/lib/server/protocol.ts +5 -5
  132. package/lib/task/activity-log.ts +6 -1
  133. package/lib/task/artifact-lifecycle.ts +5 -3
  134. package/lib/task/codex-orchestration.ts +40 -45
  135. package/lib/task/command-options.ts +1 -2
  136. package/lib/task/commands/cat.ts +0 -4
  137. package/lib/task/commands/decisions.ts +80 -75
  138. package/lib/task/commands/files.ts +6 -6
  139. package/lib/task/commands/grep.ts +23 -51
  140. package/lib/task/commands/issue-body.ts +6 -6
  141. package/lib/task/commands/log.ts +22 -10
  142. package/lib/task/commands/show.ts +5 -6
  143. package/lib/task/commands/status.ts +8 -8
  144. package/lib/task/commit-operation.ts +25 -30
  145. package/lib/task/commit-policy.ts +1 -2
  146. package/lib/task/control-authority.ts +563 -0
  147. package/lib/task/create.ts +6 -1
  148. package/lib/task/current-contract.ts +49 -0
  149. package/lib/task/decision-details.ts +340 -0
  150. package/lib/task/decision-intents.ts +7 -2
  151. package/lib/task/delegation-receipts.ts +8 -6
  152. package/lib/task/events.ts +10 -5
  153. package/lib/task/finalization.ts +84 -42
  154. package/lib/task/index.ts +19 -28
  155. package/lib/task/ledger-intents.ts +6 -8
  156. package/lib/task/ledger.ts +17 -7
  157. package/lib/task/lifecycle.ts +20 -0
  158. package/lib/task/orchestration.ts +42 -16
  159. package/lib/task/review-artifacts.ts +53 -15
  160. package/lib/task/review-finalization.ts +33 -7
  161. package/lib/task/verification-engine.ts +33 -21
  162. package/lib/task/verification-review.ts +1 -1
  163. package/lib/task/workspace-snapshot.ts +4 -13
  164. package/lib/task/write.ts +20 -1
  165. package/lib/update.ts +6 -40
  166. package/lib/version.ts +6 -1
  167. package/package.json +1 -1
  168. package/templates/.agents/QUICKSTART.en.md +2 -3
  169. package/templates/.agents/QUICKSTART.zh-CN.md +2 -3
  170. package/templates/.agents/README.en.md +5 -3
  171. package/templates/.agents/README.zh-CN.md +5 -3
  172. package/templates/.agents/rules/README.en.md +1 -0
  173. package/templates/.agents/rules/README.zh-CN.md +1 -0
  174. package/templates/.agents/rules/compatibility-policy.en.md +40 -0
  175. package/templates/.agents/rules/compatibility-policy.zh-CN.md +40 -0
  176. package/templates/.agents/rules/create-issue.github.en.md +1 -1
  177. package/templates/.agents/rules/create-issue.github.zh-CN.md +1 -1
  178. package/templates/.agents/rules/human-decision-context.en.md +9 -7
  179. package/templates/.agents/rules/human-decision-context.zh-CN.md +9 -7
  180. package/templates/.agents/rules/issue-fields.github.en.md +1 -1
  181. package/templates/.agents/rules/issue-fields.github.zh-CN.md +1 -1
  182. package/templates/.agents/rules/issue-pr-commands.en.md +1 -1
  183. package/templates/.agents/rules/issue-pr-commands.github.en.md +1 -1
  184. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +1 -1
  185. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
  186. package/templates/.agents/rules/issue-sync.github.en.md +1 -1
  187. package/templates/.agents/rules/issue-sync.github.zh-CN.md +2 -2
  188. package/templates/.agents/rules/lifecycle-orchestration.en.md +4 -4
  189. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +4 -4
  190. package/templates/.agents/rules/milestone-inference.github.en.md +1 -1
  191. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +1 -1
  192. package/templates/.agents/rules/next-step-output.en.md +3 -3
  193. package/templates/.agents/rules/next-step-output.zh-CN.md +3 -3
  194. package/templates/.agents/rules/no-mid-flow-questions.en.md +1 -1
  195. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +1 -1
  196. package/templates/.agents/rules/pr-sync.en.md +2 -2
  197. package/templates/.agents/rules/pr-sync.github.en.md +3 -2
  198. package/templates/.agents/rules/pr-sync.github.zh-CN.md +3 -1
  199. package/templates/.agents/rules/pr-sync.zh-CN.md +2 -1
  200. package/templates/.agents/rules/release-commands.github.en.md +6 -0
  201. package/templates/.agents/rules/release-commands.github.zh-CN.md +6 -0
  202. package/templates/.agents/rules/review-handshake.en.md +1 -1
  203. package/templates/.agents/rules/review-handshake.zh-CN.md +1 -1
  204. package/templates/.agents/rules/review-method.en.md +1 -0
  205. package/templates/.agents/rules/review-method.zh-CN.md +1 -0
  206. package/templates/.agents/rules/task-management.en.md +1 -2
  207. package/templates/.agents/rules/task-management.zh-CN.md +1 -2
  208. package/templates/.agents/skills/analyze-task/SKILL.en.md +4 -3
  209. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +4 -3
  210. package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
  211. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
  212. package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
  213. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
  214. package/templates/.agents/skills/check-task/SKILL.en.md +2 -2
  215. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +2 -2
  216. package/templates/.agents/skills/close-codescan/SKILL.en.md +1 -1
  217. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +1 -1
  218. package/templates/.agents/skills/close-dependabot/SKILL.en.md +1 -1
  219. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +1 -1
  220. package/templates/.agents/skills/code-task/SKILL.en.md +4 -3
  221. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +5 -3
  222. package/templates/.agents/skills/commit/SKILL.en.md +27 -7
  223. package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -4
  224. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +5 -5
  225. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +5 -5
  226. package/templates/.agents/skills/complete-task/SKILL.en.md +3 -3
  227. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
  228. package/templates/.agents/skills/create-pr/SKILL.en.md +15 -11
  229. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +15 -11
  230. package/templates/.agents/skills/create-pr/reference/change-report.en.md +46 -0
  231. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +46 -0
  232. package/templates/.agents/skills/create-pr/scripts/change-report.mjs +203 -0
  233. package/templates/.agents/skills/create-release-note/SKILL.en.md +5 -6
  234. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +5 -6
  235. package/templates/.agents/skills/create-task/SKILL.en.md +1 -1
  236. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -1
  237. package/templates/.agents/skills/import-issue/SKILL.en.md +1 -1
  238. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +1 -1
  239. package/templates/.agents/skills/plan-task/SKILL.en.md +5 -4
  240. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +5 -4
  241. package/templates/.agents/skills/restore-task/SKILL.en.md +1 -1
  242. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +1 -1
  243. package/templates/.agents/skills/review-analysis/SKILL.en.md +5 -3
  244. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +5 -3
  245. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -0
  246. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -0
  247. package/templates/.agents/skills/review-code/SKILL.en.md +5 -3
  248. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -3
  249. package/templates/.agents/skills/review-code/config/verify.en.json +1 -0
  250. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -0
  251. package/templates/.agents/skills/review-code/reference/migration-risks.en.md +9 -6
  252. package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +9 -6
  253. package/templates/.agents/skills/review-plan/SKILL.en.md +5 -3
  254. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +5 -3
  255. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -0
  256. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -0
  257. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +7 -3
  258. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +7 -3
  259. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +1 -1
  260. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +1 -1
  261. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -2
  262. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -2
  263. package/templates/.agents/skills/run-task/SKILL.en.md +6 -2
  264. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +6 -2
  265. package/templates/.agents/skills/run-task/reference/host-validation.en.md +2 -2
  266. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +2 -2
  267. package/templates/.agents/skills/update-agent-infra/SKILL.en.md +2 -2
  268. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +2 -2
  269. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +159 -104
  270. package/templates/.agents/skills/watch-pr/SKILL.en.md +2 -2
  271. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +2 -2
  272. package/templates/.agents/templates/task.en.md +1 -1
  273. package/templates/.agents/templates/task.zh-CN.md +1 -1
  274. package/templates/.claude/commands/analyze-task.en.md +1 -1
  275. package/templates/.claude/commands/analyze-task.zh-CN.md +1 -1
  276. package/templates/.claude/commands/block-task.en.md +1 -1
  277. package/templates/.claude/commands/block-task.zh-CN.md +1 -1
  278. package/templates/.claude/commands/cancel-task.en.md +1 -1
  279. package/templates/.claude/commands/cancel-task.zh-CN.md +1 -1
  280. package/templates/.claude/commands/check-task.en.md +1 -1
  281. package/templates/.claude/commands/check-task.zh-CN.md +1 -1
  282. package/templates/.claude/commands/code-task.en.md +1 -1
  283. package/templates/.claude/commands/code-task.zh-CN.md +1 -1
  284. package/templates/.claude/commands/commit.en.md +1 -1
  285. package/templates/.claude/commands/commit.zh-CN.md +1 -1
  286. package/templates/.claude/commands/complete-manual-validation.en.md +1 -1
  287. package/templates/.claude/commands/complete-manual-validation.zh-CN.md +1 -1
  288. package/templates/.claude/commands/complete-task.en.md +1 -1
  289. package/templates/.claude/commands/complete-task.zh-CN.md +1 -1
  290. package/templates/.claude/commands/create-pr.en.md +1 -1
  291. package/templates/.claude/commands/create-pr.zh-CN.md +1 -1
  292. package/templates/.claude/commands/plan-task.en.md +1 -1
  293. package/templates/.claude/commands/plan-task.zh-CN.md +1 -1
  294. package/templates/.claude/commands/review-analysis.en.md +1 -1
  295. package/templates/.claude/commands/review-analysis.zh-CN.md +1 -1
  296. package/templates/.claude/commands/review-code.en.md +1 -1
  297. package/templates/.claude/commands/review-code.zh-CN.md +1 -1
  298. package/templates/.claude/commands/review-plan.en.md +1 -1
  299. package/templates/.claude/commands/review-plan.zh-CN.md +1 -1
  300. package/templates/.claude/commands/run-manual-validation.en.md +1 -1
  301. package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
  302. package/templates/.claude/commands/run-task.en.md +1 -1
  303. package/templates/.claude/commands/run-task.zh-CN.md +1 -1
  304. package/templates/.claude/commands/watch-pr.en.md +1 -1
  305. package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
  306. package/templates/.traecli/commands/update-agent-infra.en.md +7 -0
  307. package/templates/.traecli/commands/update-agent-infra.zh-CN.md +7 -0
  308. package/dist/lib/builtin-tuis.js +0 -40
  309. package/lib/builtin-tuis.ts +0 -56
@@ -126,10 +126,12 @@ function defaultProbe(manifest, identity) {
126
126
  function assertRegistrationBinding(registration, manifest, buildIdentity) {
127
127
  if (registration.taskId !== manifest.taskId
128
128
  || registration.controlGeneration !== manifest.generation
129
- || registration.containerId !== manifest.containerIdentity.id
130
- || JSON.stringify(registration.buildIdentity) !== JSON.stringify(buildIdentity)) {
129
+ || registration.containerId !== manifest.containerIdentity.id) {
131
130
  fail('CODEX_SANDBOX_CONTROLLER_REGISTRATION_INVALID', 'controller registration binding is invalid');
132
131
  }
132
+ if (registration.buildIdentity.protocolVersion !== buildIdentity.protocolVersion) {
133
+ fail('CODEX_LIFECYCLE_PROTOCOL_MISMATCH', 'Codex lifecycle protocol version does not match');
134
+ }
133
135
  }
134
136
  function atomicWrite(file, value) {
135
137
  const temporary = path.join(path.dirname(file), `.${path.basename(file)}.${process.pid}.${crypto.randomUUID()}.tmp`);
@@ -1,15 +1,32 @@
1
- import { spawn, spawnSync } from 'node:child_process';
1
+ import { spawn } from 'node:child_process';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { randomUUID } from 'node:crypto';
5
5
  import { getProcessStartTime } from '../../server/process-state.js';
6
6
  import { createTask } from '../../task/create-service.js';
7
7
  import { applyTaskFinalization } from '../../task/finalization.js';
8
- import { verifyTaskEvent } from '../../task/verification.js';
9
- import { bindSandboxControlTask } from './protocol.js';
10
- import { atomicWriteJson, executionPath, terminateSandboxControlExecution } from './state.js';
8
+ import { bindSandboxControlTask, validateSandboxControlRequest } from './protocol.js';
9
+ import { atomicWriteJson, executionPath, readActiveLease, terminateSandboxControlExecution } from './state.js';
10
+ import { createSandboxExecutorExecutionContext, dispatchTaskControlOperation, parseTaskControlOperation } from '../../task/control-authority.js';
11
+ import { assertSandboxControlBrokerOwner, readSandboxControlManifest } from './lifecycle.js';
11
12
  import { computeLifecycleBuildIdentity } from '../../agent-clients/adapters/codex-lifecycle/build-identity.js';
12
13
  import { closeCodexControllerRegistration, CodexControllerRegistrationError, openCodexControllerRegistration, resolveCodexControllerBinding } from './controller-registration.js';
14
+ function sameBrokerOwner(left, right) {
15
+ return left.version === right.version
16
+ && left.pid === right.pid
17
+ && left.startTime === right.startTime
18
+ && left.brokerId === right.brokerId
19
+ && left.token === right.token
20
+ && left.generation === right.generation;
21
+ }
22
+ export function assertSandboxControlExecutorAuthority(manifest, gateOwner) {
23
+ const owner = assertSandboxControlBrokerOwner(manifest);
24
+ if (gateOwner && !sameBrokerOwner(owner, gateOwner)) {
25
+ throw new Error('SANDBOX_CONTROL_GATE_OWNER_MISMATCH');
26
+ }
27
+ if (readActiveLease(manifest))
28
+ throw new Error('SANDBOX_CONTROL_HANDOFF_ACTIVE');
29
+ }
13
30
  function safeEnv(env) {
14
31
  return Object.fromEntries(Object.entries(env).filter(([key]) => !key.toUpperCase().startsWith('AGENT_INFRA_CONTROL_')));
15
32
  }
@@ -74,12 +91,15 @@ export async function prepareSandboxControlExecution(params) {
74
91
  start(canWrite = () => true) {
75
92
  if (!child.connected)
76
93
  throw new Error('SANDBOX_CONTROL_EXECUTOR_GATE_CLOSED');
94
+ if (!canWrite())
95
+ throw new Error('SANDBOX_CONTROL_OWNER_LOST');
96
+ const gateOwner = assertSandboxControlBrokerOwner(params.manifest);
77
97
  if (!canWrite())
78
98
  throw new Error('SANDBOX_CONTROL_OWNER_LOST');
79
99
  atomicWriteJson(executionPath(params.manifest, params.request.id), { ...execution, phase: 'running', updatedAt: Date.now() });
80
100
  if (!canWrite())
81
101
  throw new Error('SANDBOX_CONTROL_OWNER_LOST');
82
- child.send({ version: 1, nonce });
102
+ child.send({ version: 1, nonce, owner: gateOwner });
83
103
  },
84
104
  completion,
85
105
  terminate(updateState = true) {
@@ -104,11 +124,16 @@ function waitForGate(nonce, timeoutMs = 2_000) {
104
124
  clearTimeout(timer);
105
125
  process.off('disconnect', onDisconnect);
106
126
  const value = message;
107
- if (!value || value.version !== 1 || value.nonce !== nonce) {
127
+ const owner = value?.owner;
128
+ if (!value || value.version !== 1 || value.nonce !== nonce
129
+ || !owner || owner.version !== 3 || !Number.isSafeInteger(owner.pid) || (owner.pid ?? 0) <= 0
130
+ || typeof owner.startTime !== 'number' || !Number.isSafeInteger(owner.startTime)
131
+ || typeof owner.brokerId !== 'string' || owner.brokerId.length === 0
132
+ || typeof owner.token !== 'string' || typeof owner.generation !== 'string') {
108
133
  reject(new Error('SANDBOX_CONTROL_EXECUTOR_GATE_INVALID'));
109
134
  return;
110
135
  }
111
- resolve();
136
+ resolve(owner);
112
137
  });
113
138
  });
114
139
  }
@@ -117,12 +142,15 @@ function controllerFailure(error) {
117
142
  ? error.code
118
143
  : /^([A-Z][A-Z0-9_]+)/u.exec(error instanceof Error ? error.message : String(error))?.[1]
119
144
  ?? 'CODEX_SANDBOX_CONTROLLER_FAILED';
145
+ const message = error instanceof CodexControllerRegistrationError
146
+ ? error.message
147
+ : `${code}: controller operation failed; inspect the sandbox controller and rebuild the sandbox if needed`;
120
148
  const payload = {
121
149
  version: 1,
122
150
  status: 'failed',
123
151
  changed: false,
124
152
  lease: null,
125
- error: { code, message: `${code}: controller request failed`, retryable: false }
153
+ error: { code, message, retryable: false }
126
154
  };
127
155
  return { exitCode: 1, stdout: `${JSON.stringify(payload)}\n`, stderr: '' };
128
156
  }
@@ -136,6 +164,16 @@ function orchestrationFailure(code, message) {
136
164
  stderr: ''
137
165
  };
138
166
  }
167
+ function lifecycleFailure(code, message) {
168
+ return {
169
+ exitCode: 1,
170
+ stdout: `${JSON.stringify({
171
+ status: 'failed', changed: false,
172
+ error: { code, message }
173
+ })}\n`,
174
+ stderr: ''
175
+ };
176
+ }
139
177
  function finalizationResult(result) {
140
178
  const payload = {
141
179
  version: 1,
@@ -151,19 +189,7 @@ function finalizationResult(result) {
151
189
  stderr: ''
152
190
  };
153
191
  }
154
- function isCodexPrepare(args) {
155
- if (args[1] !== 'prepare')
156
- return false;
157
- const values = [];
158
- for (let index = 2; index < args.length; index += 1) {
159
- if (args[index] === '--client')
160
- values.push(args[index + 1] ?? '');
161
- else if (args[index]?.startsWith('--client='))
162
- values.push(args[index].slice('--client='.length));
163
- }
164
- return values.length === 1 && values[0] === 'codex';
165
- }
166
- export function executeRequest(manifest, manifestPath, request, options = {}) {
192
+ export async function executeRequest(manifest, manifestPath, request, options = {}) {
167
193
  if (request.family === 'task-create') {
168
194
  const result = createTask(request.candidate, { repoRoot: manifest.repoRoot });
169
195
  return {
@@ -217,12 +243,41 @@ export function executeRequest(manifest, manifestPath, request, options = {}) {
217
243
  }
218
244
  }
219
245
  if (request.family === 'task-finalization') {
220
- return finalizationResult(applyTaskFinalization({ taskRef: manifest.taskId, intent: 'complete', agent: request.agent }, { repoRoot: manifest.repoRoot, preflight: (input, options) => verifyTaskEvent({ ...input, event: 'complete-task.hard-preflight' }, options) }));
246
+ const operation = parseTaskControlOperation('task-finalization', [manifest.taskId, 'complete', '--agent', request.agent]);
247
+ if (operation.family !== 'task-finalization')
248
+ throw new Error('SANDBOX_CONTROL_FINALIZATION_OPERATION_INVALID');
249
+ const result = dispatchTaskControlOperation(createSandboxExecutorExecutionContext({
250
+ repoRoot: manifest.repoRoot,
251
+ worktreeRoot: manifest.worktreeRoot,
252
+ runtimeDir: manifest.runtimeDir,
253
+ taskId: manifest.taskId,
254
+ generation: manifest.generation,
255
+ manifestPath,
256
+ requestId: request.id
257
+ }), operation);
258
+ return finalizationResult(result);
221
259
  }
222
260
  const boundArgs = bindSandboxControlTask(request, manifest.taskId);
261
+ if (request.family === 'task-orchestration') {
262
+ boundArgs.push('--git-worktree-root', manifest.worktreeRoot);
263
+ }
264
+ let operation;
265
+ try {
266
+ operation = parseTaskControlOperation(request.family, boundArgs);
267
+ }
268
+ catch (error) {
269
+ const message = error instanceof Error ? error.message : String(error);
270
+ const code = /^([A-Z][A-Z0-9_]+)/u.exec(message)?.[1] ?? 'TASK_CONTROL_OPERATION_INVALID';
271
+ return request.family === 'task-lifecycle'
272
+ ? lifecycleFailure('LIFECYCLE_PAYLOAD_INVALID', message)
273
+ : orchestrationFailure(code, message);
274
+ }
223
275
  let controllerBinding = null;
224
276
  if (request.family === 'task-orchestration') {
225
- if (isCodexPrepare(request.args)) {
277
+ const codexPrepare = operation.family === 'task-orchestration'
278
+ && operation.intent === 'prepare'
279
+ && operation.input.client === 'codex';
280
+ if (codexPrepare) {
226
281
  if (!request.controllerProof) {
227
282
  return orchestrationFailure('CODEX_SANDBOX_CONTROLLER_PROOF_REQUIRED', 'Codex prepare requires a current controller lease proof');
228
283
  }
@@ -244,33 +299,73 @@ export function executeRequest(manifest, manifestPath, request, options = {}) {
244
299
  else if (request.controllerProof !== null) {
245
300
  return orchestrationFailure('CODEX_SANDBOX_CONTROLLER_PROOF_INVALID', 'Controller proof is only accepted for canonical Codex prepare');
246
301
  }
247
- boundArgs.push('--git-worktree-root', manifest.worktreeRoot);
248
302
  }
249
- const result = (options.spawnDomain ?? spawnSync)(process.execPath, nodeEntryArgs(process.argv[1], [request.family, ...boundArgs]), {
250
- cwd: manifest.repoRoot,
251
- encoding: 'utf8',
252
- env: {
253
- ...safeEnv(process.env),
254
- AGENT_INFRA_RUNTIME_DIR: manifest.runtimeDir,
255
- ...(controllerBinding
256
- ? { AGENT_INFRA_CONTROL_CONTROLLER_BINDING: JSON.stringify(controllerBinding) }
257
- : {})
258
- }
303
+ const context = createSandboxExecutorExecutionContext({
304
+ repoRoot: manifest.repoRoot,
305
+ worktreeRoot: manifest.worktreeRoot,
306
+ runtimeDir: manifest.runtimeDir,
307
+ taskId: manifest.taskId,
308
+ generation: manifest.generation,
309
+ manifestPath,
310
+ requestId: request.id,
311
+ ...(controllerBinding ? { controllerBinding } : {})
259
312
  });
260
- return { exitCode: result.status ?? 1, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };
313
+ const format = (value) => {
314
+ const result = value;
315
+ return {
316
+ exitCode: result.status === 'failed' ? 1 : 0,
317
+ stdout: `${JSON.stringify(value)}\n`,
318
+ stderr: ''
319
+ };
320
+ };
321
+ if (request.family === 'task-orchestration') {
322
+ if (operation.family !== 'task-orchestration')
323
+ throw new Error('SANDBOX_CONTROL_ORCHESTRATION_OPERATION_INVALID');
324
+ return format(await dispatchTaskControlOperation(context, operation));
325
+ }
326
+ if (operation.family !== 'task-lifecycle')
327
+ throw new Error('SANDBOX_CONTROL_LIFECYCLE_OPERATION_INVALID');
328
+ return format(dispatchTaskControlOperation(context, operation));
261
329
  }
262
330
  export async function runSandboxControlExecutor(requestPath, nonce) {
263
- await waitForGate(nonce);
331
+ const gateOwner = await waitForGate(nonce);
264
332
  process.disconnect?.();
265
- const root = fs.realpathSync.native(process.cwd());
266
- const request = JSON.parse(fs.readFileSync(requestPath, 'utf8'));
267
333
  const manifestPath = process.env.AGENT_INFRA_EXECUTOR_MANIFEST;
268
334
  if (!manifestPath)
269
335
  throw new Error('SANDBOX_CONTROL_EXECUTOR_MANIFEST_MISSING');
270
- const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
336
+ const manifest = readSandboxControlManifest(manifestPath);
337
+ const root = fs.realpathSync.native(process.cwd());
271
338
  if (fs.realpathSync.native(manifest.repoRoot) !== root)
272
339
  throw new Error('SANDBOX_CONTROL_EXECUTOR_ROOT_INVALID');
273
- const result = executeRequest(manifest, manifestPath, request);
340
+ const raw = JSON.parse(fs.readFileSync(requestPath, 'utf8'));
341
+ const request = validateSandboxControlRequest(raw, manifest);
342
+ const requestDirectory = path.resolve(path.dirname(requestPath));
343
+ const processingDirectory = path.resolve(path.join(manifest.processingDir, request.id));
344
+ const channelRequestDirectory = path.resolve(path.join(manifest.channelDir, 'requests'));
345
+ if (requestDirectory !== processingDirectory && requestDirectory !== channelRequestDirectory) {
346
+ throw new Error('SANDBOX_CONTROL_EXECUTOR_REQUEST_INVALID');
347
+ }
348
+ let result;
349
+ try {
350
+ assertSandboxControlExecutorAuthority(manifest, gateOwner);
351
+ result = await executeRequest(manifest, manifestPath, request);
352
+ }
353
+ catch (error) {
354
+ const detail = error instanceof Error ? error.message : String(error);
355
+ const code = /^([A-Z][A-Z0-9_]+)/u.exec(detail)?.[1] ?? 'SANDBOX_CONTROL_EXECUTOR_FAILED';
356
+ result = request.family === 'task-finalization'
357
+ ? {
358
+ exitCode: 1,
359
+ stdout: `${JSON.stringify({
360
+ version: 1, status: 'failed', changed: false, accepted: true, result: null,
361
+ error: { code, message: detail, retryable: false }
362
+ })}\n`,
363
+ stderr: ''
364
+ }
365
+ : request.family === 'task-lifecycle'
366
+ ? lifecycleFailure(code, detail)
367
+ : orchestrationFailure(code, detail);
368
+ }
274
369
  process.stdout.write(result.stdout);
275
370
  process.stderr.write(result.stderr);
276
371
  process.exitCode = result.exitCode;
@@ -414,8 +414,6 @@ function readProcessingSnapshot(root) {
414
414
  export function captureSandboxControlCutoverSnapshot(root) {
415
415
  const resolvedRoot = path.resolve(root);
416
416
  const manifestPath = path.join(resolvedRoot, 'manifest.json');
417
- if (fs.existsSync(manifestPath))
418
- readSandboxControlManifestForTransition(manifestPath);
419
417
  return {
420
418
  root: resolvedRoot,
421
419
  manifestRaw: readOptionalRaw(manifestPath),
@@ -430,7 +428,7 @@ export function assertSandboxControlCutoverSnapshot(snapshot) {
430
428
  throw new Error('SANDBOX_CONTROL_OWNER_TRANSITION');
431
429
  }
432
430
  }
433
- function readSandboxControlManifestValue(manifestPath, allowLegacy) {
431
+ function readSandboxControlManifestValue(manifestPath) {
434
432
  if (!regularFile(manifestPath))
435
433
  throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
436
434
  let manifest;
@@ -445,8 +443,14 @@ function readSandboxControlManifestValue(manifestPath, allowLegacy) {
445
443
  throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
446
444
  }
447
445
  const candidate = manifest;
448
- if (candidate.version !== 4 && candidate.version !== 5) {
449
- throw new Error('SANDBOX_CONTROL_MANIFEST_VERSION_INVALID: expected version 5; container-only recreation is required');
446
+ const expectedKeys = [
447
+ 'branch', 'channelDir', 'container', 'containerIdentity', 'engine', 'generation',
448
+ 'mode', 'processingDir', 'project', 'publicStatusDir', 'repoRoot', 'runtimeDir',
449
+ 'taskId', 'token', 'worktreeRoot'
450
+ ];
451
+ if ('version' in candidate || typeof candidate.runtimeDir !== 'string'
452
+ || Object.keys(manifest).sort().join(',') !== expectedKeys.sort().join(',')) {
453
+ throw new Error('SANDBOX_CONTROL_MANIFEST_REBUILD_REQUIRED: container-only recreation/rebuild is required');
450
454
  }
451
455
  if (typeof candidate.containerIdentity !== 'object' || candidate.containerIdentity === null
452
456
  || Array.isArray(candidate.containerIdentity))
@@ -463,7 +467,9 @@ function readSandboxControlManifestValue(manifestPath, allowLegacy) {
463
467
  || (candidate.taskId !== null && typeof candidate.taskId !== 'string')
464
468
  || typeof candidate.channelDir !== 'string' || typeof candidate.publicStatusDir !== 'string'
465
469
  || typeof candidate.processingDir !== 'string' || typeof candidate.token !== 'string'
466
- || typeof candidate.generation !== 'string')
470
+ || typeof candidate.generation !== 'string'
471
+ || (candidate.mode === 'task-bound' && (typeof candidate.taskId !== 'string' || candidate.taskId.length === 0))
472
+ || (candidate.mode === 'branch-only' && candidate.taskId !== null))
467
473
  throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
468
474
  const root = path.dirname(path.resolve(manifestPath));
469
475
  if (path.resolve(candidate.channelDir) !== path.join(root, 'channel')
@@ -471,22 +477,13 @@ function readSandboxControlManifestValue(manifestPath, allowLegacy) {
471
477
  || path.resolve(candidate.processingDir) !== path.join(root, 'processing')) {
472
478
  throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
473
479
  }
474
- if (candidate.version === 4) {
475
- if (!allowLegacy) {
476
- throw new Error('SANDBOX_CONTROL_MANIFEST_VERSION_INVALID: expected version 5; container-only recreation is required');
477
- }
478
- return candidate;
479
- }
480
- if (typeof candidate.runtimeDir !== 'string' || path.resolve(candidate.runtimeDir) !== path.join(root, 'runtime')) {
480
+ if (path.resolve(candidate.runtimeDir) !== path.join(root, 'runtime')) {
481
481
  throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
482
482
  }
483
483
  return candidate;
484
484
  }
485
485
  export function readSandboxControlManifest(manifestPath) {
486
- return readSandboxControlManifestValue(manifestPath, false);
487
- }
488
- export function readSandboxControlManifestForTransition(manifestPath) {
489
- return readSandboxControlManifestValue(manifestPath, true);
486
+ return readSandboxControlManifestValue(manifestPath);
490
487
  }
491
488
  function readBrokerOwner(filePath) {
492
489
  if (!fs.existsSync(filePath))
@@ -507,6 +504,18 @@ function readBrokerOwner(filePath) {
507
504
  throw new Error('SANDBOX_CONTROL_OWNER_MISMATCH');
508
505
  return owner;
509
506
  }
507
+ export function assertSandboxControlBrokerOwner(manifest, options = {}) {
508
+ const root = path.dirname(path.resolve(manifest.publicStatusDir));
509
+ const owner = readBrokerOwner(path.join(root, 'broker.json'));
510
+ if (!owner)
511
+ throw new Error('SANDBOX_CONTROL_OWNER_EVIDENCE_MISSING');
512
+ if (owner.token !== manifest.token || owner.generation !== manifest.generation) {
513
+ throw new Error('SANDBOX_CONTROL_OWNER_MISMATCH');
514
+ }
515
+ if (!ownerLive(owner, options.identityProbe))
516
+ throw new Error('SANDBOX_CONTROL_OWNER_LOST');
517
+ return owner;
518
+ }
510
519
  function readStatusOwner(filePath) {
511
520
  if (!fs.existsSync(filePath))
512
521
  return null;
@@ -641,7 +650,7 @@ export async function quiesceSandboxControlRoot(root, options = {}) {
641
650
  markSandboxControlRootQuiescing(resolvedRoot);
642
651
  await waitForStartupTransition(resolvedRoot, Math.max(0, forceAt - Date.now()), identityProbe);
643
652
  const manifestPath = path.join(resolvedRoot, 'manifest.json');
644
- const manifest = fs.existsSync(manifestPath) ? readSandboxControlManifestForTransition(manifestPath) : null;
653
+ const manifest = fs.existsSync(manifestPath) ? readSandboxControlManifest(manifestPath) : null;
645
654
  const broker = readBrokerOwner(path.join(resolvedRoot, 'broker.json'));
646
655
  const status = readStatusOwner(path.join(resolvedRoot, 'public', 'status.json'));
647
656
  const statusOwner = status ? status.broker : null;
@@ -730,7 +739,7 @@ export async function removeSandboxControlRoot(root, options) {
730
739
  if (!stat.isDirectory() || stat.isSymbolicLink())
731
740
  throw new Error('SANDBOX_CONTROL_CHANNEL_INVALID');
732
741
  const manifestPath = path.join(resolvedRoot, 'manifest.json');
733
- const manifest = readSandboxControlManifestForTransition(manifestPath);
742
+ const manifest = readSandboxControlManifest(manifestPath);
734
743
  const inspectContainer = options.inspectContainer
735
744
  ?? ((timeoutMs) => inspectSandboxControlContainer(manifest, { timeoutMs }));
736
745
  const timeoutMs = options.timeoutMs ?? options.timing?.quiesceDeadlineMs ?? DEFAULT_QUIESCE_TIMEOUT_MS;
@@ -792,7 +801,7 @@ export async function removeSandboxControlRoot(root, options) {
792
801
  : 'SANDBOX_CONTROL_CONTAINER_STILL_EXISTS');
793
802
  }
794
803
  }
795
- const currentManifest = readSandboxControlManifestForTransition(manifestPath);
804
+ const currentManifest = readSandboxControlManifest(manifestPath);
796
805
  if (currentManifest.token !== manifest.token || currentManifest.generation !== manifest.generation
797
806
  || !isSandboxControlRootQuiescing(resolvedRoot)) {
798
807
  throw new Error('SANDBOX_CONTROL_OWNER_TRANSITION');
@@ -197,6 +197,7 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
197
197
  if (!recoverProcessing(manifest, brokerOwns))
198
198
  return;
199
199
  while (!signal.aborted) {
200
+ let settledExecution = null;
200
201
  if (!brokerOwns())
201
202
  break;
202
203
  let current;
@@ -255,22 +256,7 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
255
256
  if (active?.settled) {
256
257
  if (!brokerOwns())
257
258
  break;
258
- if (active.result) {
259
- if (!brokerOwns())
260
- break;
261
- writeResponse(manifest, {
262
- version: 2, id: active.request.id, phase: 'completed', exitCode: active.result.exitCode,
263
- stdout: active.result.stdout, stderr: active.result.stderr, error: null
264
- });
265
- }
266
- else {
267
- if (!brokerOwns())
268
- break;
269
- writeResponse(manifest, unknown(active.request.id));
270
- }
271
- if (!brokerOwns())
272
- break;
273
- fs.rmSync(path.join(manifest.processingDir, active.request.id), { recursive: true, force: true });
259
+ settledExecution = active;
274
260
  active = null;
275
261
  }
276
262
  let reasonCode = null;
@@ -313,6 +299,22 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
313
299
  appendSandboxControlAudit(manifest, 'broker-state', { state, reasonCode, requestId: active?.request.id ?? null });
314
300
  lastState = stateKey;
315
301
  }
302
+ if (settledExecution) {
303
+ if (!brokerOwns())
304
+ break;
305
+ if (settledExecution.result) {
306
+ writeResponse(manifest, {
307
+ version: 2, id: settledExecution.request.id, phase: 'completed', exitCode: settledExecution.result.exitCode,
308
+ stdout: settledExecution.result.stdout, stderr: settledExecution.result.stderr, error: null
309
+ });
310
+ }
311
+ else {
312
+ writeResponse(manifest, unknown(settledExecution.request.id));
313
+ }
314
+ if (!brokerOwns())
315
+ break;
316
+ fs.rmSync(path.join(manifest.processingDir, settledExecution.request.id), { recursive: true, force: true });
317
+ }
316
318
  let retiring = false;
317
319
  for (const name of fs.readdirSync(requestsDir).sort()) {
318
320
  if (!/^[a-f0-9-]{16,64}\.json$/.test(name))
@@ -2,7 +2,8 @@ import path from 'node:path';
2
2
  import { shareBranchDir, shareCommonDir, shellConfigDirCandidates, worktreeDirCandidates } from './constants.js';
3
3
  import { sandboxWorkspaceViewStatePaths } from './workspace-view.js';
4
4
  export function sandboxCoreBindMounts(config, branch, overrides) {
5
- const taskBound = Boolean(overrides.taskSource && overrides.taskId);
5
+ const taskSources = overrides.taskSources ?? [];
6
+ const taskBound = Boolean(taskSources.length > 0 && overrides.taskId);
6
7
  const workspaceMounts = sandboxWorkspaceViewStatePaths(overrides.workspaceViewRoot).map(({ state, hostPath }) => taskBound && state === 'active'
7
8
  ? {
8
9
  hostPaths: [path.join(hostPath, '.short-ids.json')],
@@ -26,7 +27,7 @@ export function sandboxCoreBindMounts(config, branch, overrides) {
26
27
  ];
27
28
  if (taskBound) {
28
29
  mounts.push({
29
- hostPaths: [overrides.taskSource],
30
+ hostPaths: taskSources,
30
31
  containerPath: path.posix.join('/workspace/.agents/workspace/active', overrides.taskId),
31
32
  readOnly: false
32
33
  });