@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,8 @@
1
+ import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.ts';
1
2
  import { applyTaskLifecycle, lifecycleIntentCatalog } from '../task/lifecycle.ts';
2
3
  import type { TaskLifecycleRequest } from '../task/lifecycle.ts';
4
+ import { resolveTaskRef } from '../task/resolve-ref.ts';
5
+ import { TaskExecutionLockError, withTaskExecutionLock } from '../task/task-execution-lock.ts';
3
6
 
4
7
  const USAGE = `Usage: agent-infra-internal task-lifecycle <N | TASK-id> <intent> --agent <agent> [intent flags] [--dry-run]\n\nIntents: ${lifecycleIntentCatalog.join(', ')}\n`;
5
8
  const FLAGS: Record<string, string> = {
@@ -33,7 +36,29 @@ function taskLifecycle(args: string[] = []): void {
33
36
  seen.add(flag);
34
37
  values[key] = key === 'alertNumber' || key === 'issueNumber' ? Number(value) : value;
35
38
  }
36
- const result = applyTaskLifecycle(values as TaskLifecycleRequest);
39
+ const agent = normalizeAgentToken(String(values.agent ?? ''));
40
+ if (!agent) { usageFailure(`invalid --agent '${values.agent}': ${AGENT_USAGE_HINT}`); return; }
41
+ values.agent = agent;
42
+ const resolved = resolveTaskRef(String(values.taskRef));
43
+ if (!resolved.ok) {
44
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: resolved.code, message: resolved.message } })}\n`);
45
+ process.exitCode = 1;
46
+ return;
47
+ }
48
+ let result: ReturnType<typeof applyTaskLifecycle>;
49
+ try {
50
+ result = withTaskExecutionLock(
51
+ resolved.repoRoot,
52
+ resolved.taskId,
53
+ `task-lifecycle.${String(values.intent)}`,
54
+ () => applyTaskLifecycle(values as TaskLifecycleRequest)
55
+ );
56
+ } catch (error) {
57
+ if (!(error instanceof TaskExecutionLockError)) throw error;
58
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: error.code, message: error.message } })}\n`);
59
+ process.exitCode = 1;
60
+ return;
61
+ }
37
62
  process.stdout.write(`${JSON.stringify(result)}\n`);
38
63
  if (result.status === 'failed') process.exitCode = 1;
39
64
  }
@@ -1,19 +1,26 @@
1
+ import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.ts';
1
2
  import {
3
+ abortCommitIntent,
2
4
  activateMatchingOrchestrationDelegation,
3
5
  activateOrchestrationDelegation,
4
6
  advanceOrchestration,
7
+ beginCommitIntent,
5
8
  beginOrResumeOrchestration,
6
- completeCommitOrchestrationStage,
9
+ checkpointCommitIntent,
10
+ completeCommitIntent,
7
11
  pauseOrchestration,
8
12
  prepareOrchestrationDelegation,
13
+ recoverCommitIntent,
9
14
  routeOrchestration,
10
15
  sealMatchingOrchestrationDelegation,
11
16
  sealOrchestrationDelegation,
17
+ statusCommitIntent,
12
18
  statusOrchestration
13
19
  } from '../task/orchestration.ts';
20
+ import { isAgentClientId } from '../agent-clients/types.ts';
14
21
  import type { AgentClientId } from '../agent-clients/types.ts';
15
22
 
16
- const USAGE = 'Usage: agent-infra-internal task-orchestration <task-ref|auto> <begin-or-resume|route|prepare|hook-start|stage-completed|hook-stop|advance|pause|status> [options]\n';
23
+ const USAGE = 'Usage: agent-infra-internal task-orchestration <task-ref|auto> <begin-or-resume|route|prepare|hook-start|hook-stop|advance|pause|status|commit-begin|commit-checkpoint|commit-complete|commit-recover|commit-abort|commit-status> [options]\n';
17
24
 
18
25
  function usageFailure(message: string): void {
19
26
  process.stdout.write(`${JSON.stringify({
@@ -34,18 +41,32 @@ function taskOrchestration(args: string[] = []): void {
34
41
  return;
35
42
  }
36
43
  const [taskRef, intent] = args;
37
- if (!['begin-or-resume', 'route', 'prepare', 'hook-start', 'stage-completed', 'hook-stop', 'advance', 'pause', 'status'].includes(intent!)) {
44
+ if (![
45
+ 'begin-or-resume', 'route', 'prepare', 'hook-start', 'hook-stop', 'advance', 'pause', 'status',
46
+ 'commit-begin', 'commit-checkpoint', 'commit-complete', 'commit-recover', 'commit-abort', 'commit-status'
47
+ ].includes(intent!)) {
38
48
  usageFailure(`unknown intent '${intent}'`);
39
49
  return;
40
50
  }
41
51
  const values: Record<string, string> = {};
42
52
  const seen = new Set<string>();
53
+ let orchestrated = false;
43
54
  for (let index = 2; index < args.length; index += 1) {
44
55
  const flag = args[index]!;
56
+ if (flag === '--orchestrated') {
57
+ if (seen.has(flag)) { usageFailure(`duplicate option '${flag}'`); return; }
58
+ seen.add(flag);
59
+ orchestrated = true;
60
+ continue;
61
+ }
45
62
  if (![
46
- '--max-steps', '--client', '--requested-model', '--parent-id', '--before-fingerprint',
47
- '--native-agent', '--child-id', '--spawn-mode', '--actual-model', '--fallback-reason',
48
- '--exit-code', '--after-fingerprint', '--changed-paths', '--code', '--message', '--recoverable', '--agent'
63
+ '--max-steps', '--executor-model', '--executor-reasoning-effort',
64
+ '--reviewer-model', '--reviewer-reasoning-effort',
65
+ '--client', '--requested-model', '--requested-reasoning-effort', '--parent-id', '--before-fingerprint',
66
+ '--native-agent', '--child-id', '--spawn-mode', '--actual-model', '--actual-reasoning-effort',
67
+ '--model-fallback-reason', '--reasoning-effort-fallback-reason',
68
+ '--exit-code', '--after-fingerprint', '--changed-paths', '--code', '--message', '--recoverable', '--agent',
69
+ '--baseline-head', '--token', '--kind', '--head', '--remote', '--ref', '--expected-head'
49
70
  ].includes(flag)) {
50
71
  usageFailure(`unknown option '${flag}'`);
51
72
  return;
@@ -62,14 +83,102 @@ function taskOrchestration(args: string[] = []): void {
62
83
  }
63
84
  values[flag] = value;
64
85
  }
86
+ const commitIntentFlags: Record<string, readonly string[]> = {
87
+ 'commit-begin': ['--agent', '--baseline-head', '--orchestrated'],
88
+ 'commit-checkpoint': ['--token', '--kind', '--head', '--remote', '--ref'],
89
+ 'commit-complete': ['--token', '--agent'],
90
+ 'commit-recover': ['--agent'],
91
+ 'commit-abort': ['--token', '--expected-head'],
92
+ 'commit-status': []
93
+ };
94
+ if (intent! in commitIntentFlags) {
95
+ const allowed = commitIntentFlags[intent!]!;
96
+ const invalid = [...seen].find((flag) => !allowed.includes(flag));
97
+ if (invalid) { usageFailure(`intent '${intent}' does not accept '${invalid}'`); return; }
98
+ } else {
99
+ const commitOnly = [...seen].find((flag) => [
100
+ '--orchestrated', '--baseline-head', '--token', '--kind', '--head', '--remote', '--ref', '--expected-head'
101
+ ].includes(flag));
102
+ if (commitOnly) { usageFailure(`intent '${intent}' does not accept '${commitOnly}'`); return; }
103
+ }
65
104
  const requireValues = (flags: string[]) => flags.find((flag) => values[flag] === undefined);
105
+ if (values['--client'] !== undefined && !isAgentClientId(values['--client'])) {
106
+ usageFailure(`unknown client '${values['--client']}'`);
107
+ return;
108
+ }
66
109
  let result;
67
- if (intent === 'begin-or-resume') {
110
+ if (intent === 'commit-begin') {
111
+ const missing = requireValues(['--agent', '--baseline-head']);
112
+ if (missing) { usageFailure(`intent 'commit-begin' requires '${missing}'`); return; }
113
+ const agent = normalizeAgentToken(values['--agent']!);
114
+ if (!agent) { usageFailure(`invalid --agent '${values['--agent']}': ${AGENT_USAGE_HINT}`); return; }
115
+ result = beginCommitIntent(taskRef!, {
116
+ agent, orchestrated, baselineHead: values['--baseline-head']!
117
+ });
118
+ } else if (intent === 'commit-checkpoint') {
119
+ const missing = requireValues(['--token', '--kind', '--head']);
120
+ if (missing) { usageFailure(`intent 'commit-checkpoint' requires '${missing}'`); return; }
121
+ if (!['committed', 'pushed'].includes(values['--kind']!)) {
122
+ usageFailure('--kind must be committed or pushed'); return;
123
+ }
124
+ if (values['--kind'] === 'pushed') {
125
+ const pushedMissing = requireValues(['--remote', '--ref']);
126
+ if (pushedMissing) { usageFailure(`pushed checkpoint requires '${pushedMissing}'`); return; }
127
+ } else if (values['--remote'] !== undefined || values['--ref'] !== undefined) {
128
+ usageFailure('committed checkpoint does not accept --remote or --ref'); return;
129
+ }
130
+ result = checkpointCommitIntent(taskRef!, {
131
+ token: values['--token']!, kind: values['--kind'] as 'committed' | 'pushed',
132
+ head: values['--head']!, remote: values['--remote'], ref: values['--ref']
133
+ });
134
+ } else if (intent === 'commit-complete') {
135
+ const missing = requireValues(['--token', '--agent']);
136
+ if (missing) { usageFailure(`intent 'commit-complete' requires '${missing}'`); return; }
137
+ const agent = normalizeAgentToken(values['--agent']!);
138
+ if (!agent) { usageFailure(`invalid --agent '${values['--agent']}': ${AGENT_USAGE_HINT}`); return; }
139
+ result = completeCommitIntent(taskRef!, { token: values['--token']!, agent });
140
+ } else if (intent === 'commit-recover') {
141
+ const missing = requireValues(['--agent']);
142
+ if (missing) { usageFailure(`intent 'commit-recover' requires '${missing}'`); return; }
143
+ const agent = normalizeAgentToken(values['--agent']!);
144
+ if (!agent) { usageFailure(`invalid --agent '${values['--agent']}': ${AGENT_USAGE_HINT}`); return; }
145
+ result = recoverCommitIntent(taskRef!, { agent });
146
+ } else if (intent === 'commit-abort') {
147
+ const missing = requireValues(['--token', '--expected-head']);
148
+ if (missing) { usageFailure(`intent 'commit-abort' requires '${missing}'`); return; }
149
+ result = abortCommitIntent(taskRef!, { token: values['--token']!, expectedHead: values['--expected-head']! });
150
+ } else if (intent === 'commit-status') {
151
+ result = statusCommitIntent(taskRef!);
152
+ } else if (intent === 'begin-or-resume') {
153
+ const missing = requireValues(['--client']);
154
+ if (missing) { usageFailure(`intent 'begin-or-resume' requires '${missing}'`); return; }
68
155
  const maxSteps = values['--max-steps'] === undefined ? undefined : Number(values['--max-steps']);
69
156
  if (maxSteps !== undefined && (!Number.isInteger(maxSteps) || maxSteps < 1)) {
70
157
  usageFailure('--max-steps must be a positive integer'); return;
71
158
  }
72
- result = beginOrResumeOrchestration(taskRef!, { maxSteps });
159
+ const policyFlags = [
160
+ '--executor-model', '--executor-reasoning-effort',
161
+ '--reviewer-model', '--reviewer-reasoning-effort'
162
+ ];
163
+ const hasAnyPolicy = policyFlags.some((flag) => values[flag] !== undefined);
164
+ if (hasAnyPolicy && policyFlags.some((flag) => values[flag] === undefined)) {
165
+ usageFailure('explicit model policy requires executor/reviewer model and reasoning effort');
166
+ return;
167
+ }
168
+ result = beginOrResumeOrchestration(taskRef!, {
169
+ maxSteps,
170
+ client: values['--client'] as AgentClientId,
171
+ modelPolicy: hasAnyPolicy ? {
172
+ executor: {
173
+ model: values['--executor-model']!,
174
+ reasoningEffort: values['--executor-reasoning-effort']!
175
+ },
176
+ reviewer: {
177
+ model: values['--reviewer-model']!,
178
+ reasoningEffort: values['--reviewer-reasoning-effort']!
179
+ }
180
+ } : undefined
181
+ });
73
182
  } else if (intent === 'route') {
74
183
  result = routeOrchestration(taskRef!);
75
184
  } else if (intent === 'status') {
@@ -79,7 +188,8 @@ function taskOrchestration(args: string[] = []): void {
79
188
  if (missing) { usageFailure(`intent 'prepare' requires '${missing}'`); return; }
80
189
  result = prepareOrchestrationDelegation(taskRef!, {
81
190
  client: values['--client'] as AgentClientId,
82
- requestedModel: values['--requested-model']
191
+ requestedModel: values['--requested-model'],
192
+ requestedReasoningEffort: values['--requested-reasoning-effort']
83
193
  });
84
194
  } else if (intent === 'hook-start') {
85
195
  const missing = requireValues([
@@ -90,7 +200,10 @@ function taskOrchestration(args: string[] = []): void {
90
200
  const event = {
91
201
  nativeAgent: values['--native-agent']!, childId: values['--child-id']!,
92
202
  parentId: values['--parent-id']!, spawnMode: values['--spawn-mode']!,
93
- actualModel: values['--actual-model'], modelFallbackReason: values['--fallback-reason']
203
+ actualModel: values['--actual-model'],
204
+ actualReasoningEffort: values['--actual-reasoning-effort'],
205
+ modelFallbackReason: values['--model-fallback-reason'],
206
+ reasoningEffortFallbackReason: values['--reasoning-effort-fallback-reason']
94
207
  };
95
208
  result = taskRef === 'auto'
96
209
  ? activateMatchingOrchestrationDelegation(values['--client'] as AgentClientId, event)
@@ -113,10 +226,6 @@ function taskOrchestration(args: string[] = []): void {
113
226
  changedPaths: values['--changed-paths'] ? values['--changed-paths']!.split(',').filter(Boolean) : []
114
227
  });
115
228
  }
116
- } else if (intent === 'stage-completed') {
117
- const missing = requireValues(['--agent']);
118
- if (missing) { usageFailure(`intent 'stage-completed' requires '${missing}'`); return; }
119
- result = completeCommitOrchestrationStage(taskRef!, values['--agent']!);
120
229
  } else if (intent === 'advance') {
121
230
  result = advanceOrchestration(taskRef!);
122
231
  } else {
@@ -1,6 +1,6 @@
1
1
  import { finalizeReviewSummary } from '../task/review-finalization.ts';
2
2
 
3
- const USAGE = 'Usage: agent-infra-internal task-review <task-ref> finalize-summary --stage <analysis|plan|code> --artifact <review-*.md> [--dry-run]\n';
3
+ const USAGE = 'Usage: agent-infra-internal task-review <task-ref> finalize-summary --stage <analysis|plan|code> --artifact <review-*.md> [--orchestrated] [--dry-run]\n';
4
4
 
5
5
  function failUsage(message: string): void {
6
6
  process.stdout.write(`${JSON.stringify({
@@ -29,10 +29,11 @@ function taskReview(args: string[] = []): void {
29
29
  let stage = '';
30
30
  let artifact = '';
31
31
  let dryRun = false;
32
+ let orchestrated = false;
32
33
  const seen = new Set<string>();
33
34
  for (let index = 2; index < args.length; index += 1) {
34
35
  const flag = args[index]!;
35
- if (!['--stage', '--artifact', '--dry-run'].includes(flag)) {
36
+ if (!['--stage', '--artifact', '--orchestrated', '--dry-run'].includes(flag)) {
36
37
  failUsage(`unknown option '${flag}'`);
37
38
  return;
38
39
  }
@@ -45,6 +46,10 @@ function taskReview(args: string[] = []): void {
45
46
  dryRun = true;
46
47
  continue;
47
48
  }
49
+ if (flag === '--orchestrated') {
50
+ orchestrated = true;
51
+ continue;
52
+ }
48
53
  const value = args[++index];
49
54
  if (!value || value.startsWith('--')) {
50
55
  failUsage(`option '${flag}' requires a value`);
@@ -57,7 +62,7 @@ function taskReview(args: string[] = []): void {
57
62
  failUsage("options '--stage' and '--artifact' are required");
58
63
  return;
59
64
  }
60
- const result = finalizeReviewSummary({ taskRef: args[0]!, stage, artifact, dryRun });
65
+ const result = finalizeReviewSummary({ taskRef: args[0]!, stage, artifact, orchestrated, dryRun });
61
66
  process.stdout.write(`${JSON.stringify(result)}\n`);
62
67
  if (result.status === 'failed') process.exitCode = 1;
63
68
  }
@@ -6,6 +6,11 @@ type PlatformAdapterContext = {
6
6
  client?: unknown;
7
7
  };
8
8
 
9
+ type PlatformMergeability = {
10
+ state: 'mergeable' | 'conflicting' | 'unknown';
11
+ detail: string | null;
12
+ };
13
+
9
14
  type PlatformChangeRequestSnapshot = {
10
15
  repository: string;
11
16
  number: number;
@@ -22,6 +27,7 @@ type PlatformChangeRequestSnapshot = {
22
27
  labels: string[];
23
28
  assignees: string[];
24
29
  milestone: string | null;
30
+ mergeability?: PlatformMergeability;
25
31
  };
26
32
 
27
33
  type PlatformCheckSnapshot = {
@@ -45,6 +51,11 @@ type ChangeRequestInspectionContext = PlatformAdapterContext & {
45
51
  number: number;
46
52
  };
47
53
 
54
+ type IssueClosingChangeRequestsContext = PlatformAdapterContext & {
55
+ repository: string;
56
+ issueNumber: number;
57
+ };
58
+
48
59
  type RequiredChecksInspectionContext = ChangeRequestInspectionContext & {
49
60
  headSha: string;
50
61
  };
@@ -65,6 +76,9 @@ type PlatformAdapter = {
65
76
  inspectChangeRequest?(
66
77
  context: ChangeRequestInspectionContext
67
78
  ): PlatformInspectionResult<PlatformChangeRequestSnapshot>;
79
+ inspectIssueClosingChangeRequests?(
80
+ context: IssueClosingChangeRequestsContext
81
+ ): PlatformInspectionResult<PlatformChangeRequestSnapshot[]>;
68
82
  inspectRequiredChecks?(
69
83
  context: RequiredChecksInspectionContext
70
84
  ): PlatformInspectionResult<PlatformCheckSnapshot[]>;
@@ -88,7 +102,7 @@ function registerPlatformCapabilities(
88
102
  type: string,
89
103
  capabilities: Pick<
90
104
  PlatformAdapter,
91
- 'inspectChangeRequest' | 'inspectRequiredChecks' | 'resolveChangeRequestGitEvidence'
105
+ 'inspectChangeRequest' | 'inspectIssueClosingChangeRequests' | 'inspectRequiredChecks' | 'resolveChangeRequestGitEvidence'
92
106
  >
93
107
  ): void {
94
108
  const adapter = adapters.get(type);
@@ -98,14 +112,24 @@ function registerPlatformCapabilities(
98
112
 
99
113
  function hasPlatformCapability(
100
114
  type: string | null,
101
- capability: 'change-request' | 'required-checks' | 'change-request-git-evidence'
115
+ capability: 'change-request' | 'issue-closing-change-requests' | 'required-checks' | 'change-request-git-evidence'
102
116
  ): boolean {
103
117
  const adapter = getPlatformAdapter(type);
104
118
  if (capability === 'change-request') return typeof adapter?.inspectChangeRequest === 'function';
119
+ if (capability === 'issue-closing-change-requests') return typeof adapter?.inspectIssueClosingChangeRequests === 'function';
105
120
  if (capability === 'required-checks') return typeof adapter?.inspectRequiredChecks === 'function';
106
121
  return typeof adapter?.resolveChangeRequestGitEvidence === 'function';
107
122
  }
108
123
 
124
+ function inspectPlatformIssueClosingChangeRequests(
125
+ type: string | null,
126
+ context: IssueClosingChangeRequestsContext
127
+ ): PlatformInspectionResult<PlatformChangeRequestSnapshot[]> {
128
+ const adapter = getPlatformAdapter(type);
129
+ return adapter?.inspectIssueClosingChangeRequests?.(context) ??
130
+ unsupported(type, 'issue closing change-request inspection');
131
+ }
132
+
109
133
  function unsupported<T>(type: string | null, capability: string): PlatformInspectionResult<T> {
110
134
  return {
111
135
  ok: false,
@@ -150,6 +174,7 @@ export {
150
174
  getPlatformAdapter,
151
175
  hasPlatformCapability,
152
176
  inspectPlatformChangeRequest,
177
+ inspectPlatformIssueClosingChangeRequests,
153
178
  inspectPlatformRequiredChecks,
154
179
  listPlatformAdapters,
155
180
  registerPlatformAdapter,
@@ -159,11 +184,13 @@ export {
159
184
  export type {
160
185
  ChangeRequestGitEvidenceContext,
161
186
  ChangeRequestInspectionContext,
187
+ IssueClosingChangeRequestsContext,
162
188
  PlatformAdapter,
163
189
  PlatformAdapterContext,
164
190
  PlatformChangeRequestGitEvidenceSpec,
165
191
  PlatformChangeRequestSnapshot,
166
192
  PlatformCheckSnapshot,
167
193
  PlatformInspectionResult,
194
+ PlatformMergeability,
168
195
  RequiredChecksInspectionContext
169
196
  };
@@ -0,0 +1,134 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ import { COMPLETION_BACKFILL_FAMILIES, inspectCompletionArtifacts } from '../task/finalization-artifacts.ts';
5
+ import { parseArtifactName } from '../task/artifact-lifecycle.ts';
6
+ import { parseTaskFrontmatter } from '../task/frontmatter.ts';
7
+ import { resolveTaskRef } from '../task/resolve-ref.ts';
8
+ import { getOpenWorkflowWarnings } from '../task/workflow-warnings.ts';
9
+ import { applyWorkflowWarningIntent } from '../task/workflow-warning-intents.ts';
10
+ import { captureTaskWriteMetadata } from '../task/write.ts';
11
+ import { syncPlatformComment } from './issue-comments.ts';
12
+ import type { GitHubClient } from './github-client.ts';
13
+ import { platformResult } from './types.ts';
14
+ import type { PlatformOperation, PlatformResult } from './types.ts';
15
+
16
+ type CompletionBackfillOptions = { agent: string; cwd?: string; client?: GitHubClient };
17
+ type CompletionBackfillResult = PlatformResult & {
18
+ artifacts: Array<{ artifact: string; status: PlatformResult['status'] }>;
19
+ warnings: Array<{ id: string; status: string }>;
20
+ };
21
+
22
+ function result(
23
+ base: PlatformResult,
24
+ artifacts: CompletionBackfillResult['artifacts'],
25
+ warnings: CompletionBackfillResult['warnings']
26
+ ): CompletionBackfillResult {
27
+ return { ...base, artifacts, warnings };
28
+ }
29
+
30
+ function excludedPrReview(taskDir: string, message: string): string | null {
31
+ const names = [...message.matchAll(/(?:^|[^A-Za-z0-9_-])(pr-review(?:-r[1-9]\d*)?\.md)(?=$|[^A-Za-z0-9_.-])/g)]
32
+ .map((match) => match[1]!);
33
+ if (names.length !== 1) return null;
34
+ const parsed = parseArtifactName(names[0]!);
35
+ if (!parsed || parsed.family !== 'pr-review') return null;
36
+ const artifactPath = path.join(taskDir, parsed.name);
37
+ try {
38
+ const stat = fs.lstatSync(artifactPath);
39
+ return stat.isFile() && !stat.isSymbolicLink() ? parsed.name : null;
40
+ } catch {
41
+ return null;
42
+ }
43
+ }
44
+
45
+ function backfillCompletionComments(
46
+ taskRef: string,
47
+ options: CompletionBackfillOptions
48
+ ): CompletionBackfillResult {
49
+ const resolved = resolveTaskRef(taskRef, options.cwd ? { repoRoot: options.cwd } : {});
50
+ if (!resolved.ok) return result(platformResult('failed', {
51
+ error: { code: resolved.code, message: resolved.message, retryable: false }
52
+ }), [], []);
53
+ const inventory = inspectCompletionArtifacts(resolved.taskId, { repoRoot: resolved.repoRoot });
54
+ if (inventory.status === 'failed') return result(platformResult('failed', {
55
+ error: {
56
+ code: inventory.error?.code || 'ARTIFACT_TOPOLOGY_CONFLICT',
57
+ message: inventory.error?.message || 'Completion artifact inventory failed',
58
+ retryable: false
59
+ }
60
+ }), [], []);
61
+ const initialContent = fs.readFileSync(resolved.taskMdPath, 'utf8');
62
+ const issueNumber = Number(parseTaskFrontmatter(initialContent).issue_number);
63
+ if (!Number.isInteger(issueNumber) || issueNumber <= 0) return result(platformResult('no-op', {
64
+ error: { code: 'ISSUE_NOT_LINKED', message: 'Task has no valid issue_number', retryable: false }
65
+ }), [], []);
66
+
67
+ const artifacts: CompletionBackfillResult['artifacts'] = [];
68
+ const operations: PlatformOperation[] = [];
69
+ let latest = platformResult('no-op', { error: null });
70
+ for (const artifact of inventory.artifacts) {
71
+ latest = syncPlatformComment(resolved.taskId, {
72
+ kind: 'artifact',
73
+ artifact: artifact.name,
74
+ agent: options.agent,
75
+ backfill: true,
76
+ cwd: resolved.repoRoot,
77
+ client: options.client
78
+ });
79
+ operations.push(...latest.operations.map((operation) => ({
80
+ ...operation,
81
+ name: `${artifact.name}:${operation.name}`
82
+ })));
83
+ artifacts.push({ artifact: artifact.name, status: latest.status });
84
+ if (latest.status === 'failed' || latest.status === 'blocked') return result({ ...latest, operations }, artifacts, []);
85
+ if (latest.error) return result(platformResult(latest.error.retryable ? 'blocked' : 'failed', {
86
+ platform: latest.platform,
87
+ resource: latest.resource,
88
+ capabilities: latest.capabilities,
89
+ operations,
90
+ error: latest.error
91
+ }), artifacts, []);
92
+ }
93
+
94
+ const matching = getOpenWorkflowWarnings(initialContent).flatMap((warning) => {
95
+ if (warning.step !== 'complete-task' || warning.code !== 'COMMENT_SYNC_FAILED' || warning.target !== 'artifact') return [];
96
+ const excluded = excludedPrReview(resolved.taskDir, warning.message);
97
+ return excluded ? [{ warning, excluded }] : [];
98
+ });
99
+ const warnings: CompletionBackfillResult['warnings'] = [];
100
+ let metadata: ReturnType<typeof captureTaskWriteMetadata> | null = null;
101
+ for (const { warning, excluded } of matching) {
102
+ metadata ??= captureTaskWriteMetadata();
103
+ const resolution = [
104
+ `excluded=${excluded}`,
105
+ `completionFamilies=${COMPLETION_BACKFILL_FAMILIES.join(',')}`,
106
+ `synchronized=${inventory.artifacts.map((artifact) => artifact.name).join(',') || 'none'}`,
107
+ `completedAt=${metadata.timestamp}`
108
+ ].join('; ');
109
+ const updated = applyWorkflowWarningIntent({
110
+ kind: 'set-status', taskRef: resolved.taskId, id: warning.id, status: 'resolved', resolution
111
+ }, { repoRoot: resolved.repoRoot, metadataProvider: () => metadata! });
112
+ if (updated.status === 'failed') return result(platformResult('failed', {
113
+ platform: latest.platform,
114
+ resource: latest.resource,
115
+ capabilities: latest.capabilities,
116
+ operations,
117
+ changed: artifacts.some((item) => item.status === 'applied'),
118
+ error: { code: updated.error?.code || 'WARNING_UPDATE_FAILED', message: updated.error?.message || 'Unable to resolve workflow warning', retryable: false }
119
+ }), artifacts, warnings);
120
+ warnings.push({ id: warning.id, status: updated.status });
121
+ }
122
+ const changed = artifacts.some((item) => item.status === 'applied') || warnings.some((item) => item.status === 'applied');
123
+ return result(platformResult(changed ? 'applied' : 'no-op', {
124
+ platform: latest.platform,
125
+ resource: latest.resource,
126
+ capabilities: latest.capabilities,
127
+ changed,
128
+ operations,
129
+ error: null
130
+ }), artifacts, warnings);
131
+ }
132
+
133
+ export { backfillCompletionComments };
134
+ export type { CompletionBackfillOptions, CompletionBackfillResult };
@@ -24,6 +24,15 @@ type ClientOptions = {
24
24
  };
25
25
 
26
26
  const MINIMUM_GITHUB_CLI_VERSION = '2.16.0';
27
+ const GITHUB_CLI_MAX_BUFFER = 64 * 1024 * 1024;
28
+ const ERROR_DETAIL_LIMIT = 4096;
29
+
30
+ function boundedFailureDetail(result: RunResult): string {
31
+ const diagnostic = `${result.stderr}\n${result.error?.message || ''}`.trim() || result.stdout.trim();
32
+ return diagnostic.length <= ERROR_DETAIL_LIMIT
33
+ ? diagnostic
34
+ : `${diagnostic.slice(0, ERROR_DETAIL_LIMIT)}… [truncated]`;
35
+ }
27
36
 
28
37
  function defaultRunner(args: string[], options: RunOptions): RunResult {
29
38
  const command = process.env.AGENT_INFRA_GH_BIN || 'gh';
@@ -38,6 +47,7 @@ function defaultRunner(args: string[], options: RunOptions): RunResult {
38
47
  encoding: 'utf8',
39
48
  env: process.env,
40
49
  input: options.input,
50
+ maxBuffer: GITHUB_CLI_MAX_BUFFER,
41
51
  shell: false
42
52
  });
43
53
  return {
@@ -60,7 +70,15 @@ function defaultSleep(delayMs: number): void {
60
70
  }
61
71
 
62
72
  function classifyGitHubFailure(result: RunResult): PlatformError {
63
- const detail = `${result.stderr}\n${result.stdout}\n${result.error?.message || ''}`.trim();
73
+ const errorCode = result.error && 'code' in result.error ? (result.error as NodeJS.ErrnoException).code : undefined;
74
+ if (errorCode === 'ENOBUFS') {
75
+ return {
76
+ code: 'PLATFORM_OUTPUT_TOO_LARGE',
77
+ message: 'GitHub CLI output exceeded the configured limit',
78
+ retryable: false
79
+ };
80
+ }
81
+ const detail = boundedFailureDetail(result);
64
82
  const lower = detail.toLowerCase();
65
83
  if (/\b401\b|bad credentials|authentication required|not logged into/.test(lower)) {
66
84
  return { code: 'AUTH_REQUIRED', message: detail || 'GitHub authentication is required', retryable: false };
@@ -77,7 +95,7 @@ function classifyGitHubFailure(result: RunResult): PlatformError {
77
95
  if (/\b422\b|validation failed/.test(lower)) {
78
96
  return { code: 'PLATFORM_REQUEST_INVALID', message: detail || 'GitHub rejected the request', retryable: false };
79
97
  }
80
- if (result.error && 'code' in result.error && (result.error as NodeJS.ErrnoException).code === 'ENOENT') {
98
+ if (errorCode === 'ENOENT') {
81
99
  return { code: 'PLATFORM_DEPENDENCY_MISSING', message: detail || 'GitHub CLI is unavailable', retryable: false };
82
100
  }
83
101
  return { code: 'PLATFORM_REQUEST_FAILED', message: detail || 'GitHub request failed', retryable: false };
@@ -38,7 +38,8 @@ const ARTIFACT_TITLES: Record<string, string> = {
38
38
  'review-plan': '技术方案审查',
39
39
  code: '实现报告',
40
40
  'review-code': '代码审查',
41
- 'manual-validation': '人工验证报告'
41
+ 'manual-validation': '人工验证报告',
42
+ 'pr-review': 'PR 审查报告'
42
43
  };
43
44
 
44
45
  function normalizeCommentContent(content: string): string {
@@ -74,7 +75,7 @@ function renderTaskComment(content: string, taskId: string, agent: string): stri
74
75
 
75
76
  function artifactIdentity(artifact: string): { stem: string; title: string } {
76
77
  const stem = path.basename(artifact, '.md');
77
- const match = stem.match(/^(analysis|review-analysis|plan|review-plan|code|review-code|manual-validation)(?:-r(\d+))?$/);
78
+ const match = stem.match(/^(analysis|review-analysis|plan|review-plan|code|review-code|manual-validation|pr-review)(?:-r(\d+))?$/);
78
79
  if (!match) throw new Error(`unsupported artifact '${artifact}'`);
79
80
  const base = ARTIFACT_TITLES[match[1]!]!;
80
81
  const round = match[2] ? Number(match[2]) : 1;