@fitlab-ai/agent-infra 0.9.1 → 0.9.3

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 (476) hide show
  1. package/README.md +24 -11
  2. package/README.zh-CN.md +24 -11
  3. package/bin/cli.ts +12 -0
  4. package/dist/bin/cli.js +14 -0
  5. package/dist/bin/internal-cli.js +30 -0
  6. package/dist/lib/agent-client.js +163 -0
  7. package/dist/lib/agent-clients/adapter.js +337 -0
  8. package/dist/lib/agent-clients/adapters/antigravity-cli.js +64 -0
  9. package/dist/lib/agent-clients/adapters/claude-code.js +71 -0
  10. package/dist/lib/agent-clients/adapters/codex-sandbox.js +210 -0
  11. package/dist/lib/agent-clients/adapters/codex.js +63 -0
  12. package/dist/lib/agent-clients/adapters/index.js +20 -0
  13. package/dist/lib/agent-clients/adapters/opencode.js +73 -0
  14. package/dist/lib/agent-clients/config.js +215 -0
  15. package/dist/lib/agent-clients/custom-tuis.js +99 -0
  16. package/dist/lib/agent-clients/invocation.js +9 -0
  17. package/dist/lib/agent-clients/next-steps.js +47 -0
  18. package/dist/lib/agent-clients/project-assets.js +45 -0
  19. package/dist/lib/agent-clients/reconcile.js +236 -0
  20. package/dist/lib/agent-clients/registry.js +78 -0
  21. package/dist/lib/agent-clients/schema.js +75 -0
  22. package/dist/lib/agent-clients/tokens.js +49 -0
  23. package/dist/lib/agent-clients/types.js +29 -0
  24. package/dist/lib/builtin-tuis.js +9 -14
  25. package/dist/lib/defaults.json +85 -73
  26. package/dist/lib/git/review-snapshot.js +25 -10
  27. package/dist/lib/git/reviewed-commit-equivalence.js +110 -0
  28. package/dist/lib/git/workflow.js +54 -1
  29. package/dist/lib/init.js +47 -91
  30. package/dist/lib/internal/agent-client.js +174 -0
  31. package/dist/lib/internal/git-workflow.js +7 -2
  32. package/dist/lib/internal/platform-checks.js +3 -3
  33. package/dist/lib/internal/platform-comment.js +29 -2
  34. package/dist/lib/internal/platform-issue.js +7 -0
  35. package/dist/lib/internal/platform-pr-review.js +132 -0
  36. package/dist/lib/internal/platform-pr.js +20 -2
  37. package/dist/lib/internal/platform-release-notes.js +52 -16
  38. package/dist/lib/internal/pr-review-grade.js +140 -0
  39. package/dist/lib/internal/release-workflow.js +82 -20
  40. package/dist/lib/internal/task-activity.js +73 -0
  41. package/dist/lib/internal/task-event.js +17 -1
  42. package/dist/lib/internal/task-lifecycle.js +7 -0
  43. package/dist/lib/internal/task-orchestration.js +196 -0
  44. package/dist/lib/internal/task-review.js +70 -0
  45. package/dist/lib/merge.js +2 -1
  46. package/dist/lib/platform/adapters.js +45 -1
  47. package/dist/lib/platform/change-request-git-evidence.js +113 -0
  48. package/dist/lib/platform/completion-backfill.js +122 -0
  49. package/dist/lib/platform/issue-comments.js +3 -2
  50. package/dist/lib/platform/merged-pr-equivalence.js +156 -16
  51. package/dist/lib/platform/pr-checks.js +101 -50
  52. package/dist/lib/platform/pr-review.js +166 -0
  53. package/dist/lib/platform/pull-requests.js +432 -7
  54. package/dist/lib/platform/release-notes.js +85 -3
  55. package/dist/lib/platform/releases.js +1 -1
  56. package/dist/lib/platform/verification-required.js +8 -10
  57. package/dist/lib/pr-review/evidence-grading.js +229 -0
  58. package/dist/lib/prompt.js +15 -3
  59. package/dist/lib/release/channels.js +4 -1
  60. package/dist/lib/release/workflow.js +4 -2
  61. package/dist/lib/remove-dir.js +25 -0
  62. package/dist/lib/run/tui.js +11 -7
  63. package/dist/lib/sandbox/agent-client-reconciler.js +234 -0
  64. package/dist/lib/sandbox/clipboard/linux.js +2 -1
  65. package/dist/lib/sandbox/commands/create.js +76 -200
  66. package/dist/lib/sandbox/commands/enter.js +17 -1
  67. package/dist/lib/sandbox/commands/prune.js +2 -2
  68. package/dist/lib/sandbox/commands/rm.js +3 -2
  69. package/dist/lib/sandbox/commands/show.js +1 -1
  70. package/dist/lib/sandbox/config.js +21 -4
  71. package/dist/lib/sandbox/constants.js +3 -0
  72. package/dist/lib/sandbox/dockerfile.js +2 -1
  73. package/dist/lib/sandbox/managed-fs.js +10 -5
  74. package/dist/lib/sandbox/recovery.js +52 -36
  75. package/dist/lib/sandbox/shell.js +1 -1
  76. package/dist/lib/sandbox/tool-types.js +8 -0
  77. package/dist/lib/sandbox/tools.js +2 -126
  78. package/dist/lib/task/activity-intent.js +101 -0
  79. package/dist/lib/task/artifact-lifecycle.js +3 -50
  80. package/dist/lib/task/commands/decisions.js +50 -20
  81. package/dist/lib/task/commands/log.js +15 -14
  82. package/dist/lib/task/delegation-receipts.js +128 -0
  83. package/dist/lib/task/events.js +146 -8
  84. package/dist/lib/task/finalization-artifacts.js +35 -0
  85. package/dist/lib/task/lifecycle-execution.js +46 -0
  86. package/dist/lib/task/orchestration.js +784 -0
  87. package/dist/lib/task/review-artifacts.js +143 -59
  88. package/dist/lib/task/review-finalization.js +186 -0
  89. package/dist/lib/task/review-fingerprint.js +4 -0
  90. package/dist/lib/task/task-execution-lock.js +231 -0
  91. package/dist/lib/task/verification-checks.js +2 -1
  92. package/dist/lib/task/verification-engine.js +372 -28
  93. package/dist/lib/task/verification-review.js +1 -1
  94. package/dist/lib/task/verification.js +5 -2
  95. package/dist/lib/task/workspace-snapshot.js +46 -0
  96. package/dist/lib/update.js +42 -161
  97. package/lib/agent-client.ts +214 -0
  98. package/lib/agent-clients/adapter.ts +534 -0
  99. package/lib/agent-clients/adapters/antigravity-cli.ts +65 -0
  100. package/lib/agent-clients/adapters/claude-code.ts +79 -0
  101. package/lib/agent-clients/adapters/codex-sandbox.ts +245 -0
  102. package/lib/agent-clients/adapters/codex.ts +67 -0
  103. package/lib/agent-clients/adapters/index.ts +27 -0
  104. package/lib/agent-clients/adapters/opencode.ts +75 -0
  105. package/lib/agent-clients/config.ts +323 -0
  106. package/lib/agent-clients/custom-tuis.ts +149 -0
  107. package/lib/agent-clients/invocation.ts +19 -0
  108. package/lib/agent-clients/next-steps.ts +85 -0
  109. package/lib/agent-clients/project-assets.ts +96 -0
  110. package/lib/agent-clients/reconcile.ts +325 -0
  111. package/lib/agent-clients/registry.ts +154 -0
  112. package/lib/agent-clients/schema.ts +80 -0
  113. package/lib/agent-clients/tokens.ts +53 -0
  114. package/lib/agent-clients/types.ts +92 -0
  115. package/lib/benchmark/schemas/v1.0.0/case-manifest.schema.json +120 -0
  116. package/lib/benchmark/schemas/v1.0.0/common.schema.json +109 -0
  117. package/lib/benchmark/schemas/v1.0.0/grader-result.schema.json +160 -0
  118. package/lib/benchmark/schemas/v1.0.0/run-manifest.schema.json +122 -0
  119. package/lib/benchmark/schemas/v1.0.0/subject.schema.json +227 -0
  120. package/lib/builtin-tuis.ts +16 -15
  121. package/lib/defaults.json +24 -12
  122. package/lib/git/review-snapshot.ts +39 -9
  123. package/lib/git/reviewed-commit-equivalence.ts +135 -0
  124. package/lib/git/workflow.ts +66 -2
  125. package/lib/init.ts +53 -121
  126. package/lib/internal/agent-client.ts +186 -0
  127. package/lib/internal/git-workflow.ts +6 -2
  128. package/lib/internal/platform-checks.ts +4 -4
  129. package/lib/internal/platform-comment.ts +17 -2
  130. package/lib/internal/platform-issue.ts +4 -0
  131. package/lib/internal/platform-pr-review.ts +104 -0
  132. package/lib/internal/platform-pr.ts +14 -1
  133. package/lib/internal/platform-release-notes.ts +59 -16
  134. package/lib/internal/pr-review-grade.ts +130 -0
  135. package/lib/internal/release-workflow.ts +79 -20
  136. package/lib/internal/task-activity.ts +55 -0
  137. package/lib/internal/task-event.ts +9 -1
  138. package/lib/internal/task-lifecycle.ts +4 -0
  139. package/lib/internal/task-orchestration.ts +171 -0
  140. package/lib/internal/task-review.ts +70 -0
  141. package/lib/merge.ts +2 -1
  142. package/lib/platform/adapters.ts +169 -3
  143. package/lib/platform/change-request-git-evidence.ts +159 -0
  144. package/lib/platform/completion-backfill.ts +134 -0
  145. package/lib/platform/issue-comments.ts +3 -2
  146. package/lib/platform/merged-pr-equivalence.ts +178 -19
  147. package/lib/platform/pr-checks.ts +121 -66
  148. package/lib/platform/pr-review.ts +201 -0
  149. package/lib/platform/pull-requests.ts +529 -27
  150. package/lib/platform/release-notes.ts +100 -4
  151. package/lib/platform/releases.ts +1 -1
  152. package/lib/platform/verification-required.ts +12 -10
  153. package/lib/pr-review/evidence-grading.ts +318 -0
  154. package/lib/prompt.ts +16 -3
  155. package/lib/release/channels.ts +4 -1
  156. package/lib/release/workflow.ts +4 -3
  157. package/lib/remove-dir.ts +28 -0
  158. package/lib/run/tui.ts +12 -5
  159. package/lib/sandbox/agent-client-reconciler.ts +378 -0
  160. package/lib/sandbox/clipboard/linux.ts +2 -1
  161. package/lib/sandbox/commands/create.ts +111 -212
  162. package/lib/sandbox/commands/enter.ts +23 -1
  163. package/lib/sandbox/commands/prune.ts +2 -2
  164. package/lib/sandbox/commands/rm.ts +3 -2
  165. package/lib/sandbox/commands/show.ts +1 -1
  166. package/lib/sandbox/config.ts +31 -4
  167. package/lib/sandbox/constants.ts +6 -0
  168. package/lib/sandbox/dockerfile.ts +2 -1
  169. package/lib/sandbox/managed-fs.ts +18 -5
  170. package/lib/sandbox/recovery.ts +98 -67
  171. package/lib/sandbox/shell.ts +1 -1
  172. package/lib/sandbox/tool-types.ts +143 -0
  173. package/lib/sandbox/tools.ts +5 -157
  174. package/lib/server/server.schema.json +2 -2
  175. package/lib/task/activity-intent.ts +128 -0
  176. package/lib/task/artifact-lifecycle.ts +3 -39
  177. package/lib/task/commands/decisions.ts +53 -20
  178. package/lib/task/commands/log.ts +15 -14
  179. package/lib/task/delegation-receipts.ts +199 -0
  180. package/lib/task/events.ts +164 -11
  181. package/lib/task/finalization-artifacts.ts +58 -0
  182. package/lib/task/lifecycle-execution.ts +106 -0
  183. package/lib/task/orchestration.ts +1022 -0
  184. package/lib/task/review-artifacts.ts +201 -69
  185. package/lib/task/review-finalization.ts +306 -0
  186. package/lib/task/review-fingerprint.ts +5 -0
  187. package/lib/task/task-execution-lock.ts +296 -0
  188. package/lib/task/verification-checks.ts +2 -1
  189. package/lib/task/verification-engine.ts +424 -28
  190. package/lib/task/verification-review.ts +1 -0
  191. package/lib/task/verification.ts +8 -3
  192. package/lib/task/workspace-snapshot.ts +57 -0
  193. package/lib/update.ts +48 -184
  194. package/package.json +4 -4
  195. package/templates/.agents/QUICKSTART.en.md +25 -8
  196. package/templates/.agents/QUICKSTART.zh-CN.md +25 -8
  197. package/templates/.agents/README.en.md +29 -25
  198. package/templates/.agents/README.zh-CN.md +29 -25
  199. package/templates/.agents/hooks/lifecycle-delegation.js +75 -0
  200. package/templates/.agents/rules/README.en.md +2 -0
  201. package/templates/.agents/rules/README.zh-CN.md +2 -0
  202. package/templates/.agents/rules/commit-and-pr.en.md +1 -0
  203. package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -0
  204. package/templates/.agents/rules/create-issue.github.en.md +4 -2
  205. package/templates/.agents/rules/create-issue.github.zh-CN.md +4 -2
  206. package/templates/.agents/rules/human-decision-context.en.md +14 -12
  207. package/templates/.agents/rules/human-decision-context.zh-CN.md +14 -12
  208. package/templates/.agents/rules/issue-fields.github.en.md +3 -1
  209. package/templates/.agents/rules/issue-fields.github.zh-CN.md +3 -1
  210. package/templates/.agents/rules/issue-pr-commands.en.md +5 -3
  211. package/templates/.agents/rules/issue-pr-commands.github.en.md +5 -3
  212. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +5 -3
  213. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +5 -3
  214. package/templates/.agents/rules/issue-sync.github.en.md +7 -3
  215. package/templates/.agents/rules/issue-sync.github.zh-CN.md +8 -4
  216. package/templates/.agents/rules/lifecycle-orchestration.en.md +24 -0
  217. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +24 -0
  218. package/templates/.agents/rules/milestone-inference.github.en.md +4 -2
  219. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +4 -2
  220. package/templates/.agents/rules/next-step-output.en.md +18 -0
  221. package/templates/.agents/rules/next-step-output.zh-CN.md +18 -0
  222. package/templates/.agents/rules/no-mid-flow-questions.en.md +19 -0
  223. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +19 -0
  224. package/templates/.agents/rules/pr-checks-commands.en.md +3 -3
  225. package/templates/.agents/rules/pr-checks-commands.github.en.md +2 -2
  226. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +2 -2
  227. package/templates/.agents/rules/pr-checks-commands.zh-CN.md +3 -3
  228. package/templates/.agents/rules/pr-sync.en.md +3 -1
  229. package/templates/.agents/rules/pr-sync.github.en.md +11 -1
  230. package/templates/.agents/rules/pr-sync.github.zh-CN.md +11 -1
  231. package/templates/.agents/rules/pr-sync.zh-CN.md +3 -1
  232. package/templates/.agents/rules/release-commands.en.md +1 -1
  233. package/templates/.agents/rules/release-commands.github.en.md +21 -5
  234. package/templates/.agents/rules/release-commands.github.zh-CN.md +21 -5
  235. package/templates/.agents/rules/release-commands.zh-CN.md +1 -1
  236. package/templates/.agents/rules/review-handshake.en.md +4 -4
  237. package/templates/.agents/rules/review-handshake.zh-CN.md +4 -4
  238. package/templates/.agents/rules/review-method.en.md +113 -0
  239. package/templates/.agents/rules/review-method.zh-CN.md +98 -0
  240. package/templates/.agents/rules/task-management.en.md +11 -0
  241. package/templates/.agents/rules/task-management.zh-CN.md +11 -0
  242. package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -12
  243. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +15 -12
  244. package/templates/.agents/skills/block-task/SKILL.en.md +11 -9
  245. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +11 -9
  246. package/templates/.agents/skills/cancel-task/SKILL.en.md +10 -8
  247. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +11 -9
  248. package/templates/.agents/skills/check-task/SKILL.en.md +16 -16
  249. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -16
  250. package/templates/.agents/skills/close-codescan/SKILL.en.md +7 -5
  251. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +7 -5
  252. package/templates/.agents/skills/close-dependabot/SKILL.en.md +7 -5
  253. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +7 -5
  254. package/templates/.agents/skills/code-task/SKILL.en.md +10 -7
  255. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +13 -10
  256. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +14 -16
  257. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +14 -16
  258. package/templates/.agents/skills/code-task/reference/output-template.en.md +3 -3
  259. package/templates/.agents/skills/code-task/reference/output-template.zh-CN.md +3 -3
  260. package/templates/.agents/skills/commit/SKILL.en.md +13 -1
  261. package/templates/.agents/skills/commit/SKILL.zh-CN.md +13 -1
  262. package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -1
  263. package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -1
  264. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
  265. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
  266. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  267. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  268. package/templates/.agents/skills/commit/reference/task-status-update.en.md +24 -28
  269. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +24 -28
  270. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +6 -4
  271. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +6 -4
  272. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +1 -1
  273. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
  274. package/templates/.agents/skills/complete-task/SKILL.en.md +23 -8
  275. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +23 -8
  276. package/templates/.agents/skills/complete-task/config/verify.en.json +1 -0
  277. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +1 -0
  278. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +17 -0
  279. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +17 -0
  280. package/templates/.agents/skills/create-pr/SKILL.en.md +13 -11
  281. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +13 -11
  282. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +1 -1
  283. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +1 -1
  284. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +3 -3
  285. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +3 -3
  286. package/templates/.agents/skills/create-release-note/SKILL.en.md +17 -16
  287. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +17 -16
  288. package/templates/.agents/skills/create-task/SKILL.en.md +16 -14
  289. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +16 -14
  290. package/templates/.agents/skills/import-codescan/SKILL.en.md +5 -5
  291. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +5 -5
  292. package/templates/.agents/skills/import-dependabot/SKILL.en.md +5 -5
  293. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +5 -5
  294. package/templates/.agents/skills/import-issue/SKILL.en.md +10 -8
  295. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +10 -8
  296. package/templates/.agents/skills/init-labels/SKILL.en.md +4 -4
  297. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +4 -4
  298. package/templates/.agents/skills/init-milestones/SKILL.en.md +4 -4
  299. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +4 -4
  300. package/templates/.agents/skills/plan-task/SKILL.en.md +13 -10
  301. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +13 -10
  302. package/templates/.agents/skills/post-release/SKILL.en.md +2 -0
  303. package/templates/.agents/skills/post-release/SKILL.zh-CN.md +2 -0
  304. package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
  305. package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
  306. package/templates/.agents/skills/release/SKILL.en.md +16 -10
  307. package/templates/.agents/skills/release/SKILL.zh-CN.md +16 -10
  308. package/templates/.agents/skills/restore-task/SKILL.en.md +4 -1
  309. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +4 -1
  310. package/templates/.agents/skills/review-analysis/SKILL.en.md +18 -4
  311. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +19 -5
  312. package/templates/.agents/skills/review-analysis/config/verify.en.json +6 -0
  313. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +6 -0
  314. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +13 -15
  315. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +13 -15
  316. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +51 -5
  317. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +52 -6
  318. package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +25 -22
  319. package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +25 -22
  320. package/templates/.agents/skills/review-code/SKILL.en.md +35 -12
  321. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +35 -12
  322. package/templates/.agents/skills/review-code/config/verify.en.json +7 -0
  323. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +7 -0
  324. package/templates/.agents/skills/review-code/reference/concurrency-risks.en.md +25 -0
  325. package/templates/.agents/skills/review-code/reference/concurrency-risks.zh-CN.md +25 -0
  326. package/templates/.agents/skills/review-code/reference/cross-platform-risks.en.md +27 -0
  327. package/templates/.agents/skills/review-code/reference/cross-platform-risks.zh-CN.md +27 -0
  328. package/templates/.agents/skills/review-code/reference/documentation-antipatterns.en.md +13 -0
  329. package/templates/.agents/skills/review-code/reference/documentation-antipatterns.zh-CN.md +13 -0
  330. package/templates/.agents/skills/review-code/reference/migration-risks.en.md +25 -0
  331. package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +25 -0
  332. package/templates/.agents/skills/review-code/reference/output-templates.en.md +22 -24
  333. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +22 -24
  334. package/templates/.agents/skills/review-code/reference/report-template.en.md +54 -7
  335. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +54 -7
  336. package/templates/.agents/skills/review-code/reference/review-criteria.en.md +29 -24
  337. package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +29 -24
  338. package/templates/.agents/skills/review-code/reference/security-risks.en.md +25 -0
  339. package/templates/.agents/skills/review-code/reference/security-risks.zh-CN.md +25 -0
  340. package/templates/.agents/skills/review-plan/SKILL.en.md +18 -4
  341. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +19 -5
  342. package/templates/.agents/skills/review-plan/config/verify.en.json +6 -0
  343. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +6 -0
  344. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +13 -15
  345. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +13 -15
  346. package/templates/.agents/skills/review-plan/reference/report-template.en.md +61 -5
  347. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +61 -5
  348. package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +21 -24
  349. package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +21 -24
  350. package/templates/.agents/skills/review-pr/SKILL.en.md +158 -0
  351. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +158 -0
  352. package/templates/.agents/skills/review-pr/config/verify.en.json +37 -0
  353. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +37 -0
  354. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +65 -0
  355. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +65 -0
  356. package/templates/.agents/skills/review-pr/reference/output-guidance.en.md +18 -0
  357. package/templates/.agents/skills/review-pr/reference/output-guidance.zh-CN.md +18 -0
  358. package/templates/.agents/skills/review-pr/reference/report-template.en.md +85 -0
  359. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +85 -0
  360. package/templates/.agents/skills/run-task/SKILL.en.md +22 -0
  361. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +22 -0
  362. package/templates/.agents/skills/run-task/config/verify.en.json +10 -0
  363. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +10 -0
  364. package/templates/.agents/skills/run-task/reference/host-validation.en.md +20 -0
  365. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +20 -0
  366. package/templates/.agents/skills/test/SKILL.en.md +4 -4
  367. package/templates/.agents/skills/test/SKILL.zh-CN.md +4 -4
  368. package/templates/.agents/skills/test-integration/SKILL.en.md +4 -4
  369. package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +4 -4
  370. package/templates/.agents/skills/update-agent-infra/SKILL.en.md +5 -5
  371. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +5 -5
  372. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +664 -246
  373. package/templates/.agents/skills/upgrade-dependency/SKILL.en.md +4 -4
  374. package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +4 -4
  375. package/templates/.agents/skills/watch-pr/SKILL.en.md +21 -21
  376. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +21 -21
  377. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +27 -6
  378. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +26 -5
  379. package/templates/.agents/templates/task.en.md +1 -1
  380. package/templates/.agents/templates/task.zh-CN.md +1 -1
  381. package/templates/.agents/workflows/bug-fix.en.yaml +3 -3
  382. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +3 -3
  383. package/templates/.agents/workflows/code-review.en.yaml +1 -1
  384. package/templates/.agents/workflows/code-review.zh-CN.yaml +1 -1
  385. package/templates/.agents/workflows/feature-development.en.yaml +4 -4
  386. package/templates/.agents/workflows/feature-development.zh-CN.yaml +4 -4
  387. package/templates/.agents/workflows/refactoring.en.yaml +3 -3
  388. package/templates/.agents/workflows/refactoring.zh-CN.yaml +3 -3
  389. package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +6 -0
  390. package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +6 -0
  391. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +6 -0
  392. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +6 -0
  393. package/templates/.claude/commands/post-release.en.md +1 -0
  394. package/templates/.claude/commands/post-release.zh-CN.md +1 -0
  395. package/templates/.claude/commands/review-pr.en.md +8 -0
  396. package/templates/.claude/commands/review-pr.zh-CN.md +8 -0
  397. package/templates/.claude/commands/run-task.en.md +8 -0
  398. package/templates/.claude/commands/run-task.zh-CN.md +8 -0
  399. package/templates/.claude/settings.json +24 -0
  400. package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +3 -0
  401. package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +3 -0
  402. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +3 -0
  403. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +3 -0
  404. package/templates/.gemini/commands/_project_/review-pr.en.toml +10 -0
  405. package/templates/.gemini/commands/_project_/review-pr.zh-CN.toml +10 -0
  406. package/templates/.opencode/commands/post-release.en.md +2 -0
  407. package/templates/.opencode/commands/post-release.zh-CN.md +2 -0
  408. package/templates/.opencode/commands/review-pr.en.md +11 -0
  409. package/templates/.opencode/commands/review-pr.zh-CN.md +11 -0
  410. package/templates/.opencode/commands/run-task.en.md +11 -0
  411. package/templates/.opencode/commands/run-task.zh-CN.md +11 -0
  412. package/templates/.gemini/commands/_project_/analyze-task.en.toml +0 -10
  413. package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +0 -10
  414. package/templates/.gemini/commands/_project_/archive-tasks.en.toml +0 -10
  415. package/templates/.gemini/commands/_project_/archive-tasks.zh-CN.toml +0 -10
  416. package/templates/.gemini/commands/_project_/block-task.en.toml +0 -10
  417. package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +0 -10
  418. package/templates/.gemini/commands/_project_/cancel-task.en.toml +0 -10
  419. package/templates/.gemini/commands/_project_/cancel-task.zh-CN.toml +0 -10
  420. package/templates/.gemini/commands/_project_/check-task.en.toml +0 -10
  421. package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +0 -10
  422. package/templates/.gemini/commands/_project_/close-codescan.en.toml +0 -8
  423. package/templates/.gemini/commands/_project_/close-codescan.zh-CN.toml +0 -8
  424. package/templates/.gemini/commands/_project_/close-dependabot.en.toml +0 -8
  425. package/templates/.gemini/commands/_project_/close-dependabot.zh-CN.toml +0 -8
  426. package/templates/.gemini/commands/_project_/code-task.en.toml +0 -10
  427. package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +0 -10
  428. package/templates/.gemini/commands/_project_/commit.en.toml +0 -10
  429. package/templates/.gemini/commands/_project_/commit.zh-CN.toml +0 -10
  430. package/templates/.gemini/commands/_project_/complete-manual-validation.en.toml +0 -10
  431. package/templates/.gemini/commands/_project_/complete-manual-validation.zh-CN.toml +0 -10
  432. package/templates/.gemini/commands/_project_/complete-task.en.toml +0 -10
  433. package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +0 -10
  434. package/templates/.gemini/commands/_project_/create-pr.en.toml +0 -10
  435. package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +0 -10
  436. package/templates/.gemini/commands/_project_/create-release-note.en.toml +0 -8
  437. package/templates/.gemini/commands/_project_/create-release-note.zh-CN.toml +0 -8
  438. package/templates/.gemini/commands/_project_/create-task.en.toml +0 -8
  439. package/templates/.gemini/commands/_project_/create-task.zh-CN.toml +0 -8
  440. package/templates/.gemini/commands/_project_/import-codescan.en.toml +0 -8
  441. package/templates/.gemini/commands/_project_/import-codescan.zh-CN.toml +0 -8
  442. package/templates/.gemini/commands/_project_/import-dependabot.en.toml +0 -8
  443. package/templates/.gemini/commands/_project_/import-dependabot.zh-CN.toml +0 -8
  444. package/templates/.gemini/commands/_project_/import-issue.en.toml +0 -8
  445. package/templates/.gemini/commands/_project_/import-issue.zh-CN.toml +0 -8
  446. package/templates/.gemini/commands/_project_/init-labels.en.toml +0 -8
  447. package/templates/.gemini/commands/_project_/init-labels.zh-CN.toml +0 -8
  448. package/templates/.gemini/commands/_project_/init-milestones.en.toml +0 -10
  449. package/templates/.gemini/commands/_project_/init-milestones.zh-CN.toml +0 -10
  450. package/templates/.gemini/commands/_project_/plan-task.en.toml +0 -10
  451. package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +0 -10
  452. package/templates/.gemini/commands/_project_/post-release.en.toml +0 -6
  453. package/templates/.gemini/commands/_project_/post-release.zh-CN.toml +0 -6
  454. package/templates/.gemini/commands/_project_/refine-title.en.toml +0 -8
  455. package/templates/.gemini/commands/_project_/refine-title.zh-CN.toml +0 -8
  456. package/templates/.gemini/commands/_project_/release.en.toml +0 -8
  457. package/templates/.gemini/commands/_project_/release.zh-CN.toml +0 -8
  458. package/templates/.gemini/commands/_project_/restore-task.en.toml +0 -8
  459. package/templates/.gemini/commands/_project_/restore-task.zh-CN.toml +0 -8
  460. package/templates/.gemini/commands/_project_/review-analysis.en.toml +0 -10
  461. package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +0 -10
  462. package/templates/.gemini/commands/_project_/review-code.en.toml +0 -10
  463. package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +0 -10
  464. package/templates/.gemini/commands/_project_/review-plan.en.toml +0 -10
  465. package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +0 -10
  466. package/templates/.gemini/commands/_project_/test-integration.en.toml +0 -6
  467. package/templates/.gemini/commands/_project_/test-integration.zh-CN.toml +0 -6
  468. package/templates/.gemini/commands/_project_/test.en.toml +0 -6
  469. package/templates/.gemini/commands/_project_/test.zh-CN.toml +0 -6
  470. package/templates/.gemini/commands/_project_/update-agent-infra.en.toml +0 -6
  471. package/templates/.gemini/commands/_project_/update-agent-infra.zh-CN.toml +0 -6
  472. package/templates/.gemini/commands/_project_/upgrade-dependency.en.toml +0 -8
  473. package/templates/.gemini/commands/_project_/upgrade-dependency.zh-CN.toml +0 -8
  474. package/templates/.gemini/commands/_project_/watch-pr.en.toml +0 -10
  475. package/templates/.gemini/commands/_project_/watch-pr.zh-CN.toml +0 -10
  476. package/templates/.gemini/settings.json +0 -3
@@ -6,14 +6,15 @@ import { execFileSync } from 'node:child_process';
6
6
  import { parseArgs } from 'node:util';
7
7
  import * as p from '@clack/prompts';
8
8
  import pc from 'picocolors';
9
- import * as toml from 'smol-toml';
9
+ import { listAgentClientAdapters } from '../../agent-clients/registry.js';
10
10
  import { loadConfig } from '../config.js';
11
- import { assertValidBranchName, containerName, containerNameCandidates, parsePositiveIntegerOption, sandboxBranchLabel, sandboxImageConfigLabel, sandboxImageRefreshLabel, sandboxLabel, shareBranchDir, shareCommonDir, shellConfigDir, worktreeDirCandidates } from '../constants.js';
11
+ import { assertValidBranchName, containerName, containerNameCandidates, parsePositiveIntegerOption, sandboxBranchLabel, sandboxImageConfigLabel, sandboxImageRefreshLabel, sandboxLabel, sandboxRuntimeCapabilityLabel, shareBranchDir, shareCommonDir, shellConfigDir, worktreeDirCandidates } from '../constants.js';
12
12
  import { prepareDockerfile } from '../dockerfile.js';
13
13
  import { assertBuildProxyCompatibility, buildProxyFailureHint, prepareBuildProxy, redactBuildProxyValues } from '../build-proxy.js';
14
14
  import { detectEngine, ensureDocker } from '../engine.js';
15
15
  import { commandForEngine, execEngine, run, runEngine, runOk, runOkEngine, runSafe, runSafeEngine, runVerboseEngine } from '../shell.js';
16
16
  import { resolveTaskBranch } from '../task-resolver.js';
17
+ import { createSandboxCapabilityPlan, runSandboxHooks, runBoundedSandboxHookCommand } from '../agent-client-reconciler.js';
17
18
  import { resolveTools, tmpfsSeedStagingPath, tmpfsSeedTargetPath, toolConfigDirCandidates } from '../tools.js';
18
19
  import { assertFreshSandboxReady, hydrateTmpfsSeedEntries, prepareTmpfsMounts } from '../recovery.js';
19
20
  import { hostJoin, toEnginePath, volumeArg } from '../engines/wsl2-paths.js';
@@ -22,32 +23,13 @@ import { clipboardHostDir, CONTAINER_CLIPBOARD_MOUNT } from '../clipboard/paths.
22
23
  import { validateSelinuxDisableEnv } from '../engines/selinux.js';
23
24
  import { dotfilesCacheDir, materializeDotfiles } from '../dotfiles.js';
24
25
  import { ensureSandboxDiscoveryReadmes } from '../readme-scaffold.js';
26
+ import { removeDirRecursive } from '../../remove-dir.js';
25
27
  import { prepareClaudeCredentials, redactCommandError, validateClaudeCredentialsEnvOverride } from '../credentials.js';
26
28
  import { detectHostTimezone } from '../host-timezone.js';
27
29
  import { buildImageSignature, buildSandboxImageArgs, isRefreshDisabled, isRefreshDue, parseImageLabels, parseRefreshTimestamp } from '../image-build.js';
28
- const OPENCODE_YOLO_PERMISSION = '{"*":"allow","read":"allow","bash":"allow","edit":"allow","webfetch":"allow","external_directory":"allow","doom_loop":"allow"}';
30
+ export { ensureCodexModelInheritance, ensureCodexWorkspaceTrust } from '../../agent-clients/adapters/codex-sandbox.js';
29
31
  const SANDBOX_ALIAS_BLOCK_BEGIN = '# >>> agent-infra managed aliases >>>';
30
32
  const SANDBOX_ALIAS_BLOCK_END = '# <<< agent-infra managed aliases <<<';
31
- const SANDBOX_ALIAS_NAMES = [
32
- 'claude-yolo',
33
- 'opencode-yolo',
34
- 'codex-yolo',
35
- 'gemini-yolo',
36
- 'cy',
37
- 'oy',
38
- 'xy',
39
- 'gy'
40
- ];
41
- const DEFAULT_SANDBOX_ALIASES = `alias claude-yolo='claude --dangerously-skip-permissions; tput ed'
42
- alias opencode-yolo='OPENCODE_PERMISSION='\\''${OPENCODE_YOLO_PERMISSION}'\\'' opencode; tput ed'
43
- alias codex-yolo='codex --yolo; tput ed'
44
- alias gemini-yolo='gemini --yolo; tput ed'
45
-
46
- alias cy='claude --dangerously-skip-permissions; tput ed'
47
- alias oy='OPENCODE_PERMISSION='\\''${OPENCODE_YOLO_PERMISSION}'\\'' opencode; tput ed'
48
- alias xy='codex --yolo; tput ed'
49
- alias gy='gemini --yolo; tput ed'
50
- `;
51
33
  const CONTAINER_HOME = '/home/devuser';
52
34
  const CONTAINER_SHELL_CONFIG_MOUNT = `${CONTAINER_HOME}/.host-shell-config`;
53
35
  const USAGE = `Usage: ai sandbox create <branch> [base] [--cpu <n>] [--memory <n>] [--no-refresh] [--inherit-proxy|-P] [--inherit-build-proxy|-B]
@@ -268,7 +250,7 @@ export function ensureShellConfigSymlinks(engine, container, execFn = execEngine
268
250
  }
269
251
  export function prepareHostShellConfig({ home, project, branch, repoRoot }) {
270
252
  const hostDir = hostShellConfigDir(home, project, branch);
271
- fs.rmSync(hostDir, { recursive: true, force: true });
253
+ removeDirRecursive(hostDir);
272
254
  fs.mkdirSync(hostDir, { recursive: true });
273
255
  writeSanitizedGitconfig({
274
256
  home,
@@ -306,11 +288,19 @@ function normalizeWorktreePath(worktreePath) {
306
288
  if (!worktreePath) {
307
289
  return '';
308
290
  }
291
+ const wslMount = process.platform === 'win32'
292
+ ? worktreePath.match(/^\/mnt\/([A-Za-z])(?:\/(.*))?$/)
293
+ : null;
294
+ const hostPath = wslMount
295
+ ? `${wslMount[1].toUpperCase()}:\\${(wslMount[2] ?? '').replace(/\//g, '\\')}`
296
+ : worktreePath;
309
297
  try {
310
- return fs.existsSync(worktreePath) ? fs.realpathSync(worktreePath) : path.resolve(worktreePath);
298
+ const normalized = fs.existsSync(hostPath) ? fs.realpathSync(hostPath) : path.resolve(hostPath);
299
+ return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
311
300
  }
312
301
  catch {
313
- return path.resolve(worktreePath);
302
+ const normalized = path.resolve(hostPath);
303
+ return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
314
304
  }
315
305
  }
316
306
  export function getGitSigningKey({ home, repoPath = null, execFn = execFileSync } = {}) {
@@ -481,7 +471,7 @@ export function collectHostProxyEntries(env) {
481
471
  });
482
472
  }
483
473
  export function buildContainerEnvFile(resolvedTools, engine, runSafeEngineFn = runSafeEngine, options = {}) {
484
- const { additionalEntries = [], mkdtempFn = fs.mkdtempSync, writeFileFn = fs.writeFileSync, chmodFn = fs.chmodSync, rmFn = fs.rmSync, tmpDir = os.tmpdir(), runSafeFn = runSafe } = options;
474
+ const { additionalEntries = [], mkdtempFn = fs.mkdtempSync, writeFileFn = fs.writeFileSync, chmodFn = fs.chmodSync, rmFn = removeDirRecursive, tmpDir = os.tmpdir(), runSafeFn = runSafe } = options;
485
475
  const entries = resolvedTools.flatMap(({ tool }) => Object.entries(tool.envVars ?? {}));
486
476
  entries.push(...additionalEntries);
487
477
  let ghToken = runSafeEngineFn(engine, 'gh', ['auth', 'token']);
@@ -705,141 +695,6 @@ export function ensureClaudeSettings(toolDir, hostHomeDir) {
705
695
  fs.writeFileSync(settingsPath, JSON.stringify(data, null, 4), 'utf8');
706
696
  }
707
697
  }
708
- function resolveHostCatalogPath(value, hostHomeDir) {
709
- if (typeof value !== 'string' || value === '') {
710
- return null;
711
- }
712
- let resolved;
713
- if (value === '~' || value.startsWith('~/') || value.startsWith('~\\')) {
714
- resolved = path.join(hostHomeDir, value.slice(1).replace(/^[/\\]+/, ''));
715
- }
716
- else if (path.isAbsolute(value)) {
717
- resolved = value;
718
- }
719
- else {
720
- resolved = path.join(hostHomeDir, '.codex', value);
721
- }
722
- try {
723
- if (!fs.statSync(resolved).isFile()) {
724
- return null;
725
- }
726
- fs.accessSync(resolved, fs.constants.R_OK);
727
- return resolved;
728
- }
729
- catch {
730
- return null;
731
- }
732
- }
733
- const CODEX_DISABLED_FEATURE_FLAGS = ['apps', 'enable_mcp_apps'];
734
- function removeCodexMcpServers(sandboxParsed) {
735
- if (!Object.hasOwn(sandboxParsed, 'mcp_servers')) {
736
- return false;
737
- }
738
- delete sandboxParsed.mcp_servers;
739
- return true;
740
- }
741
- function inheritDisabledCodexFeatureFlags(sandboxParsed, hostParsed) {
742
- if (!isJsonObjectRecord(hostParsed.features)) {
743
- return false;
744
- }
745
- if (Object.hasOwn(sandboxParsed, 'features') && !isJsonObjectRecord(sandboxParsed.features)) {
746
- return false;
747
- }
748
- let sandboxFeatures = sandboxParsed.features;
749
- let changed = false;
750
- for (const key of CODEX_DISABLED_FEATURE_FLAGS) {
751
- if (hostParsed.features[key] !== false) {
752
- continue;
753
- }
754
- if (!sandboxFeatures) {
755
- sandboxFeatures = {};
756
- sandboxParsed.features = sandboxFeatures;
757
- }
758
- if (sandboxFeatures[key] !== false) {
759
- sandboxFeatures[key] = false;
760
- changed = true;
761
- }
762
- }
763
- return changed;
764
- }
765
- export function ensureCodexModelInheritance(toolDir, hostHomeDir, containerCodexDir = '/home/devuser/.codex') {
766
- if (!hostHomeDir) {
767
- return;
768
- }
769
- const hostConfigPath = path.join(hostHomeDir, '.codex', 'config.toml');
770
- if (!fs.existsSync(hostConfigPath)) {
771
- return;
772
- }
773
- let hostParsed;
774
- try {
775
- hostParsed = toml.parse(fs.readFileSync(hostConfigPath, 'utf8'));
776
- }
777
- catch {
778
- return;
779
- }
780
- const sandboxConfigPath = path.join(toolDir, 'config.toml');
781
- // This rewrites sandbox-side TOML and drops comments; the host config stays untouched.
782
- let sandboxParsed = {};
783
- if (fs.existsSync(sandboxConfigPath)) {
784
- try {
785
- sandboxParsed = toml.parse(fs.readFileSync(sandboxConfigPath, 'utf8'));
786
- }
787
- catch {
788
- return;
789
- }
790
- }
791
- let changed = removeCodexMcpServers(sandboxParsed);
792
- changed = inheritDisabledCodexFeatureFlags(sandboxParsed, hostParsed) || changed;
793
- const inheritSpecs = [
794
- ['model', 'string'],
795
- ['model_reasoning_effort', 'string'],
796
- ['model_auto_compact_token_limit', 'number']
797
- ];
798
- for (const [key, type] of inheritSpecs) {
799
- if (Object.hasOwn(sandboxParsed, key)) {
800
- continue;
801
- }
802
- const value = hostParsed[key];
803
- if (type === 'string' && (typeof value !== 'string' || value === '')) {
804
- continue;
805
- }
806
- if (type === 'number' && (typeof value !== 'number' || !Number.isFinite(value) || value <= 0)) {
807
- continue;
808
- }
809
- sandboxParsed[key] = value;
810
- changed = true;
811
- }
812
- if (!Object.hasOwn(sandboxParsed, 'model_catalog_json')) {
813
- const hostCatalogPath = resolveHostCatalogPath(hostParsed['model_catalog_json'], hostHomeDir);
814
- if (hostCatalogPath) {
815
- try {
816
- const basename = path.basename(hostCatalogPath);
817
- const destDir = path.join(toolDir, 'model-catalogs');
818
- fs.mkdirSync(destDir, { recursive: true });
819
- fs.copyFileSync(hostCatalogPath, path.join(destDir, basename));
820
- sandboxParsed['model_catalog_json'] = path.posix.join(containerCodexDir, 'model-catalogs', basename);
821
- changed = true;
822
- }
823
- catch {
824
- // Copy failed (e.g. permissions): skip catalog, keep scalar inheritance intact.
825
- }
826
- }
827
- }
828
- if (changed) {
829
- fs.writeFileSync(sandboxConfigPath, `${toml.stringify(sandboxParsed)}\n`, 'utf8');
830
- }
831
- }
832
- export function ensureCodexWorkspaceTrust(toolDir) {
833
- const configPath = path.join(toolDir, 'config.toml');
834
- let content = '';
835
- if (fs.existsSync(configPath)) {
836
- content = fs.readFileSync(configPath, 'utf8');
837
- }
838
- if (!content.includes('[projects."/workspace"]')) {
839
- const entry = '\n[projects."/workspace"]\ntrust_level = "trusted"\n';
840
- fs.writeFileSync(configPath, content + entry, 'utf8');
841
- }
842
- }
843
698
  export function ensureOpenCodeModelInheritance(toolDir, hostHomeDir) {
844
699
  if (!hostHomeDir) {
845
700
  return;
@@ -874,22 +729,6 @@ export function ensureOpenCodeModelInheritance(toolDir, hostHomeDir) {
874
729
  fs.writeFileSync(sandboxConfigPath, JSON.stringify(sandboxJson, null, 2), 'utf8');
875
730
  }
876
731
  }
877
- export function ensureGeminiWorkspaceTrust(toolDir) {
878
- const trustPath = path.join(toolDir, 'trustedFolders.json');
879
- let data = {};
880
- if (fs.existsSync(trustPath)) {
881
- try {
882
- data = JSON.parse(fs.readFileSync(trustPath, 'utf8'));
883
- }
884
- catch {
885
- // malformed JSON, start fresh
886
- }
887
- }
888
- if (data['/workspace'] !== 'TRUST_FOLDER') {
889
- data['/workspace'] = 'TRUST_FOLDER';
890
- fs.writeFileSync(trustPath, JSON.stringify(data, null, 2), 'utf8');
891
- }
892
- }
893
732
  export function sandboxAliasesPath(home) {
894
733
  return hostJoin(home, '.agent-infra', 'aliases', 'sandbox.sh');
895
734
  }
@@ -900,7 +739,7 @@ function stripManagedSandboxAliasBlocks(content) {
900
739
  const blockPattern = new RegExp(`${escapeRegExp(SANDBOX_ALIAS_BLOCK_BEGIN)}[\\s\\S]*?${escapeRegExp(SANDBOX_ALIAS_BLOCK_END)}\\n?`, 'g');
901
740
  return content.replace(blockPattern, '').trimEnd();
902
741
  }
903
- function isLegacyManagedSandboxAliasFile(content) {
742
+ function isLegacyManagedSandboxAliasFile(content, aliases) {
904
743
  const lines = content
905
744
  .split(/\r?\n/)
906
745
  .map((line) => line.trim())
@@ -908,19 +747,25 @@ function isLegacyManagedSandboxAliasFile(content) {
908
747
  if (lines.length === 0) {
909
748
  return false;
910
749
  }
911
- const aliasPattern = new RegExp(`^alias (${SANDBOX_ALIAS_NAMES.map(escapeRegExp).join('|')})=`);
750
+ const aliasPattern = new RegExp(`^alias (${aliases.map((alias) => escapeRegExp(alias.name)).join('|')})=`);
912
751
  return lines.every((line) => aliasPattern.test(line));
913
752
  }
914
- export function ensureSandboxAliasesFile(home) {
753
+ function registrySandboxAliases() {
754
+ return listAgentClientAdapters().flatMap((adapter) => adapter.sandbox.aliases);
755
+ }
756
+ function renderSandboxAliases(aliases) {
757
+ return `${aliases.map((alias) => `alias ${alias.name}='${alias.command.replaceAll("'", "'\\''")}'`).join('\n')}\n`;
758
+ }
759
+ export function ensureSandboxAliasesFile(home, aliases = registrySandboxAliases()) {
915
760
  const aliasesPath = sandboxAliasesPath(home);
916
- const managedBlock = `${SANDBOX_ALIAS_BLOCK_BEGIN}\n${DEFAULT_SANDBOX_ALIASES}${SANDBOX_ALIAS_BLOCK_END}\n`;
761
+ const managedBlock = `${SANDBOX_ALIAS_BLOCK_BEGIN}\n${renderSandboxAliases(aliases)}${SANDBOX_ALIAS_BLOCK_END}\n`;
917
762
  fs.mkdirSync(path.dirname(aliasesPath), { recursive: true });
918
763
  const created = !fs.existsSync(aliasesPath);
919
764
  let existing = '';
920
765
  if (!created) {
921
766
  existing = fs.readFileSync(aliasesPath, 'utf8');
922
767
  }
923
- const userContent = isLegacyManagedSandboxAliasFile(existing)
768
+ const userContent = isLegacyManagedSandboxAliasFile(existing, aliases)
924
769
  ? ''
925
770
  : stripManagedSandboxAliasBlocks(existing);
926
771
  const nextContent = userContent
@@ -1018,15 +863,14 @@ export async function create(args) {
1018
863
  };
1019
864
  const worktreeCandidates = worktreeDirCandidates(effectiveConfig, branch);
1020
865
  assertBranchAvailable(config.repoRoot, branch, { allowedWorktrees: worktreeCandidates });
1021
- const tools = resolveTools(effectiveConfig);
866
+ const capabilityPlan = createSandboxCapabilityPlan(effectiveConfig);
867
+ const tools = [...capabilityPlan.tools];
1022
868
  const resolvedTools = resolveToolDirs(effectiveConfig, tools, branch);
1023
869
  // Fatal credential states still fail before filesystem/docker side effects.
1024
- // A genuinely missing Claude Code credential only removes Claude Code's
1025
- // sandbox config and credential mounts for this create run.
870
+ // Missing credentials leave the selected Claude Code capability installed
871
+ // and mounted; only the absent live credential file is omitted.
1026
872
  const credentialOutcome = prepareClaudeCredentials(effectiveConfig.home, effectiveConfig.project, resolvedTools);
1027
- const effectiveResolvedTools = credentialOutcome.status === 'SKIPPED'
1028
- ? resolvedTools.filter(({ tool }) => tool.id !== 'claude-code')
1029
- : resolvedTools;
873
+ const effectiveResolvedTools = resolvedTools;
1030
874
  const container = containerName(effectiveConfig, branch);
1031
875
  const worktree = worktreeCandidates.find((candidate) => fs.existsSync(candidate)) ?? worktreeCandidates[0] ?? '';
1032
876
  const shareCommon = shareCommonDir(effectiveConfig);
@@ -1045,6 +889,16 @@ export async function create(args) {
1045
889
  }
1046
890
  try {
1047
891
  p.log.step('Checking container engine...');
892
+ const prepareHookResults = await runSandboxHooks({
893
+ hooks: capabilityPlan.hooksByPhase.prepare,
894
+ phase: 'prepare',
895
+ context: { config: effectiveConfig, plan: capabilityPlan },
896
+ runCommand: runBoundedSandboxHookCommand
897
+ });
898
+ const prepareFailure = prepareHookResults.find((result) => result.status === 'fatal');
899
+ if (prepareFailure) {
900
+ throw new Error(prepareFailure.message ?? `Sandbox hook '${prepareFailure.hookId}' failed.`);
901
+ }
1048
902
  await ensureDocker(effectiveConfig, (detail) => {
1049
903
  p.log.info(` ${detail}`);
1050
904
  });
@@ -1111,7 +965,7 @@ export async function create(args) {
1111
965
  if (fs.readdirSync(worktree).length > 0) {
1112
966
  return `Worktree exists at ${worktree}`;
1113
967
  }
1114
- fs.rmSync(worktree, { recursive: true, force: true });
968
+ removeDirRecursive(worktree);
1115
969
  }
1116
970
  const branchExists = runOk('git', [
1117
971
  '-C',
@@ -1200,7 +1054,7 @@ export async function create(args) {
1200
1054
  runSafeEngine(engine, 'docker', ['rm', name]);
1201
1055
  }
1202
1056
  }
1203
- const aliasesFile = ensureSandboxAliasesFile(effectiveConfig.home);
1057
+ const aliasesFile = ensureSandboxAliasesFile(effectiveConfig.home, capabilityPlan.aliases);
1204
1058
  if (aliasesFile.created) {
1205
1059
  message(`Created default sandbox aliases at ${aliasesFile.path}`);
1206
1060
  }
@@ -1229,6 +1083,24 @@ export async function create(args) {
1229
1083
  let hostShellConfig;
1230
1084
  let tmpfsSeedPlan = [];
1231
1085
  try {
1086
+ const beforeCreateResults = await runSandboxHooks({
1087
+ hooks: capabilityPlan.hooksByPhase['before-container-create'],
1088
+ phase: 'before-container-create',
1089
+ context: {
1090
+ config: effectiveConfig,
1091
+ plan: capabilityPlan,
1092
+ create: {
1093
+ hostHome: effectiveConfig.home,
1094
+ resolvedTools: effectiveResolvedTools
1095
+ }
1096
+ },
1097
+ runCommand: runBoundedSandboxHookCommand
1098
+ });
1099
+ const beforeCreateFailure = beforeCreateResults.find((result) => result.status === 'fatal');
1100
+ if (beforeCreateFailure) {
1101
+ throw new Error(beforeCreateFailure.message
1102
+ ?? `Sandbox hook '${beforeCreateFailure.hookId}' failed.`);
1103
+ }
1232
1104
  const claudeCodeEntry = effectiveResolvedTools.find(({ tool }) => tool.id === 'claude-code');
1233
1105
  if (claudeCodeEntry) {
1234
1106
  ensureClaudeOnboarding(claudeCodeEntry.dir, effectiveConfig.home);
@@ -1237,15 +1109,6 @@ export async function create(args) {
1237
1109
  // provider/API settings are enough for Claude Code. If no usable
1238
1110
  // auth was present, the claude-code entry was removed above.
1239
1111
  }
1240
- const codexEntry = effectiveResolvedTools.find(({ tool }) => tool.id === 'codex');
1241
- if (codexEntry) {
1242
- ensureCodexModelInheritance(codexEntry.dir, effectiveConfig.home, codexEntry.tool.containerMount);
1243
- ensureCodexWorkspaceTrust(codexEntry.dir);
1244
- }
1245
- const geminiEntry = effectiveResolvedTools.find(({ tool }) => tool.id === 'gemini-cli');
1246
- if (geminiEntry) {
1247
- ensureGeminiWorkspaceTrust(geminiEntry.dir);
1248
- }
1249
1112
  const opencodeEntry = effectiveResolvedTools.find(({ tool }) => tool.id === 'opencode');
1250
1113
  if (opencodeEntry) {
1251
1114
  // The TUI reads <toolDir>/opencode.json via OPENCODE_CONFIG pinned in tools.js.
@@ -1315,6 +1178,8 @@ export async function create(args) {
1315
1178
  sandboxLabel(effectiveConfig),
1316
1179
  '--label',
1317
1180
  `${sandboxBranchLabel(effectiveConfig)}=${branch}`,
1181
+ '--label',
1182
+ `${sandboxRuntimeCapabilityLabel(effectiveConfig)}=${capabilityPlan.runtimeSignature}`,
1318
1183
  ...coreVolumes,
1319
1184
  ...buildClipboardVolumeArgs(engine, effectiveConfig.home),
1320
1185
  '-v',
@@ -1392,6 +1257,17 @@ export async function create(args) {
1392
1257
  runSafeEngine(engine, 'docker', ['exec', container, 'bash', '-lc', command]);
1393
1258
  }
1394
1259
  }
1260
+ const afterStartResults = await runSandboxHooks({
1261
+ hooks: capabilityPlan.hooksByPhase['after-container-start'],
1262
+ phase: 'after-container-start',
1263
+ context: { config: effectiveConfig, plan: capabilityPlan },
1264
+ runCommand: runBoundedSandboxHookCommand
1265
+ });
1266
+ const afterStartFailure = afterStartResults.find((result) => result.status === 'fatal');
1267
+ if (afterStartFailure) {
1268
+ throw new Error(afterStartFailure.message
1269
+ ?? `Sandbox hook '${afterStartFailure.hookId}' failed.`);
1270
+ }
1395
1271
  return 'Container started';
1396
1272
  }
1397
1273
  }
@@ -2,6 +2,7 @@ import { loadConfig } from '../config.js';
2
2
  import { assertValidBranchName, containerNameCandidates, sandboxBranchLabel, sandboxLabel } from '../constants.js';
3
3
  import { detectEngine } from '../engine.js';
4
4
  import { ensureSandboxReady } from '../recovery.js';
5
+ import { createSandboxCapabilityPlan, runBoundedSandboxHookCommand, runSandboxHooks } from '../agent-client-reconciler.js';
5
6
  import { formatCredentialWarnings, formatRemaining, hasClaudeProviderAuth, reconcileClaudeCredentials, redactCommandError, validateClaudeCredentialsEnvOverride } from '../credentials.js';
6
7
  import { runInteractiveEngine } from '../shell.js';
7
8
  import { dotfilesCacheDir, materializeDotfiles } from '../dotfiles.js';
@@ -123,7 +124,22 @@ export async function enter(args) {
123
124
  });
124
125
  const container = ready.container;
125
126
  const cmd = parsed.command;
126
- if (config.tools.includes('claude-code')) {
127
+ const capabilityPlan = createSandboxCapabilityPlan(config);
128
+ const enterHookResults = await runSandboxHooks({
129
+ hooks: capabilityPlan.hooksByPhase['before-enter'],
130
+ phase: 'before-enter',
131
+ context: { config, plan: capabilityPlan },
132
+ runCommand: runBoundedSandboxHookCommand
133
+ });
134
+ for (const result of enterHookResults) {
135
+ if (result.status === 'fatal') {
136
+ throw new Error(result.message ?? `Sandbox hook '${result.hookId}' failed.`);
137
+ }
138
+ if (result.status === 'warning') {
139
+ process.stderr.write(`Warning: ${result.message ?? `Sandbox hook '${result.hookId}' did not complete.`}\n`);
140
+ }
141
+ }
142
+ if (capabilityPlan.selectedAgentClients.some((adapter) => adapter.id === 'claude-code')) {
127
143
  try {
128
144
  // Scan all projects so a refresh from a neighbouring sandbox can still flow back to the host.
129
145
  const providerAuthAvailable = hasClaudeProviderAuth(config.home);
@@ -10,7 +10,7 @@ import { hostJoin } from '../engines/wsl2-paths.js';
10
10
  import { removeManagedDir, removeWorktreeDir } from '../managed-fs.js';
11
11
  import { parseLabels } from './ls.js';
12
12
  import { runEngine, runSafe } from '../shell.js';
13
- import { resolveTools } from '../tools.js';
13
+ import { createSandboxCapabilityPlan } from '../agent-client-reconciler.js';
14
14
  const USAGE = `Usage: ai sandbox prune [--dry-run]`;
15
15
  function listChildDirs(base) {
16
16
  if (!fs.existsSync(base)) {
@@ -129,7 +129,7 @@ export async function prune(args) {
129
129
  return;
130
130
  }
131
131
  const config = loadConfig();
132
- const tools = resolveTools(config);
132
+ const tools = [...createSandboxCapabilityPlan(config).cleanupInventory];
133
133
  const engine = detectEngine(config);
134
134
  const psArgs = [
135
135
  'ps',
@@ -10,7 +10,8 @@ import { pruneSandboxDanglingImages } from '../image-prune.js';
10
10
  import { removeManagedDir, removeWorktreeDir } from '../managed-fs.js';
11
11
  import { runOk, runSafe, runSafeEngine } from '../shell.js';
12
12
  import { resolveTaskBranch } from '../task-resolver.js';
13
- import { resolveTools, toolConfigDirCandidates, toolProjectDirCandidates } from '../tools.js';
13
+ import { toolConfigDirCandidates, toolProjectDirCandidates } from '../tools.js';
14
+ import { createSandboxCapabilityPlan } from '../agent-client-reconciler.js';
14
15
  import { fetchSandboxRows } from './list-running.js';
15
16
  import { lookupShortIdByBranch } from '../../task/short-id.js';
16
17
  const USAGE = `Usage:
@@ -284,7 +285,7 @@ export async function rm(args) {
284
285
  throw new Error(USAGE);
285
286
  }
286
287
  const config = loadConfig();
287
- const tools = resolveTools(config);
288
+ const tools = [...createSandboxCapabilityPlan(config).cleanupInventory];
288
289
  if (values.purge) {
289
290
  await rmPurge(config, tools);
290
291
  return;
@@ -8,7 +8,7 @@ import { resolveTools, toolConfigDirCandidates } from '../tools.js';
8
8
  const USAGE = `Usage: ai sandbox show <branch | TASK-id | N>
9
9
 
10
10
  Shows one sandbox's worktree path and per-tool state paths (Claude Code,
11
- Codex, Gemini CLI, OpenCode). The argument follows the same contract as
11
+ Codex, Antigravity CLI, OpenCode). The argument follows the same contract as
12
12
  'ai sandbox exec' and 'ai sandbox start': N (bare) is the recommended form
13
13
  for task short ids (e.g. 'ai sandbox show 11'); a TASK-id or a plain
14
14
  branch name are also accepted. Use 'ai sandbox ls' for the container list.`;
@@ -3,6 +3,8 @@ import path from 'node:path';
3
3
  import { homedir, platform } from 'node:os';
4
4
  import { execFileSync } from 'node:child_process';
5
5
  import pc from 'picocolors';
6
+ import { normalizeAgentClients } from '../agent-clients/config.js';
7
+ import { isAgentClientId } from '../agent-clients/types.js';
6
8
  import { validateSandboxEngine } from './engine.js';
7
9
  import { hostJoin } from './engines/wsl2-paths.js';
8
10
  import { findRuntimeEngineMismatches } from './runtime-engines.js';
@@ -10,7 +12,7 @@ import { parseCustomTools } from './tools.js';
10
12
  const DEFAULTS = Object.freeze({
11
13
  engine: null,
12
14
  runtimes: ['node22'],
13
- tools: ['agent-infra', 'claude-code', 'codex', 'gemini-cli', 'opencode'],
15
+ tools: ['agent-infra'],
14
16
  refreshIntervalDays: 7,
15
17
  dockerfile: null,
16
18
  vm: {
@@ -46,6 +48,18 @@ function cloneDefaults() {
46
48
  vm: { ...DEFAULTS.vm }
47
49
  };
48
50
  }
51
+ function resolveSandboxToolIds(sandbox, agentClients, defaults) {
52
+ if (Array.isArray(sandbox.tools)) {
53
+ const tools = sandbox.tools.filter((tool) => typeof tool === 'string');
54
+ return agentClients.source === 'canonical'
55
+ ? tools.filter((tool) => !isAgentClientId(tool))
56
+ : tools;
57
+ }
58
+ if (agentClients.remainingSandboxTools !== undefined) {
59
+ return [...agentClients.remainingSandboxTools];
60
+ }
61
+ return [...defaults];
62
+ }
49
63
  export function loadConfig({ platformFn = platform, writeStderr = (chunk) => process.stderr.write(chunk) } = {}) {
50
64
  const repoRoot = detectRepoRoot();
51
65
  const home = homedir();
@@ -57,6 +71,8 @@ export function loadConfig({ platformFn = platform, writeStderr = (chunk) => pro
57
71
  throw new Error('No .agents/.airc.json found. Run "ai init" first.');
58
72
  }
59
73
  const airc = JSON.parse(fs.readFileSync(configPath, 'utf8'));
74
+ const sandboxInput = airc.sandbox;
75
+ const agentClients = normalizeAgentClients(airc);
60
76
  const defaults = cloneDefaults();
61
77
  const sandbox = airc.sandbox ?? {};
62
78
  const engine = validateSandboxEngine(sandbox.engine ?? defaults.engine, { platformFn });
@@ -83,6 +99,7 @@ export function loadConfig({ platformFn = platform, writeStderr = (chunk) => pro
83
99
  }
84
100
  }
85
101
  const customTools = parseCustomTools(sandbox.customTools, { home });
102
+ const tools = resolveSandboxToolIds(sandbox, agentClients, defaults.tools);
86
103
  return {
87
104
  repoRoot,
88
105
  configPath,
@@ -97,10 +114,10 @@ export function loadConfig({ platformFn = platform, writeStderr = (chunk) => pro
97
114
  dotfilesDir: hostJoin(home, '.agent-infra', 'dotfiles'),
98
115
  engine,
99
116
  runtimes,
100
- tools: Array.isArray(sandbox.tools) && sandbox.tools.length > 0
101
- ? [...sandbox.tools]
102
- : defaults.tools,
117
+ tools,
103
118
  customTools,
119
+ agentClientState: agentClients.state,
120
+ agentClientSource: agentClients.source,
104
121
  refreshIntervalDays: asNonNegativeIntegerOrDefault(sandbox.refreshIntervalDays, defaults.refreshIntervalDays),
105
122
  dockerfile,
106
123
  vm: {
@@ -75,6 +75,9 @@ export function sandboxImageConfigLabel(config) {
75
75
  export function sandboxImageRefreshLabel(config) {
76
76
  return `${sandboxLabel(config)}.last-refresh`;
77
77
  }
78
+ export function sandboxRuntimeCapabilityLabel(config) {
79
+ return `agent-infra.sandbox.runtime-capability.${config.project}`;
80
+ }
78
81
  export function parsePositiveIntegerOption(value, optionName) {
79
82
  if (value === undefined || value === null) {
80
83
  return undefined;
@@ -3,6 +3,7 @@ import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { createHash } from 'node:crypto';
5
5
  import { fileURLToPath } from 'node:url';
6
+ import { removeDirRecursive } from '../remove-dir.js';
6
7
  const RUNTIMES_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), 'runtimes');
7
8
  function listRuntimeFragments() {
8
9
  return fs.readdirSync(RUNTIMES_DIR)
@@ -63,7 +64,7 @@ export function prepareDockerfile(config) {
63
64
  path: tempPath,
64
65
  signature: dockerfileSignature(config),
65
66
  cleanup() {
66
- fs.rmSync(tempDir, { recursive: true, force: true });
67
+ removeDirRecursive(tempDir);
67
68
  }
68
69
  };
69
70
  }
@@ -1,6 +1,6 @@
1
- import fs from 'node:fs';
2
1
  import path from 'node:path';
3
- import { run } from './shell.js';
2
+ import { run, runSafe } from './shell.js';
3
+ import { removeDirRecursive } from '../remove-dir.js';
4
4
  export function assertManagedPath(root, target) {
5
5
  const resolvedRoot = path.resolve(root);
6
6
  const resolvedTarget = path.resolve(target);
@@ -12,14 +12,19 @@ export function assertManagedPath(root, target) {
12
12
  }
13
13
  export function removeManagedDir(root, dir) {
14
14
  assertManagedPath(root, dir);
15
- fs.rmSync(dir, { recursive: true, force: true });
15
+ removeDirRecursive(dir);
16
16
  }
17
- export function removeWorktreeDir(repoRoot, worktreeBase, dir) {
17
+ export function removeWorktreeDir(repoRoot, worktreeBase, dir, { runFn = run, runSafeFn = runSafe } = {}) {
18
18
  try {
19
- run('git', ['-C', repoRoot, 'worktree', 'remove', dir, '--force']);
19
+ runFn('git', ['-C', repoRoot, 'worktree', 'remove', dir, '--force']);
20
20
  }
21
21
  catch {
22
+ // On WSL2 the worktree is registered under its `/mnt/<drive>/...` path, so
23
+ // `git worktree remove <windows-path>` cannot match it. Delete the managed
24
+ // directory directly, then prune the now-dangling worktree metadata so the
25
+ // branch is no longer reported as checked out.
22
26
  removeManagedDir(worktreeBase, dir);
27
+ runSafeFn('git', ['-C', repoRoot, 'worktree', 'prune']);
23
28
  }
24
29
  }
25
30
  //# sourceMappingURL=managed-fs.js.map