@fitlab-ai/agent-infra 0.12.1 → 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 (303) 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 +18 -10
  21. package/dist/lib/internal/task-create.js +1 -1
  22. package/dist/lib/internal/task-event.js +1 -8
  23. package/dist/lib/internal/task-finalization.js +0 -1
  24. package/dist/lib/internal/task-lifecycle.js +2 -2
  25. package/dist/lib/internal/task-operation-registry.js +4 -20
  26. package/dist/lib/internal/task-review.js +4 -4
  27. package/dist/lib/platform/comment-safety.js +1 -7
  28. package/dist/lib/platform/in-label-sync.js +1 -14
  29. package/dist/lib/platform/issue-comments.js +1 -16
  30. package/dist/lib/platform/issues.js +1 -1
  31. package/dist/lib/platform/operation-coordinator.js +4 -2
  32. package/dist/lib/platform/pr-change-report.js +1 -4
  33. package/dist/lib/platform/pr-checks.js +2 -8
  34. package/dist/lib/platform/provider-validation.js +0 -20
  35. package/dist/lib/platform/pull-requests.js +73 -84
  36. package/dist/lib/platform/releases.js +1 -43
  37. package/dist/lib/platform/verification-required.js +0 -2
  38. package/dist/lib/platform/verification-sync.js +1 -79
  39. package/dist/lib/process-data/normalize.js +1 -185
  40. package/dist/lib/process-data/privacy.js +1 -16
  41. package/dist/lib/process-data/sources.js +2 -279
  42. package/dist/lib/render.js +0 -12
  43. package/dist/lib/run/index.js +15 -10
  44. package/dist/lib/run/skills.js +0 -3
  45. package/dist/lib/sandbox/commands/create.js +40 -53
  46. package/dist/lib/sandbox/commands/list-running.js +0 -18
  47. package/dist/lib/sandbox/commands/start.js +7 -8
  48. package/dist/lib/sandbox/constants.js +0 -6
  49. package/dist/lib/sandbox/control/client.js +0 -1
  50. package/dist/lib/sandbox/control/container-identity.js +1 -16
  51. package/dist/lib/sandbox/control/executor.js +0 -4
  52. package/dist/lib/sandbox/control/identity-sentinel.js +0 -7
  53. package/dist/lib/sandbox/control/lifecycle.js +21 -37
  54. package/dist/lib/sandbox/control/native-file-lock.js +0 -3
  55. package/dist/lib/sandbox/control/server.js +18 -38
  56. package/dist/lib/sandbox/control/state.js +1 -9
  57. package/dist/lib/sandbox/dockerfile.js +0 -6
  58. package/dist/lib/sandbox/engine.js +0 -14
  59. package/dist/lib/sandbox/engines/docker-exact-discovery.js +1 -4
  60. package/dist/lib/sandbox/engines/wsl2-paths.js +0 -3
  61. package/dist/lib/sandbox/recovery.js +24 -26
  62. package/dist/lib/sandbox/removal.js +11 -519
  63. package/dist/lib/sandbox/task-resolver.js +0 -41
  64. package/dist/lib/sandbox/tools.js +1 -4
  65. package/dist/lib/sandbox/workspace-view.js +1 -2
  66. package/dist/lib/server/display.js +0 -6
  67. package/dist/lib/task/activity-intent.js +45 -40
  68. package/dist/lib/task/activity-log.js +9 -16
  69. package/dist/lib/task/artifact-command.js +1 -1
  70. package/dist/lib/task/artifact-lifecycle.js +61 -63
  71. package/dist/lib/task/artifact-name.js +0 -6
  72. package/dist/lib/task/artifact-operations.js +3 -3
  73. package/dist/lib/task/capabilities.js +4 -5
  74. package/dist/lib/task/commands/log.js +0 -6
  75. package/dist/lib/task/commands/status.js +17 -60
  76. package/dist/lib/task/commit-operation.js +28 -39
  77. package/dist/lib/task/completion-facts.js +56 -43
  78. package/dist/lib/task/control-authority.js +23 -256
  79. package/dist/lib/task/control-recovery.js +3 -5
  80. package/dist/lib/task/create.js +2 -4
  81. package/dist/lib/task/decision-intents.js +8 -9
  82. package/dist/lib/task/delivery-target.js +1 -40
  83. package/dist/lib/task/events.js +84 -107
  84. package/dist/lib/task/finalization.js +44 -8
  85. package/dist/lib/task/ledger-intents.js +1 -1
  86. package/dist/lib/task/lifecycle-execution.js +38 -33
  87. package/dist/lib/task/lifecycle.js +49 -41
  88. package/dist/lib/task/local-artifact-finalization.js +1 -4
  89. package/dist/lib/task/manual-validation-evidence.js +1 -37
  90. package/dist/lib/task/platform-operation-recovery.js +67 -24
  91. package/dist/lib/task/pr-delivery-fact.js +2 -5
  92. package/dist/lib/task/qualification-confirmation.js +5 -7
  93. package/dist/lib/task/resolve-ref.js +1 -25
  94. package/dist/lib/task/review-command.js +2 -2
  95. package/dist/lib/task/review-finalization.js +1 -21
  96. package/dist/lib/task/review-fingerprint.js +0 -4
  97. package/dist/lib/task/secure-fs.js +0 -56
  98. package/dist/lib/task/short-id.js +1 -39
  99. package/dist/lib/task/skill-scope.js +0 -1
  100. package/dist/lib/task/verification-engine.js +58 -282
  101. package/dist/lib/task/verification.js +6 -3
  102. package/dist/lib/task/write.js +11 -1
  103. package/lib/agent-clients/adapter.ts +0 -76
  104. package/lib/agent-clients/adapters/antigravity-cli.ts +0 -5
  105. package/lib/agent-clients/adapters/claude-code-credentials.ts +0 -19
  106. package/lib/agent-clients/adapters/claude-code.ts +0 -9
  107. package/lib/agent-clients/adapters/codex.ts +0 -56
  108. package/lib/agent-clients/adapters/opencode.ts +0 -5
  109. package/lib/agent-clients/adapters/traecli.ts +0 -5
  110. package/lib/agent-clients/config.ts +20 -61
  111. package/lib/agent-clients/registry.ts +1 -34
  112. package/lib/agent-clients/schema.ts +0 -18
  113. package/lib/agent-clients/tokens.ts +1 -2
  114. package/lib/agent-clients/types.ts +0 -15
  115. package/lib/decide.ts +1 -0
  116. package/lib/git/worktree-identity.ts +0 -10
  117. package/lib/internal/agent-client.ts +2 -70
  118. package/lib/internal/cli-route-inventory.ts +1 -4
  119. package/lib/internal/manual-validation.ts +16 -9
  120. package/lib/internal/task-create.ts +0 -1
  121. package/lib/internal/task-event.ts +1 -5
  122. package/lib/internal/task-finalization.ts +0 -1
  123. package/lib/internal/task-lifecycle.ts +3 -5
  124. package/lib/internal/task-operation-registry.ts +3 -19
  125. package/lib/internal/task-review.ts +4 -4
  126. package/lib/platform/comment-safety.ts +0 -10
  127. package/lib/platform/github-provider.ts +0 -2
  128. package/lib/platform/in-label-sync.ts +0 -16
  129. package/lib/platform/issue-comments.ts +0 -21
  130. package/lib/platform/issues.ts +0 -2
  131. package/lib/platform/operation-coordinator.ts +4 -2
  132. package/lib/platform/pr-change-report.ts +0 -5
  133. package/lib/platform/pr-checks.ts +1 -10
  134. package/lib/platform/pr-review.ts +1 -1
  135. package/lib/platform/provider-bridge.ts +0 -1
  136. package/lib/platform/provider-loader.ts +1 -5
  137. package/lib/platform/provider-validation.ts +1 -49
  138. package/lib/platform/pull-requests.ts +64 -99
  139. package/lib/platform/releases.ts +1 -40
  140. package/lib/platform/verification-required.ts +0 -2
  141. package/lib/platform/verification-sync.ts +0 -94
  142. package/lib/process-data/normalize.ts +1 -186
  143. package/lib/process-data/privacy.ts +2 -19
  144. package/lib/process-data/sources.ts +3 -283
  145. package/lib/render.ts +0 -15
  146. package/lib/run/index.ts +13 -7
  147. package/lib/run/skills.ts +0 -4
  148. package/lib/sandbox/commands/create.ts +37 -74
  149. package/lib/sandbox/commands/list-running.ts +0 -19
  150. package/lib/sandbox/commands/start.ts +7 -10
  151. package/lib/sandbox/constants.ts +0 -8
  152. package/lib/sandbox/control/client.ts +0 -1
  153. package/lib/sandbox/control/container-identity.ts +1 -16
  154. package/lib/sandbox/control/executor.ts +1 -5
  155. package/lib/sandbox/control/identity-sentinel.ts +0 -8
  156. package/lib/sandbox/control/lifecycle.ts +18 -51
  157. package/lib/sandbox/control/native-file-lock.ts +0 -8
  158. package/lib/sandbox/control/protocol.ts +0 -2
  159. package/lib/sandbox/control/server.ts +13 -39
  160. package/lib/sandbox/control/state.ts +1 -10
  161. package/lib/sandbox/dockerfile.ts +0 -11
  162. package/lib/sandbox/engine.ts +0 -17
  163. package/lib/sandbox/engines/docker-exact-discovery.ts +1 -5
  164. package/lib/sandbox/engines/wsl2-paths.ts +0 -4
  165. package/lib/sandbox/recovery.ts +24 -26
  166. package/lib/sandbox/removal.ts +11 -696
  167. package/lib/sandbox/shell.ts +1 -1
  168. package/lib/sandbox/task-resolver.ts +0 -48
  169. package/lib/sandbox/tools.ts +1 -5
  170. package/lib/sandbox/workspace-view.ts +2 -4
  171. package/lib/server/display.ts +0 -14
  172. package/lib/server/process-control.ts +1 -1
  173. package/lib/task/activity-intent.ts +36 -44
  174. package/lib/task/activity-log.ts +9 -22
  175. package/lib/task/artifact-command.ts +1 -1
  176. package/lib/task/artifact-lifecycle.ts +58 -67
  177. package/lib/task/artifact-name.ts +0 -7
  178. package/lib/task/artifact-operations.ts +3 -3
  179. package/lib/task/capabilities.ts +5 -6
  180. package/lib/task/commands/log.ts +0 -7
  181. package/lib/task/commands/status.ts +14 -79
  182. package/lib/task/commit-operation.ts +29 -51
  183. package/lib/task/completion-facts.ts +45 -42
  184. package/lib/task/control-authority.ts +27 -317
  185. package/lib/task/control-recovery.ts +2 -5
  186. package/lib/task/create.ts +2 -5
  187. package/lib/task/decision-intents.ts +5 -5
  188. package/lib/task/delivery-target.ts +0 -40
  189. package/lib/task/events.ts +89 -123
  190. package/lib/task/finalization.ts +41 -9
  191. package/lib/task/ledger-intents.ts +1 -1
  192. package/lib/task/lifecycle-execution.ts +37 -89
  193. package/lib/task/lifecycle.ts +48 -44
  194. package/lib/task/local-artifact-finalization.ts +0 -7
  195. package/lib/task/manual-validation-evidence.ts +1 -47
  196. package/lib/task/platform-operation-recovery.ts +50 -26
  197. package/lib/task/pr-delivery-fact.ts +2 -11
  198. package/lib/task/qualification-confirmation.ts +6 -6
  199. package/lib/task/resolve-ref.ts +0 -23
  200. package/lib/task/review-command.ts +2 -2
  201. package/lib/task/review-finalization.ts +1 -27
  202. package/lib/task/review-fingerprint.ts +0 -8
  203. package/lib/task/secure-fs.ts +0 -42
  204. package/lib/task/short-id.ts +0 -43
  205. package/lib/task/skill-scope.ts +0 -1
  206. package/lib/task/verification-engine.ts +56 -287
  207. package/lib/task/verification.ts +5 -5
  208. package/lib/task/write.ts +12 -1
  209. package/package.json +2 -2
  210. package/templates/.agents/README.en.md +1 -3
  211. package/templates/.agents/README.zh-CN.md +0 -2
  212. package/templates/.agents/rules/README.en.md +0 -1
  213. package/templates/.agents/rules/README.zh-CN.md +0 -1
  214. package/templates/.agents/rules/commit-and-pr.en.md +1 -1
  215. package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -1
  216. package/templates/.agents/rules/no-mid-flow-questions.en.md +0 -10
  217. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +0 -10
  218. package/templates/.agents/rules/pr-sync.en.md +1 -1
  219. package/templates/.agents/rules/pr-sync.zh-CN.md +1 -1
  220. package/templates/.agents/rules/task-management.en.md +3 -3
  221. package/templates/.agents/rules/task-management.zh-CN.md +3 -3
  222. package/templates/.agents/skills/analyze-task/SKILL.en.md +3 -3
  223. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +3 -3
  224. package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
  225. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
  226. package/templates/.agents/skills/code-task/SKILL.en.md +2 -2
  227. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +4 -4
  228. package/templates/.agents/skills/commit/SKILL.en.md +2 -2
  229. package/templates/.agents/skills/commit/SKILL.zh-CN.md +2 -2
  230. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +6 -6
  231. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +6 -6
  232. package/templates/.agents/skills/plan-task/SKILL.en.md +2 -2
  233. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -2
  234. package/templates/.agents/skills/review-analysis/SKILL.en.md +3 -3
  235. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +3 -3
  236. package/templates/.agents/skills/review-code/SKILL.en.md +5 -5
  237. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -5
  238. package/templates/.agents/skills/review-plan/SKILL.en.md +3 -3
  239. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +3 -3
  240. package/templates/.agents/skills/review-pr/SKILL.en.md +4 -4
  241. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +4 -4
  242. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +1 -1
  243. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +1 -1
  244. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +3 -75
  245. package/templates/.agents/templates/task.en.md +1 -0
  246. package/templates/.agents/templates/task.zh-CN.md +1 -0
  247. package/templates/.claude/settings.json +0 -24
  248. package/templates/.codex/hooks.json +0 -50
  249. package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +0 -582
  250. package/dist/lib/agent-clients/adapters/codex-lifecycle/binding.js +0 -114
  251. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +0 -237
  252. package/dist/lib/agent-clients/adapters/codex-lifecycle/cli.js +0 -443
  253. package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +0 -236
  254. package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +0 -292
  255. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +0 -267
  256. package/dist/lib/agent-clients/adapters/codex-orchestration.js +0 -466
  257. package/dist/lib/internal/task-orchestration.js +0 -71
  258. package/dist/lib/platform/verification.js +0 -6
  259. package/dist/lib/run/prompt.js +0 -2
  260. package/dist/lib/sandbox/engines/authority.js +0 -289
  261. package/dist/lib/task/delegation-receipts.js +0 -410
  262. package/dist/lib/task/orchestration.js +0 -1233
  263. package/dist/lib/task/verification-checks.js +0 -9
  264. package/dist/lib/task/workspace-snapshot.js +0 -121
  265. package/dist/lifecycle-build-manifest.json +0 -6
  266. package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +0 -688
  267. package/lib/agent-clients/adapters/codex-lifecycle/binding.ts +0 -147
  268. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +0 -349
  269. package/lib/agent-clients/adapters/codex-lifecycle/cli.ts +0 -506
  270. package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +0 -385
  271. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +0 -41
  272. package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +0 -418
  273. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +0 -354
  274. package/lib/agent-clients/adapters/codex-orchestration.ts +0 -630
  275. package/lib/internal/task-orchestration.ts +0 -74
  276. package/lib/platform/verification.ts +0 -11
  277. package/lib/run/prompt.ts +0 -1
  278. package/lib/sandbox/engines/authority.ts +0 -365
  279. package/lib/task/delegation-receipts.ts +0 -547
  280. package/lib/task/orchestration.ts +0 -1651
  281. package/lib/task/verification-checks.ts +0 -10
  282. package/lib/task/workspace-snapshot.ts +0 -144
  283. package/templates/.agents/hooks/lifecycle-delegation.js +0 -140
  284. package/templates/.agents/rules/lifecycle-orchestration.en.md +0 -44
  285. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +0 -44
  286. package/templates/.agents/skills/run-task/SKILL.en.md +0 -29
  287. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +0 -29
  288. package/templates/.agents/skills/run-task/config/verify.en.json +0 -10
  289. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +0 -10
  290. package/templates/.agents/skills/run-task/reference/host-validation.en.md +0 -24
  291. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +0 -24
  292. package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +0 -6
  293. package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +0 -6
  294. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +0 -6
  295. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +0 -6
  296. package/templates/.claude/commands/run-task.en.md +0 -8
  297. package/templates/.claude/commands/run-task.zh-CN.md +0 -8
  298. package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +0 -3
  299. package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +0 -3
  300. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +0 -3
  301. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +0 -3
  302. package/templates/.opencode/commands/run-task.en.md +0 -11
  303. package/templates/.opencode/commands/run-task.zh-CN.md +0 -11
@@ -1,25 +1,22 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { createHash } from 'node:crypto';
4
3
  import * as p from '@clack/prompts';
5
4
  import pc from 'picocolors';
6
5
  import { assertValidBranchName, containerNameCandidates, sandboxBranchLabel, sandboxLabel, sandboxTaskIdLabel, sandboxWorkspaceModeLabel, shareBranchDir, shellConfigDirCandidates, worktreeDirCandidates } from './constants.js';
7
- import { ENGINES, detectEngine, engineDisplayName, isManagedEngine, stopManagedVm } from './engine.js';
8
- import { pruneSandboxDanglingImages } from './image-prune.js';
9
- import { assertManagedPath, removeManagedDir, removeWorktreeDir } from './managed-fs.js';
10
- import { run, runEngine, runOk, runOkEngine, runSafe, runSafeEngine } from './shell.js';
11
- import { parseSandboxWorkspaceIdentity, resolveSandboxCleanupTarget, resolveSandboxTarget, sameSandboxWorkspaceIdentity } from './workspace-identity.js';
6
+ import { detectEngine } from './engine.js';
7
+ import './image-prune.js';
8
+ import { assertManagedPath, removeWorktreeDir } from './managed-fs.js';
9
+ import { runEngine, runOk, runSafe, runSafeEngine } from './shell.js';
10
+ import { resolveSandboxCleanupTarget, resolveSandboxTarget } from './workspace-identity.js';
12
11
  import { sandboxControlPaths, sandboxWorkspaceViewPaths } from './workspace-view.js';
13
- import { advanceSandboxRemovalJournalToPhase, advanceSandboxRemovalJournalPhase, claimSandboxRemovalJournal, clearSandboxRemovalJournalRecord, isDefaultSandboxRemovalJournal, listSandboxRemovalJournals, removeSandboxControlRoot, readSandboxControlManifest, sandboxRemovalPhaseIndex } from './control/lifecycle.js';
14
- import { inspectSandboxControlContainer } from './control/container-identity.js';
15
- import { commandForSandboxAuthority } from './engines/authority.js';
16
- import { acquireSandboxResourceLock } from './control/native-file-lock.js';
12
+ import './control/lifecycle.js';
13
+ import './control/container-identity.js';
17
14
  import { toolConfigDirCandidates, toolProjectDirCandidates } from './tools.js';
18
- import { getProcessStartTime } from '../server/process-state.js';
15
+ import '../server/process-state.js';
19
16
  import { releaseStaleShortIdRegistry } from '../task/short-id.js';
20
17
  import { fetchSandboxRows } from './commands/list-running.js';
21
- import { createSandboxControlBindingEvidence } from './task-cleanup.js';
22
- import { createCleanPermit, createDiscardPermit, formatWorktreeSnapshot, inspectRecoveredWorktree, inspectWorktrees, verifyWorktreePermit } from './worktree-safety.js';
18
+ import './task-cleanup.js';
19
+ import { createCleanPermit, createDiscardPermit, formatWorktreeSnapshot, inspectRecoveredWorktree, inspectWorktrees } from './worktree-safety.js';
23
20
  function projectToolDirs(config, tools) {
24
21
  return tools.flatMap((tool) => toolProjectDirCandidates(tool, config.project));
25
22
  }
@@ -61,105 +58,6 @@ function addOwnerWriteToDirectories(root) {
61
58
  function isPermissionRemovalError(error) {
62
59
  return ['EACCES', 'EPERM', 'ENOTEMPTY'].includes(removalErrorCode(error) ?? '');
63
60
  }
64
- function canonicalPath(input) {
65
- try {
66
- return fs.realpathSync.native(input);
67
- }
68
- catch {
69
- return path.resolve(input);
70
- }
71
- }
72
- function isMissingTaskRecordError(error) {
73
- return error instanceof Error && /^Task not found: TASK-\d{8}-\d{6}$/.test(error.message);
74
- }
75
- function digestCleanupValue(value) {
76
- return createHash('sha256').update(JSON.stringify(value)).digest('hex');
77
- }
78
- function removalTargetDigest(config, target) {
79
- return digestCleanupValue({
80
- project: config.project,
81
- branch: target.effectiveBranch,
82
- workspace: target.workspace,
83
- controlRoots: target.controlRoots.map((candidate) => path.resolve(candidate)),
84
- workspaceViewRoots: target.workspaceViewRoots.map((candidate) => path.resolve(candidate)),
85
- managedPathCandidates: (target.managedPathCandidates ?? []).map((candidate) => path.resolve(candidate)).sort()
86
- });
87
- }
88
- function removalPermitDigest(permits) {
89
- return digestCleanupValue([...permits.entries()]
90
- .map(([worktree, permit]) => [path.resolve(worktree), permit.mode, permit.snapshot.identity])
91
- .sort(([left], [right]) => String(left).localeCompare(String(right))));
92
- }
93
- function removalPermitCommits(permits) {
94
- return [...permits.entries()]
95
- .map(([worktree, permit]) => ({
96
- path: path.resolve(worktree),
97
- mode: permit.mode,
98
- snapshot: permit.snapshot
99
- }))
100
- .sort((left, right) => left.path.localeCompare(right.path));
101
- }
102
- function removalTargetCommit(config, target, permits, removeWorktree, removeBranch, removeShare) {
103
- return {
104
- branch: target.effectiveBranch,
105
- project: config.project,
106
- controlRoot: path.resolve(target.controlRoots[0] ?? path.join(config.controlBase, config.project)),
107
- targetDigest: removalTargetDigest(config, target),
108
- permitDigest: removalPermitDigest(permits),
109
- removeWorktree,
110
- removeBranch,
111
- removeShare,
112
- worktreePaths: target.existingWorktrees.map((candidate) => path.resolve(candidate)).sort(),
113
- workspaceViewPaths: target.workspaceViewRoots.map((candidate) => path.resolve(candidate)).sort(),
114
- toolPaths: target.toolCandidates.flatMap(({ candidates }) => candidates.map((candidate) => path.resolve(candidate))).sort(),
115
- shellPaths: shellConfigDirCandidates(config, target.effectiveBranch).map((candidate) => path.resolve(candidate)).sort(),
116
- sharePath: path.resolve(shareBranchDir(config, target.effectiveBranch)),
117
- permits: removalPermitCommits(permits)
118
- };
119
- }
120
- function assertRemovalSelectionMatches(expected, actual) {
121
- const normalize = (value) => ({
122
- ...value,
123
- controlRoot: '',
124
- permits: value.permits
125
- });
126
- if (JSON.stringify(normalize(expected)) !== JSON.stringify(normalize(actual))) {
127
- throw new Error('SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH');
128
- }
129
- }
130
- function advanceRemovalJournals(project, target, targetDigest, phase, resourceLocks) {
131
- return listSandboxRemovalJournals({ branch: target.effectiveBranch, project, targetDigest }).map((journal) => {
132
- if (sandboxRemovalPhaseIndex(journal.phase) >= sandboxRemovalPhaseIndex(phase))
133
- return journal;
134
- const lock = resourceLocks.get(journal.target.controlRoot);
135
- if (!lock)
136
- throw new Error('SANDBOX_CONTROL_REMOVAL_LOCK_MISMATCH');
137
- return advanceSandboxRemovalJournalToPhase(journal, phase, lock);
138
- });
139
- }
140
- function prepareRemovalAction(project, target, targetDigest, startPhase, completedPhase, resourceLocks) {
141
- const journals = listSandboxRemovalJournals({
142
- branch: target.effectiveBranch,
143
- project,
144
- targetDigest
145
- });
146
- const startIndex = sandboxRemovalPhaseIndex(startPhase);
147
- const completedIndex = sandboxRemovalPhaseIndex(completedPhase);
148
- const shouldRun = journals.length === 0
149
- || journals.some((journal) => sandboxRemovalPhaseIndex(journal.phase) < completedIndex);
150
- const recovering = journals.some((journal) => {
151
- const index = sandboxRemovalPhaseIndex(journal.phase);
152
- return index >= startIndex && index < completedIndex;
153
- });
154
- advanceRemovalJournals(project, target, targetDigest, startPhase, resourceLocks);
155
- return { run: shouldRun, recovering };
156
- }
157
- function assertRemovalPathsAbsent(paths) {
158
- const remaining = paths.filter((candidate) => fs.existsSync(candidate));
159
- if (remaining.length > 0) {
160
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${remaining[0]}`);
161
- }
162
- }
163
61
  function assertBranchRemovalIdentity(config, branch, permits) {
164
62
  if (!runOk('git', ['-C', config.repoRoot, 'show-ref', '--verify', `refs/heads/${branch}`]))
165
63
  return;
@@ -174,412 +72,6 @@ function assertBranchRemovalIdentity(config, branch, permits) {
174
72
  throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${branch}`);
175
73
  }
176
74
  }
177
- function removalTombstonePath(targetDigest, kind, source) {
178
- const sourceDigest = createHash('sha256')
179
- .update(`${kind}\0${path.resolve(source)}`)
180
- .digest('hex')
181
- .slice(0, 24);
182
- return path.join(path.dirname(path.resolve(source)), `.agent-infra-removal-${targetDigest.slice(0, 16)}-${kind}-${sourceDigest}`);
183
- }
184
- const REMOVAL_TOMBSTONE_MARKER = '.agent-infra-removal-ownership.json';
185
- const REMOVAL_TOMBSTONE_PAYLOAD = 'payload';
186
- function removalSourceClaimPath(source, ownership) {
187
- const claimDigest = createHash('sha256')
188
- .update(JSON.stringify(ownership))
189
- .digest('hex')
190
- .slice(0, 24);
191
- return path.join(source, `.agent-infra-removal-source-${claimDigest}.json`);
192
- }
193
- function removalSourceIdentity(source) {
194
- const stat = fs.lstatSync(source, { bigint: true });
195
- if (!stat.isDirectory() || stat.isSymbolicLink() || stat.dev === 0n || stat.ino === 0n) {
196
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${source}`);
197
- }
198
- return { dev: String(stat.dev), ino: String(stat.ino) };
199
- }
200
- function sameRemovalSourceIdentity(left, right) {
201
- return left.dev === right.dev && left.ino === right.ino;
202
- }
203
- function removalSourceClaimMatches(source, ownership, identity) {
204
- try {
205
- const claimPath = removalSourceClaimPath(source, ownership);
206
- const claimStat = fs.lstatSync(claimPath);
207
- if (!claimStat.isFile() || claimStat.isSymbolicLink())
208
- return false;
209
- const record = JSON.parse(fs.readFileSync(claimPath, 'utf8'));
210
- return record.version === ownership.version
211
- && record.targetDigest === ownership.targetDigest
212
- && record.permitDigest === ownership.permitDigest
213
- && record.kind === ownership.kind
214
- && typeof record.source === 'string'
215
- && path.resolve(record.source) === path.resolve(ownership.source)
216
- && record.sourceIdentity?.dev === identity.dev
217
- && record.sourceIdentity?.ino === identity.ino;
218
- }
219
- catch {
220
- return false;
221
- }
222
- }
223
- function isOwnedRemovalSourceClaim(source, ownership) {
224
- try {
225
- const claimPath = removalSourceClaimPath(source, ownership);
226
- const claimStat = fs.lstatSync(claimPath);
227
- if (!claimStat.isFile() || claimStat.isSymbolicLink())
228
- return false;
229
- const record = JSON.parse(fs.readFileSync(claimPath, 'utf8'));
230
- return record.version === ownership.version
231
- && record.targetDigest === ownership.targetDigest
232
- && record.permitDigest === ownership.permitDigest
233
- && record.kind === ownership.kind
234
- && typeof record.source === 'string'
235
- && path.resolve(record.source) === path.resolve(ownership.source);
236
- }
237
- catch {
238
- return false;
239
- }
240
- }
241
- function removeOwnedSourceClaim(source, ownership) {
242
- try {
243
- const claimPath = removalSourceClaimPath(source, ownership);
244
- if (isOwnedRemovalSourceClaim(source, ownership))
245
- fs.unlinkSync(claimPath);
246
- }
247
- catch {
248
- // Preserve the source when the claim cannot be revalidated.
249
- }
250
- }
251
- function readRemovalTombstoneRecord(root, tombstone) {
252
- assertManagedPath(root, tombstone);
253
- try {
254
- const tombstoneStat = fs.lstatSync(tombstone);
255
- const markerStat = fs.lstatSync(removalTombstoneMarker(tombstone));
256
- if (!tombstoneStat.isDirectory() || tombstoneStat.isSymbolicLink()
257
- || !markerStat.isFile() || markerStat.isSymbolicLink())
258
- return null;
259
- const record = JSON.parse(fs.readFileSync(removalTombstoneMarker(tombstone), 'utf8'));
260
- if (record.version !== 1
261
- || typeof record.targetDigest !== 'string'
262
- || typeof record.permitDigest !== 'string'
263
- || typeof record.kind !== 'string'
264
- || typeof record.source !== 'string'
265
- || record.sourceIdentity?.dev === undefined
266
- || record.sourceIdentity.ino === undefined)
267
- return null;
268
- return record;
269
- }
270
- catch {
271
- return null;
272
- }
273
- }
274
- function removalTombstonePayload(tombstone) {
275
- return path.join(tombstone, REMOVAL_TOMBSTONE_PAYLOAD);
276
- }
277
- function removalTombstoneMarker(tombstone) {
278
- return path.join(tombstone, REMOVAL_TOMBSTONE_MARKER);
279
- }
280
- function isOwnedRemovalTombstone(root, tombstone, ownership) {
281
- const record = readRemovalTombstoneRecord(root, tombstone);
282
- return record !== null
283
- && record.version === 1
284
- && record.targetDigest === ownership.targetDigest
285
- && record.permitDigest === ownership.permitDigest
286
- && record.kind === ownership.kind
287
- && typeof record.source === 'string'
288
- && path.resolve(record.source) === path.resolve(ownership.source);
289
- }
290
- function isOwnedRemovalPayload(root, tombstone, ownership) {
291
- const record = readRemovalTombstoneRecord(root, tombstone);
292
- if (!record || record.targetDigest !== ownership.targetDigest
293
- || record.permitDigest !== ownership.permitDigest
294
- || record.kind !== ownership.kind
295
- || path.resolve(record.source) !== path.resolve(ownership.source))
296
- return false;
297
- try {
298
- const payload = removalTombstonePayload(tombstone);
299
- const payloadIdentity = removalSourceIdentity(payload);
300
- return sameRemovalSourceIdentity(payloadIdentity, record.sourceIdentity)
301
- && removalSourceClaimMatches(payload, ownership, record.sourceIdentity);
302
- }
303
- catch {
304
- return false;
305
- }
306
- }
307
- function assertOwnedRemovalTombstone(root, tombstone, ownership) {
308
- if (!isOwnedRemovalTombstone(root, tombstone, ownership)) {
309
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${ownership.source}`);
310
- }
311
- }
312
- function shouldStageManagedRemoval(source, tombstone, recovering) {
313
- return fs.existsSync(source) || (recovering && fs.existsSync(tombstone));
314
- }
315
- function stageManagedRemoval(root, source, tombstone, recovering, ownership) {
316
- assertManagedPath(root, source);
317
- assertManagedPath(root, tombstone);
318
- const sourceExists = fs.existsSync(source);
319
- const tombstoneExists = fs.existsSync(tombstone);
320
- if (tombstoneExists) {
321
- assertOwnedRemovalTombstone(root, tombstone, ownership);
322
- if (sourceExists) {
323
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${source}`);
324
- }
325
- if (recovering) {
326
- if (!isOwnedRemovalPayload(root, tombstone, ownership)) {
327
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${source}`);
328
- }
329
- return;
330
- }
331
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${source}`);
332
- }
333
- if (recovering) {
334
- throw new Error(`SANDBOX_CONTROL_REMOVAL_ACTION_OUTCOME_UNKNOWN: ${source}`);
335
- }
336
- if (!sourceExists)
337
- return;
338
- // The operator authorizes cleanup of this managed target after execution stops.
339
- // Path checks detect conflicts; they do not provide an atomic source-instance move.
340
- const expectedIdentity = removalSourceIdentity(source);
341
- const claimPath = removalSourceClaimPath(source, ownership);
342
- try {
343
- fs.writeFileSync(claimPath, `${JSON.stringify({ ...ownership, sourceIdentity: expectedIdentity })}\n`, {
344
- encoding: 'utf8',
345
- mode: 0o600,
346
- flag: 'wx'
347
- });
348
- }
349
- catch {
350
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${source}`);
351
- }
352
- if (!sameRemovalSourceIdentity(expectedIdentity, removalSourceIdentity(source))) {
353
- removeOwnedSourceClaim(source, ownership);
354
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${source}`);
355
- }
356
- let moved = false;
357
- try {
358
- fs.mkdirSync(tombstone, { mode: 0o700 });
359
- fs.writeFileSync(removalTombstoneMarker(tombstone), `${JSON.stringify({ ...ownership, sourceIdentity: expectedIdentity })}\n`, {
360
- encoding: 'utf8',
361
- mode: 0o600,
362
- flag: 'wx'
363
- });
364
- fs.renameSync(source, removalTombstonePayload(tombstone));
365
- moved = true;
366
- if (!isOwnedRemovalPayload(root, tombstone, ownership)) {
367
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${source}`);
368
- }
369
- }
370
- catch (error) {
371
- if (!moved)
372
- removeOwnedSourceClaim(source, ownership);
373
- throw error;
374
- }
375
- }
376
- function cleanupManagedTombstones(root, targetDigest, permitDigest, kind, sources) {
377
- for (const source of sources) {
378
- const tombstone = removalTombstonePath(targetDigest, kind, source);
379
- if (!fs.existsSync(tombstone))
380
- continue;
381
- const ownership = { version: 1, targetDigest, permitDigest, kind, source };
382
- if (!isOwnedRemovalTombstone(root, tombstone, ownership))
383
- continue;
384
- if (!isOwnedRemovalPayload(root, tombstone, ownership)) {
385
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${source}`);
386
- }
387
- removeManagedDir(root, tombstone);
388
- }
389
- }
390
- function branchRemovalTombstoneRef(targetDigest) {
391
- return `refs/agent-infra/sandbox-removal/${targetDigest}/branch`;
392
- }
393
- function branchPermitHead(branch, permits) {
394
- const heads = new Set([...permits.values()]
395
- .filter((permit) => permit.snapshot.branch === branch)
396
- .map((permit) => permit.snapshot.head));
397
- return heads.size === 1 ? [...heads][0] : null;
398
- }
399
- function stageBranchRemoval(config, branch, targetDigest, permits, recovering) {
400
- const expectedHead = branchPermitHead(branch, permits);
401
- if (!expectedHead)
402
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${branch}`);
403
- const branchName = `refs/heads/${branch}`;
404
- const tombstone = branchRemovalTombstoneRef(targetDigest);
405
- const branchExists = runOk('git', ['-C', config.repoRoot, 'show-ref', '--verify', branchName]);
406
- const tombstoneExists = runOk('git', ['-C', config.repoRoot, 'show-ref', '--verify', tombstone]);
407
- if (branchExists && tombstoneExists) {
408
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${branch}`);
409
- }
410
- if (recovering) {
411
- if (branchExists && !tombstoneExists) {
412
- throw new Error(`SANDBOX_CONTROL_REMOVAL_ACTION_OUTCOME_UNKNOWN: ${branch}`);
413
- }
414
- if (tombstoneExists && runSafe('git', ['-C', config.repoRoot, 'rev-parse', tombstone]) !== expectedHead) {
415
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${branch}`);
416
- }
417
- return;
418
- }
419
- if (!branchExists)
420
- return;
421
- assertBranchRemovalIdentity(config, branch, permits);
422
- const actualHead = runSafe('git', ['-C', config.repoRoot, 'rev-parse', branchName]);
423
- if (!runOk('git', ['-C', config.repoRoot, 'update-ref', tombstone, actualHead, '0'.repeat(40)])) {
424
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${branch}`);
425
- }
426
- if (!runOk('git', ['-C', config.repoRoot, 'update-ref', '-d', branchName, actualHead])) {
427
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${branch}`);
428
- }
429
- }
430
- function cleanupBranchTombstone(config, branch, targetDigest, permits) {
431
- const tombstone = branchRemovalTombstoneRef(targetDigest);
432
- if (!runOk('git', ['-C', config.repoRoot, 'show-ref', '--verify', tombstone]))
433
- return;
434
- const expectedHead = branchPermitHead(branch, permits);
435
- if (!expectedHead || runSafe('git', ['-C', config.repoRoot, 'rev-parse', tombstone]) !== expectedHead) {
436
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${branch}`);
437
- }
438
- if (!runOk('git', ['-C', config.repoRoot, 'update-ref', '-d', tombstone, expectedHead])) {
439
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${branch}`);
440
- }
441
- }
442
- function worktreeRegistration(config, worktree) {
443
- const lines = runSafe('git', ['-C', config.repoRoot, 'worktree', 'list', '--porcelain']).split('\n');
444
- let current = null;
445
- const flush = () => {
446
- if (!current || path.resolve(current.path) !== path.resolve(worktree))
447
- return null;
448
- return { head: current.head, branch: current.branch };
449
- };
450
- for (const line of lines) {
451
- if (line.startsWith('worktree ')) {
452
- const previous = flush();
453
- if (previous)
454
- return previous;
455
- current = { path: line.slice('worktree '.length), head: '', branch: null };
456
- }
457
- else if (current && line.startsWith('HEAD ')) {
458
- current.head = line.slice('HEAD '.length);
459
- }
460
- else if (current && line.startsWith('branch ')) {
461
- current.branch = line.slice('branch '.length);
462
- }
463
- }
464
- return flush();
465
- }
466
- function assertWorktreeRegistrationIdentity(config, worktree, permit) {
467
- const registration = worktreeRegistration(config, worktree);
468
- if (!registration)
469
- return;
470
- if (registration.head !== permit.snapshot.head
471
- || registration.branch !== `refs/heads/${permit.snapshot.branch}`) {
472
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${worktree}`);
473
- }
474
- }
475
- function pruneWorktreeRegistration(config, worktree) {
476
- runSafe('git', ['-C', config.repoRoot, 'worktree', 'prune']);
477
- if (worktreeRegistration(config, worktree)) {
478
- throw new Error(`SANDBOX_CONTROL_REMOVAL_ACTION_OUTCOME_UNKNOWN: ${worktree}`);
479
- }
480
- }
481
- function stageWorktreeRemoval(config, worktree, permit, tombstone, recovering, ownership) {
482
- assertManagedPath(config.worktreeBase, worktree);
483
- assertManagedPath(config.worktreeBase, tombstone);
484
- const worktreeExists = fs.existsSync(worktree);
485
- const tombstoneExists = fs.existsSync(tombstone);
486
- if (worktreeExists || !recovering)
487
- verifyWorktreePermit(permit);
488
- if (recovering) {
489
- if (worktreeExists || !tombstoneExists) {
490
- if (worktreeExists && tombstoneExists) {
491
- throw new Error(`SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH: ${worktree}`);
492
- }
493
- throw new Error(`SANDBOX_CONTROL_REMOVAL_ACTION_OUTCOME_UNKNOWN: ${worktree}`);
494
- }
495
- assertOwnedRemovalTombstone(config.worktreeBase, tombstone, ownership);
496
- assertWorktreeRegistrationIdentity(config, worktree, permit);
497
- pruneWorktreeRegistration(config, worktree);
498
- return;
499
- }
500
- if (!worktreeExists)
501
- return;
502
- stageManagedRemoval(config.worktreeBase, worktree, tombstone, false, ownership);
503
- pruneWorktreeRegistration(config, worktree);
504
- }
505
- function cleanupCompletedRemovalArtifacts(config, target, committedTarget, targetDigest) {
506
- const journals = listSandboxRemovalJournals({
507
- branch: target.effectiveBranch,
508
- project: config.project,
509
- targetDigest
510
- });
511
- if (journals.length === 0)
512
- return;
513
- const completed = (phase) => journals.every((journal) => (sandboxRemovalPhaseIndex(journal.phase) >= sandboxRemovalPhaseIndex(phase)));
514
- if (completed('workspace-removed')) {
515
- cleanupManagedTombstones(config.workspaceViewBase, targetDigest, committedTarget.permitDigest, 'workspace', target.workspaceViewRoots);
516
- cleanupManagedTombstones(path.join(config.controlBase, config.project), targetDigest, committedTarget.permitDigest, 'workspace', target.controlRoots);
517
- cleanupManagedTombstones(config.worktreeBase, targetDigest, committedTarget.permitDigest, 'worktree', committedTarget.worktreePaths);
518
- }
519
- if (completed('branch-removed')) {
520
- cleanupBranchTombstone(config, target.effectiveBranch, targetDigest, new Map(committedTarget.permits.map((permit) => [path.resolve(permit.path), {
521
- mode: permit.mode,
522
- snapshot: permit.snapshot
523
- }])));
524
- }
525
- if (completed('tool-removed')) {
526
- cleanupManagedTombstones(config.home, targetDigest, committedTarget.permitDigest, 'tool', committedTarget.toolPaths);
527
- }
528
- if (completed('shell-removed')) {
529
- cleanupManagedTombstones(config.shellConfigBase, targetDigest, committedTarget.permitDigest, 'shell', committedTarget.shellPaths);
530
- }
531
- if (completed('share-removed')) {
532
- cleanupManagedTombstones(config.shareBase, targetDigest, committedTarget.permitDigest, 'share', [committedTarget.sharePath]);
533
- }
534
- }
535
- function removalActionPaths(target, config, phase) {
536
- if (phase === 'workspace-removed') {
537
- return [...target.workspaceViewRoots, ...target.controlRoots];
538
- }
539
- if (phase === 'tool-removed') {
540
- return target.toolCandidates.flatMap(({ candidates }) => candidates);
541
- }
542
- if (phase === 'shell-removed') {
543
- return shellConfigDirCandidates(config, target.effectiveBranch);
544
- }
545
- if (phase === 'share-removed') {
546
- return [shareBranchDir(config, target.effectiveBranch)];
547
- }
548
- return [];
549
- }
550
- function permitsFromJournal(journals, target, expectedTargetDigest) {
551
- const permits = new Map();
552
- for (const journal of journals) {
553
- if (journal.target.targetDigest !== expectedTargetDigest)
554
- continue;
555
- if (journal.target.branch !== target.effectiveBranch) {
556
- throw new Error('SANDBOX_CONTROL_REMOVAL_TARGET_MISMATCH');
557
- }
558
- for (const entry of journal.target.permits) {
559
- if (path.resolve(entry.path) !== path.resolve(entry.snapshot.worktree)) {
560
- throw new Error('SANDBOX_CONTROL_REMOVAL_PERMIT_MISMATCH');
561
- }
562
- permits.set(path.resolve(entry.path), {
563
- mode: entry.mode,
564
- snapshot: entry.snapshot
565
- });
566
- }
567
- }
568
- return permits;
569
- }
570
- export function sandboxManagedPathKey(candidate, platform = process.platform, resolveExistingPath = (resolved) => fs.realpathSync.native(resolved)) {
571
- const resolved = path.resolve(candidate);
572
- let identity = resolved;
573
- try {
574
- identity = resolveExistingPath(resolved);
575
- }
576
- catch (error) {
577
- if (!isMissingPathError(error)) {
578
- throw new Error(`SANDBOX_CLEANUP_BATCH_PREFLIGHT_FAILED: unable to determine managed path identity for '${resolved}'`);
579
- }
580
- }
581
- return platform === 'win32' ? identity.toLowerCase() : identity;
582
- }
583
75
  function resolveRmTarget(config, tools, cleanupTarget, options = {}) {
584
76
  assertValidBranchName(cleanupTarget.branch);
585
77
  const engine = detectEngine(config);
@@ -941,7 +433,7 @@ async function rmUnbound(config, tools, options) {
941
433
  p.outro(`Dry run: ${targets.length} sandbox(es) found, nothing deleted`);
942
434
  return;
943
435
  }
944
- for (const { row, cleanupTarget, target } of targets) {
436
+ for (const { cleanupTarget, target } of targets) {
945
437
  await runRmOne(config, tools, cleanupTarget.branch, {
946
438
  assumeYes: options.assumeYes,
947
439
  target,
@@ -1,37 +1,11 @@
1
- import { spawnSync } from 'node:child_process';
2
1
  import fs from 'node:fs';
3
2
  import path from 'node:path';
4
- import { isRemovedHashShortIdInput } from '../task/short-id.js';
5
3
  import { resolveProjectTaskWorkspaceRoot } from '../task/workspace-root.js';
6
4
  const TASK_ID_RE = /^TASK-\d{8}-\d{6}$/;
7
- const SHORT_ID_RE = /^\d+$/;
8
5
  export const TASK_WORKSPACE_STATES = ['active', 'completed', 'blocked', 'archive'];
9
- function resolveShortIdStrict(arg, repoRoot) {
10
- const scriptPath = path.join(repoRoot, '.agents', 'scripts', 'task-short-id.js');
11
- if (!fs.existsSync(scriptPath)) {
12
- throw new Error(`Short id '${arg}' provided but task-short-id.js script is missing at ${scriptPath}`);
13
- }
14
- const result = spawnSync('node', [scriptPath, 'resolve', arg], { encoding: 'utf8', cwd: repoRoot });
15
- if (result.status !== 0) {
16
- throw new Error(`Short id '${arg}' not found in active task registry: ${(result.stderr || '').trim()}`);
17
- }
18
- return result.stdout.trim();
19
- }
20
6
  function stripQuotes(value) {
21
7
  return value.replace(/^(["'])(.*)\1$/, '$2');
22
8
  }
23
- function readTaskContent(repoRoot, taskId) {
24
- const taskRoot = resolveProjectTaskWorkspaceRoot(repoRoot);
25
- for (const state of TASK_WORKSPACE_STATES) {
26
- const taskPath = state === 'archive'
27
- ? path.join(taskRoot, state, ...findArchiveTaskParts(repoRoot, taskId), 'local', 'task.md')
28
- : path.join(taskRoot, state, taskId, 'task.md');
29
- if (fs.existsSync(taskPath)) {
30
- return { content: fs.readFileSync(taskPath, 'utf8'), state, taskMd: taskPath };
31
- }
32
- }
33
- throw new Error(`Task not found: ${taskId}`);
34
- }
35
9
  function taskWorkspaceCandidates(repoRoot, taskId) {
36
10
  const taskRoot = resolveProjectTaskWorkspaceRoot(repoRoot);
37
11
  const hot = TASK_WORKSPACE_STATES.filter((state) => state !== 'archive').flatMap((state) => {
@@ -89,21 +63,6 @@ function resolveBranchFromTaskContent(content, taskId) {
89
63
  }
90
64
  throw new Error(`Task ${taskId} has no branch field in task.md`);
91
65
  }
92
- export function resolveTaskBranch(arg, repoRoot) {
93
- if (isRemovedHashShortIdInput(arg)) {
94
- throw new Error(`Invalid task short id '${arg}': task short ids must use bare digits`);
95
- }
96
- if (SHORT_ID_RE.test(arg)) {
97
- const taskId = resolveShortIdStrict(arg, repoRoot);
98
- const { content } = readTaskContent(repoRoot, taskId);
99
- return resolveBranchFromTaskContent(content, taskId);
100
- }
101
- if (!TASK_ID_RE.test(arg)) {
102
- return arg;
103
- }
104
- const { content } = readTaskContent(repoRoot, arg);
105
- return resolveBranchFromTaskContent(content, arg);
106
- }
107
66
  export function resolveTaskWorkspace(taskId, repoRoot) {
108
67
  if (!TASK_ID_RE.test(taskId))
109
68
  throw new Error(`Invalid task id: ${taskId}`);
@@ -1,6 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import { createSandboxCapabilityPlan } from './agent-client-reconciler.js';
3
- import { safeNameCandidates, sanitizeBranchName } from './constants.js';
3
+ import { safeNameCandidates } from './constants.js';
4
4
  import { hostJoin } from './engines/wsl2-paths.js';
5
5
  export function tmpfsSeedStagingPath(toolId, index) {
6
6
  return `/run/agent-infra/tmpfs-seeds/${toolId}/${index}`;
@@ -233,9 +233,6 @@ export function parseCustomTools(value, options) {
233
233
  export function resolveTools(config) {
234
234
  return [...createSandboxCapabilityPlan(config).tools];
235
235
  }
236
- export function toolConfigDir(tool, project, branch) {
237
- return hostJoin(tool.sandboxBase, project, sanitizeBranchName(branch));
238
- }
239
236
  export function toolConfigDirCandidates(tool, project, branch) {
240
237
  return safeNameCandidates(branch).map((name) => hostJoin(tool.sandboxBase, project, name));
241
238
  }
@@ -295,8 +295,7 @@ export function finalizeSandboxControlManifest(setup, identity) {
295
295
  const manifest = {
296
296
  ...setup.manifestDraft,
297
297
  engine: identity.engine,
298
- containerIdentity: { id: identity.id, labels: { ...identity.labels } },
299
- authorityEvidence: identity.authorityEvidence
298
+ containerIdentity: { id: identity.id, labels: { ...identity.labels } }
300
299
  };
301
300
  const persistedManifest = {
302
301
  ...manifest,
@@ -4,9 +4,6 @@ export function textMessage(text) {
4
4
  export function markdownMessage(markdown) {
5
5
  return { kind: 'markdown', markdown };
6
6
  }
7
- export function tableMessage(columns, rows, title) {
8
- return { kind: 'table', title, columns, rows };
9
- }
10
7
  export function statusCard(title, tone, fields, body) {
11
8
  return { kind: 'status-card', title, tone, fields, body };
12
9
  }
@@ -20,9 +17,6 @@ export function streamEvent(title, phase, text, exitCode, signal) {
20
17
  message.signal = signal;
21
18
  return message;
22
19
  }
23
- export function commandResult(title, exitCode, signal, stdout, stderr) {
24
- return { kind: 'command-result', title, exitCode, signal, stdout, stderr };
25
- }
26
20
  export function normalizeOutbound(message) {
27
21
  return typeof message === 'string' ? textMessage(message) : message;
28
22
  }