@fitlab-ai/agent-infra 0.12.0 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (331) hide show
  1. package/README.md +0 -2
  2. package/README.zh-CN.md +0 -2
  3. package/dist/bin/internal-cli.js +2 -17
  4. package/dist/lib/agent-clients/adapter.js +0 -13
  5. package/dist/lib/agent-clients/adapters/antigravity-cli.js +0 -5
  6. package/dist/lib/agent-clients/adapters/claude-code-credentials.js +0 -17
  7. package/dist/lib/agent-clients/adapters/claude-code.js +0 -9
  8. package/dist/lib/agent-clients/adapters/codex.js +0 -52
  9. package/dist/lib/agent-clients/adapters/opencode.js +0 -5
  10. package/dist/lib/agent-clients/adapters/traecli.js +0 -5
  11. package/dist/lib/agent-clients/config.js +19 -54
  12. package/dist/lib/agent-clients/registry.js +1 -12
  13. package/dist/lib/agent-clients/schema.js +0 -18
  14. package/dist/lib/agent-clients/tokens.js +1 -2
  15. package/dist/lib/agent-clients/types.js +0 -1
  16. package/dist/lib/decide.js +2 -0
  17. package/dist/lib/git/worktree-identity.js +1 -9
  18. package/dist/lib/internal/agent-client.js +2 -62
  19. package/dist/lib/internal/cli-route-inventory.js +1 -5
  20. package/dist/lib/internal/manual-validation.js +29 -27
  21. package/dist/lib/internal/platform-comment.js +56 -7
  22. package/dist/lib/internal/task-create.js +1 -1
  23. package/dist/lib/internal/task-event.js +1 -8
  24. package/dist/lib/internal/task-finalization.js +0 -1
  25. package/dist/lib/internal/task-lifecycle.js +2 -2
  26. package/dist/lib/internal/task-operation-registry.js +4 -20
  27. package/dist/lib/internal/task-review.js +4 -4
  28. package/dist/lib/platform/comment-safety.js +1 -7
  29. package/dist/lib/platform/in-label-sync.js +1 -14
  30. package/dist/lib/platform/issue-comments.js +373 -282
  31. package/dist/lib/platform/issue-summary-content.js +112 -0
  32. package/dist/lib/platform/issues.js +1 -1
  33. package/dist/lib/platform/operation-coordinator.js +4 -2
  34. package/dist/lib/platform/pr-change-report.js +176 -30
  35. package/dist/lib/platform/pr-checks.js +2 -8
  36. package/dist/lib/platform/pr-summary-content.js +54 -0
  37. package/dist/lib/platform/pr-summary.js +318 -284
  38. package/dist/lib/platform/provider-validation.js +0 -20
  39. package/dist/lib/platform/pull-requests.js +73 -84
  40. package/dist/lib/platform/releases.js +1 -43
  41. package/dist/lib/platform/summary-content-pipeline.js +18 -0
  42. package/dist/lib/platform/verification-required.js +0 -2
  43. package/dist/lib/platform/verification-sync.js +1 -79
  44. package/dist/lib/process-data/normalize.js +1 -185
  45. package/dist/lib/process-data/privacy.js +1 -16
  46. package/dist/lib/process-data/sources.js +2 -279
  47. package/dist/lib/render.js +0 -12
  48. package/dist/lib/run/index.js +15 -10
  49. package/dist/lib/run/skills.js +0 -3
  50. package/dist/lib/sandbox/commands/create.js +40 -53
  51. package/dist/lib/sandbox/commands/list-running.js +0 -18
  52. package/dist/lib/sandbox/commands/start.js +7 -8
  53. package/dist/lib/sandbox/constants.js +0 -6
  54. package/dist/lib/sandbox/control/client.js +0 -1
  55. package/dist/lib/sandbox/control/container-identity.js +1 -16
  56. package/dist/lib/sandbox/control/executor.js +0 -4
  57. package/dist/lib/sandbox/control/identity-sentinel.js +0 -7
  58. package/dist/lib/sandbox/control/lifecycle.js +21 -37
  59. package/dist/lib/sandbox/control/native-file-lock.js +0 -3
  60. package/dist/lib/sandbox/control/server.js +18 -38
  61. package/dist/lib/sandbox/control/state.js +1 -9
  62. package/dist/lib/sandbox/dockerfile.js +0 -6
  63. package/dist/lib/sandbox/engine.js +0 -14
  64. package/dist/lib/sandbox/engines/docker-exact-discovery.js +1 -4
  65. package/dist/lib/sandbox/engines/wsl2-paths.js +0 -3
  66. package/dist/lib/sandbox/recovery.js +24 -26
  67. package/dist/lib/sandbox/removal.js +67 -518
  68. package/dist/lib/sandbox/task-resolver.js +0 -41
  69. package/dist/lib/sandbox/tools.js +1 -4
  70. package/dist/lib/sandbox/workspace-view.js +1 -2
  71. package/dist/lib/server/display.js +0 -6
  72. package/dist/lib/task/activity-intent.js +45 -40
  73. package/dist/lib/task/activity-log.js +9 -16
  74. package/dist/lib/task/artifact-command.js +1 -1
  75. package/dist/lib/task/artifact-lifecycle.js +61 -63
  76. package/dist/lib/task/artifact-name.js +0 -6
  77. package/dist/lib/task/artifact-operations.js +3 -3
  78. package/dist/lib/task/capabilities.js +4 -5
  79. package/dist/lib/task/commands/log.js +0 -6
  80. package/dist/lib/task/commands/status.js +17 -60
  81. package/dist/lib/task/commit-operation.js +28 -39
  82. package/dist/lib/task/completion-facts.js +56 -43
  83. package/dist/lib/task/control-authority.js +23 -256
  84. package/dist/lib/task/control-recovery.js +3 -5
  85. package/dist/lib/task/create.js +2 -4
  86. package/dist/lib/task/decision-intents.js +8 -9
  87. package/dist/lib/task/delivery-target.js +1 -40
  88. package/dist/lib/task/events.js +84 -107
  89. package/dist/lib/task/finalization.js +60 -15
  90. package/dist/lib/task/ledger-intents.js +1 -1
  91. package/dist/lib/task/lifecycle-execution.js +38 -33
  92. package/dist/lib/task/lifecycle.js +49 -41
  93. package/dist/lib/task/local-artifact-finalization.js +1 -4
  94. package/dist/lib/task/manual-validation-evidence.js +1 -37
  95. package/dist/lib/task/platform-operation-recovery.js +151 -108
  96. package/dist/lib/task/pr-delivery-fact.js +2 -5
  97. package/dist/lib/task/qualification-confirmation.js +5 -7
  98. package/dist/lib/task/resolve-ref.js +1 -25
  99. package/dist/lib/task/review-command.js +2 -2
  100. package/dist/lib/task/review-finalization.js +1 -21
  101. package/dist/lib/task/review-fingerprint.js +0 -4
  102. package/dist/lib/task/secure-fs.js +0 -56
  103. package/dist/lib/task/short-id.js +1 -39
  104. package/dist/lib/task/skill-scope.js +0 -1
  105. package/dist/lib/task/verification-engine.js +58 -282
  106. package/dist/lib/task/verification.js +6 -3
  107. package/dist/lib/task/write.js +11 -1
  108. package/lib/agent-clients/adapter.ts +0 -76
  109. package/lib/agent-clients/adapters/antigravity-cli.ts +0 -5
  110. package/lib/agent-clients/adapters/claude-code-credentials.ts +0 -19
  111. package/lib/agent-clients/adapters/claude-code.ts +0 -9
  112. package/lib/agent-clients/adapters/codex.ts +0 -56
  113. package/lib/agent-clients/adapters/opencode.ts +0 -5
  114. package/lib/agent-clients/adapters/traecli.ts +0 -5
  115. package/lib/agent-clients/config.ts +20 -61
  116. package/lib/agent-clients/registry.ts +1 -34
  117. package/lib/agent-clients/schema.ts +0 -18
  118. package/lib/agent-clients/tokens.ts +1 -2
  119. package/lib/agent-clients/types.ts +0 -15
  120. package/lib/decide.ts +1 -0
  121. package/lib/git/worktree-identity.ts +0 -10
  122. package/lib/internal/agent-client.ts +2 -70
  123. package/lib/internal/cli-route-inventory.ts +1 -4
  124. package/lib/internal/manual-validation.ts +28 -27
  125. package/lib/internal/platform-comment.ts +46 -4
  126. package/lib/internal/task-create.ts +0 -1
  127. package/lib/internal/task-event.ts +1 -5
  128. package/lib/internal/task-finalization.ts +0 -1
  129. package/lib/internal/task-lifecycle.ts +3 -5
  130. package/lib/internal/task-operation-registry.ts +3 -19
  131. package/lib/internal/task-review.ts +4 -4
  132. package/lib/platform/comment-safety.ts +0 -10
  133. package/lib/platform/github-provider.ts +0 -2
  134. package/lib/platform/in-label-sync.ts +0 -16
  135. package/lib/platform/issue-comments.ts +478 -301
  136. package/lib/platform/issue-summary-content.ts +132 -0
  137. package/lib/platform/issues.ts +0 -2
  138. package/lib/platform/operation-coordinator.ts +4 -2
  139. package/lib/platform/pr-change-report.ts +165 -25
  140. package/lib/platform/pr-checks.ts +1 -10
  141. package/lib/platform/pr-review.ts +1 -1
  142. package/lib/platform/pr-summary-content.ts +60 -0
  143. package/lib/platform/pr-summary.ts +364 -257
  144. package/lib/platform/provider-bridge.ts +0 -1
  145. package/lib/platform/provider-loader.ts +1 -5
  146. package/lib/platform/provider-validation.ts +1 -49
  147. package/lib/platform/pull-requests.ts +64 -99
  148. package/lib/platform/releases.ts +1 -40
  149. package/lib/platform/summary-content-pipeline.ts +23 -0
  150. package/lib/platform/verification-required.ts +0 -2
  151. package/lib/platform/verification-sync.ts +0 -94
  152. package/lib/process-data/normalize.ts +1 -186
  153. package/lib/process-data/privacy.ts +2 -19
  154. package/lib/process-data/sources.ts +3 -283
  155. package/lib/render.ts +0 -15
  156. package/lib/run/index.ts +13 -7
  157. package/lib/run/skills.ts +0 -4
  158. package/lib/sandbox/commands/create.ts +37 -74
  159. package/lib/sandbox/commands/list-running.ts +0 -19
  160. package/lib/sandbox/commands/start.ts +7 -10
  161. package/lib/sandbox/constants.ts +0 -8
  162. package/lib/sandbox/control/client.ts +0 -1
  163. package/lib/sandbox/control/container-identity.ts +1 -16
  164. package/lib/sandbox/control/executor.ts +1 -5
  165. package/lib/sandbox/control/identity-sentinel.ts +0 -8
  166. package/lib/sandbox/control/lifecycle.ts +18 -51
  167. package/lib/sandbox/control/native-file-lock.ts +0 -8
  168. package/lib/sandbox/control/protocol.ts +0 -2
  169. package/lib/sandbox/control/server.ts +13 -39
  170. package/lib/sandbox/control/state.ts +1 -10
  171. package/lib/sandbox/dockerfile.ts +0 -11
  172. package/lib/sandbox/engine.ts +0 -17
  173. package/lib/sandbox/engines/docker-exact-discovery.ts +1 -5
  174. package/lib/sandbox/engines/wsl2-paths.ts +0 -4
  175. package/lib/sandbox/recovery.ts +24 -26
  176. package/lib/sandbox/removal.ts +58 -687
  177. package/lib/sandbox/shell.ts +1 -1
  178. package/lib/sandbox/task-resolver.ts +0 -48
  179. package/lib/sandbox/tools.ts +1 -5
  180. package/lib/sandbox/workspace-view.ts +2 -4
  181. package/lib/server/display.ts +0 -14
  182. package/lib/server/process-control.ts +1 -1
  183. package/lib/task/activity-intent.ts +36 -44
  184. package/lib/task/activity-log.ts +9 -22
  185. package/lib/task/artifact-command.ts +1 -1
  186. package/lib/task/artifact-lifecycle.ts +58 -67
  187. package/lib/task/artifact-name.ts +0 -7
  188. package/lib/task/artifact-operations.ts +3 -3
  189. package/lib/task/capabilities.ts +5 -6
  190. package/lib/task/commands/log.ts +0 -7
  191. package/lib/task/commands/status.ts +14 -79
  192. package/lib/task/commit-operation.ts +29 -51
  193. package/lib/task/completion-facts.ts +45 -42
  194. package/lib/task/control-authority.ts +27 -317
  195. package/lib/task/control-recovery.ts +2 -5
  196. package/lib/task/create.ts +2 -5
  197. package/lib/task/decision-intents.ts +5 -5
  198. package/lib/task/delivery-target.ts +0 -40
  199. package/lib/task/events.ts +89 -123
  200. package/lib/task/finalization.ts +52 -15
  201. package/lib/task/ledger-intents.ts +1 -1
  202. package/lib/task/lifecycle-execution.ts +37 -89
  203. package/lib/task/lifecycle.ts +48 -44
  204. package/lib/task/local-artifact-finalization.ts +0 -7
  205. package/lib/task/manual-validation-evidence.ts +1 -47
  206. package/lib/task/platform-operation-recovery.ts +117 -104
  207. package/lib/task/pr-delivery-fact.ts +2 -11
  208. package/lib/task/qualification-confirmation.ts +6 -6
  209. package/lib/task/resolve-ref.ts +0 -23
  210. package/lib/task/review-command.ts +2 -2
  211. package/lib/task/review-finalization.ts +1 -27
  212. package/lib/task/review-fingerprint.ts +0 -8
  213. package/lib/task/secure-fs.ts +0 -42
  214. package/lib/task/short-id.ts +0 -43
  215. package/lib/task/skill-scope.ts +0 -1
  216. package/lib/task/verification-engine.ts +56 -287
  217. package/lib/task/verification.ts +5 -5
  218. package/lib/task/write.ts +12 -1
  219. package/package.json +2 -2
  220. package/templates/.agents/README.en.md +1 -3
  221. package/templates/.agents/README.zh-CN.md +0 -2
  222. package/templates/.agents/rules/README.en.md +0 -1
  223. package/templates/.agents/rules/README.zh-CN.md +0 -1
  224. package/templates/.agents/rules/commit-and-pr.en.md +1 -1
  225. package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -1
  226. package/templates/.agents/rules/no-mid-flow-questions.en.md +0 -10
  227. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +0 -10
  228. package/templates/.agents/rules/pr-sync.en.md +4 -2
  229. package/templates/.agents/rules/pr-sync.zh-CN.md +6 -9
  230. package/templates/.agents/rules/task-management.en.md +3 -3
  231. package/templates/.agents/rules/task-management.zh-CN.md +3 -3
  232. package/templates/.agents/skills/analyze-task/SKILL.en.md +3 -3
  233. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +3 -3
  234. package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
  235. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
  236. package/templates/.agents/skills/code-task/SKILL.en.md +2 -2
  237. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +4 -4
  238. package/templates/.agents/skills/commit/SKILL.en.md +2 -2
  239. package/templates/.agents/skills/commit/SKILL.zh-CN.md +2 -2
  240. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +6 -6
  241. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +6 -6
  242. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  243. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  244. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +2 -2
  245. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +2 -2
  246. package/templates/.agents/skills/complete-task/SKILL.en.md +10 -25
  247. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +11 -26
  248. package/templates/.agents/skills/create-pr/SKILL.en.md +1 -1
  249. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +1 -1
  250. package/templates/.agents/skills/create-pr/reference/change-report.en.md +9 -2
  251. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +9 -2
  252. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +2 -2
  253. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +2 -2
  254. package/templates/.agents/skills/create-task/SKILL.en.md +0 -18
  255. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +0 -18
  256. package/templates/.agents/skills/plan-task/SKILL.en.md +2 -2
  257. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -2
  258. package/templates/.agents/skills/review-analysis/SKILL.en.md +3 -3
  259. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +3 -3
  260. package/templates/.agents/skills/review-code/SKILL.en.md +5 -5
  261. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -5
  262. package/templates/.agents/skills/review-plan/SKILL.en.md +3 -3
  263. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +3 -3
  264. package/templates/.agents/skills/review-pr/SKILL.en.md +4 -4
  265. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +4 -4
  266. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +1 -1
  267. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +1 -1
  268. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +3 -75
  269. package/templates/.agents/skills/watch-pr/SKILL.en.md +1 -1
  270. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +1 -1
  271. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +3 -3
  272. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +3 -3
  273. package/templates/.agents/templates/task.en.md +1 -0
  274. package/templates/.agents/templates/task.zh-CN.md +1 -0
  275. package/templates/.claude/settings.json +0 -24
  276. package/templates/.codex/hooks.json +0 -50
  277. package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +0 -582
  278. package/dist/lib/agent-clients/adapters/codex-lifecycle/binding.js +0 -114
  279. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +0 -237
  280. package/dist/lib/agent-clients/adapters/codex-lifecycle/cli.js +0 -443
  281. package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +0 -236
  282. package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +0 -292
  283. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +0 -267
  284. package/dist/lib/agent-clients/adapters/codex-orchestration.js +0 -466
  285. package/dist/lib/internal/task-orchestration.js +0 -71
  286. package/dist/lib/platform/verification.js +0 -6
  287. package/dist/lib/run/prompt.js +0 -2
  288. package/dist/lib/sandbox/engines/authority.js +0 -289
  289. package/dist/lib/task/delegation-receipts.js +0 -410
  290. package/dist/lib/task/orchestration.js +0 -1233
  291. package/dist/lib/task/verification-checks.js +0 -9
  292. package/dist/lib/task/workspace-snapshot.js +0 -121
  293. package/dist/lifecycle-build-manifest.json +0 -6
  294. package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +0 -688
  295. package/lib/agent-clients/adapters/codex-lifecycle/binding.ts +0 -147
  296. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +0 -349
  297. package/lib/agent-clients/adapters/codex-lifecycle/cli.ts +0 -506
  298. package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +0 -385
  299. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +0 -41
  300. package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +0 -418
  301. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +0 -354
  302. package/lib/agent-clients/adapters/codex-orchestration.ts +0 -630
  303. package/lib/internal/task-orchestration.ts +0 -74
  304. package/lib/platform/verification.ts +0 -11
  305. package/lib/run/prompt.ts +0 -1
  306. package/lib/sandbox/engines/authority.ts +0 -365
  307. package/lib/task/delegation-receipts.ts +0 -547
  308. package/lib/task/orchestration.ts +0 -1651
  309. package/lib/task/verification-checks.ts +0 -10
  310. package/lib/task/workspace-snapshot.ts +0 -144
  311. package/templates/.agents/hooks/lifecycle-delegation.js +0 -140
  312. package/templates/.agents/rules/lifecycle-orchestration.en.md +0 -44
  313. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +0 -44
  314. package/templates/.agents/skills/run-task/SKILL.en.md +0 -29
  315. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +0 -29
  316. package/templates/.agents/skills/run-task/config/verify.en.json +0 -10
  317. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +0 -10
  318. package/templates/.agents/skills/run-task/reference/host-validation.en.md +0 -24
  319. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +0 -24
  320. package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +0 -6
  321. package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +0 -6
  322. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +0 -6
  323. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +0 -6
  324. package/templates/.claude/commands/run-task.en.md +0 -8
  325. package/templates/.claude/commands/run-task.zh-CN.md +0 -8
  326. package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +0 -3
  327. package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +0 -3
  328. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +0 -3
  329. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +0 -3
  330. package/templates/.opencode/commands/run-task.en.md +0 -11
  331. package/templates/.opencode/commands/run-task.zh-CN.md +0 -11
@@ -57,12 +57,7 @@ import {
57
57
  runSandboxHooks,
58
58
  runBoundedSandboxHookCommand
59
59
  } from '../agent-client-reconciler.ts';
60
- import {
61
- resolveTools,
62
- tmpfsSeedStagingPath,
63
- tmpfsSeedTargetPath,
64
- toolConfigDirCandidates
65
- } from '../tools.ts';
60
+ import { tmpfsSeedStagingPath, tmpfsSeedTargetPath, toolConfigDirCandidates } from '../tools.ts';
66
61
  import type { SandboxTool, TmpfsSeedEntry } from '../tools.ts';
67
62
  import {
68
63
  assertFreshSandboxReady,
@@ -96,12 +91,6 @@ import {
96
91
  } from '../workspace-view.ts';
97
92
  import { clipboardHostDir, CONTAINER_CLIPBOARD_MOUNT } from '../clipboard/paths.ts';
98
93
  import { validateSelinuxDisableEnv } from '../engines/selinux.ts';
99
- import {
100
- captureSandboxAuthority,
101
- commandForSandboxAuthority,
102
- verifySandboxAuthority,
103
- type SandboxAuthorityEvidenceV1
104
- } from '../engines/authority.ts';
105
94
  import { dotfilesCacheDir, materializeDotfiles } from '../dotfiles.ts';
106
95
  import { ensureSandboxDiscoveryReadmes } from '../readme-scaffold.ts';
107
96
  import { removeDirRecursive } from '../../remove-dir.ts';
@@ -155,7 +144,6 @@ const MANAGED_GITHUB_GIT_CONFIG = [
155
144
  ];
156
145
 
157
146
  type SandboxCreateConfig = ReturnType<typeof loadConfig>;
158
- type PreparedDockerfile = ReturnType<typeof prepareDockerfile>;
159
147
  type ResolvedTool = { tool: SandboxTool; dir: string };
160
148
  type TmpfsSeedPlanEntry = TmpfsSeedEntry & {
161
149
  volumeArgs: string[];
@@ -175,7 +163,6 @@ type EngineRunSafeFn = EngineRunFn;
175
163
  type EngineRunVerboseFn = (engine: string, cmd: string, args: string[], opts?: { cwd?: string; env?: NodeJS.ProcessEnv }) => void;
176
164
  type DirectRunFn = (cmd: string, args: string[], opts?: { cwd?: string }) => string;
177
165
  type DirectRunSafeFn = DirectRunFn;
178
- type DirectRunVerboseFn = (cmd: string, args: string[], opts?: { cwd?: string }) => void;
179
166
  type HostShellConfig = {
180
167
  hostDir: string;
181
168
  mounts: Array<{ hostPath: string; containerPath: string }>;
@@ -933,24 +920,6 @@ function runEngineTaskCommand(engine: string, cmd: string, args: string[], opts:
933
920
  return runTaskCommand(command.cmd, command.args, opts);
934
921
  }
935
922
 
936
- function runSandboxAuthorityTaskCommand(
937
- authority: SandboxAuthorityEvidenceV1,
938
- cmd: string,
939
- args: string[],
940
- opts: { cwd?: string } = {}
941
- ): string {
942
- const command = commandForSandboxAuthority(authority, cmd, args);
943
- return runTaskCommand(command.cmd, command.args, opts);
944
- }
945
-
946
- function runSandboxAuthoritySafeCommand(
947
- authority: SandboxAuthorityEvidenceV1,
948
- args: string[]
949
- ): string {
950
- const command = commandForSandboxAuthority(authority, 'docker', args);
951
- return runSafe(command.cmd, command.args);
952
- }
953
-
954
923
  // `docker run` args for mounting a tool's containerMount as an in-container
955
924
  // tmpfs. containerMount is an in-container path, so it is NOT engine-converted.
956
925
  export function buildTmpfsRunArgs(containerMount: string, tmpfs: { size?: string; exec?: boolean }): string[] {
@@ -1317,18 +1286,29 @@ export async function create(
1317
1286
  const previousManifest = fs.existsSync(controlPaths.manifestPath)
1318
1287
  ? readSandboxControlManifest(controlPaths.manifestPath)
1319
1288
  : null;
1320
- if (hadExistingControlRoot) {
1321
- await quiesceSandboxControlRoot(controlPaths.root);
1322
- }
1323
- const previousCutoverSnapshot = hadExistingControlRoot
1324
- ? captureSandboxControlCutoverSnapshot(controlPaths.root)
1325
- : null;
1326
1289
  const existing = runSafeEngine(engine, 'docker', ['ps', '-a', '--format', '{{.Names}}']).split('\n').filter(Boolean);
1327
1290
  const matchedContainers = containerNameCandidates(effectiveConfig, branch)
1328
1291
  .filter((name) => existing.includes(name));
1329
1292
 
1293
+ const oldContainer = previousManifest ? await inspectSandboxControlContainer(previousManifest) : null;
1294
+ if (oldContainer?.state === 'unknown') {
1295
+ throw new Error(`SANDBOX_CONTROL_CONTAINER_UNKNOWN: ${oldContainer.reason}`);
1296
+ }
1297
+ if (previousManifest && (previousManifest.branch !== branch
1298
+ || previousManifest.mode !== target.workspace.mode
1299
+ || previousManifest.taskId !== (target.workspace.mode === 'task-bound' ? target.workspace.taskId : null)
1300
+ || fs.realpathSync.native(previousManifest.worktreeRoot) !== fs.realpathSync.native(worktree))) {
1301
+ throw new Error('SANDBOX_WORKSPACE_IDENTITY_CONFLICT: recorded sandbox binding does not match the requested worktree');
1302
+ }
1303
+ const removalIds: string[] = [];
1330
1304
  if (matchedContainers.length > 0) {
1331
1305
  for (const name of matchedContainers) {
1306
+ const id = runSafeEngine(engine, 'docker', ['inspect', '--format', '{{.Id}}', name]).trim();
1307
+ if (!/^[a-f0-9]{64}$/u.test(id)
1308
+ || (previousManifest && id !== previousManifest.containerIdentity.id)) {
1309
+ throw new Error('SANDBOX_CONTROL_CONTAINER_IDENTITY_MISMATCH');
1310
+ }
1311
+ removalIds.push(id);
1332
1312
  const rawLabels = runSafeEngine(engine, 'docker', [
1333
1313
  'inspect', '--format', '{{json .Config.Labels}}', name
1334
1314
  ]).trim();
@@ -1359,19 +1339,9 @@ export async function create(
1359
1339
  );
1360
1340
  }
1361
1341
  }
1362
- message('Removing old container instance...');
1363
- for (const name of matchedContainers) {
1364
- runSafeEngine(engine, 'docker', ['stop', name]);
1365
- runSafeEngine(engine, 'docker', ['rm', name]);
1366
- }
1367
1342
  }
1368
- if (previousManifest) {
1369
- const oldContainer = await inspectSandboxControlContainer(previousManifest);
1370
- if (oldContainer.state !== 'absent') {
1371
- throw new Error(oldContainer.state === 'unknown'
1372
- ? `SANDBOX_CONTROL_CONTAINER_UNKNOWN: ${oldContainer.reason}`
1373
- : 'SANDBOX_CONTROL_CONTAINER_STILL_EXISTS');
1374
- }
1343
+ if (oldContainer?.state === 'found' && !removalIds.includes(oldContainer.id)) {
1344
+ throw new Error('SANDBOX_CONTROL_CONTAINER_IDENTITY_MISMATCH');
1375
1345
  }
1376
1346
  const aliasesFile = ensureSandboxAliasesFile(
1377
1347
  effectiveConfig.home,
@@ -1455,8 +1425,17 @@ export async function create(
1455
1425
  ? prepareSandboxCompletedTaskMountSource(effectiveConfig.repoRoot, target.workspace.taskId)
1456
1426
  : null;
1457
1427
  prepareSandboxWorkspaceMountTargets(effectiveConfig.repoRoot);
1428
+ if (hadExistingControlRoot) await quiesceSandboxControlRoot(controlPaths.root);
1429
+ const previousCutoverSnapshot = hadExistingControlRoot
1430
+ ? captureSandboxControlCutoverSnapshot(controlPaths.root)
1431
+ : null;
1432
+ if (previousCutoverSnapshot) assertSandboxControlCutoverSnapshot(previousCutoverSnapshot);
1433
+ if (removalIds.length > 0) message('Removing old container instance...');
1434
+ for (const id of removalIds) {
1435
+ runEngineTaskCommand(engine, 'docker', ['stop', id]);
1436
+ runEngineTaskCommand(engine, 'docker', ['rm', id]);
1437
+ }
1458
1438
  if (previousCutoverSnapshot) {
1459
- assertSandboxControlCutoverSnapshot(previousCutoverSnapshot);
1460
1439
  if (previousManifest) {
1461
1440
  const finalOldContainer = await inspectSandboxControlContainer(previousManifest);
1462
1441
  if (finalOldContainer.state !== 'absent') {
@@ -1559,11 +1538,8 @@ export async function create(
1559
1538
  const tzFlags = hostTz ? ['-e', `TZ=${hostTz}`] : [];
1560
1539
 
1561
1540
  let createdContainerRef: string | null = null;
1562
- let creationAuthority: SandboxAuthorityEvidenceV1 | null = null;
1563
1541
  try {
1564
- creationAuthority = captureSandboxAuthority(engine);
1565
- commandForSandboxAuthority(creationAuthority, 'docker');
1566
- const dockerRunId = runSandboxAuthorityTaskCommand(creationAuthority, 'docker', [
1542
+ const dockerRunId = runEngineTaskCommand(engine, 'docker', [
1567
1543
  'run',
1568
1544
  '-d',
1569
1545
  '--init',
@@ -1622,11 +1598,11 @@ export async function create(
1622
1598
  effectiveConfig.imageName
1623
1599
  ]);
1624
1600
  createdContainerRef = dockerRunId.trim();
1625
- const containerId = runSandboxAuthorityTaskCommand(creationAuthority, 'docker', [
1601
+ const containerId = runEngineTaskCommand(engine, 'docker', [
1626
1602
  'inspect', '--format', '{{.Id}}', dockerRunId.trim()
1627
1603
  ]).trim();
1628
- if (!containerId) throw new Error('SANDBOX_CONTROL_CONTAINER_ID_INVALID');
1629
- const rawContainerLabels = runSandboxAuthorityTaskCommand(creationAuthority, 'docker', [
1604
+ if (!/^[a-f0-9]{64}$/u.test(containerId)) throw new Error('SANDBOX_CONTROL_CONTAINER_ID_INVALID');
1605
+ const rawContainerLabels = runEngineTaskCommand(engine, 'docker', [
1630
1606
  'inspect', '--format', '{{json .Config.Labels}}', containerId
1631
1607
  ]).trim();
1632
1608
  let inspectedLabels: unknown;
@@ -1651,18 +1627,10 @@ export async function create(
1651
1627
  for (const [key, expected] of Object.entries(expectedLabels)) {
1652
1628
  if (labels[key] !== expected) throw new Error('SANDBOX_CONTROL_CONTAINER_IDENTITY_MISMATCH');
1653
1629
  }
1654
- const authorityEvidence = captureSandboxAuthority(engine, {
1655
- route: creationAuthority,
1656
- lockDomain: creationAuthority.lockDomain
1657
- });
1658
- if (verifySandboxAuthority(creationAuthority, authorityEvidence).state !== 'verified') {
1659
- throw new Error('SANDBOX_AUTHORITY_DRIFT_DURING_CREATE');
1660
- }
1661
1630
  finalizeSandboxControlManifest(control, {
1662
1631
  engine,
1663
1632
  id: containerId,
1664
- labels: expectedLabels,
1665
- authorityEvidence
1633
+ labels: expectedLabels
1666
1634
  });
1667
1635
  replacementLease.clearQuiescing();
1668
1636
  await startSandboxControlBroker(effectiveConfig.repoRoot, control.manifestPath);
@@ -1673,13 +1641,8 @@ export async function create(
1673
1641
  createdTmpfsSeedPlan = tmpfsSeedPlan;
1674
1642
  } catch (error) {
1675
1643
  if (createdContainerRef) {
1676
- if (creationAuthority) {
1677
- runSandboxAuthoritySafeCommand(creationAuthority, ['stop', createdContainerRef]);
1678
- runSandboxAuthoritySafeCommand(creationAuthority, ['rm', createdContainerRef]);
1679
- } else {
1680
- runSafeEngine(engine, 'docker', ['stop', createdContainerRef]);
1681
- runSafeEngine(engine, 'docker', ['rm', createdContainerRef]);
1682
- }
1644
+ runSafeEngine(engine, 'docker', ['stop', createdContainerRef]);
1645
+ runSafeEngine(engine, 'docker', ['rm', createdContainerRef]);
1683
1646
  }
1684
1647
  if (!hadExistingControlRoot) removeDirRecursive(control.root);
1685
1648
  if (replacementCutover) {
@@ -2,8 +2,6 @@ import { spawnSync } from 'node:child_process';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { runSafeEngine, runVerboseEngine } from '../shell.ts';
5
- import { resolveTaskBranch } from '../task-resolver.ts';
6
- import { isRemovedHashShortIdInput } from '../../task/short-id.ts';
7
5
  import { parseSandboxWorkspaceIdentity } from '../workspace-identity.ts';
8
6
  import { resolveProjectTaskWorkspaceRoot } from '../../task/workspace-root.ts';
9
7
 
@@ -191,23 +189,6 @@ export function resolveTaskShortRef(
191
189
  );
192
190
  }
193
191
 
194
- /**
195
- * Resolve a sandbox command argument (`<branch | TASK-id | N>`) to a
196
- * branch name, mirroring `ai sandbox exec` so that `start` and `exec` share one
197
- * input contract. Short refs go through the registry-only resolver (which throws
198
- * an actionable error on a miss); everything else flows through resolveTaskBranch
199
- * (plain branch names pass through unchanged, TASK-ids resolve via task.md).
200
- * Callers still run assertValidBranchName on the result.
201
- */
202
- export function resolveBranchArg(arg: string, ctx: { repoRoot: string }): string {
203
- if (isRemovedHashShortIdInput(arg)) {
204
- throw new Error(`Invalid task short id '${arg}': task short ids must use bare digits`);
205
- }
206
- return isTaskShortRef(arg)
207
- ? resolveTaskShortRef(arg, ctx)
208
- : resolveTaskBranch(arg, ctx.repoRoot);
209
- }
210
-
211
192
  /**
212
193
  * Pick the sandbox container row whose name matches one of the candidate
213
194
  * container names (covers both the '..' and legacy '-' branch sanitizations).
@@ -15,11 +15,10 @@ import { resolveSandboxTarget } from '../workspace-identity.ts';
15
15
 
16
16
  const USAGE = `Usage: ai sandbox start [--recreate] <branch | TASK-id | N>
17
17
 
18
- Start an existing sandbox container that has stopped (for example after the
19
- Docker daemon was restarted or replaced). The container must already exist:
20
- if none is found, run 'ai sandbox create <branch>' first. Without --recreate, a
21
- container that is already running is checked without modifying healthy runtime
22
- state. --recreate replaces the existing container even when it is healthy.`;
18
+ Start or check an existing sandbox without replacing it. A missing container
19
+ leaves its task and control data intact. --recreate explicitly restores a missing
20
+ container from its existing worktree or replaces an existing container, preserving
21
+ the worktree and host-managed data.`;
23
22
 
24
23
  export function parseStartArgs(args: string[]): { target: string; recreate: boolean; help: boolean } {
25
24
  let recreate = false;
@@ -70,10 +69,8 @@ export async function start(args: string[]): Promise<void> {
70
69
  containerNameCandidates(config, branch)
71
70
  );
72
71
 
73
- if (!found) {
74
- throw new Error(
75
- `No sandbox container for branch '${branch}'. Run 'ai sandbox create ${branch}' to create one.`
76
- );
72
+ if (!found && !parsed.recreate) {
73
+ throw new Error(`No sandbox container for branch '${branch}'. Existing task and control data were preserved; use --recreate to explicitly restore the container.`);
77
74
  }
78
75
 
79
76
  const ready = await ensureSandboxReady({
@@ -81,7 +78,7 @@ export async function start(args: string[]): Promise<void> {
81
78
  engine,
82
79
  branch,
83
80
  workspace: target.workspace,
84
- row: found,
81
+ row: found ?? null,
85
82
  allowRecreate: parsed.recreate,
86
83
  forceRecreate: parsed.recreate,
87
84
  recreate: async () => {
@@ -67,18 +67,10 @@ export function containerNameCandidates(config: Pick<SandboxPathConfig, 'contain
67
67
  return safeNameCandidates(branch).map((name) => `${config.containerPrefix}-${name}`);
68
68
  }
69
69
 
70
- export function worktreeDir(config: Pick<SandboxPathConfig, 'worktreeBase'>, branch: string): string {
71
- return hostJoin(config.worktreeBase, sanitizeBranchName(branch));
72
- }
73
-
74
70
  export function worktreeDirCandidates(config: Pick<SandboxPathConfig, 'worktreeBase'>, branch: string): string[] {
75
71
  return safeNameCandidates(branch).map((name) => hostJoin(config.worktreeBase, name));
76
72
  }
77
73
 
78
- export function shareDir(config: Pick<SandboxPathConfig, 'shareBase'>): string {
79
- return config.shareBase;
80
- }
81
-
82
74
  export function shareCommonDir(config: Pick<SandboxPathConfig, 'shareBase'>): string {
83
75
  return hostJoin(config.shareBase, 'common');
84
76
  }
@@ -188,7 +188,6 @@ function exchangeSandboxControl(request: SandboxControlRequest, params: Readonly
188
188
  const statusDir = params.statusDir ?? process.env.AGENT_INFRA_CONTROL_STATUS_DIR ?? '/run/agent-infra/control-status';
189
189
  const taskViewEffect = taskViewEffectForRequest(request);
190
190
  const hostGeneration = preflight(statusDir, taskViewEffect);
191
- const identityPath = path.join(statusDir, 'identity.json');
192
191
  if (fs.existsSync(statusDir)) {
193
192
  const identity = readSandboxControlIdentitySentinel(statusDir);
194
193
  const requestTask = canonicalRequestTask(request);
@@ -1,6 +1,5 @@
1
1
  import type { SandboxControlManifest } from './protocol.ts';
2
2
  import { runProbe } from '../shell.ts';
3
- import { captureSandboxAuthority, isSandboxAuthorityEvidence, verifySandboxAuthority } from '../engines/authority.ts';
4
3
  import { discoverExactContainer } from '../engines/docker-exact-discovery.ts';
5
4
 
6
5
  export type ContainerObservation =
@@ -46,24 +45,10 @@ export async function inspectSandboxControlContainer(
46
45
  manifest: SandboxControlManifest,
47
46
  options: { probe?: typeof runProbe; timeoutMs?: number } = {}
48
47
  ): Promise<ContainerObservation> {
49
- if (!isSandboxAuthorityEvidence(manifest.authorityEvidence)) {
50
- return { state: 'unknown', reason: 'SANDBOX_AUTHORITY_EVIDENCE_MISSING' };
51
- }
52
48
  try {
53
- const authority = captureSandboxAuthority(manifest.engine, {
54
- probe: options.probe,
55
- timeoutMs: options.timeoutMs,
56
- lockDomain: manifest.authorityEvidence.lockDomain,
57
- route: manifest.authorityEvidence
58
- });
59
- const authorityState = verifySandboxAuthority(manifest.authorityEvidence, authority);
60
- if (authorityState.state !== 'verified') {
61
- return { state: 'unknown', reason: authorityState.reason ?? 'SANDBOX_AUTHORITY_UNAVAILABLE' };
62
- }
63
49
  const discovered = discoverExactContainer(manifest.engine, manifest.containerIdentity.id, {
64
50
  probe: options.probe,
65
- timeoutMs: options.timeoutMs,
66
- authority: manifest.authorityEvidence
51
+ timeoutMs: options.timeoutMs
67
52
  });
68
53
  if (discovered.state === 'absent') return { state: 'absent', id: discovered.id };
69
54
  if (discovered.state === 'conflict') {
@@ -1,4 +1,4 @@
1
- import { spawn, type ChildProcess } 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';
@@ -424,7 +424,3 @@ function readJsonExecution(filePath: string): SandboxControlExecution {
424
424
  if (!value || value.requestId.length === 0) throw new Error('SANDBOX_CONTROL_EXECUTION_INVALID');
425
425
  return value;
426
426
  }
427
-
428
- export function disconnectExecutor(child: ChildProcess): void {
429
- if (child.connected) child.disconnect();
430
- }
@@ -127,11 +127,3 @@ export function validateSandboxControlIdentity(params: Readonly<{
127
127
  }
128
128
  return { state: 'valid', sentinel };
129
129
  }
130
-
131
- export function assertSandboxControlIdentity(params: Parameters<typeof validateSandboxControlIdentity>[0]): SandboxControlIdentitySentinel {
132
- const result = validateSandboxControlIdentity(params);
133
- if (result.state !== 'valid' || !result.sentinel) {
134
- throw new Error(`SANDBOX_CONTROL_IDENTITY_${result.state.replaceAll('-', '_').toUpperCase()}`);
135
- }
136
- return result.sentinel;
137
- }
@@ -22,7 +22,6 @@ import {
22
22
  resolveSandboxLockNamespace,
23
23
  type SandboxResourceLock
24
24
  } from './native-file-lock.ts';
25
- import { isSandboxAuthorityEvidence } from '../engines/authority.ts';
26
25
  import { validateSandboxControlIdentity } from './identity-sentinel.ts';
27
26
  import {
28
27
  parseSandboxControlStatus,
@@ -97,7 +96,6 @@ export type SandboxRemovalJournal = Readonly<{
97
96
  engine: string;
98
97
  containerId: string;
99
98
  generation: string;
100
- authorityFingerprint: string;
101
99
  carrierIdentityDigest: string;
102
100
  lockDomain: string;
103
101
  owner: ProcessIdentity & Readonly<{ leaseNonce: string }>;
@@ -144,10 +142,14 @@ function removalJournalDomain(lockDomain: string, create = true): string {
144
142
  }
145
143
 
146
144
  function removalJournalPath(manifest: SandboxControlManifest): string {
147
- return path.join(
148
- removalJournalDomain(manifest.authorityEvidence.lockDomain),
149
- `${removalCarrierDigest(manifest.engine, manifest.containerIdentity.id, manifest.generation)}.json`
150
- );
145
+ const digest = removalCarrierDigest(manifest.engine, manifest.containerIdentity.id, manifest.generation);
146
+ // Existing interrupted removals retain their original native lock namespace.
147
+ const existing = listSandboxRemovalJournals({ project: manifest.project, branch: manifest.branch })
148
+ .filter((record) => record.carrierIdentityDigest === digest);
149
+ if (existing.length > 1) throw new Error('SANDBOX_CONTROL_REMOVAL_JOURNAL_IDENTITY_MISMATCH');
150
+ if (existing[0]) return removalJournalPathForRecord(existing[0]);
151
+ const namespace = resolveSandboxLockNamespace('sandbox-removal-journal');
152
+ return path.join(removalJournalDomain(namespace.lockDomain), `${digest}.json`);
151
153
  }
152
154
 
153
155
  function removalJournalPathForRecord(record: SandboxRemovalJournal): string {
@@ -195,8 +197,10 @@ function parseRemovalJournal(raw: string): SandboxRemovalJournal {
195
197
  } catch {
196
198
  throw new Error('SANDBOX_CONTROL_REMOVAL_JOURNAL_INVALID');
197
199
  }
200
+ // TODO(compat): Remove obsolete-field normalization after pre-simplification removal journals drain.
201
+ if (isRecord(value)) delete value.authorityFingerprint;
198
202
  if (!isRecord(value) || !hasExactKeys(value, [
199
- 'authorityFingerprint', 'carrierIdentityDigest', 'containerId', 'engine', 'expectedOldJournalRevision',
203
+ 'carrierIdentityDigest', 'containerId', 'engine', 'expectedOldJournalRevision',
200
204
  'generation', 'handoffId', 'lockDomain', 'newOperation', 'oldOperation', 'operation', 'owner', 'phase',
201
205
  'recordedAt', 'revision', 'target', 'transitionId', 'version'
202
206
  ]) || !isRecord(value.owner) || !hasExactKeys(value.owner, ['leaseNonce', 'pid', 'startTime'])
@@ -211,7 +215,6 @@ function parseRemovalJournal(raw: string): SandboxRemovalJournal {
211
215
  || typeof value.engine !== 'string' || value.engine.length === 0
212
216
  || typeof value.containerId !== 'string' || value.containerId.length === 0
213
217
  || typeof value.generation !== 'string' || value.generation.length === 0
214
- || typeof value.authorityFingerprint !== 'string' || !/^[a-f0-9]{64}$/u.test(value.authorityFingerprint)
215
218
  || typeof value.carrierIdentityDigest !== 'string' || !/^[a-f0-9]{64}$/u.test(value.carrierIdentityDigest)
216
219
  || typeof value.lockDomain !== 'string' || !/^[a-f0-9]{64}$/u.test(value.lockDomain)
217
220
  || !Number.isSafeInteger(value.owner.pid) || (value.owner.pid as number) <= 0
@@ -254,7 +257,6 @@ function parseRemovalJournal(raw: string): SandboxRemovalJournal {
254
257
  engine: value.engine as string,
255
258
  containerId: value.containerId as string,
256
259
  generation: value.generation as string,
257
- authorityFingerprint: value.authorityFingerprint as string,
258
260
  carrierIdentityDigest: value.carrierIdentityDigest as string,
259
261
  lockDomain: value.lockDomain as string,
260
262
  owner: {
@@ -470,9 +472,7 @@ function startRemovalJournal(
470
472
  const target = removalJournalPath(manifest);
471
473
  const existing = readRemovalJournalAt(target);
472
474
  if (existing && (existing.engine !== manifest.engine || existing.containerId !== manifest.containerIdentity.id
473
- || existing.generation !== manifest.generation
474
- || existing.authorityFingerprint !== manifest.authorityEvidence.authorityFingerprint
475
- || existing.lockDomain !== manifest.authorityEvidence.lockDomain)) {
475
+ || existing.generation !== manifest.generation)) {
476
476
  throw new Error('SANDBOX_CONTROL_REMOVAL_JOURNAL_IDENTITY_MISMATCH');
477
477
  }
478
478
  const targetCommit = options.target ?? existing?.target ?? defaultRemovalTarget(manifest);
@@ -496,9 +496,8 @@ function startRemovalJournal(
496
496
  engine: manifest.engine,
497
497
  containerId: manifest.containerIdentity.id,
498
498
  generation: manifest.generation,
499
- authorityFingerprint: manifest.authorityEvidence.authorityFingerprint,
500
499
  carrierIdentityDigest: removalCarrierDigest(manifest.engine, manifest.containerIdentity.id, manifest.generation),
501
- lockDomain: manifest.authorityEvidence.lockDomain,
500
+ lockDomain: existing?.lockDomain ?? resolveSandboxLockNamespace('sandbox-removal-journal').lockDomain,
502
501
  owner: { pid: process.pid, startTime, leaseNonce: randomUUID() },
503
502
  target: targetCommit
504
503
  };
@@ -574,21 +573,6 @@ export function advanceSandboxRemovalJournalPhase(
574
573
  }
575
574
  }
576
575
 
577
- export function advanceSandboxRemovalJournalToPhase(
578
- journal: SandboxRemovalJournal,
579
- phase: SandboxRemovalJournalPhase,
580
- resourceLock: SandboxResourceLock
581
- ): SandboxRemovalJournal {
582
- let current = journal;
583
- while (phaseIndex(current.phase) < phaseIndex(phase)) {
584
- const next = current.phase === 'target-committed' && phase === 'container-absent'
585
- ? phase : SANDBOX_REMOVAL_JOURNAL_PHASES[phaseIndex(current.phase) + 1];
586
- if (!next) throw new Error('SANDBOX_CONTROL_REMOVAL_PHASE_TRANSITION_INVALID');
587
- current = advanceSandboxRemovalJournalPhase(current, next, { resourceLock });
588
- }
589
- return current;
590
- }
591
-
592
576
  async function awaitWithDeadline<T>(
593
577
  operation: () => Promise<T>,
594
578
  deadlineAt: number,
@@ -682,7 +666,6 @@ function recordSandboxRemovalPending(
682
666
  phase,
683
667
  containerId: manifest.containerIdentity.id,
684
668
  generation: manifest.generation,
685
- authorityFingerprint: manifest.authorityEvidence.authorityFingerprint,
686
669
  recordedAt: Date.now()
687
670
  })}\n`, { mode: 0o600, flag: 'wx' });
688
671
  fs.renameSync(temporary, pendingPath);
@@ -1104,11 +1087,13 @@ function readSandboxControlManifestValue(manifestPath: string): SandboxControlMa
1104
1087
  } catch {
1105
1088
  throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
1106
1089
  }
1090
+ // TODO(compat): Remove obsolete-field normalization after existing sandbox manifests are rewritten by their lifecycle.
1091
+ delete manifest.authorityEvidence;
1107
1092
  const candidate = manifest as Partial<SandboxControlManifest>;
1108
1093
  const expectedKeys = [
1109
1094
  'branch', 'channelDir', 'container', 'containerIdentity', 'engine', 'generation',
1110
1095
  'mode', 'processingDir', 'project', 'publicStatusDir', 'repoRoot', 'runtimeDir',
1111
- 'taskId', 'token', 'worktreeRoot', 'authorityEvidence', 'controlRootId',
1096
+ 'taskId', 'token', 'worktreeRoot', 'controlRootId',
1112
1097
  ];
1113
1098
  const actualKeys = Object.keys(manifest).sort().join(',');
1114
1099
  if (actualKeys !== expectedKeys.sort().join(',')) {
@@ -1134,8 +1119,7 @@ function readSandboxControlManifestValue(manifestPath: string): SandboxControlMa
1134
1119
  || typeof candidate.generation !== 'string'
1135
1120
  || typeof candidate.controlRootId !== 'string' || !/^[a-f0-9]{64,128}$/u.test(candidate.controlRootId)
1136
1121
  || (candidate.mode === 'task-bound' && (typeof candidate.taskId !== 'string' || candidate.taskId.length === 0))
1137
- || (candidate.mode === 'branch-only' && candidate.taskId !== null)
1138
- || !isSandboxAuthorityEvidence(candidate.authorityEvidence)) throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
1122
+ || (candidate.mode === 'branch-only' && candidate.taskId !== null)) throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
1139
1123
  const root = path.dirname(path.resolve(manifestPath));
1140
1124
  const canonicalRoot = fs.realpathSync.native(root);
1141
1125
  const resolveControlChildPath = (candidatePath: string, name: string): string | null => {
@@ -1174,7 +1158,6 @@ function readSandboxControlManifestValue(manifestPath: string): SandboxControlMa
1174
1158
  id: containerIdentity.id as string,
1175
1159
  labels: { ...(containerIdentity.labels as Record<string, string>) }
1176
1160
  },
1177
- authorityEvidence: candidate.authorityEvidence,
1178
1161
  branch: candidate.branch,
1179
1162
  mode: candidate.mode,
1180
1163
  taskId: candidate.taskId,
@@ -1489,7 +1472,7 @@ async function removeSandboxControlRootAttempt(
1489
1472
  const manifest = readSandboxControlManifest(manifestPath);
1490
1473
  const resourceLock = options.resourceLock ?? acquireSandboxResourceLock(
1491
1474
  `${manifest.engine}:${manifest.containerIdentity.id}`,
1492
- { lockDomain: manifest.authorityEvidence.lockDomain }
1475
+ { lockDomain: readSandboxRemovalJournal(manifest)?.lockDomain }
1493
1476
  );
1494
1477
  try {
1495
1478
  if (fs.readFileSync(manifestPath, 'utf8') !== manifestRawBeforeLock) {
@@ -1603,7 +1586,6 @@ async function removeSandboxControlRootAttempt(
1603
1586
  if (currentManifestRaw !== manifestRawBeforeLock
1604
1587
  || currentManifest.engine !== manifest.engine
1605
1588
  || currentManifest.containerIdentity.id !== manifest.containerIdentity.id
1606
- || currentManifest.authorityEvidence.lockDomain !== manifest.authorityEvidence.lockDomain
1607
1589
  || currentManifest.token !== manifest.token || currentManifest.generation !== manifest.generation
1608
1590
  || !isSandboxControlRootQuiescing(resolvedRoot)) {
1609
1591
  throw new Error('SANDBOX_CONTROL_MANIFEST_CHANGED');
@@ -1683,18 +1665,3 @@ async function removeSandboxControlRootAttempt(
1683
1665
  if (!options.resourceLock) resourceLock.release();
1684
1666
  }
1685
1667
  }
1686
-
1687
- export type GarbageCollectSandboxControlOptions = Omit<RemoveSandboxControlOptions, 'removeContainer' | 'requireAbsent'>;
1688
-
1689
- export async function garbageCollectSandboxControlRoot(
1690
- root: string,
1691
- options: GarbageCollectSandboxControlOptions = {}
1692
- ): Promise<void> {
1693
- await removeSandboxControlRoot(path.resolve(root), {
1694
- ...options,
1695
- requireAbsent: true,
1696
- removeContainer: async () => {
1697
- throw new Error('SANDBOX_CONTROL_CONTAINER_REAPPEARED');
1698
- }
1699
- });
1700
- }
@@ -86,14 +86,6 @@ export function resolveSandboxLockNamespace(
86
86
  };
87
87
  }
88
88
 
89
- export function stableSandboxLockPath(
90
- carrierIdentity: string,
91
- lockDomain?: string,
92
- options: Readonly<{ home?: string }> = {}
93
- ): string {
94
- return resolveSandboxLockNamespace(carrierIdentity, { lockDomain, home: options.home }).lockPath;
95
- }
96
-
97
89
  export function acquireSandboxResourceLock(
98
90
  carrierIdentity: string,
99
91
  options: Readonly<{ lockDomain?: string; home?: string }> = {}
@@ -1,7 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { validateTaskCreateCandidate, type TaskCreateCandidateV1 } from '../../task/create.ts';
3
3
  import type { ProcessIdentity } from '../../server/process-state.ts';
4
- import type { SandboxAuthorityEvidenceV1 } from '../engines/authority.ts';
5
4
  import type { SandboxTaskView } from './task-view.ts';
6
5
 
7
6
  export const SANDBOX_CONTROL_MAX_BYTES = 64 * 1024;
@@ -36,7 +35,6 @@ export type SandboxControlContainerIdentity = Readonly<{
36
35
  export type SandboxControlManifestBase = Readonly<{
37
36
  engine: string; repoRoot: string; worktreeRoot: string; project: string; container: string;
38
37
  containerIdentity: SandboxControlContainerIdentity;
39
- authorityEvidence: SandboxAuthorityEvidenceV1;
40
38
  branch: string; mode: 'task-bound' | 'branch-only'; taskId: string | null; token: string;
41
39
  generation: string; controlRootId: string; channelDir: string; publicStatusDir: string; processingDir: string;
42
40
  }>;