@fitlab-ai/agent-infra 0.9.2 → 0.9.4

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 +12 -9
  2. package/README.zh-CN.md +12 -9
  3. package/bin/cli.ts +12 -0
  4. package/dist/bin/cli.js +14 -0
  5. package/dist/bin/internal-cli.js +134 -108
  6. package/dist/lib/agent-clients/adapter.js +137 -4
  7. package/dist/lib/agent-clients/adapters/antigravity-cli.js +64 -0
  8. package/dist/lib/{sandbox/credentials.js → agent-clients/adapters/claude-code-credentials.js} +4 -14
  9. package/dist/lib/agent-clients/adapters/claude-code-refresh.js +85 -0
  10. package/dist/lib/agent-clients/adapters/claude-code-sandbox.js +247 -0
  11. package/dist/lib/agent-clients/adapters/claude-code.js +27 -4
  12. package/dist/lib/agent-clients/adapters/codex.js +9 -0
  13. package/dist/lib/agent-clients/adapters/index.js +2 -2
  14. package/dist/lib/agent-clients/adapters/opencode-sandbox.js +108 -0
  15. package/dist/lib/agent-clients/adapters/opencode.js +24 -3
  16. package/dist/lib/agent-clients/adapters/runtimes/claude-code.dockerfile +65 -0
  17. package/dist/lib/agent-clients/config.js +42 -4
  18. package/dist/lib/agent-clients/next-steps.js +11 -2
  19. package/dist/lib/agent-clients/reconcile.js +2 -1
  20. package/dist/lib/agent-clients/registry.js +16 -2
  21. package/dist/lib/agent-clients/schema.js +18 -0
  22. package/dist/lib/agent-clients/tokens.js +49 -0
  23. package/dist/lib/agent-clients/types.js +1 -1
  24. package/dist/lib/defaults.json +1 -1
  25. package/dist/lib/git/workflow.js +54 -1
  26. package/dist/lib/internal/agent-client.js +61 -4
  27. package/dist/lib/internal/git-workflow.js +6 -1
  28. package/dist/lib/internal/platform-checks.js +3 -3
  29. package/dist/lib/internal/platform-comment.js +29 -2
  30. package/dist/lib/internal/platform-issue.js +7 -0
  31. package/dist/lib/internal/platform-pr-review.js +132 -0
  32. package/dist/lib/internal/platform-pr.js +20 -2
  33. package/dist/lib/internal/platform-release-notes.js +52 -16
  34. package/dist/lib/internal/pr-review-grade.js +140 -0
  35. package/dist/lib/internal/release-workflow.js +13 -6
  36. package/dist/lib/internal/sandbox-control.js +24 -0
  37. package/dist/lib/internal/task-activity.js +105 -0
  38. package/dist/lib/internal/task-event.js +17 -1
  39. package/dist/lib/internal/task-ledger.js +12 -3
  40. package/dist/lib/internal/task-lifecycle.js +26 -1
  41. package/dist/lib/internal/task-orchestration.js +167 -18
  42. package/dist/lib/internal/task-review.js +8 -3
  43. package/dist/lib/platform/adapters.js +8 -1
  44. package/dist/lib/platform/completion-backfill.js +122 -0
  45. package/dist/lib/platform/github-client.js +19 -2
  46. package/dist/lib/platform/issue-comments.js +3 -2
  47. package/dist/lib/platform/merged-pr-equivalence.js +115 -5
  48. package/dist/lib/platform/pr-checks.js +65 -42
  49. package/dist/lib/platform/pr-review.js +166 -0
  50. package/dist/lib/platform/pull-requests.js +371 -4
  51. package/dist/lib/platform/release-notes.js +85 -3
  52. package/dist/lib/platform/releases.js +13 -5
  53. package/dist/lib/pr-review/evidence-grading.js +229 -0
  54. package/dist/lib/process-data/index.js +239 -0
  55. package/dist/lib/process-data/normalize.js +198 -0
  56. package/dist/lib/process-data/privacy.js +33 -0
  57. package/dist/lib/process-data/reconcile.js +95 -0
  58. package/dist/lib/process-data/repair.js +58 -0
  59. package/dist/lib/process-data/sources.js +345 -0
  60. package/dist/lib/process-data/store.js +282 -0
  61. package/dist/lib/process-data/types.js +2 -0
  62. package/dist/lib/run/index.js +4 -3
  63. package/dist/lib/run/tui.js +10 -13
  64. package/dist/lib/sandbox/agent-client-reconciler.js +26 -2
  65. package/dist/lib/sandbox/capture.js +7 -2
  66. package/dist/lib/sandbox/commands/create.js +109 -248
  67. package/dist/lib/sandbox/commands/enter.js +15 -47
  68. package/dist/lib/sandbox/commands/list-running.js +16 -6
  69. package/dist/lib/sandbox/commands/ls.js +10 -6
  70. package/dist/lib/sandbox/commands/rebuild.js +4 -3
  71. package/dist/lib/sandbox/commands/refresh.js +4 -84
  72. package/dist/lib/sandbox/commands/rm.js +24 -3
  73. package/dist/lib/sandbox/commands/show.js +13 -4
  74. package/dist/lib/sandbox/commands/start.js +7 -4
  75. package/dist/lib/sandbox/config.js +2 -0
  76. package/dist/lib/sandbox/constants.js +6 -0
  77. package/dist/lib/sandbox/control/client.js +44 -0
  78. package/dist/lib/sandbox/control/protocol.js +35 -0
  79. package/dist/lib/sandbox/control/server.js +109 -0
  80. package/dist/lib/sandbox/dockerfile.js +36 -13
  81. package/dist/lib/sandbox/mounts.js +17 -4
  82. package/dist/lib/sandbox/recovery.js +128 -5
  83. package/dist/lib/sandbox/redaction.js +12 -0
  84. package/dist/lib/sandbox/runtimes/base.dockerfile +24 -74
  85. package/dist/lib/sandbox/workspace-identity.js +95 -0
  86. package/dist/lib/sandbox/workspace-view.js +103 -0
  87. package/dist/lib/task/activity-intent.js +307 -0
  88. package/dist/lib/task/artifact-lifecycle.js +2 -1
  89. package/dist/lib/task/commands/log.js +15 -14
  90. package/dist/lib/task/commit-finalization.js +267 -0
  91. package/dist/lib/task/commit-intent.js +165 -0
  92. package/dist/lib/task/decision-intents.js +31 -17
  93. package/dist/lib/task/delegation-receipts.js +25 -4
  94. package/dist/lib/task/events.js +67 -28
  95. package/dist/lib/task/finalization-artifacts.js +35 -0
  96. package/dist/lib/task/implementation-inputs.js +54 -7
  97. package/dist/lib/task/ledger-intents.js +35 -1
  98. package/dist/lib/task/lifecycle-execution.js +46 -0
  99. package/dist/lib/task/orchestration.js +753 -54
  100. package/dist/lib/task/resolve-ref.js +41 -1
  101. package/dist/lib/task/review-finalization.js +29 -9
  102. package/dist/lib/task/task-execution-lock.js +231 -0
  103. package/dist/lib/task/verification-checks.js +1 -1
  104. package/dist/lib/task/verification-engine.js +218 -2
  105. package/dist/lib/task/verification.js +4 -3
  106. package/dist/lib/task/workspace-snapshot.js +17 -5
  107. package/lib/agent-clients/adapter.ts +201 -4
  108. package/lib/agent-clients/adapters/antigravity-cli.ts +65 -0
  109. package/lib/{sandbox/credentials.ts → agent-clients/adapters/claude-code-credentials.ts} +3 -18
  110. package/lib/agent-clients/adapters/claude-code-refresh.ts +128 -0
  111. package/lib/agent-clients/adapters/claude-code-sandbox.ts +295 -0
  112. package/lib/agent-clients/adapters/claude-code.ts +31 -4
  113. package/lib/agent-clients/adapters/codex.ts +9 -0
  114. package/lib/agent-clients/adapters/index.ts +2 -2
  115. package/lib/agent-clients/adapters/opencode-sandbox.ts +136 -0
  116. package/lib/agent-clients/adapters/opencode.ts +27 -3
  117. package/lib/agent-clients/adapters/runtimes/claude-code.dockerfile +65 -0
  118. package/lib/agent-clients/config.ts +49 -4
  119. package/lib/agent-clients/next-steps.ts +15 -2
  120. package/lib/agent-clients/reconcile.ts +2 -1
  121. package/lib/agent-clients/registry.ts +19 -1
  122. package/lib/agent-clients/schema.ts +18 -0
  123. package/lib/agent-clients/tokens.ts +53 -0
  124. package/lib/agent-clients/types.ts +15 -1
  125. package/lib/defaults.json +1 -1
  126. package/lib/git/workflow.ts +66 -2
  127. package/lib/internal/agent-client.ts +59 -4
  128. package/lib/internal/git-workflow.ts +5 -1
  129. package/lib/internal/platform-checks.ts +4 -4
  130. package/lib/internal/platform-comment.ts +17 -2
  131. package/lib/internal/platform-issue.ts +4 -0
  132. package/lib/internal/platform-pr-review.ts +104 -0
  133. package/lib/internal/platform-pr.ts +14 -1
  134. package/lib/internal/platform-release-notes.ts +59 -16
  135. package/lib/internal/pr-review-grade.ts +130 -0
  136. package/lib/internal/release-workflow.ts +13 -6
  137. package/lib/internal/sandbox-control.ts +24 -0
  138. package/lib/internal/task-activity.ts +91 -0
  139. package/lib/internal/task-event.ts +9 -1
  140. package/lib/internal/task-ledger.ts +12 -3
  141. package/lib/internal/task-lifecycle.ts +26 -1
  142. package/lib/internal/task-orchestration.ts +123 -14
  143. package/lib/internal/task-review.ts +8 -3
  144. package/lib/platform/adapters.ts +29 -2
  145. package/lib/platform/completion-backfill.ts +134 -0
  146. package/lib/platform/github-client.ts +20 -2
  147. package/lib/platform/issue-comments.ts +3 -2
  148. package/lib/platform/merged-pr-equivalence.ts +127 -5
  149. package/lib/platform/pr-checks.ts +73 -46
  150. package/lib/platform/pr-review.ts +201 -0
  151. package/lib/platform/pull-requests.ts +444 -3
  152. package/lib/platform/release-notes.ts +100 -4
  153. package/lib/platform/releases.ts +16 -4
  154. package/lib/pr-review/evidence-grading.ts +318 -0
  155. package/lib/process-data/index.ts +224 -0
  156. package/lib/process-data/normalize.ts +202 -0
  157. package/lib/process-data/privacy.ts +41 -0
  158. package/lib/process-data/reconcile.ts +110 -0
  159. package/lib/process-data/repair.ts +64 -0
  160. package/lib/process-data/sources.ts +354 -0
  161. package/lib/process-data/store.ts +315 -0
  162. package/lib/process-data/types.ts +135 -0
  163. package/lib/run/index.ts +5 -3
  164. package/lib/run/tui.ts +14 -12
  165. package/lib/sandbox/agent-client-reconciler.ts +44 -2
  166. package/lib/sandbox/capture.ts +9 -2
  167. package/lib/sandbox/commands/create.ts +126 -280
  168. package/lib/sandbox/commands/enter.ts +13 -59
  169. package/lib/sandbox/commands/list-running.ts +23 -6
  170. package/lib/sandbox/commands/ls.ts +22 -6
  171. package/lib/sandbox/commands/rebuild.ts +4 -3
  172. package/lib/sandbox/commands/refresh.ts +4 -126
  173. package/lib/sandbox/commands/rm.ts +24 -3
  174. package/lib/sandbox/commands/show.ts +30 -4
  175. package/lib/sandbox/commands/start.ts +6 -4
  176. package/lib/sandbox/config.ts +4 -0
  177. package/lib/sandbox/constants.ts +8 -0
  178. package/lib/sandbox/control/client.ts +55 -0
  179. package/lib/sandbox/control/protocol.ts +75 -0
  180. package/lib/sandbox/control/server.ts +117 -0
  181. package/lib/sandbox/dockerfile.ts +66 -13
  182. package/lib/sandbox/mounts.ts +24 -4
  183. package/lib/sandbox/recovery.ts +163 -6
  184. package/lib/sandbox/redaction.ts +14 -0
  185. package/lib/sandbox/runtimes/base.dockerfile +24 -74
  186. package/lib/sandbox/tool-types.ts +16 -0
  187. package/lib/sandbox/workspace-identity.ts +123 -0
  188. package/lib/sandbox/workspace-view.ts +143 -0
  189. package/lib/server/server.schema.json +2 -2
  190. package/lib/task/activity-intent.ts +417 -0
  191. package/lib/task/artifact-lifecycle.ts +2 -1
  192. package/lib/task/commands/log.ts +15 -14
  193. package/lib/task/commit-finalization.ts +356 -0
  194. package/lib/task/commit-intent.ts +230 -0
  195. package/lib/task/decision-intents.ts +32 -12
  196. package/lib/task/delegation-receipts.ts +34 -5
  197. package/lib/task/events.ts +75 -30
  198. package/lib/task/finalization-artifacts.ts +58 -0
  199. package/lib/task/implementation-inputs.ts +62 -8
  200. package/lib/task/ledger-intents.ts +43 -3
  201. package/lib/task/lifecycle-execution.ts +106 -0
  202. package/lib/task/orchestration.ts +1019 -72
  203. package/lib/task/resolve-ref.ts +46 -1
  204. package/lib/task/review-finalization.ts +40 -9
  205. package/lib/task/task-execution-lock.ts +296 -0
  206. package/lib/task/verification-checks.ts +1 -1
  207. package/lib/task/verification-engine.ts +249 -2
  208. package/lib/task/verification.ts +5 -3
  209. package/lib/task/workspace-snapshot.ts +26 -5
  210. package/package.json +3 -3
  211. package/templates/.agents/QUICKSTART.en.md +25 -8
  212. package/templates/.agents/QUICKSTART.zh-CN.md +25 -8
  213. package/templates/.agents/README.en.md +10 -7
  214. package/templates/.agents/README.zh-CN.md +10 -7
  215. package/templates/.agents/hooks/lifecycle-delegation.js +15 -4
  216. package/templates/.agents/rules/README.en.md +1 -1
  217. package/templates/.agents/rules/README.zh-CN.md +1 -1
  218. package/templates/.agents/rules/create-issue.github.en.md +4 -2
  219. package/templates/.agents/rules/create-issue.github.zh-CN.md +4 -2
  220. package/templates/.agents/rules/human-decision-context.en.md +11 -2
  221. package/templates/.agents/rules/human-decision-context.zh-CN.md +11 -2
  222. package/templates/.agents/rules/issue-fields.github.en.md +3 -1
  223. package/templates/.agents/rules/issue-fields.github.zh-CN.md +3 -1
  224. package/templates/.agents/rules/issue-pr-commands.en.md +5 -3
  225. package/templates/.agents/rules/issue-pr-commands.github.en.md +5 -3
  226. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +5 -3
  227. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +5 -3
  228. package/templates/.agents/rules/issue-sync.github.en.md +7 -3
  229. package/templates/.agents/rules/issue-sync.github.zh-CN.md +8 -4
  230. package/templates/.agents/rules/lifecycle-orchestration.en.md +5 -2
  231. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +5 -2
  232. package/templates/.agents/rules/milestone-inference.github.en.md +4 -2
  233. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +4 -2
  234. package/templates/.agents/rules/next-step-output.en.md +3 -1
  235. package/templates/.agents/rules/next-step-output.zh-CN.md +3 -1
  236. package/templates/.agents/rules/no-mid-flow-questions.en.md +17 -0
  237. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +17 -0
  238. package/templates/.agents/rules/pr-checks-commands.en.md +3 -3
  239. package/templates/.agents/rules/pr-checks-commands.github.en.md +2 -2
  240. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +3 -3
  241. package/templates/.agents/rules/pr-checks-commands.zh-CN.md +3 -3
  242. package/templates/.agents/rules/pr-sync.en.md +3 -1
  243. package/templates/.agents/rules/pr-sync.github.en.md +11 -1
  244. package/templates/.agents/rules/pr-sync.github.zh-CN.md +11 -1
  245. package/templates/.agents/rules/pr-sync.zh-CN.md +3 -1
  246. package/templates/.agents/rules/release-commands.en.md +1 -1
  247. package/templates/.agents/rules/release-commands.github.en.md +12 -2
  248. package/templates/.agents/rules/release-commands.github.zh-CN.md +12 -2
  249. package/templates/.agents/rules/release-commands.zh-CN.md +1 -1
  250. package/templates/.agents/rules/review-handshake.zh-CN.md +1 -1
  251. package/templates/.agents/rules/task-management.en.md +13 -0
  252. package/templates/.agents/rules/task-management.zh-CN.md +13 -0
  253. package/templates/.agents/skills/analyze-task/SKILL.en.md +10 -7
  254. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +10 -7
  255. package/templates/.agents/skills/block-task/SKILL.en.md +7 -5
  256. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +7 -5
  257. package/templates/.agents/skills/cancel-task/SKILL.en.md +6 -4
  258. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +6 -4
  259. package/templates/.agents/skills/close-codescan/SKILL.en.md +3 -1
  260. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +3 -1
  261. package/templates/.agents/skills/close-dependabot/SKILL.en.md +3 -1
  262. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +3 -1
  263. package/templates/.agents/skills/code-task/SKILL.en.md +10 -7
  264. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +12 -9
  265. package/templates/.agents/skills/commit/SKILL.en.md +23 -11
  266. package/templates/.agents/skills/commit/SKILL.zh-CN.md +29 -11
  267. package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -1
  268. package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -1
  269. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +49 -0
  270. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +55 -0
  271. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
  272. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
  273. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  274. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  275. package/templates/.agents/skills/commit/reference/task-status-update.en.md +4 -4
  276. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +4 -4
  277. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +6 -4
  278. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +6 -4
  279. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +1 -1
  280. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
  281. package/templates/.agents/skills/complete-task/SKILL.en.md +22 -7
  282. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +22 -7
  283. package/templates/.agents/skills/complete-task/config/verify.en.json +1 -0
  284. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +1 -0
  285. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +17 -0
  286. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +17 -0
  287. package/templates/.agents/skills/create-pr/SKILL.en.md +7 -5
  288. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +7 -5
  289. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +1 -1
  290. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +1 -1
  291. package/templates/.agents/skills/create-release-note/SKILL.en.md +17 -16
  292. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +17 -16
  293. package/templates/.agents/skills/create-task/SKILL.en.md +5 -3
  294. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +5 -3
  295. package/templates/.agents/skills/create-task/reference/context-capture.en.md +34 -0
  296. package/templates/.agents/skills/create-task/reference/context-capture.zh-CN.md +34 -0
  297. package/templates/.agents/skills/import-issue/SKILL.en.md +5 -3
  298. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +5 -3
  299. package/templates/.agents/skills/plan-task/SKILL.en.md +8 -5
  300. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +8 -5
  301. package/templates/.agents/skills/post-release/SKILL.en.md +2 -0
  302. package/templates/.agents/skills/post-release/SKILL.zh-CN.md +2 -0
  303. package/templates/.agents/skills/release/SKILL.en.md +16 -10
  304. package/templates/.agents/skills/release/SKILL.zh-CN.md +16 -10
  305. package/templates/.agents/skills/restore-task/SKILL.en.md +4 -1
  306. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +4 -1
  307. package/templates/.agents/skills/review-analysis/SKILL.en.md +7 -4
  308. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +7 -4
  309. package/templates/.agents/skills/review-code/SKILL.en.md +11 -8
  310. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +11 -8
  311. package/templates/.agents/skills/review-code/reference/output-templates.en.md +1 -1
  312. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +1 -1
  313. package/templates/.agents/skills/review-plan/SKILL.en.md +7 -4
  314. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +7 -4
  315. package/templates/.agents/skills/review-pr/SKILL.en.md +186 -0
  316. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +186 -0
  317. package/templates/.agents/skills/review-pr/config/verify.en.json +37 -0
  318. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +37 -0
  319. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +65 -0
  320. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +65 -0
  321. package/templates/.agents/skills/review-pr/reference/output-guidance.en.md +18 -0
  322. package/templates/.agents/skills/review-pr/reference/output-guidance.zh-CN.md +18 -0
  323. package/templates/.agents/skills/review-pr/reference/report-template.en.md +85 -0
  324. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +85 -0
  325. package/templates/.agents/skills/run-task/SKILL.en.md +8 -8
  326. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +8 -8
  327. package/templates/.agents/skills/run-task/config/verify.en.json +2 -1
  328. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +2 -1
  329. package/templates/.agents/skills/run-task/reference/host-validation.en.md +20 -0
  330. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +20 -0
  331. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +98 -107
  332. package/templates/.agents/skills/watch-pr/SKILL.en.md +13 -13
  333. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +13 -13
  334. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +27 -6
  335. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +26 -5
  336. package/templates/.agents/templates/task.en.md +2 -2
  337. package/templates/.agents/templates/task.zh-CN.md +2 -2
  338. package/templates/.agents/workflows/bug-fix.en.yaml +3 -3
  339. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +3 -3
  340. package/templates/.agents/workflows/code-review.en.yaml +1 -1
  341. package/templates/.agents/workflows/code-review.zh-CN.yaml +1 -1
  342. package/templates/.agents/workflows/feature-development.en.yaml +4 -4
  343. package/templates/.agents/workflows/feature-development.zh-CN.yaml +4 -4
  344. package/templates/.agents/workflows/refactoring.en.yaml +3 -3
  345. package/templates/.agents/workflows/refactoring.zh-CN.yaml +3 -3
  346. package/templates/.claude/commands/post-release.en.md +1 -0
  347. package/templates/.claude/commands/post-release.zh-CN.md +1 -0
  348. package/templates/.claude/commands/review-pr.en.md +8 -0
  349. package/templates/.claude/commands/review-pr.zh-CN.md +8 -0
  350. package/templates/.claude/commands/watch-pr.en.md +1 -1
  351. package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
  352. package/templates/.claude/rules/tool-preferences.en.md +20 -0
  353. package/templates/.claude/rules/tool-preferences.zh-CN.md +20 -0
  354. package/templates/.opencode/commands/post-release.en.md +2 -0
  355. package/templates/.opencode/commands/post-release.zh-CN.md +2 -0
  356. package/templates/.opencode/commands/review-pr.en.md +11 -0
  357. package/templates/.opencode/commands/review-pr.zh-CN.md +11 -0
  358. package/templates/.opencode/commands/watch-pr.en.md +1 -1
  359. package/templates/.opencode/commands/watch-pr.zh-CN.md +1 -1
  360. package/dist/lib/agent-clients/adapters/gemini-cli.js +0 -64
  361. package/lib/agent-clients/adapters/gemini-cli.ts +0 -65
  362. package/templates/.gemini/commands/_project_/analyze-task.en.toml +0 -10
  363. package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +0 -10
  364. package/templates/.gemini/commands/_project_/archive-tasks.en.toml +0 -10
  365. package/templates/.gemini/commands/_project_/archive-tasks.zh-CN.toml +0 -10
  366. package/templates/.gemini/commands/_project_/block-task.en.toml +0 -10
  367. package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +0 -10
  368. package/templates/.gemini/commands/_project_/cancel-task.en.toml +0 -10
  369. package/templates/.gemini/commands/_project_/cancel-task.zh-CN.toml +0 -10
  370. package/templates/.gemini/commands/_project_/check-task.en.toml +0 -10
  371. package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +0 -10
  372. package/templates/.gemini/commands/_project_/close-codescan.en.toml +0 -8
  373. package/templates/.gemini/commands/_project_/close-codescan.zh-CN.toml +0 -8
  374. package/templates/.gemini/commands/_project_/close-dependabot.en.toml +0 -8
  375. package/templates/.gemini/commands/_project_/close-dependabot.zh-CN.toml +0 -8
  376. package/templates/.gemini/commands/_project_/code-task.en.toml +0 -10
  377. package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +0 -10
  378. package/templates/.gemini/commands/_project_/commit.en.toml +0 -10
  379. package/templates/.gemini/commands/_project_/commit.zh-CN.toml +0 -10
  380. package/templates/.gemini/commands/_project_/complete-manual-validation.en.toml +0 -10
  381. package/templates/.gemini/commands/_project_/complete-manual-validation.zh-CN.toml +0 -10
  382. package/templates/.gemini/commands/_project_/complete-task.en.toml +0 -10
  383. package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +0 -10
  384. package/templates/.gemini/commands/_project_/create-pr.en.toml +0 -10
  385. package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +0 -10
  386. package/templates/.gemini/commands/_project_/create-release-note.en.toml +0 -8
  387. package/templates/.gemini/commands/_project_/create-release-note.zh-CN.toml +0 -8
  388. package/templates/.gemini/commands/_project_/create-task.en.toml +0 -8
  389. package/templates/.gemini/commands/_project_/create-task.zh-CN.toml +0 -8
  390. package/templates/.gemini/commands/_project_/import-codescan.en.toml +0 -8
  391. package/templates/.gemini/commands/_project_/import-codescan.zh-CN.toml +0 -8
  392. package/templates/.gemini/commands/_project_/import-dependabot.en.toml +0 -8
  393. package/templates/.gemini/commands/_project_/import-dependabot.zh-CN.toml +0 -8
  394. package/templates/.gemini/commands/_project_/import-issue.en.toml +0 -8
  395. package/templates/.gemini/commands/_project_/import-issue.zh-CN.toml +0 -8
  396. package/templates/.gemini/commands/_project_/init-labels.en.toml +0 -8
  397. package/templates/.gemini/commands/_project_/init-labels.zh-CN.toml +0 -8
  398. package/templates/.gemini/commands/_project_/init-milestones.en.toml +0 -10
  399. package/templates/.gemini/commands/_project_/init-milestones.zh-CN.toml +0 -10
  400. package/templates/.gemini/commands/_project_/plan-task.en.toml +0 -10
  401. package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +0 -10
  402. package/templates/.gemini/commands/_project_/post-release.en.toml +0 -6
  403. package/templates/.gemini/commands/_project_/post-release.zh-CN.toml +0 -6
  404. package/templates/.gemini/commands/_project_/refine-title.en.toml +0 -8
  405. package/templates/.gemini/commands/_project_/refine-title.zh-CN.toml +0 -8
  406. package/templates/.gemini/commands/_project_/release.en.toml +0 -8
  407. package/templates/.gemini/commands/_project_/release.zh-CN.toml +0 -8
  408. package/templates/.gemini/commands/_project_/restore-task.en.toml +0 -8
  409. package/templates/.gemini/commands/_project_/restore-task.zh-CN.toml +0 -8
  410. package/templates/.gemini/commands/_project_/review-analysis.en.toml +0 -10
  411. package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +0 -10
  412. package/templates/.gemini/commands/_project_/review-code.en.toml +0 -10
  413. package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +0 -10
  414. package/templates/.gemini/commands/_project_/review-plan.en.toml +0 -10
  415. package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +0 -10
  416. package/templates/.gemini/commands/_project_/run-task.en.toml +0 -8
  417. package/templates/.gemini/commands/_project_/run-task.zh-CN.toml +0 -8
  418. package/templates/.gemini/commands/_project_/test-integration.en.toml +0 -6
  419. package/templates/.gemini/commands/_project_/test-integration.zh-CN.toml +0 -6
  420. package/templates/.gemini/commands/_project_/test.en.toml +0 -6
  421. package/templates/.gemini/commands/_project_/test.zh-CN.toml +0 -6
  422. package/templates/.gemini/commands/_project_/update-agent-infra.en.toml +0 -6
  423. package/templates/.gemini/commands/_project_/update-agent-infra.zh-CN.toml +0 -6
  424. package/templates/.gemini/commands/_project_/upgrade-dependency.en.toml +0 -8
  425. package/templates/.gemini/commands/_project_/upgrade-dependency.zh-CN.toml +0 -8
  426. package/templates/.gemini/commands/_project_/watch-pr.en.toml +0 -10
  427. package/templates/.gemini/commands/_project_/watch-pr.zh-CN.toml +0 -10
  428. package/templates/.gemini/settings.json +0 -3
@@ -1,5 +1,6 @@
1
1
  import { defineAgentClientAdapter } from '../adapter.js';
2
2
  import { hostJoin } from '../../sandbox/engines/wsl2-paths.js';
3
+ import { opencodeBeforeContainerCreateHook, opencodeRecoveryChecks } from './opencode-sandbox.js';
3
4
  const YOLO_PERMISSION = '{"*":"allow","read":"allow","bash":"allow","edit":"allow","webfetch":"allow","external_directory":"allow","doom_loop":"allow"}';
4
5
  const opencodeAdapter = defineAgentClientAdapter({
5
6
  id: 'opencode',
@@ -15,6 +16,15 @@ const opencodeAdapter = defineAgentClientAdapter({
15
16
  sandbox: { level: 'integrated' },
16
17
  verification: { level: 'compatible' }
17
18
  },
19
+ modelSelection: {
20
+ kind: 'interactive-only',
21
+ command: '/models',
22
+ guidance: 'Use the host model picker for the complete model and reasoning-effort catalog.'
23
+ },
24
+ delegationEvidence: {
25
+ actualModel: 'unavailable',
26
+ actualReasoningEffort: 'unavailable'
27
+ },
18
28
  project: {
19
29
  ownedPathPrefixes: ['.opencode/'],
20
30
  managed: ['.opencode/commands/'],
@@ -26,9 +36,17 @@ const opencodeAdapter = defineAgentClientAdapter({
26
36
  'zh-CN': '.opencode/commands/update-agent-infra.zh-CN.md'
27
37
  },
28
38
  target: '.opencode/commands/update-agent-infra.md'
29
- }]
39
+ }],
40
+ customCommand: {
41
+ target: '.opencode/commands/${skillName}.md',
42
+ frontmatter: { agent: 'general', subtask: false },
43
+ argumentsToken: '$ARGUMENTS'
44
+ }
30
45
  },
31
46
  sandbox: {
47
+ image: {
48
+ dotfilesExclusions: ['.config/opencode']
49
+ },
32
50
  createTool: ({ home }) => ({
33
51
  id: 'opencode',
34
52
  name: 'OpenCode',
@@ -38,7 +56,9 @@ const opencodeAdapter = defineAgentClientAdapter({
38
56
  versionCmd: 'opencode --version',
39
57
  setupHint: 'Configure OpenCode credentials inside the container before first use.',
40
58
  envVars: {
41
- OPENCODE_CONFIG: '/home/devuser/.local/share/opencode/opencode.json'
59
+ XDG_DATA_HOME: '/home/devuser/.local/share',
60
+ XDG_CONFIG_HOME: '/home/devuser/.local/share/opencode/.xdg/config',
61
+ XDG_STATE_HOME: '/home/devuser/.local/share/opencode/.xdg/state'
42
62
  },
43
63
  hostLiveMounts: [
44
64
  {
@@ -57,7 +77,8 @@ const opencodeAdapter = defineAgentClientAdapter({
57
77
  command: `OPENCODE_PERMISSION='${YOLO_PERMISSION}' opencode; tput ed`
58
78
  }
59
79
  ],
60
- hooks: []
80
+ hooks: [opencodeBeforeContainerCreateHook],
81
+ recoveryChecks: opencodeRecoveryChecks
61
82
  }
62
83
  });
63
84
  export { opencodeAdapter };
@@ -0,0 +1,65 @@
1
+ RUN cat > /usr/local/bin/cc-token-status <<'SCRIPT' && chmod +x /usr/local/bin/cc-token-status
2
+ #!/bin/sh
3
+ set -eu
4
+
5
+ SETTINGS_FILE="/home/devuser/.claude/settings.json"
6
+ if [ -r "$SETTINGS_FILE" ] && jq -e '
7
+ def has_nonempty($v):
8
+ if ($v | type) == "string" then ($v | gsub("^\\s+|\\s+$"; "") | length) > 0 else false end;
9
+ (if type == "object" then . else {} end) as $settings
10
+ | (if ($settings.env | type) == "object" then $settings.env else {} end) as $env
11
+ | has_nonempty($env.ANTHROPIC_AUTH_TOKEN)
12
+ or has_nonempty($env.ANTHROPIC_API_KEY)
13
+ or has_nonempty($settings.apiKeyHelper)
14
+ ' "$SETTINGS_FILE" >/dev/null 2>&1; then
15
+ exit 0
16
+ fi
17
+
18
+ CRED_FILE="/home/devuser/.claude/.credentials.json"
19
+ [ -r "$CRED_FILE" ] || exit 0
20
+
21
+ EXPIRES_MS=$(jq -r '(.claudeAiOauth.expiresAt // .expiresAt) // empty' "$CRED_FILE" 2>/dev/null || true)
22
+ case "$EXPIRES_MS" in
23
+ ''|*[!0-9]*) exit 0 ;;
24
+ esac
25
+
26
+ NOW_MS=$(($(date +%s) * 1000))
27
+ DIFF_MS=$((EXPIRES_MS - NOW_MS))
28
+ DIFF_S=$((DIFF_MS / 1000))
29
+
30
+ DIM='#[fg=colour245]'
31
+ YELLOW='#[fg=yellow]'
32
+ YELLOW_BOLD='#[fg=yellow,bold]'
33
+ RED_BOLD='#[fg=red,bold]'
34
+ RED_REV='#[fg=red,reverse]'
35
+ RESET='#[default]'
36
+
37
+ if [ "$DIFF_S" -le 0 ]; then
38
+ ELAPSED=$(( -DIFF_S ))
39
+ M=$((ELAPSED / 60))
40
+ printf '%sClaude Code auth EXPIRED %dm ago%s' "$RED_REV" "$M" "$RESET"
41
+ elif [ "$DIFF_S" -lt 60 ]; then
42
+ printf '%sClaude Code auth expires in %ds%s' "$RED_BOLD" "$DIFF_S" "$RESET"
43
+ elif [ "$DIFF_S" -lt 300 ]; then
44
+ M=$((DIFF_S / 60))
45
+ S=$((DIFF_S % 60))
46
+ printf '%sClaude Code auth expires in %dm %ds%s' "$RED_BOLD" "$M" "$S" "$RESET"
47
+ elif [ "$DIFF_S" -lt 1800 ]; then
48
+ M=$((DIFF_S / 60))
49
+ printf '%sClaude Code auth expires in %dm%s' "$YELLOW_BOLD" "$M" "$RESET"
50
+ elif [ "$DIFF_S" -lt 3600 ]; then
51
+ M=$((DIFF_S / 60))
52
+ printf '%sClaude Code auth expires in %dm%s' "$YELLOW" "$M" "$RESET"
53
+ else
54
+ TOTAL_M=$((DIFF_S / 60))
55
+ H=$((TOTAL_M / 60))
56
+ M=$((TOTAL_M % 60))
57
+ printf '%sClaude Code auth expires in %dh %dm%s' "$DIM" "$H" "$M" "$RESET"
58
+ fi
59
+ SCRIPT
60
+
61
+ RUN test -s /usr/local/bin/cc-token-status && test -x /usr/local/bin/cc-token-status
62
+
63
+ RUN printf '%s\n' \
64
+ "set -g status-right '#(/usr/local/bin/cc-token-status) | %H:%M'" \
65
+ >> /etc/tmux.conf
@@ -20,6 +20,37 @@ function isRecord(value) {
20
20
  function fail(code, path) {
21
21
  throw new AgentClientConfigError({ code, path });
22
22
  }
23
+ function parseExactText(value, path) {
24
+ if (typeof value !== 'string' || value.length === 0 || value.trim() !== value) {
25
+ fail('INVALID_AGENT_CLIENTS', path);
26
+ }
27
+ return value;
28
+ }
29
+ function parseOrchestrationPolicy(value, path) {
30
+ if (!isRecord(value))
31
+ fail('INVALID_AGENT_CLIENTS', path);
32
+ const keys = Object.keys(value);
33
+ if (keys.length !== 2
34
+ || !hasOwn(value, 'executor')
35
+ || !hasOwn(value, 'reviewer')) {
36
+ fail('INVALID_AGENT_CLIENTS', path);
37
+ }
38
+ const parseRole = (candidate, rolePath) => {
39
+ if (!isRecord(candidate)
40
+ || Object.keys(candidate).length !== 2
41
+ || !hasOwn(candidate, 'model')
42
+ || !hasOwn(candidate, 'reasoningEffort')) {
43
+ fail('INVALID_AGENT_CLIENTS', rolePath);
44
+ }
45
+ return Object.freeze({
46
+ model: parseExactText(candidate.model, `${rolePath}.model`),
47
+ reasoningEffort: parseExactText(candidate.reasoningEffort, `${rolePath}.reasoningEffort`)
48
+ });
49
+ };
50
+ const executor = parseRole(value.executor, `${path}.executor`);
51
+ const reviewer = parseRole(value.reviewer, `${path}.reviewer`);
52
+ return Object.freeze({ executor, reviewer });
53
+ }
23
54
  function parseCanonical(value) {
24
55
  if (!Array.isArray(value))
25
56
  fail('INVALID_AGENT_CLIENTS', 'agentClients');
@@ -29,10 +60,11 @@ function parseCanonical(value) {
29
60
  if (!isRecord(candidate))
30
61
  fail('INVALID_AGENT_CLIENTS', path);
31
62
  const keys = Object.keys(candidate);
32
- if (keys.length !== 3
63
+ if ((keys.length !== 3 && keys.length !== 4)
33
64
  || !hasOwn(candidate, 'id')
34
65
  || !hasOwn(candidate, 'enabled')
35
- || !hasOwn(candidate, 'installInSandbox')) {
66
+ || !hasOwn(candidate, 'installInSandbox')
67
+ || (keys.length === 4 && !hasOwn(candidate, 'orchestration'))) {
36
68
  fail('INVALID_AGENT_CLIENTS', path);
37
69
  }
38
70
  if (!isAgentClientId(candidate.id)) {
@@ -47,7 +79,10 @@ function parseCanonical(value) {
47
79
  }
48
80
  entries.set(candidate.id, {
49
81
  enabled: candidate.enabled,
50
- installInSandbox: candidate.installInSandbox
82
+ installInSandbox: candidate.installInSandbox,
83
+ ...(hasOwn(candidate, 'orchestration')
84
+ ? { orchestration: parseOrchestrationPolicy(candidate.orchestration, `${path}.orchestration`) }
85
+ : {})
51
86
  });
52
87
  }
53
88
  for (const id of AGENT_CLIENT_IDS) {
@@ -60,7 +95,10 @@ function serializeAgentClients(state) {
60
95
  return AGENT_CLIENT_IDS.map((id) => ({
61
96
  id,
62
97
  enabled: state[id].enabled,
63
- installInSandbox: state[id].installInSandbox
98
+ installInSandbox: state[id].installInSandbox,
99
+ ...(state[id].orchestration
100
+ ? { orchestration: structuredClone(state[id].orchestration) }
101
+ : {})
64
102
  }));
65
103
  }
66
104
  function projectLegacyTuis(value, diagnostics) {
@@ -1,5 +1,6 @@
1
1
  import { listEnabledAgentClientAdapters } from './registry.js';
2
2
  import { renderAgentClientInvocation } from './invocation.js';
3
+ import semver from 'semver';
3
4
  const SAFE_NAME = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
4
5
  const SAFE_TASK_REF = /^(?:\d+|TASK-\d{8}-\d{6})$/;
5
6
  function requireSafeName(value, field) {
@@ -13,6 +14,14 @@ function renderNextStepCommands(input) {
13
14
  if (input.taskRef !== undefined && !SAFE_TASK_REF.test(input.taskRef)) {
14
15
  throw new Error('Invalid task ref');
15
16
  }
17
+ if (input.version !== undefined
18
+ && (!/^[0-9]/.test(input.version) || semver.valid(input.version) !== input.version)) {
19
+ throw new Error('Invalid version');
20
+ }
21
+ const args = [
22
+ ...(input.taskRef === undefined ? [] : [input.taskRef]),
23
+ ...(input.version === undefined ? [] : [input.version])
24
+ ];
16
25
  const builtins = listEnabledAgentClientAdapters(input.state).map((adapter) => Object.freeze({
17
26
  source: 'builtin',
18
27
  clientId: adapter.id,
@@ -20,7 +29,7 @@ function renderNextStepCommands(input) {
20
29
  command: renderAgentClientInvocation(adapter.invocation, {
21
30
  projectName: input.projectName,
22
31
  skillName: input.skillName,
23
- args: input.taskRef === undefined ? [] : [input.taskRef]
32
+ args
24
33
  })
25
34
  }));
26
35
  const custom = input.customTUIs.map((tool) => Object.freeze({
@@ -29,7 +38,7 @@ function renderNextStepCommands(input) {
29
38
  command: renderAgentClientInvocation(tool.invocation, {
30
39
  projectName: input.projectName,
31
40
  skillName: input.skillName,
32
- args: input.taskRef === undefined ? [] : [input.taskRef]
41
+ args
33
42
  })
34
43
  }));
35
44
  return Object.freeze([...builtins, ...custom]);
@@ -158,7 +158,8 @@ function planAgentClientReconciliation(input) {
158
158
  skillName: 'update-agent-infra'
159
159
  });
160
160
  const actionableSeed = seedOperations.some((operation) => operation.kind === 'write' || operation.kind === 'remove');
161
- const changed = JSON.stringify(nextConfig) !== JSON.stringify(input.config) || actionableSeed;
161
+ const changed = JSON.stringify(nextConfig) !== JSON.stringify(input.config)
162
+ || actionableSeed;
162
163
  return Object.freeze({
163
164
  source: normalized.source,
164
165
  before: normalized.state,
@@ -52,6 +52,12 @@ function listInstalledAgentClientAdapters(state) {
52
52
  function getAgentClientCapability(id, capability) {
53
53
  return getAgentClientAdapter(id).capabilities[capability];
54
54
  }
55
+ function getAgentClientModelSelection(id) {
56
+ return getAgentClientAdapter(id).modelSelection;
57
+ }
58
+ function getAgentClientDelegationEvidence(id) {
59
+ return getAgentClientAdapter(id).delegationEvidence;
60
+ }
55
61
  function listEnabledAgentClientAdaptersByCapability(state, capability, acceptedLevels) {
56
62
  const accepted = new Set(acceptedLevels);
57
63
  return Object.freeze(AGENT_CLIENT_ADAPTERS.filter((adapter) => state[adapter.id].enabled
@@ -65,8 +71,16 @@ function createAgentClientManifest() {
65
71
  ownedPathPrefixes: Object.freeze([...adapter.project.ownedPathPrefixes]),
66
72
  managed: Object.freeze([...adapter.project.managed]),
67
73
  merged: Object.freeze([...adapter.project.merged]),
68
- ejected: Object.freeze([...adapter.project.ejected])
74
+ ejected: Object.freeze([...adapter.project.ejected]),
75
+ ...(adapter.project.customCommand === undefined
76
+ ? {}
77
+ : {
78
+ customCommand: Object.freeze({
79
+ ...adapter.project.customCommand,
80
+ frontmatter: Object.freeze({ ...adapter.project.customCommand.frontmatter })
81
+ })
82
+ })
69
83
  })));
70
84
  }
71
- export { AGENT_CLIENT_REGISTRY, createAgentClientManifest, getAgentClientAdapter, getAgentClientCapability, listAgentClientAdapters, listEnabledAgentClientAdapters, listEnabledAgentClientAdaptersByCapability, listInstalledAgentClientAdapters };
85
+ export { AGENT_CLIENT_REGISTRY, createAgentClientManifest, getAgentClientAdapter, getAgentClientCapability, getAgentClientDelegationEvidence, getAgentClientModelSelection, listAgentClientAdapters, listEnabledAgentClientAdapters, listEnabledAgentClientAdaptersByCapability, listInstalledAgentClientAdapters };
72
86
  //# sourceMappingURL=registry.js.map
@@ -24,6 +24,15 @@ const AGENT_CLIENTS_SCHEMA = {
24
24
  },
25
25
  installInSandbox: {
26
26
  type: 'boolean'
27
+ },
28
+ orchestration: {
29
+ type: 'object',
30
+ additionalProperties: false,
31
+ required: ['executor', 'reviewer'],
32
+ properties: {
33
+ executor: { $ref: '#/definitions/orchestrationRolePolicy' },
34
+ reviewer: { $ref: '#/definitions/orchestrationRolePolicy' }
35
+ }
27
36
  }
28
37
  }
29
38
  }
@@ -43,6 +52,15 @@ const AGENT_CLIENTS_SCHEMA = {
43
52
  }
44
53
  },
45
54
  definitions: {
55
+ orchestrationRolePolicy: {
56
+ type: 'object',
57
+ additionalProperties: false,
58
+ required: ['model', 'reasoningEffort'],
59
+ properties: {
60
+ model: { type: 'string', minLength: 1 },
61
+ reasoningEffort: { type: 'string', minLength: 1 }
62
+ }
63
+ },
46
64
  agentClientCapabilityId: {
47
65
  type: 'string',
48
66
  enum: [...AGENT_CLIENT_CAPABILITY_IDS]
@@ -0,0 +1,49 @@
1
+ // Active AI collaborator short tokens — the write-side whitelist for the
2
+ // activity log. Migrated from lib/task/commands/log.ts so that the write-side
3
+ // internal commands and the rendering side share one definition. Historical
4
+ // Gemini tokens remain read-only and are handled by classifyAgent below.
5
+ export const KNOWN_AI_AGENTS = new Set(['claude', 'codex', 'antigravity', 'opencode', 'cursor']);
6
+ // Long name -> short name mapping (HD-4, decision A): `claude-code` reuses the
7
+ // existing orchestration precedent, and `antigravity-cli` is the active
8
+ // client. `gemini-cli` is intentionally not writable.
9
+ export const AGENT_LONG_NAMES = {
10
+ 'claude-code': 'claude',
11
+ 'antigravity-cli': 'antigravity'
12
+ };
13
+ export const AGENT_USAGE_HINT = "agent must be a short token (claude/codex/antigravity/opencode/cursor), " +
14
+ "a long name (claude-code -> claude, antigravity-cli -> antigravity), or 'human'";
15
+ // Read-side historical compatibility for activity-log rendering: `gemini` and
16
+ // `gemini-cli` stay recognizable when displaying old logs, but are never
17
+ // accepted by normalizeAgentToken (write side).
18
+ const READ_KNOWN_AI_AGENTS = new Set([...KNOWN_AI_AGENTS, 'gemini']);
19
+ const READ_AGENT_LONG_NAMES = {
20
+ ...AGENT_LONG_NAMES,
21
+ 'gemini-cli': 'gemini'
22
+ };
23
+ // Strict write-side validation: the value must be exactly a short token, a
24
+ // long name, or 'human'; returns the normalized short token, or null when
25
+ // the value is not a recognized agent.
26
+ export function normalizeAgentToken(value) {
27
+ const trimmed = value.trim();
28
+ if (trimmed === 'human')
29
+ return 'human';
30
+ if (KNOWN_AI_AGENTS.has(trimmed))
31
+ return trimmed;
32
+ const short = AGENT_LONG_NAMES[trimmed];
33
+ return short ?? null;
34
+ }
35
+ // Loose rendering-side classification: tolerates historical parenthetical
36
+ // annotations; unknown tokens keep the `human` grouping but get a visible
37
+ // signal. The "known AI token" test is `classifyAgent(value).status === 'ai'`.
38
+ export function classifyAgent(raw) {
39
+ const token = raw.trim().split(/\s+/)[0]?.replace(/\(.*$/, '') ?? '';
40
+ if (token === '')
41
+ return { status: 'unknown', display: 'human' };
42
+ if (token === 'human')
43
+ return { status: 'human', display: 'human' };
44
+ if (READ_KNOWN_AI_AGENTS.has(token))
45
+ return { status: 'ai', display: token };
46
+ const short = READ_AGENT_LONG_NAMES[token];
47
+ return short ? { status: 'ai', display: short } : { status: 'unknown', display: 'human' };
48
+ }
49
+ //# sourceMappingURL=tokens.js.map
@@ -1,7 +1,7 @@
1
1
  const AGENT_CLIENT_IDS = [
2
2
  'claude-code',
3
3
  'codex',
4
- 'gemini-cli',
4
+ 'antigravity-cli',
5
5
  'opencode'
6
6
  ];
7
7
  const AGENT_CLIENT_CAPABILITY_IDS = [
@@ -14,7 +14,7 @@
14
14
  "installInSandbox": true
15
15
  },
16
16
  {
17
- "id": "gemini-cli",
17
+ "id": "antigravity-cli",
18
18
  "enabled": true,
19
19
  "installInSandbox": true
20
20
  },
@@ -1,4 +1,6 @@
1
1
  import { spawnSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
2
4
  const defaultRunner = (args, cwd) => {
3
5
  const result = spawnSync('git', [...args], { cwd, encoding: 'utf8' });
4
6
  return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };
@@ -10,6 +12,9 @@ function value(runner, cwd, args, trim = true) {
10
12
  const result = run(runner, cwd, args);
11
13
  return result.status === 0 ? (trim ? result.stdout.trim() : result.stdout.replace(/\n$/, '')) : null;
12
14
  }
15
+ function cleanMessage(message) {
16
+ return message.replace(/(https?:\/\/)[^\s/@:]+(?::[^\s/@]*)?@/gi, '$1***@').trim();
17
+ }
13
18
  function inspectGitWorkflow(cwd, runner = defaultRunner, remoteInput) {
14
19
  const head = value(runner, cwd, ['rev-parse', 'HEAD']);
15
20
  const branch = value(runner, cwd, ['branch', '--show-current']);
@@ -97,5 +102,53 @@ function pushGitRefs(input, runner = defaultRunner) {
97
102
  const failures = operations.filter((item) => item.status === 'failed').length;
98
103
  return { status: failures === 0 ? 'applied' : failures === operations.length ? 'failed' : 'degraded', changed: failures < operations.length, snapshot: inspectGitWorkflow(input.cwd, runner).snapshot, operations, error: failures ? { code: 'GIT_PUSH_PARTIAL', message: `${failures} ref push operation(s) failed` } : null };
99
104
  }
100
- export { commitExplicitPaths, inspectGitWorkflow, pushGitRefs };
105
+ function pushRebasedBranch(input, runner = defaultRunner) {
106
+ const sha = /^[0-9a-f]{40}$/i;
107
+ const refName = /^(?!-)(?!.*\.\.)(?!.*(?:^|\/)\.)(?!.*[~^:?*\[\\\s])(?:[A-Za-z0-9._-]+\/)*[A-Za-z0-9._-]+$/;
108
+ if (!input.remote || !refName.test(input.remote) || !refName.test(input.branch) || !refName.test(input.baseBranch) ||
109
+ !sha.test(input.expectedOldHead) || !sha.test(input.newHead) || !sha.test(input.expectedBaseHead)) {
110
+ return { status: 'failed', changed: false, snapshot: null, operations: [], error: { code: 'GIT_REBASED_INPUT_INVALID', message: 'Remote, branches, and full 40-character SHAs are required' } };
111
+ }
112
+ const snapshot = inspectGitWorkflow(input.cwd, runner).snapshot;
113
+ if (!snapshot)
114
+ return { status: 'failed', changed: false, snapshot: null, operations: [], error: { code: 'GIT_INSPECT_FAILED', message: 'Unable to inspect Git repository' } };
115
+ if (snapshot.branch !== input.branch || snapshot.head !== input.newHead) {
116
+ return { status: 'failed', changed: false, snapshot, operations: [], error: { code: 'GIT_LOCAL_IDENTITY_MISMATCH', message: 'Current branch or HEAD does not match the rebased intent' } };
117
+ }
118
+ const rebasePaths = ['rebase-merge', 'rebase-apply']
119
+ .map((name) => value(runner, input.cwd, ['rev-parse', '--git-path', name]))
120
+ .filter((candidate) => Boolean(candidate));
121
+ if (snapshot.worktree.length > 0 || snapshot.staged.length > 0 ||
122
+ run(runner, input.cwd, ['rev-parse', '-q', '--verify', 'REBASE_HEAD']).status === 0 ||
123
+ rebasePaths.some((candidate) => fs.existsSync(path.isAbsolute(candidate) ? candidate : path.join(input.cwd, candidate)))) {
124
+ return { status: 'failed', changed: false, snapshot, operations: [], error: { code: 'GIT_LOCAL_STATE_UNSAFE', message: 'Working tree must be clean with no rebase in progress' } };
125
+ }
126
+ const remoteRef = `refs/heads/${input.branch}`;
127
+ const baseRef = `refs/heads/${input.baseBranch}`;
128
+ const remoteHead = value(runner, input.cwd, ['ls-remote', '--exit-code', input.remote, remoteRef])?.split(/\s+/)[0] ?? null;
129
+ if (remoteHead !== input.expectedOldHead) {
130
+ return { status: 'failed', changed: false, snapshot, operations: [], error: { code: 'GIT_REMOTE_HEAD_MISMATCH', message: `Expected remote head ${input.expectedOldHead}, received ${remoteHead ?? 'unavailable'}` } };
131
+ }
132
+ const baseHead = value(runner, input.cwd, ['ls-remote', '--exit-code', input.remote, baseRef])?.split(/\s+/)[0] ?? null;
133
+ if (baseHead !== input.expectedBaseHead) {
134
+ return { status: 'failed', changed: false, snapshot, operations: [], error: { code: 'GIT_REMOTE_BASE_MISMATCH', message: `Expected base head ${input.expectedBaseHead}, received ${baseHead ?? 'unavailable'}` } };
135
+ }
136
+ if (run(runner, input.cwd, ['merge-base', '--is-ancestor', input.expectedBaseHead, input.newHead]).status !== 0) {
137
+ return { status: 'failed', changed: false, snapshot, operations: [], error: { code: 'GIT_REBASED_ANCESTOR_MISMATCH', message: 'Rebased head does not contain the expected base head' } };
138
+ }
139
+ const pushed = run(runner, input.cwd, [
140
+ 'push', `--force-with-lease=${remoteRef}:${input.expectedOldHead}`,
141
+ input.remote, `${input.newHead}:${remoteRef}`
142
+ ]);
143
+ if (pushed.status !== 0) {
144
+ const message = cleanMessage(pushed.stderr) || 'Rebased branch push was rejected';
145
+ return { status: 'failed', changed: false, snapshot: inspectGitWorkflow(input.cwd, runner).snapshot, operations: [{ name: 'push-rebased', status: 'failed', ref: input.branch, message }], error: { code: 'GIT_REBASED_PUSH_REJECTED', message } };
146
+ }
147
+ const verified = value(runner, input.cwd, ['ls-remote', '--exit-code', input.remote, remoteRef])?.split(/\s+/)[0] ?? null;
148
+ if (verified !== input.newHead) {
149
+ return { status: 'failed', changed: true, snapshot: inspectGitWorkflow(input.cwd, runner).snapshot, operations: [{ name: 'push-rebased', status: 'failed', ref: input.branch, message: 'Remote ref verification failed' }], error: { code: 'GIT_REBASED_VERIFY_FAILED', message: `Expected pushed head ${input.newHead}, received ${verified ?? 'unavailable'}` } };
150
+ }
151
+ return { status: 'applied', changed: true, snapshot: inspectGitWorkflow(input.cwd, runner).snapshot, operations: [{ name: 'push-rebased', status: 'applied', ref: input.branch }], error: null };
152
+ }
153
+ export { commitExplicitPaths, inspectGitWorkflow, pushGitRefs, pushRebasedBranch };
101
154
  //# sourceMappingURL=workflow.js.map
@@ -3,7 +3,9 @@ import path from 'node:path';
3
3
  import { AgentClientConfigError, normalizeAgentClients } from '../agent-clients/config.js';
4
4
  import { normalizeCustomTUIs } from '../agent-clients/custom-tuis.js';
5
5
  import { renderNextStepCommands } from '../agent-clients/next-steps.js';
6
- const USAGE = 'Usage: agent-infra-internal agent-client next-steps --skill <skill-name> [--task-ref <NN|TASK-id>] [--format text|json]\n';
6
+ import { getAgentClientModelSelection } from '../agent-clients/registry.js';
7
+ import { isAgentClientId } from '../agent-clients/types.js';
8
+ const USAGE = 'Usage: agent-infra-internal agent-client <next-steps|model-selection> [options]\n';
7
9
  function failure(code, message) {
8
10
  process.stdout.write(`${JSON.stringify({
9
11
  status: 'failed',
@@ -25,11 +27,12 @@ function parseArgs(args) {
25
27
  }
26
28
  let skillName;
27
29
  let taskRef;
30
+ let version;
28
31
  let format = 'text';
29
32
  const seen = new Set();
30
33
  for (let index = 1; index < args.length; index += 1) {
31
34
  const flag = args[index];
32
- if (!['--skill', '--task-ref', '--format'].includes(flag)) {
35
+ if (!['--skill', '--task-ref', '--version', '--format'].includes(flag)) {
33
36
  failure('AGENT_CLIENT_PAYLOAD_INVALID', `unknown option '${flag}'`);
34
37
  return null;
35
38
  }
@@ -47,6 +50,8 @@ function parseArgs(args) {
47
50
  skillName = value;
48
51
  if (flag === '--task-ref')
49
52
  taskRef = value;
53
+ if (flag === '--version')
54
+ version = value;
50
55
  if (flag === '--format') {
51
56
  if (value !== 'text' && value !== 'json') {
52
57
  failure('AGENT_CLIENT_PAYLOAD_INVALID', "format must be 'text' or 'json'");
@@ -59,9 +64,60 @@ function parseArgs(args) {
59
64
  failure('AGENT_CLIENT_PAYLOAD_INVALID', "option '--skill' is required");
60
65
  return null;
61
66
  }
62
- return { skillName, ...(taskRef ? { taskRef } : {}), format };
67
+ return {
68
+ skillName,
69
+ ...(taskRef ? { taskRef } : {}),
70
+ ...(version ? { version } : {}),
71
+ format
72
+ };
63
73
  }
64
74
  function agentClient(args = []) {
75
+ if (args[0] === 'model-selection') {
76
+ const values = {};
77
+ const seen = new Set();
78
+ for (let index = 1; index < args.length; index += 1) {
79
+ const flag = args[index];
80
+ if (!['--client', '--format'].includes(flag) || seen.has(flag)) {
81
+ failure('AGENT_CLIENT_PAYLOAD_INVALID', `invalid or duplicate option '${flag}'`);
82
+ return;
83
+ }
84
+ const value = args[++index];
85
+ if (!value || value.startsWith('--')) {
86
+ failure('AGENT_CLIENT_PAYLOAD_INVALID', `option '${flag}' requires a value`);
87
+ return;
88
+ }
89
+ seen.add(flag);
90
+ values[flag] = value;
91
+ }
92
+ const client = values['--client'];
93
+ const format = values['--format'] ?? 'text';
94
+ if (!isAgentClientId(client) || !['text', 'json'].includes(format)) {
95
+ failure('AGENT_CLIENT_PAYLOAD_INVALID', 'model-selection requires a known --client and text|json format');
96
+ return;
97
+ }
98
+ const context = getAgentClientModelSelection(client);
99
+ if (format === 'json') {
100
+ process.stdout.write(`${JSON.stringify({
101
+ status: 'resolved', changed: false, client, context, error: null
102
+ })}\n`);
103
+ return;
104
+ }
105
+ if (context.kind === 'interactive-only') {
106
+ process.stdout.write(`Model selection: interactive-only\nCommand: ${context.command}\n${context.guidance}\n`);
107
+ }
108
+ else {
109
+ process.stdout.write(`Model selection: ${context.completeness} catalog\nSource: ${context.source}\n`);
110
+ for (const model of context.models) {
111
+ const efforts = model.reasoningEfforts?.length
112
+ ? ` (${model.reasoningEfforts.join(', ')})`
113
+ : '';
114
+ process.stdout.write(`- ${model.id}${efforts}\n`);
115
+ }
116
+ if (context.guidance)
117
+ process.stdout.write(`${context.guidance}\n`);
118
+ }
119
+ return;
120
+ }
65
121
  const parsed = parseArgs(args);
66
122
  if (!parsed || process.exitCode)
67
123
  return;
@@ -86,7 +142,8 @@ function agentClient(args = []) {
86
142
  state: clients.state,
87
143
  customTUIs: custom.items,
88
144
  skillName: parsed.skillName,
89
- ...(parsed.taskRef ? { taskRef: parsed.taskRef } : {})
145
+ ...(parsed.taskRef ? { taskRef: parsed.taskRef } : {}),
146
+ ...(parsed.version ? { version: parsed.version } : {})
90
147
  });
91
148
  if (parsed.format === 'json') {
92
149
  process.stdout.write(`${JSON.stringify({
@@ -1,5 +1,5 @@
1
1
  import fs from 'node:fs';
2
- import { commitExplicitPaths, inspectGitWorkflow, pushGitRefs } from '../git/workflow.js';
2
+ import { commitExplicitPaths, inspectGitWorkflow, pushGitRefs, pushRebasedBranch } from '../git/workflow.js';
3
3
  import { compareReviewTrees, snapshotReview } from '../git/review-snapshot.js';
4
4
  import { resolvePostReviewGlobs } from '../task/review-fingerprint.js';
5
5
  function output(value) { process.stdout.write(`${JSON.stringify(value)}\n`); }
@@ -23,6 +23,11 @@ function gitWorkflow(args = []) {
23
23
  const input = inputIndex >= 0 && rest[inputIndex + 1] ? JSON.parse(fs.readFileSync(rest[inputIndex + 1], 'utf8')) : null;
24
24
  result = input ? pushGitRefs({ cwd: cwd ?? process.cwd(), ...input }) : { status: 'failed', changed: false, error: { code: 'GIT_INPUT_REQUIRED', message: '--input JSON file is required' } };
25
25
  }
26
+ else if (action === 'push-rebased') {
27
+ const inputIndex = rest.indexOf('--input');
28
+ const input = inputIndex >= 0 && rest[inputIndex + 1] ? JSON.parse(fs.readFileSync(rest[inputIndex + 1], 'utf8')) : null;
29
+ result = input ? pushRebasedBranch({ cwd: cwd ?? process.cwd(), ...input }) : { status: 'failed', changed: false, error: { code: 'GIT_INPUT_REQUIRED', message: '--input JSON file is required' } };
30
+ }
26
31
  else if (action === 'snapshot' || action === 'compare-trees') {
27
32
  const inputIndex = rest.indexOf('--input');
28
33
  const input = inputIndex >= 0 && rest[inputIndex + 1] ? JSON.parse(fs.readFileSync(rest[inputIndex + 1], 'utf8')) : null;
@@ -1,5 +1,5 @@
1
1
  import path from 'node:path';
2
- import { fetchPlatformCheckLogs, inspectRequiredChecks, resolvePlatformCheckRun, watchPlatformChecks } from '../platform/pr-checks.js';
2
+ import { fetchPlatformCheckLogs, inspectPullRequestReadiness, resolvePlatformCheckRun, watchPullRequestReadiness } from '../platform/pr-checks.js';
3
3
  const USAGE = `Usage: agent-infra-internal platform-checks inspect <task-ref> [--cwd <path>]
4
4
  agent-infra-internal platform-checks watch <task-ref> --interval-seconds <N> --deadline-seconds <N> [--cwd <path>]
5
5
  agent-infra-internal platform-checks resolve-run <task-ref> --check-name <name> [--details-url <url>] [--cwd <path>]
@@ -76,7 +76,7 @@ async function platformChecks(args = []) {
76
76
  return;
77
77
  }
78
78
  if (operation === 'inspect') {
79
- finish(inspectRequiredChecks(taskRef, { cwd }));
79
+ finish(inspectPullRequestReadiness(taskRef, { cwd }));
80
80
  return;
81
81
  }
82
82
  if (operation === 'resolve-run') {
@@ -108,7 +108,7 @@ async function platformChecks(args = []) {
108
108
  process.once('SIGINT', abort);
109
109
  process.once('SIGTERM', abort);
110
110
  try {
111
- finish(await watchPlatformChecks(taskRef, { cwd, intervalSeconds, deadlineSeconds, signal: controller.signal }));
111
+ finish(await watchPullRequestReadiness(taskRef, { cwd, intervalSeconds, deadlineSeconds, signal: controller.signal }));
112
112
  }
113
113
  finally {
114
114
  process.removeListener('SIGINT', abort);