@fitlab-ai/agent-infra 0.9.13 → 0.9.15

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 (428) hide show
  1. package/README.md +10 -0
  2. package/README.zh-CN.md +10 -0
  3. package/bin/cli.ts +26 -9
  4. package/bin/internal-cli.sh +45 -0
  5. package/dist/bin/cli.js +173 -157
  6. package/dist/bin/internal-cli.js +126 -42
  7. package/dist/lib/agent-client.js +5 -0
  8. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +165 -27
  9. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +3 -2
  10. package/dist/lib/defaults.json +103 -103
  11. package/dist/lib/fs/durable-write.js +37 -0
  12. package/dist/lib/fs/file-lock.js +111 -0
  13. package/dist/lib/host-control/audit.js +19 -0
  14. package/dist/lib/host-control/client.js +142 -0
  15. package/dist/lib/host-control/command.js +49 -0
  16. package/dist/lib/host-control/path.js +160 -0
  17. package/dist/lib/host-control/secure-fs.js +140 -0
  18. package/dist/lib/host-control/server.js +159 -0
  19. package/dist/lib/host-control/service.js +112 -0
  20. package/dist/lib/init.js +11 -2
  21. package/dist/lib/internal/agent-client.js +5 -2
  22. package/dist/lib/internal/cli-route-inventory.js +154 -0
  23. package/dist/lib/internal/codex-lifecycle.js +15 -12
  24. package/dist/lib/internal/codex-sandbox-controller.js +8 -2
  25. package/dist/lib/internal/demo-promotion.js +322 -0
  26. package/dist/lib/internal/demo-transcript.js +454 -0
  27. package/dist/lib/internal/git-workflow.js +10 -6
  28. package/dist/lib/internal/host-control.js +28 -0
  29. package/dist/lib/internal/manual-validation.js +322 -0
  30. package/dist/lib/internal/platform-checks.js +16 -4
  31. package/dist/lib/internal/platform-comment.js +16 -4
  32. package/dist/lib/internal/platform-context.js +4 -1
  33. package/dist/lib/internal/platform-issue.js +12 -4
  34. package/dist/lib/internal/platform-metadata.js +88 -0
  35. package/dist/lib/internal/platform-pr-review.js +16 -3
  36. package/dist/lib/internal/platform-pr.js +42 -14
  37. package/dist/lib/internal/platform-release-notes.js +6 -3
  38. package/dist/lib/internal/platform-security.js +93 -0
  39. package/dist/lib/internal/pr-review-grade.js +14 -3
  40. package/dist/lib/internal/release-workflow.js +82 -89
  41. package/dist/lib/internal/sandbox-control.js +171 -7
  42. package/dist/lib/internal/task-activity.js +13 -4
  43. package/dist/lib/internal/task-artifact.js +19 -107
  44. package/dist/lib/internal/task-context.js +4 -1
  45. package/dist/lib/internal/task-create.js +48 -14
  46. package/dist/lib/internal/task-delivery.js +4 -1
  47. package/dist/lib/internal/task-event.js +38 -35
  48. package/dist/lib/internal/task-finalization.js +4 -1
  49. package/dist/lib/internal/task-invalidation.js +4 -1
  50. package/dist/lib/internal/task-ledger.js +12 -1
  51. package/dist/lib/internal/task-lifecycle.js +4 -1
  52. package/dist/lib/internal/task-operation-registry.js +519 -0
  53. package/dist/lib/internal/task-orchestration.js +12 -0
  54. package/dist/lib/internal/task-override.js +10 -3
  55. package/dist/lib/internal/task-qualification.js +90 -0
  56. package/dist/lib/internal/task-review.js +10 -52
  57. package/dist/lib/internal/task-short-id.js +11 -1
  58. package/dist/lib/internal/task-snapshot.js +4 -1
  59. package/dist/lib/internal/task-validate.js +37 -12
  60. package/dist/lib/internal/task-verify.js +5 -1
  61. package/dist/lib/internal/task-warning.js +8 -1
  62. package/dist/lib/owned-path.js +33 -0
  63. package/dist/lib/platform/check-status.js +11 -0
  64. package/dist/lib/platform/comment-safety.js +229 -0
  65. package/dist/lib/platform/completion-backfill.js +1 -1
  66. package/dist/lib/platform/github-data.js +241 -0
  67. package/dist/lib/platform/github-provider.js +248 -26
  68. package/dist/lib/platform/issue-comments.js +146 -34
  69. package/dist/lib/platform/issues.js +1 -179
  70. package/dist/lib/platform/pr-change-report.js +6 -12
  71. package/dist/lib/platform/pr-checks.js +12 -65
  72. package/dist/lib/platform/pr-summary.js +83 -10
  73. package/dist/lib/platform/provider-contract.d.ts +67 -1
  74. package/dist/lib/platform/provider-contract.js +6 -2
  75. package/dist/lib/platform/provider-validation.js +76 -3
  76. package/dist/lib/platform/pull-requests.js +117 -275
  77. package/dist/lib/platform/repository-metadata.js +377 -0
  78. package/dist/lib/platform/security-alerts.js +155 -0
  79. package/dist/lib/platform/snapshots.js +2 -0
  80. package/dist/lib/platform/verification-sync.js +154 -162
  81. package/dist/lib/process-data/index.js +7 -0
  82. package/dist/lib/release/workflow.js +1 -1
  83. package/dist/lib/run/index.js +5 -0
  84. package/dist/lib/sandbox/commands/control-status.js +22 -0
  85. package/dist/lib/sandbox/commands/create.js +39 -8
  86. package/dist/lib/sandbox/commands/ls.js +5 -0
  87. package/dist/lib/sandbox/commands/rm.js +3 -807
  88. package/dist/lib/sandbox/commands/show.js +16 -0
  89. package/dist/lib/sandbox/control/audit.js +203 -0
  90. package/dist/lib/sandbox/control/client.js +125 -12
  91. package/dist/lib/sandbox/control/completed-reentry.js +85 -0
  92. package/dist/lib/sandbox/control/container-identity.js +28 -31
  93. package/dist/lib/sandbox/control/executor.js +233 -34
  94. package/dist/lib/sandbox/control/finalization-response.js +27 -0
  95. package/dist/lib/sandbox/control/identity-sentinel.js +107 -0
  96. package/dist/lib/sandbox/control/lifecycle.js +656 -128
  97. package/dist/lib/sandbox/control/native-file-lock.js +85 -0
  98. package/dist/lib/sandbox/control/protocol.js +55 -4
  99. package/dist/lib/sandbox/control/server.js +720 -79
  100. package/dist/lib/sandbox/control/state.js +63 -3
  101. package/dist/lib/sandbox/control/task-view.js +183 -0
  102. package/dist/lib/sandbox/control/task-workflow.js +74 -0
  103. package/dist/lib/sandbox/control/workflow-executor.js +99 -0
  104. package/dist/lib/sandbox/engines/authority.js +289 -0
  105. package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
  106. package/dist/lib/sandbox/index.js +7 -2
  107. package/dist/lib/sandbox/recovery.js +49 -5
  108. package/dist/lib/sandbox/removal.js +1717 -0
  109. package/dist/lib/sandbox/task-cleanup.js +217 -0
  110. package/dist/lib/sandbox/workspace-view.js +15 -15
  111. package/dist/lib/sandbox/worktree-safety.js +4 -1
  112. package/dist/lib/server/index.js +8 -0
  113. package/dist/lib/task/activity-intent.js +2 -1
  114. package/dist/lib/task/activity-log.js +30 -24
  115. package/dist/lib/task/artifact-command.js +101 -0
  116. package/dist/lib/task/artifact-lifecycle.js +71 -40
  117. package/dist/lib/task/artifact-name.js +36 -0
  118. package/dist/lib/task/artifact-operations.js +474 -0
  119. package/dist/lib/task/artifact-receipts.js +3 -15
  120. package/dist/lib/task/artifact-repair-intent.js +130 -0
  121. package/dist/lib/task/artifact-schema.js +127 -0
  122. package/dist/lib/task/capabilities.js +83 -19
  123. package/dist/lib/task/codex-orchestration.js +71 -25
  124. package/dist/lib/task/commit-identity.js +28 -0
  125. package/dist/lib/task/commit-operation.js +2 -16
  126. package/dist/lib/task/control-authority.js +375 -5
  127. package/dist/lib/task/control-recovery.js +128 -0
  128. package/dist/lib/task/create-service.js +103 -4
  129. package/dist/lib/task/create.js +80 -2
  130. package/dist/lib/task/decision-details.js +2 -46
  131. package/dist/lib/task/events.js +306 -76
  132. package/dist/lib/task/finalization-state.js +9 -0
  133. package/dist/lib/task/human-override.js +3 -6
  134. package/dist/lib/task/implementation-inputs.js +3 -3
  135. package/dist/lib/task/index.js +11 -3
  136. package/dist/lib/task/intermediate-cleanup.js +383 -0
  137. package/dist/lib/task/invalidation.js +18 -65
  138. package/dist/lib/task/ledger-intents.js +7 -22
  139. package/dist/lib/task/ledger.js +1 -3
  140. package/dist/lib/task/lifecycle.js +19 -1
  141. package/dist/lib/task/local-artifact-finalization.js +190 -290
  142. package/dist/lib/task/manual-validation-completion.js +26 -0
  143. package/dist/lib/task/manual-validation-evidence.js +130 -0
  144. package/dist/lib/task/manual-validation-receipt.js +101 -0
  145. package/dist/lib/task/manual-validation-shared.js +40 -0
  146. package/dist/lib/task/manual-validation-transaction.js +243 -0
  147. package/dist/lib/task/markdown.js +47 -0
  148. package/dist/lib/task/orchestration.js +206 -69
  149. package/dist/lib/task/qualification-audit.js +476 -0
  150. package/dist/lib/task/qualification-confirmation.js +109 -0
  151. package/dist/lib/task/qualification-intents.js +148 -0
  152. package/dist/lib/task/review-artifacts.js +23 -40
  153. package/dist/lib/task/review-command.js +25 -0
  154. package/dist/lib/task/review-finalization.js +146 -97
  155. package/dist/lib/task/review-fingerprint.js +2 -2
  156. package/dist/lib/task/sections.js +34 -54
  157. package/dist/lib/task/verification-config.js +11 -0
  158. package/dist/lib/task/verification-engine.js +170 -327
  159. package/dist/lib/task/verification.js +1 -1
  160. package/dist/lib/task/workflow-command.js +17 -0
  161. package/dist/lib/task/workflow-warning-intents.js +0 -16
  162. package/dist/lib/task/workflow-warnings.js +28 -2
  163. package/dist/lib/update.js +2 -0
  164. package/dist/lifecycle-build-manifest.json +3 -3
  165. package/lib/agent-client.ts +9 -0
  166. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +223 -33
  167. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +3 -2
  168. package/lib/fs/durable-write.ts +29 -0
  169. package/lib/fs/file-lock.ts +113 -0
  170. package/lib/host-control/audit.ts +22 -0
  171. package/lib/host-control/client.ts +172 -0
  172. package/lib/host-control/command.ts +60 -0
  173. package/lib/host-control/path.ts +167 -0
  174. package/lib/host-control/secure-fs.ts +135 -0
  175. package/lib/host-control/server.ts +180 -0
  176. package/lib/host-control/service.ts +133 -0
  177. package/lib/init.ts +15 -2
  178. package/lib/internal/agent-client.ts +4 -2
  179. package/lib/internal/cli-route-inventory.ts +142 -0
  180. package/lib/internal/codex-lifecycle.ts +14 -12
  181. package/lib/internal/codex-sandbox-controller.ts +7 -2
  182. package/lib/internal/demo-promotion.ts +354 -0
  183. package/lib/internal/demo-transcript.ts +419 -0
  184. package/lib/internal/git-workflow.ts +9 -6
  185. package/lib/internal/host-control.ts +28 -0
  186. package/lib/internal/manual-validation.ts +306 -0
  187. package/lib/internal/platform-checks.ts +12 -4
  188. package/lib/internal/platform-comment.ts +12 -4
  189. package/lib/internal/platform-context.ts +3 -1
  190. package/lib/internal/platform-issue.ts +11 -4
  191. package/lib/internal/platform-metadata.ts +70 -0
  192. package/lib/internal/platform-pr-review.ts +14 -3
  193. package/lib/internal/platform-pr.ts +38 -14
  194. package/lib/internal/platform-release-notes.ts +5 -3
  195. package/lib/internal/platform-security.ts +83 -0
  196. package/lib/internal/pr-review-grade.ts +10 -3
  197. package/lib/internal/release-workflow.ts +91 -87
  198. package/lib/internal/sandbox-control.ts +181 -6
  199. package/lib/internal/task-activity.ts +12 -4
  200. package/lib/internal/task-artifact.ts +15 -79
  201. package/lib/internal/task-context.ts +3 -1
  202. package/lib/internal/task-create.ts +76 -15
  203. package/lib/internal/task-delivery.ts +3 -1
  204. package/lib/internal/task-event.ts +21 -10
  205. package/lib/internal/task-finalization.ts +3 -1
  206. package/lib/internal/task-invalidation.ts +3 -1
  207. package/lib/internal/task-ledger.ts +11 -1
  208. package/lib/internal/task-lifecycle.ts +3 -1
  209. package/lib/internal/task-operation-registry.ts +590 -0
  210. package/lib/internal/task-orchestration.ts +12 -0
  211. package/lib/internal/task-override.ts +9 -3
  212. package/lib/internal/task-qualification.ts +61 -0
  213. package/lib/internal/task-review.ts +7 -50
  214. package/lib/internal/task-short-id.ts +10 -1
  215. package/lib/internal/task-snapshot.ts +3 -1
  216. package/lib/internal/task-validate.ts +32 -12
  217. package/lib/internal/task-verify.ts +4 -1
  218. package/lib/internal/task-warning.ts +7 -1
  219. package/lib/owned-path.ts +26 -0
  220. package/lib/platform/check-status.ts +9 -0
  221. package/lib/platform/comment-safety.ts +255 -0
  222. package/lib/platform/completion-backfill.ts +1 -1
  223. package/lib/platform/github-data.ts +322 -0
  224. package/lib/platform/github-provider.ts +244 -27
  225. package/lib/platform/issue-comments.ts +159 -35
  226. package/lib/platform/issues.ts +4 -245
  227. package/lib/platform/pr-change-report.ts +6 -12
  228. package/lib/platform/pr-checks.ts +13 -77
  229. package/lib/platform/pr-summary.ts +88 -11
  230. package/lib/platform/provider-contract.ts +78 -3
  231. package/lib/platform/provider-validation.ts +85 -3
  232. package/lib/platform/pull-requests.ts +129 -348
  233. package/lib/platform/repository-metadata.ts +453 -0
  234. package/lib/platform/security-alerts.ts +191 -0
  235. package/lib/platform/snapshots.ts +53 -0
  236. package/lib/platform/verification-sync.ts +171 -177
  237. package/lib/process-data/index.ts +7 -0
  238. package/lib/release/workflow.ts +3 -3
  239. package/lib/run/index.ts +5 -0
  240. package/lib/sandbox/commands/control-status.ts +26 -0
  241. package/lib/sandbox/commands/create.ts +53 -12
  242. package/lib/sandbox/commands/ls.ts +7 -0
  243. package/lib/sandbox/commands/rm.ts +3 -996
  244. package/lib/sandbox/commands/show.ts +16 -0
  245. package/lib/sandbox/control/audit.ts +253 -0
  246. package/lib/sandbox/control/client.ts +150 -13
  247. package/lib/sandbox/control/completed-reentry.ts +98 -0
  248. package/lib/sandbox/control/container-identity.ts +27 -43
  249. package/lib/sandbox/control/executor.ts +262 -37
  250. package/lib/sandbox/control/finalization-response.ts +29 -0
  251. package/lib/sandbox/control/identity-sentinel.ts +137 -0
  252. package/lib/sandbox/control/lifecycle.ts +672 -18
  253. package/lib/sandbox/control/native-file-lock.ts +108 -0
  254. package/lib/sandbox/control/protocol.ts +80 -8
  255. package/lib/sandbox/control/server.ts +779 -82
  256. package/lib/sandbox/control/state.ts +84 -3
  257. package/lib/sandbox/control/task-view.ts +240 -0
  258. package/lib/sandbox/control/task-workflow.ts +95 -0
  259. package/lib/sandbox/control/workflow-executor.ts +102 -0
  260. package/lib/sandbox/engines/authority.ts +365 -0
  261. package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
  262. package/lib/sandbox/index.ts +9 -2
  263. package/lib/sandbox/recovery.ts +49 -6
  264. package/lib/sandbox/removal.ts +2144 -0
  265. package/lib/sandbox/task-cleanup.ts +209 -0
  266. package/lib/sandbox/workspace-view.ts +26 -18
  267. package/lib/sandbox/worktree-safety.ts +4 -1
  268. package/lib/server/index.ts +10 -0
  269. package/lib/task/activity-intent.ts +2 -2
  270. package/lib/task/activity-log.ts +27 -19
  271. package/lib/task/artifact-command.ts +104 -0
  272. package/lib/task/artifact-lifecycle.ts +66 -39
  273. package/lib/task/artifact-name.ts +55 -0
  274. package/lib/task/artifact-operations.ts +580 -0
  275. package/lib/task/artifact-receipts.ts +3 -14
  276. package/lib/task/artifact-repair-intent.ts +152 -0
  277. package/lib/task/artifact-schema.ts +163 -0
  278. package/lib/task/capabilities.ts +82 -22
  279. package/lib/task/codex-orchestration.ts +85 -24
  280. package/lib/task/commit-identity.ts +31 -0
  281. package/lib/task/commit-operation.ts +2 -16
  282. package/lib/task/control-authority.ts +513 -6
  283. package/lib/task/control-recovery.ts +174 -0
  284. package/lib/task/create-service.ts +131 -6
  285. package/lib/task/create.ts +83 -1
  286. package/lib/task/decision-details.ts +3 -71
  287. package/lib/task/events.ts +292 -75
  288. package/lib/task/finalization-state.ts +11 -0
  289. package/lib/task/human-override.ts +3 -8
  290. package/lib/task/implementation-inputs.ts +3 -3
  291. package/lib/task/index.ts +16 -3
  292. package/lib/task/intermediate-cleanup.ts +455 -0
  293. package/lib/task/invalidation.ts +18 -62
  294. package/lib/task/ledger-intents.ts +7 -24
  295. package/lib/task/ledger.ts +1 -3
  296. package/lib/task/lifecycle.ts +17 -1
  297. package/lib/task/local-artifact-finalization.ts +223 -388
  298. package/lib/task/manual-validation-completion.ts +40 -0
  299. package/lib/task/manual-validation-evidence.ts +209 -0
  300. package/lib/task/manual-validation-receipt.ts +152 -0
  301. package/lib/task/manual-validation-shared.ts +50 -0
  302. package/lib/task/manual-validation-transaction.ts +304 -0
  303. package/lib/task/markdown.ts +70 -0
  304. package/lib/task/orchestration.ts +191 -68
  305. package/lib/task/qualification-audit.ts +588 -0
  306. package/lib/task/qualification-confirmation.ts +117 -0
  307. package/lib/task/qualification-intents.ts +150 -0
  308. package/lib/task/review-artifacts.ts +21 -41
  309. package/lib/task/review-command.ts +23 -0
  310. package/lib/task/review-finalization.ts +154 -153
  311. package/lib/task/review-fingerprint.ts +2 -2
  312. package/lib/task/sections.ts +33 -52
  313. package/lib/task/verification-config.ts +12 -0
  314. package/lib/task/verification-engine.ts +165 -370
  315. package/lib/task/verification-types.ts +17 -0
  316. package/lib/task/verification.ts +1 -1
  317. package/lib/task/workflow-command.ts +18 -0
  318. package/lib/task/workflow-warning-intents.ts +0 -13
  319. package/lib/task/workflow-warnings.ts +21 -2
  320. package/lib/update.ts +6 -0
  321. package/package.json +7 -2
  322. package/templates/.agents/hooks/lifecycle-delegation.js +6 -6
  323. package/templates/.agents/rules/README.en.md +2 -0
  324. package/templates/.agents/rules/README.zh-CN.md +2 -0
  325. package/templates/.agents/rules/decision-qualification.en.md +22 -0
  326. package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
  327. package/templates/.agents/rules/evidence-reporting.en.md +28 -0
  328. package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
  329. package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
  330. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
  331. package/templates/.agents/rules/local-artifact-repair.en.md +5 -1
  332. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +5 -1
  333. package/templates/.agents/rules/security-alerts.en.md +8 -8
  334. package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
  335. package/templates/.agents/rules/testing-discipline.en.md +2 -0
  336. package/templates/.agents/rules/testing-discipline.zh-CN.md +2 -0
  337. package/templates/.agents/scripts/package.json +3 -0
  338. package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -2
  339. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +19 -2
  340. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
  341. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
  342. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  343. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  344. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  345. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  346. package/templates/.agents/skills/code-task/SKILL.en.md +14 -1
  347. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +14 -1
  348. package/templates/.agents/skills/code-task/config/verify.en.json +5 -14
  349. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +5 -14
  350. package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
  351. package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
  352. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
  353. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
  354. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +3 -1
  355. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
  356. package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
  357. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
  358. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +37 -21
  359. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +37 -21
  360. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  361. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  362. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +4 -0
  363. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +4 -0
  364. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +16 -7
  365. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +16 -7
  366. package/templates/.agents/skills/complete-task/SKILL.en.md +10 -23
  367. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +10 -23
  368. package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
  369. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
  370. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  371. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  372. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  373. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  374. package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
  375. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
  376. package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
  377. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
  378. package/templates/.agents/skills/plan-task/SKILL.en.md +14 -1
  379. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +16 -1
  380. package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
  381. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
  382. package/templates/.agents/skills/release/SKILL.en.md +7 -3
  383. package/templates/.agents/skills/release/SKILL.zh-CN.md +7 -3
  384. package/templates/.agents/skills/review-analysis/SKILL.en.md +14 -1
  385. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -1
  386. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
  387. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
  388. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
  389. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
  390. package/templates/.agents/skills/review-code/SKILL.en.md +14 -1
  391. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +14 -1
  392. package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
  393. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
  394. package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
  395. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
  396. package/templates/.agents/skills/review-plan/SKILL.en.md +14 -1
  397. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -1
  398. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
  399. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
  400. package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
  401. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
  402. package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
  403. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
  404. package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
  405. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
  406. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +25 -4
  407. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +25 -4
  408. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +4 -1
  409. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +4 -1
  410. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +5 -1
  411. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +5 -1
  412. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  413. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  414. package/templates/.agents/skills/test/SKILL.en.md +29 -7
  415. package/templates/.agents/skills/test/SKILL.zh-CN.md +29 -7
  416. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
  417. package/templates/.agents/templates/task.en.md +6 -0
  418. package/templates/.agents/templates/task.zh-CN.md +6 -0
  419. package/templates/.claude/commands/run-manual-validation.en.md +1 -1
  420. package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
  421. package/dist/lib/platform/adapters.js +0 -56
  422. package/lib/platform/adapters.ts +0 -197
  423. package/templates/.agents/scripts/security-alerts.github.sh +0 -151
  424. package/templates/.agents/scripts/security-alerts.sh +0 -31
  425. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
  426. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
  427. package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
  428. package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
@@ -7,6 +7,7 @@ import { fetchSandboxRows, selectSandboxContainer } from './list-running.js';
7
7
  import { resolveTools, toolConfigDirCandidates } from '../tools.js';
8
8
  import { detectEngine } from '../engine.js';
9
9
  import { resolveSandboxTarget } from '../workspace-identity.js';
10
+ import { readSandboxControlStatusForRow } from './control-status.js';
10
11
  const USAGE = `Usage: ai sandbox show <branch | TASK-id | N>
11
12
 
12
13
  Shows one sandbox's worktree path and per-tool state paths (Claude Code,
@@ -62,6 +63,21 @@ export function show(args = []) {
62
63
  p.log.step('Workspace identity');
63
64
  process.stdout.write(` Mode: ${container?.workspaceMode ?? 'legacy-invalid'}\n`);
64
65
  process.stdout.write(` Task: ${container?.taskId ?? '-'}\n`);
66
+ p.log.step('Control status');
67
+ const controlStatus = container
68
+ ? readSandboxControlStatusForRow(config, container)
69
+ : null;
70
+ if (!controlStatus) {
71
+ p.log.warn(' Control status unavailable');
72
+ }
73
+ else {
74
+ process.stdout.write(` Health: ${controlStatus.state}\n`);
75
+ process.stdout.write(` Task view: ${controlStatus.taskView.state}\n`);
76
+ process.stdout.write(` Task source: ${controlStatus.taskView.observedSource ?? '-'}\n`);
77
+ if (controlStatus.taskView.reasonCode) {
78
+ process.stdout.write(` Task view reason: ${controlStatus.taskView.reasonCode}\n`);
79
+ }
80
+ }
65
81
  for (const tool of detail.toolStates) {
66
82
  p.log.step(`${tool.name} state`);
67
83
  if (tool.entries.length === 0) {
@@ -0,0 +1,203 @@
1
+ import { createHash } from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { identityDigest as digestIdentity } from './identity-sentinel.js';
5
+ import { acquireSandboxResourceLock } from './native-file-lock.js';
6
+ import { fsyncDirectory, writeDurableFile } from '../../fs/durable-write.js';
7
+ export const SANDBOX_CONTROL_AUDIT_PHASES = Object.freeze([
8
+ 'validated', 'gated', 'reserved', 'prepared', 'accepted-authorized', 'accepted-committed',
9
+ 'start-authorized', 'started-committed', 'completed', 'evidence-written',
10
+ 'publish-authorized', 'published-committed', 'rejected', 'recovered'
11
+ ]);
12
+ const REQUEST_ID = /^[a-f0-9-]{16,64}$/u;
13
+ const SAFE_OPERATION = /^[a-z][a-z0-9.-]{0,96}$/u;
14
+ const AUDIT_MAX_BYTES = 1024 * 1024;
15
+ export function requestAuditFields(manifest, request) {
16
+ return {
17
+ requestId: request.id, requestFamily: request.family, sandboxTaskId: manifest.taskId,
18
+ requestGeneration: request.generation, requestIssuedAt: request.issuedAt, requestExpiresAt: request.expiresAt
19
+ };
20
+ }
21
+ export function resultAuditFields(result) {
22
+ return {
23
+ exitCode: result.exitCode,
24
+ outputBytes: Buffer.byteLength(result.stdout, 'utf8'), errorBytes: Buffer.byteLength(result.stderr, 'utf8'),
25
+ outputDigest: createHash('sha256').update(result.stdout, 'utf8').digest('hex'),
26
+ errorDigest: createHash('sha256').update(result.stderr, 'utf8').digest('hex')
27
+ };
28
+ }
29
+ function auditRoot(manifest) {
30
+ return path.dirname(path.resolve(manifest.publicStatusDir));
31
+ }
32
+ function auditPath(manifest) {
33
+ return path.join(auditRoot(manifest), 'audit.ndjson');
34
+ }
35
+ function manifestIdentityDigest(manifest) {
36
+ return digestIdentity({
37
+ version: 1,
38
+ mode: manifest.mode,
39
+ taskId: manifest.taskId,
40
+ generation: manifest.generation,
41
+ controlRootId: manifest.controlRootId
42
+ });
43
+ }
44
+ export function createSandboxControlAuditContext(manifest, params) {
45
+ if (!REQUEST_ID.test(params.requestId))
46
+ throw new Error('SANDBOX_CONTROL_AUDIT_REQUEST_INVALID');
47
+ if (params.operation !== null && params.operation !== undefined && !SAFE_OPERATION.test(params.operation)) {
48
+ throw new Error('SANDBOX_CONTROL_AUDIT_OPERATION_INVALID');
49
+ }
50
+ if (!SANDBOX_CONTROL_AUDIT_PHASES.includes(params.phase))
51
+ throw new Error('SANDBOX_CONTROL_AUDIT_PHASE_INVALID');
52
+ return {
53
+ requestId: params.requestId,
54
+ taskId: manifest.taskId,
55
+ family: params.family,
56
+ operation: params.operation ?? null,
57
+ phase: params.phase,
58
+ outcome: params.outcome,
59
+ generation: manifest.generation,
60
+ identityDigest: manifestIdentityDigest(manifest)
61
+ };
62
+ }
63
+ function safeFields(fields) {
64
+ const result = {};
65
+ for (const [key, value] of Object.entries(fields)) {
66
+ if (!/^[a-z][a-zA-Z0-9]{0,63}$/u.test(key))
67
+ continue;
68
+ if (/(token|secret|credential|proof|password|path|root|cwd|stdout|stderr|args|command|taskref)/iu.test(key))
69
+ continue;
70
+ if (typeof value === 'string' && value.length > 256)
71
+ continue;
72
+ result[key] = value;
73
+ }
74
+ return result;
75
+ }
76
+ function requestHasTerminalTransition(directory) {
77
+ const transitions = path.join(directory, 'transitions');
78
+ if (!fs.existsSync(transitions))
79
+ return false;
80
+ return ['published-committed', 'recovered'].some((phase) => fs.existsSync(path.join(transitions, `${phase}.json`)));
81
+ }
82
+ function hasActiveRequest(manifest) {
83
+ if (!fs.existsSync(manifest.processingDir))
84
+ return false;
85
+ return fs.readdirSync(manifest.processingDir, { withFileTypes: true })
86
+ .some((entry) => entry.isDirectory() && REQUEST_ID.test(entry.name)
87
+ && !requestHasTerminalTransition(path.join(manifest.processingDir, entry.name)));
88
+ }
89
+ function rotateAuditUnderLock(manifest, filePath) {
90
+ if (!fs.existsSync(filePath) || fs.statSync(filePath).size < AUDIT_MAX_BYTES)
91
+ return;
92
+ if (hasActiveRequest(manifest))
93
+ return;
94
+ fs.rmSync(`${filePath}.1`, { force: true });
95
+ fs.renameSync(filePath, `${filePath}.1`);
96
+ fsyncDirectory(auditRoot(manifest));
97
+ const descriptor = fs.openSync(filePath, 'a', 0o600);
98
+ try {
99
+ fs.fsyncSync(descriptor);
100
+ }
101
+ finally {
102
+ fs.closeSync(descriptor);
103
+ }
104
+ }
105
+ function appendAuditRecord(manifest, record, critical) {
106
+ const root = auditRoot(manifest);
107
+ fs.mkdirSync(root, { recursive: true, mode: 0o700 });
108
+ const lock = acquireSandboxResourceLock(`sandbox-control-audit:${root}`);
109
+ try {
110
+ const filePath = auditPath(manifest);
111
+ rotateAuditUnderLock(manifest, filePath);
112
+ const descriptor = fs.openSync(filePath, 'a', 0o600);
113
+ try {
114
+ fs.writeSync(descriptor, `${JSON.stringify(record)}\n`, undefined, 'utf8');
115
+ if (critical)
116
+ fs.fsyncSync(descriptor);
117
+ }
118
+ finally {
119
+ fs.closeSync(descriptor);
120
+ }
121
+ }
122
+ catch (error) {
123
+ if (critical)
124
+ throw new Error(`SANDBOX_CONTROL_AUDIT_UNAVAILABLE: ${error instanceof Error ? error.message : String(error)}`);
125
+ }
126
+ finally {
127
+ lock.release();
128
+ }
129
+ }
130
+ export function appendCriticalAudit(manifest, context, fields = {}, now = Date.now()) {
131
+ appendAuditRecord(manifest, {
132
+ version: 2,
133
+ at: now,
134
+ event: context.phase,
135
+ ...context,
136
+ ...safeFields(fields)
137
+ }, true);
138
+ }
139
+ export function appendDiagnosticAudit(manifest, event, fields = {}, now = Date.now()) {
140
+ try {
141
+ appendAuditRecord(manifest, {
142
+ version: 2,
143
+ at: now,
144
+ event,
145
+ generation: manifest.generation,
146
+ identityDigest: manifestIdentityDigest(manifest),
147
+ ...safeFields(fields)
148
+ }, false);
149
+ }
150
+ catch {
151
+ // Diagnostics are deliberately best effort.
152
+ }
153
+ }
154
+ function transitionPath(manifest, requestId, phase) {
155
+ if (!REQUEST_ID.test(requestId))
156
+ throw new Error('SANDBOX_CONTROL_TRANSITION_REQUEST_INVALID');
157
+ return path.join(manifest.processingDir, requestId, 'transitions', `${phase}.json`);
158
+ }
159
+ export function writeSandboxControlTransition(manifest, params) {
160
+ const transition = {
161
+ version: 1,
162
+ requestId: params.requestId,
163
+ generation: manifest.generation,
164
+ phase: params.phase,
165
+ at: params.now ?? Date.now(),
166
+ identityDigest: manifestIdentityDigest(manifest),
167
+ reference: params.reference ?? null
168
+ };
169
+ const target = transitionPath(manifest, params.requestId, params.phase);
170
+ fs.mkdirSync(path.dirname(target), { recursive: true, mode: 0o700 });
171
+ try {
172
+ writeDurableFile(target, `${JSON.stringify(transition)}\n`, { mode: 0o600, replace: false });
173
+ }
174
+ catch (error) {
175
+ if (error.code !== 'EEXIST')
176
+ throw error;
177
+ const existing = readSandboxControlTransition(manifest, params.requestId, params.phase);
178
+ if (JSON.stringify(existing) !== JSON.stringify(transition))
179
+ throw new Error('SANDBOX_CONTROL_TRANSITION_CONFLICT');
180
+ }
181
+ return transition;
182
+ }
183
+ export function readSandboxControlTransition(manifest, requestId, phase) {
184
+ const filePath = transitionPath(manifest, requestId, phase);
185
+ if (!fs.existsSync(filePath))
186
+ throw new Error('SANDBOX_CONTROL_TRANSITION_MISSING');
187
+ let value;
188
+ try {
189
+ value = JSON.parse(fs.readFileSync(filePath, 'utf8'));
190
+ }
191
+ catch {
192
+ throw new Error('SANDBOX_CONTROL_TRANSITION_INVALID');
193
+ }
194
+ const candidate = value;
195
+ if (!candidate || candidate.version !== 1 || candidate.requestId !== requestId
196
+ || candidate.generation !== manifest.generation || candidate.phase !== phase
197
+ || !Number.isSafeInteger(candidate.at) || typeof candidate.identityDigest !== 'string'
198
+ || (candidate.reference !== null && typeof candidate.reference !== 'string')) {
199
+ throw new Error('SANDBOX_CONTROL_TRANSITION_INVALID');
200
+ }
201
+ return candidate;
202
+ }
203
+ //# sourceMappingURL=audit.js.map
@@ -1,9 +1,13 @@
1
1
  import fs from 'node:fs';
2
+ import { hasTaskBoundMarker } from '../../internal/task-operation-registry.js';
2
3
  import path from 'node:path';
3
4
  import { randomUUID } from 'node:crypto';
4
5
  import { SANDBOX_CONTROL_ADMISSION_WINDOW_MS, SANDBOX_CONTROL_MAX_BYTES, SANDBOX_CONTROL_STATUS_STALE_MS, isSandboxControlFamily } from './protocol.js';
5
6
  import { normalizeAgentToken } from '../../agent-clients/tokens.js';
6
7
  import { readSandboxControlPayload, readSandboxControlStatus } from './state.js';
8
+ import { accessSandboxTaskView, taskViewFromStatus } from './task-view.js';
9
+ import { readSandboxControlIdentitySentinel } from './identity-sentinel.js';
10
+ import { configuredShortIdLength, resolveShortIdReadOnly } from '../../task/short-id.js';
7
11
  const SANDBOX_CONTROL_RESPONSE_SETTLE_MS = 250;
8
12
  export class SandboxControlClientError extends Error {
9
13
  detail;
@@ -23,7 +27,25 @@ function sleep(milliseconds) {
23
27
  function clientError(code, message, retryable, accepted = false, requestId = null) {
24
28
  throw new SandboxControlClientError({ code, message: `${code}: ${message}`, retryable }, accepted, requestId);
25
29
  }
26
- function preflight(statusDir, generation, now = Date.now()) {
30
+ function preflight(statusDir, generation, taskViewEffect = null, now = Date.now(), env = process.env) {
31
+ if (fs.existsSync(statusDir)) {
32
+ let identity;
33
+ try {
34
+ identity = readSandboxControlIdentitySentinel(statusDir);
35
+ }
36
+ catch (error) {
37
+ const code = error instanceof Error && error.message.endsWith('MISSING')
38
+ ? 'SANDBOX_CONTROL_IDENTITY_MISSING'
39
+ : 'SANDBOX_CONTROL_IDENTITY_MALFORMED';
40
+ clientError(code, 'sandbox control identity is missing or invalid', false);
41
+ }
42
+ if (identity.generation !== generation) {
43
+ clientError('SANDBOX_CONTROL_IDENTITY_GENERATION_MISMATCH', 'sandbox control identity generation does not match the request', false);
44
+ }
45
+ if (env.AGENT_INFRA_CONTROL_ROOT_ID && identity.controlRootId !== env.AGENT_INFRA_CONTROL_ROOT_ID) {
46
+ clientError('SANDBOX_CONTROL_IDENTITY_ROOT_ID_MISMATCH', 'sandbox control identity root does not match the client configuration', false);
47
+ }
48
+ }
27
49
  let status;
28
50
  try {
29
51
  status = readSandboxControlStatus(statusDir);
@@ -45,8 +67,27 @@ function preflight(statusDir, generation, now = Date.now()) {
45
67
  }
46
68
  if (status.state !== 'healthy')
47
69
  clientError('SANDBOX_CONTROL_BROKER_UNAVAILABLE', 'broker is not ready', true);
70
+ if (taskViewEffect && hasTaskBoundMarker(env)) {
71
+ const view = taskViewFromStatus(status);
72
+ if (view.taskId !== env.AGENT_INFRA_TASK_ID) {
73
+ clientError('SANDBOX_TASK_VIEW_TASK_ID_MISMATCH', 'task view task id does not match the sandbox task marker', false);
74
+ }
75
+ const access = accessSandboxTaskView(view, taskViewEffect);
76
+ if (!access.allowed) {
77
+ clientError(access.reasonCode ?? 'SANDBOX_TASK_VIEW_DENIED', access.message ?? 'task view denied', false);
78
+ }
79
+ }
48
80
  }
49
- function parseResponse(raw, id) {
81
+ function taskViewEffectForRequest(request) {
82
+ if (request.family === 'task-lifecycle' || request.family === 'task-finalization')
83
+ return 'progress';
84
+ if (request.family === 'task-orchestration')
85
+ return request.args[1] === 'status' ? 'diagnostic' : 'progress';
86
+ if (request.family === 'task-workflow')
87
+ return request.workflow.operation === 'artifact-inspect' || request.workflow.operation === 'decision-next-id' ? 'diagnostic' : 'progress';
88
+ return null;
89
+ }
90
+ function parseResponse(raw, id, accepted = false) {
50
91
  const response = JSON.parse(raw);
51
92
  if (response.version !== 2 || response.id !== id
52
93
  || !['completed', 'rejected'].includes(response.phase)
@@ -54,12 +95,12 @@ function parseResponse(raw, id) {
54
95
  || (response.outputState !== undefined && response.outputState !== 'available' && response.outputState !== 'unavailable')
55
96
  || (response.outputState === 'available' && !response.payload)
56
97
  || (response.outputState === 'unavailable' && response.payload !== null && response.payload !== undefined)) {
57
- clientError('SANDBOX_CONTROL_RESPONSE_INVALID', 'broker response is invalid', false, false, id);
98
+ clientError('SANDBOX_CONTROL_RESPONSE_INVALID', 'broker response is invalid', false, accepted, id);
58
99
  }
59
100
  return response;
60
101
  }
61
- function readPublishedResponse(raw, id, channelDir) {
62
- const response = parseResponse(raw, id);
102
+ function readPublishedResponse(raw, id, channelDir, accepted = false) {
103
+ const response = parseResponse(raw, id, accepted);
63
104
  if (response.outputState !== 'available')
64
105
  return response;
65
106
  const filePath = path.join(channelDir, 'responses', `${id}.payload.json`);
@@ -89,10 +130,59 @@ function cancelPendingRequest(requestPath) {
89
130
  throw error;
90
131
  }
91
132
  }
133
+ const CONTROL_TASK_ID_RE = /^TASK-\d{8}-\d{6}$/;
134
+ const CONTROL_SHORT_ID_RE = /^\d+$/;
135
+ // Use the current short-id contract for the first visible active registry.
136
+ export function resolveVisibleActiveShortId(ref) {
137
+ let dir = process.cwd();
138
+ for (let depth = 0; depth < 64; depth += 1) {
139
+ const registryPath = path.join(dir, '.agents', 'workspace', 'active', '.short-ids.json');
140
+ if (fs.existsSync(registryPath)) {
141
+ const resolved = resolveShortIdReadOnly(ref, dir, { shortIdLength: configuredShortIdLength(dir) });
142
+ return resolved.ok ? resolved.taskId : null;
143
+ }
144
+ const parent = path.dirname(dir);
145
+ if (parent === dir)
146
+ break;
147
+ dir = parent;
148
+ }
149
+ return null;
150
+ }
151
+ // A request's leading argument is only a task reference for some families and
152
+ // may be a documented short id. Compare canonical ids so a bound sandbox keeps
153
+ // refusing other tasks without rejecting its own task's short id.
154
+ function canonicalRequestTask(request) {
155
+ const ref = request.family === 'task-workflow'
156
+ ? request.workflow.taskId
157
+ : 'args' in request ? request.args[0] ?? null : null;
158
+ if (!ref)
159
+ return { kind: 'none' };
160
+ if (CONTROL_TASK_ID_RE.test(ref))
161
+ return { kind: 'task', taskId: ref };
162
+ if (!CONTROL_SHORT_ID_RE.test(ref))
163
+ return { kind: 'none' };
164
+ const resolved = resolveVisibleActiveShortId(ref);
165
+ return resolved ? { kind: 'task', taskId: resolved } : { kind: 'unresolved' };
166
+ }
92
167
  function exchangeSandboxControl(request, params) {
93
168
  const channelDir = params.channelDir ?? process.env.AGENT_INFRA_CONTROL_DIR ?? '/run/agent-infra/control';
94
169
  const statusDir = params.statusDir ?? process.env.AGENT_INFRA_CONTROL_STATUS_DIR ?? '/run/agent-infra/control-status';
95
- preflight(statusDir, request.generation);
170
+ const taskViewEffect = taskViewEffectForRequest(request);
171
+ preflight(statusDir, request.generation, taskViewEffect);
172
+ const identityPath = path.join(statusDir, 'identity.json');
173
+ if (fs.existsSync(statusDir)) {
174
+ const identity = readSandboxControlIdentitySentinel(statusDir);
175
+ const requestTask = canonicalRequestTask(request);
176
+ if (identity.mode === 'task-bound'
177
+ && ((process.env.AGENT_INFRA_TASK_ID && process.env.AGENT_INFRA_TASK_ID !== identity.taskId)
178
+ || requestTask.kind === 'unresolved'
179
+ || (requestTask.kind === 'task' && requestTask.taskId !== identity.taskId))) {
180
+ clientError('SANDBOX_CONTROL_IDENTITY_TOPOLOGY_MISMATCH', 'request task does not match the sandbox identity', false);
181
+ }
182
+ if (identity.mode === 'branch-only' && (request.family === 'task-finalization' || request.family === 'task-workflow')) {
183
+ clientError('SANDBOX_CONTROL_BRANCH_ONLY', 'branch-only sandboxes cannot finalize tasks', false);
184
+ }
185
+ }
96
186
  const encoded = `${JSON.stringify(request)}\n`;
97
187
  if (Buffer.byteLength(encoded, 'utf8') > SANDBOX_CONTROL_MAX_BYTES) {
98
188
  clientError('SANDBOX_CONTROL_REQUEST_TOO_LARGE', 'request exceeds the control limit', false, false, request.id);
@@ -127,7 +217,9 @@ function exchangeSandboxControl(request, params) {
127
217
  }
128
218
  let response;
129
219
  try {
130
- response = readPublishedResponse(raw, request.id, channelDir);
220
+ // The request-specific terminal proves the broker claimed the request; preserve recovery evidence if marker cleanup won the race.
221
+ accepted = true;
222
+ response = readPublishedResponse(raw, request.id, channelDir, accepted);
131
223
  malformedResponseRaw = null;
132
224
  }
133
225
  catch (error) {
@@ -153,7 +245,7 @@ function exchangeSandboxControl(request, params) {
153
245
  }
154
246
  if (!accepted) {
155
247
  try {
156
- preflight(statusDir, request.generation);
248
+ preflight(statusDir, request.generation, taskViewEffect);
157
249
  }
158
250
  catch (error) {
159
251
  if (cancelPendingRequest(requestPath))
@@ -196,7 +288,9 @@ export function recoverSandboxControl(requestId, params = {}) {
196
288
  }
197
289
  let response;
198
290
  try {
199
- response = readPublishedResponse(raw, requestId, channelDir);
291
+ // The request-specific terminal proves the broker claimed the request; preserve recovery evidence if marker cleanup won the race.
292
+ accepted = true;
293
+ response = readPublishedResponse(raw, requestId, channelDir, accepted);
200
294
  malformedResponseRaw = null;
201
295
  }
202
296
  catch (error) {
@@ -232,7 +326,7 @@ function authority(params) {
232
326
  export function requestSandboxControl(params) {
233
327
  if (!isSandboxControlFamily(params.family))
234
328
  clientError('SANDBOX_CONTROL_COMMAND_DENIED', `'${params.family}' is not allowed`, false);
235
- if (params.family === 'task-create' || params.family === 'codex-controller' || params.family === 'task-finalization') {
329
+ if (params.family === 'task-create' || params.family === 'codex-controller' || params.family === 'task-finalization' || params.family === 'task-workflow') {
236
330
  clientError('SANDBOX_CONTROL_COMMAND_DENIED', `'${params.family}' requires a typed request`, false);
237
331
  }
238
332
  const auth = authority(params);
@@ -251,14 +345,15 @@ export function requestSandboxTaskControl(params) {
251
345
  const issuedAt = Date.now();
252
346
  const request = {
253
347
  version: 3,
254
- id: randomUUID(),
348
+ id: params.authority?.requestId ?? randomUUID(),
255
349
  ...auth,
256
350
  issuedAt,
257
351
  expiresAt: issuedAt + SANDBOX_CONTROL_ADMISSION_WINDOW_MS,
258
352
  family: params.family,
259
353
  args: params.args,
260
354
  controllerProcess: null,
261
- controllerProof: params.controllerProof
355
+ controllerProof: params.authority ? null : params.controllerProof,
356
+ ...(params.authority ? { authority: params.authority } : {})
262
357
  };
263
358
  return exchangeSandboxControl(request, params);
264
359
  }
@@ -283,6 +378,24 @@ export function requestSandboxTaskFinalization(params) {
283
378
  };
284
379
  return exchangeSandboxControl(request, params);
285
380
  }
381
+ export function requestSandboxTaskWorkflow(params) {
382
+ const auth = authority(params);
383
+ const issuedAt = Date.now();
384
+ const request = {
385
+ version: 3,
386
+ id: params.workflow.id,
387
+ ...auth,
388
+ issuedAt,
389
+ expiresAt: issuedAt + SANDBOX_CONTROL_ADMISSION_WINDOW_MS,
390
+ family: 'task-workflow',
391
+ args: [],
392
+ controllerProcess: null,
393
+ controllerProof: null,
394
+ workflow: params.workflow,
395
+ ...(params.authority ? { authority: params.authority } : {})
396
+ };
397
+ return exchangeSandboxControl(request, params);
398
+ }
286
399
  function exactKeys(value, keys) {
287
400
  return Object.keys(value).sort().join(',') === [...keys].sort().join(',');
288
401
  }
@@ -0,0 +1,85 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { resolveTaskWorkspace } from '../task-resolver.js';
4
+ import { assertGitWorktreeBinding } from '../../git/worktree-identity.js';
5
+ import { parseTypedTaskFrontmatter } from '../../task/frontmatter.js';
6
+ import { readTaskFinalizationReceipt } from '../../task/finalization.js';
7
+ import { inspectSandboxControlContainer } from './container-identity.js';
8
+ import { atomicWriteJson, readSandboxControlStatus } from './state.js';
9
+ import { taskViewForManifest } from './task-view.js';
10
+ function evidencePath(manifest) {
11
+ return path.join(path.dirname(manifest.processingDir), 'completed-reentry.json');
12
+ }
13
+ function invalid() {
14
+ return new Error('SANDBOX_COMPLETED_REENTRY_EVIDENCE_INVALID');
15
+ }
16
+ export async function prepareCompletedReentry(manifest, inspect = inspectSandboxControlContainer) {
17
+ if (manifest.mode !== 'task-bound' || !manifest.taskId)
18
+ throw invalid();
19
+ assertGitWorktreeBinding(manifest.repoRoot, manifest.worktreeRoot, manifest.branch);
20
+ const container = await inspect(manifest);
21
+ if (container.state !== 'found' || container.id !== manifest.containerIdentity.id)
22
+ throw invalid();
23
+ const task = resolveTaskWorkspace(manifest.taskId, manifest.repoRoot);
24
+ const metadata = parseTypedTaskFrontmatter(fs.readFileSync(task.taskMd, 'utf8'));
25
+ if (task.state !== 'completed' || task.branch !== manifest.branch
26
+ || metadata.id !== manifest.taskId || metadata.status !== 'completed')
27
+ throw invalid();
28
+ const receipt = readTaskFinalizationReceipt(manifest.repoRoot, manifest.taskId);
29
+ if (!receipt || receipt.taskId !== manifest.taskId)
30
+ throw invalid();
31
+ const view = taskViewForManifest({ ...manifest, receipt });
32
+ if (view.state !== 'current' || view.observedSource !== 'completed' || !view.receipt)
33
+ throw invalid();
34
+ const status = readSandboxControlStatus(manifest.publicStatusDir);
35
+ const previous = status.taskView;
36
+ if (status.generation !== manifest.generation || status.activeRequestId !== null
37
+ || previous.taskId !== manifest.taskId || !previous.receipt
38
+ || previous.receipt.receiptId !== view.receipt.receiptId
39
+ || previous.receipt.generation !== view.receipt.generation
40
+ || previous.receipt.requestId !== view.receipt.requestId
41
+ || previous.receipt.revision > view.receipt.revision)
42
+ throw invalid();
43
+ const completedRoot = fs.realpathSync.native(path.join(manifest.repoRoot, '.agents', 'workspace', 'completed'));
44
+ const source = fs.realpathSync.native(path.join(completedRoot, manifest.taskId));
45
+ if (source !== path.join(completedRoot, manifest.taskId))
46
+ throw invalid();
47
+ const stat = fs.statSync(source, { bigint: true });
48
+ return {
49
+ taskId: manifest.taskId, generation: manifest.generation,
50
+ containerId: container.id, branch: manifest.branch,
51
+ worktreeRoot: fs.realpathSync.native(manifest.worktreeRoot),
52
+ source, sourceDevice: String(stat.dev), sourceInode: String(stat.ino), receipt: view.receipt
53
+ };
54
+ }
55
+ export function publishCompletedReentry(manifest, evidence) {
56
+ atomicWriteJson(evidencePath(manifest), evidence);
57
+ }
58
+ export async function completedReentryView(manifest, inspect = inspectSandboxControlContainer) {
59
+ const file = evidencePath(manifest);
60
+ if (!fs.existsSync(file))
61
+ return null;
62
+ const evidence = JSON.parse(fs.readFileSync(file, 'utf8'));
63
+ const current = await prepareCompletedReentry(manifest, inspect);
64
+ if (JSON.stringify(evidence) !== JSON.stringify(current))
65
+ throw invalid();
66
+ return {
67
+ state: 'current', taskId: current.taskId, observedSource: 'completed',
68
+ receipt: current.receipt, reasonCode: null
69
+ };
70
+ }
71
+ export async function waitForCompletedReentry(manifest, evidence) {
72
+ const deadline = Date.now() + 10_000;
73
+ while (Date.now() < deadline) {
74
+ const status = readSandboxControlStatus(manifest.publicStatusDir);
75
+ if (status.generation !== evidence.generation)
76
+ throw invalid();
77
+ if (status.taskView.state === 'current' && status.taskView.observedSource === 'completed'
78
+ && status.taskView.taskId === evidence.taskId
79
+ && JSON.stringify(status.taskView.receipt) === JSON.stringify(evidence.receipt))
80
+ return;
81
+ await new Promise((resolve) => setTimeout(resolve, 100));
82
+ }
83
+ throw new Error('SANDBOX_COMPLETED_REENTRY_STATUS_TIMEOUT');
84
+ }
85
+ //# sourceMappingURL=completed-reentry.js.map
@@ -1,15 +1,11 @@
1
- import { commandForEngine, runEngine, runProbe } from '../shell.js';
2
- function isAuthoritativeNotFound(error) {
3
- const message = error instanceof Error ? error.message : String(error);
4
- return /(?:no such (?:container|object)|container .* not found|cannot find container)/i.test(message);
5
- }
1
+ import { runProbe } from '../shell.js';
2
+ import { captureSandboxAuthority, isSandboxAuthorityEvidence, verifySandboxAuthority } from '../engines/authority.js';
3
+ import { discoverExactContainer } from '../engines/docker-exact-discovery.js';
6
4
  export function classifySandboxContainerInspection(expected, inspection) {
7
5
  if ('notFound' in inspection)
8
6
  return { state: 'absent', id: expected.id };
9
7
  if ('error' in inspection) {
10
- return isAuthoritativeNotFound(inspection.error)
11
- ? { state: 'absent', id: expected.id }
12
- : { state: 'unknown', reason: `container inspection failed: ${inspection.error instanceof Error ? inspection.error.message : String(inspection.error)}` };
8
+ return { state: 'unknown', reason: `container inspection failed: ${inspection.error instanceof Error ? inspection.error.message : String(inspection.error)}` };
13
9
  }
14
10
  const response = inspection;
15
11
  if (typeof response.id !== 'string' || response.id !== expected.id
@@ -30,32 +26,33 @@ export function classifySandboxContainerInspection(expected, inspection) {
30
26
  };
31
27
  }
32
28
  export async function inspectSandboxControlContainer(manifest, options = {}) {
29
+ if (!isSandboxAuthorityEvidence(manifest.authorityEvidence)) {
30
+ return { state: 'unknown', reason: 'SANDBOX_AUTHORITY_EVIDENCE_MISSING' };
31
+ }
33
32
  try {
34
- const args = ['inspect', '--format', '{{json .}}', manifest.containerIdentity.id];
35
- let raw;
36
- if (options.run) {
37
- raw = options.run(manifest.engine, 'docker', args, options.timeoutMs === undefined ? {} : { timeout: options.timeoutMs });
38
- }
39
- else {
40
- const command = commandForEngine(manifest.engine, 'docker', args);
41
- const result = (options.probe ?? runProbe)(command.cmd, command.args, options.timeoutMs === undefined ? {} : { timeout: options.timeoutMs });
42
- if (result.status !== 0) {
43
- const stderr = typeof result.stderr === 'string' ? result.stderr : result.stderr?.toString('utf8') ?? '';
44
- return classifySandboxContainerInspection(manifest.containerIdentity, {
45
- error: new Error(stderr || `container inspection exited with ${result.status ?? 'unknown'}`)
46
- });
47
- }
48
- raw = typeof result.stdout === 'string' ? result.stdout : result.stdout?.toString('utf8') ?? '';
33
+ const authority = captureSandboxAuthority(manifest.engine, {
34
+ probe: options.probe,
35
+ timeoutMs: options.timeoutMs,
36
+ lockDomain: manifest.authorityEvidence.lockDomain,
37
+ route: manifest.authorityEvidence
38
+ });
39
+ const authorityState = verifySandboxAuthority(manifest.authorityEvidence, authority);
40
+ if (authorityState.state !== 'verified') {
41
+ return { state: 'unknown', reason: authorityState.reason ?? 'SANDBOX_AUTHORITY_UNAVAILABLE' };
49
42
  }
50
- const parsed = JSON.parse(raw);
51
- const value = Array.isArray(parsed) && parsed.length === 1 ? parsed[0] : parsed;
52
- if (!value || Array.isArray(value))
53
- return { state: 'unknown', reason: 'container inspection response is incomplete' };
54
- return classifySandboxContainerInspection(manifest.containerIdentity, {
55
- id: value.Id,
56
- running: value.State?.Running,
57
- labels: value.Config?.Labels
43
+ const discovered = discoverExactContainer(manifest.engine, manifest.containerIdentity.id, {
44
+ probe: options.probe,
45
+ timeoutMs: options.timeoutMs,
46
+ authority: manifest.authorityEvidence
58
47
  });
48
+ if (discovered.state === 'absent')
49
+ return { state: 'absent', id: discovered.id };
50
+ if (discovered.state === 'conflict') {
51
+ return { state: 'unknown', reason: `SANDBOX_CONTROL_CONTAINER_CONFLICT: ${discovered.reason}` };
52
+ }
53
+ if (discovered.state === 'unknown')
54
+ return discovered;
55
+ return classifySandboxContainerInspection(manifest.containerIdentity, discovered);
59
56
  }
60
57
  catch (error) {
61
58
  return classifySandboxContainerInspection(manifest.containerIdentity, { error });