@fitlab-ai/agent-infra 0.9.2 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (318) hide show
  1. package/README.md +10 -9
  2. package/README.zh-CN.md +10 -9
  3. package/dist/bin/internal-cli.js +15 -0
  4. package/dist/lib/agent-clients/adapter.js +45 -2
  5. package/dist/lib/agent-clients/adapters/antigravity-cli.js +64 -0
  6. package/dist/lib/agent-clients/adapters/claude-code.js +10 -1
  7. package/dist/lib/agent-clients/adapters/codex.js +9 -0
  8. package/dist/lib/agent-clients/adapters/index.js +2 -2
  9. package/dist/lib/agent-clients/adapters/opencode.js +9 -0
  10. package/dist/lib/agent-clients/config.js +42 -4
  11. package/dist/lib/agent-clients/next-steps.js +11 -2
  12. package/dist/lib/agent-clients/reconcile.js +2 -1
  13. package/dist/lib/agent-clients/registry.js +7 -1
  14. package/dist/lib/agent-clients/schema.js +18 -0
  15. package/dist/lib/agent-clients/tokens.js +49 -0
  16. package/dist/lib/agent-clients/types.js +1 -1
  17. package/dist/lib/defaults.json +1 -1
  18. package/dist/lib/git/workflow.js +54 -1
  19. package/dist/lib/internal/agent-client.js +61 -4
  20. package/dist/lib/internal/git-workflow.js +6 -1
  21. package/dist/lib/internal/platform-checks.js +3 -3
  22. package/dist/lib/internal/platform-comment.js +29 -2
  23. package/dist/lib/internal/platform-issue.js +7 -0
  24. package/dist/lib/internal/platform-pr-review.js +132 -0
  25. package/dist/lib/internal/platform-pr.js +20 -2
  26. package/dist/lib/internal/platform-release-notes.js +52 -16
  27. package/dist/lib/internal/pr-review-grade.js +140 -0
  28. package/dist/lib/internal/release-workflow.js +13 -6
  29. package/dist/lib/internal/task-activity.js +73 -0
  30. package/dist/lib/internal/task-event.js +17 -1
  31. package/dist/lib/internal/task-lifecycle.js +7 -0
  32. package/dist/lib/internal/task-orchestration.js +51 -6
  33. package/dist/lib/internal/task-review.js +8 -3
  34. package/dist/lib/platform/adapters.js +8 -1
  35. package/dist/lib/platform/completion-backfill.js +122 -0
  36. package/dist/lib/platform/issue-comments.js +3 -2
  37. package/dist/lib/platform/merged-pr-equivalence.js +115 -5
  38. package/dist/lib/platform/pr-checks.js +64 -41
  39. package/dist/lib/platform/pr-review.js +166 -0
  40. package/dist/lib/platform/pull-requests.js +324 -3
  41. package/dist/lib/platform/release-notes.js +85 -3
  42. package/dist/lib/pr-review/evidence-grading.js +229 -0
  43. package/dist/lib/run/tui.js +3 -5
  44. package/dist/lib/sandbox/commands/create.js +0 -20
  45. package/dist/lib/sandbox/commands/show.js +1 -1
  46. package/dist/lib/task/activity-intent.js +101 -0
  47. package/dist/lib/task/artifact-lifecycle.js +2 -1
  48. package/dist/lib/task/commands/log.js +15 -14
  49. package/dist/lib/task/delegation-receipts.js +23 -2
  50. package/dist/lib/task/events.js +67 -28
  51. package/dist/lib/task/finalization-artifacts.js +35 -0
  52. package/dist/lib/task/lifecycle-execution.js +46 -0
  53. package/dist/lib/task/orchestration.js +408 -44
  54. package/dist/lib/task/review-finalization.js +29 -9
  55. package/dist/lib/task/task-execution-lock.js +231 -0
  56. package/dist/lib/task/verification-checks.js +1 -1
  57. package/dist/lib/task/verification-engine.js +218 -2
  58. package/dist/lib/task/verification.js +4 -3
  59. package/dist/lib/task/workspace-snapshot.js +17 -5
  60. package/lib/agent-clients/adapter.ts +75 -2
  61. package/lib/agent-clients/adapters/antigravity-cli.ts +65 -0
  62. package/lib/agent-clients/adapters/claude-code.ts +10 -1
  63. package/lib/agent-clients/adapters/codex.ts +9 -0
  64. package/lib/agent-clients/adapters/index.ts +2 -2
  65. package/lib/agent-clients/adapters/opencode.ts +9 -0
  66. package/lib/agent-clients/config.ts +49 -4
  67. package/lib/agent-clients/next-steps.ts +15 -2
  68. package/lib/agent-clients/reconcile.ts +2 -1
  69. package/lib/agent-clients/registry.ts +10 -0
  70. package/lib/agent-clients/schema.ts +18 -0
  71. package/lib/agent-clients/tokens.ts +53 -0
  72. package/lib/agent-clients/types.ts +15 -1
  73. package/lib/defaults.json +1 -1
  74. package/lib/git/workflow.ts +66 -2
  75. package/lib/internal/agent-client.ts +59 -4
  76. package/lib/internal/git-workflow.ts +5 -1
  77. package/lib/internal/platform-checks.ts +4 -4
  78. package/lib/internal/platform-comment.ts +17 -2
  79. package/lib/internal/platform-issue.ts +4 -0
  80. package/lib/internal/platform-pr-review.ts +104 -0
  81. package/lib/internal/platform-pr.ts +14 -1
  82. package/lib/internal/platform-release-notes.ts +59 -16
  83. package/lib/internal/pr-review-grade.ts +130 -0
  84. package/lib/internal/release-workflow.ts +13 -6
  85. package/lib/internal/task-activity.ts +55 -0
  86. package/lib/internal/task-event.ts +9 -1
  87. package/lib/internal/task-lifecycle.ts +4 -0
  88. package/lib/internal/task-orchestration.ts +45 -6
  89. package/lib/internal/task-review.ts +8 -3
  90. package/lib/platform/adapters.ts +29 -2
  91. package/lib/platform/completion-backfill.ts +134 -0
  92. package/lib/platform/issue-comments.ts +3 -2
  93. package/lib/platform/merged-pr-equivalence.ts +127 -5
  94. package/lib/platform/pr-checks.ts +72 -45
  95. package/lib/platform/pr-review.ts +201 -0
  96. package/lib/platform/pull-requests.ts +395 -2
  97. package/lib/platform/release-notes.ts +100 -4
  98. package/lib/pr-review/evidence-grading.ts +318 -0
  99. package/lib/run/tui.ts +3 -4
  100. package/lib/sandbox/commands/create.ts +0 -20
  101. package/lib/sandbox/commands/show.ts +1 -1
  102. package/lib/server/server.schema.json +2 -2
  103. package/lib/task/activity-intent.ts +128 -0
  104. package/lib/task/artifact-lifecycle.ts +2 -1
  105. package/lib/task/commands/log.ts +15 -14
  106. package/lib/task/delegation-receipts.ts +32 -3
  107. package/lib/task/events.ts +75 -30
  108. package/lib/task/finalization-artifacts.ts +58 -0
  109. package/lib/task/lifecycle-execution.ts +106 -0
  110. package/lib/task/orchestration.ts +543 -64
  111. package/lib/task/review-finalization.ts +40 -9
  112. package/lib/task/task-execution-lock.ts +296 -0
  113. package/lib/task/verification-checks.ts +1 -1
  114. package/lib/task/verification-engine.ts +249 -2
  115. package/lib/task/verification.ts +5 -3
  116. package/lib/task/workspace-snapshot.ts +26 -5
  117. package/package.json +3 -3
  118. package/templates/.agents/QUICKSTART.en.md +25 -8
  119. package/templates/.agents/QUICKSTART.zh-CN.md +25 -8
  120. package/templates/.agents/README.en.md +10 -7
  121. package/templates/.agents/README.zh-CN.md +10 -7
  122. package/templates/.agents/hooks/lifecycle-delegation.js +15 -4
  123. package/templates/.agents/rules/create-issue.github.en.md +4 -2
  124. package/templates/.agents/rules/create-issue.github.zh-CN.md +4 -2
  125. package/templates/.agents/rules/issue-fields.github.en.md +3 -1
  126. package/templates/.agents/rules/issue-fields.github.zh-CN.md +3 -1
  127. package/templates/.agents/rules/issue-pr-commands.en.md +5 -3
  128. package/templates/.agents/rules/issue-pr-commands.github.en.md +5 -3
  129. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +5 -3
  130. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +5 -3
  131. package/templates/.agents/rules/issue-sync.github.en.md +7 -3
  132. package/templates/.agents/rules/issue-sync.github.zh-CN.md +8 -4
  133. package/templates/.agents/rules/lifecycle-orchestration.en.md +5 -2
  134. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +5 -2
  135. package/templates/.agents/rules/milestone-inference.github.en.md +4 -2
  136. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +4 -2
  137. package/templates/.agents/rules/next-step-output.en.md +3 -1
  138. package/templates/.agents/rules/next-step-output.zh-CN.md +3 -1
  139. package/templates/.agents/rules/no-mid-flow-questions.en.md +17 -0
  140. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +17 -0
  141. package/templates/.agents/rules/pr-checks-commands.en.md +3 -3
  142. package/templates/.agents/rules/pr-checks-commands.github.en.md +2 -2
  143. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +2 -2
  144. package/templates/.agents/rules/pr-checks-commands.zh-CN.md +3 -3
  145. package/templates/.agents/rules/pr-sync.en.md +3 -1
  146. package/templates/.agents/rules/pr-sync.github.en.md +11 -1
  147. package/templates/.agents/rules/pr-sync.github.zh-CN.md +11 -1
  148. package/templates/.agents/rules/pr-sync.zh-CN.md +3 -1
  149. package/templates/.agents/rules/release-commands.en.md +1 -1
  150. package/templates/.agents/rules/release-commands.github.en.md +12 -2
  151. package/templates/.agents/rules/release-commands.github.zh-CN.md +12 -2
  152. package/templates/.agents/rules/release-commands.zh-CN.md +1 -1
  153. package/templates/.agents/rules/task-management.en.md +11 -0
  154. package/templates/.agents/rules/task-management.zh-CN.md +11 -0
  155. package/templates/.agents/skills/analyze-task/SKILL.en.md +10 -7
  156. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +10 -7
  157. package/templates/.agents/skills/block-task/SKILL.en.md +7 -5
  158. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +7 -5
  159. package/templates/.agents/skills/cancel-task/SKILL.en.md +6 -4
  160. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +6 -4
  161. package/templates/.agents/skills/close-codescan/SKILL.en.md +3 -1
  162. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +3 -1
  163. package/templates/.agents/skills/close-dependabot/SKILL.en.md +3 -1
  164. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +3 -1
  165. package/templates/.agents/skills/code-task/SKILL.en.md +9 -6
  166. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +11 -8
  167. package/templates/.agents/skills/commit/SKILL.en.md +3 -1
  168. package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -1
  169. package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -1
  170. package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -1
  171. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
  172. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
  173. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  174. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  175. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +6 -4
  176. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +6 -4
  177. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +1 -1
  178. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
  179. package/templates/.agents/skills/complete-task/SKILL.en.md +21 -6
  180. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +21 -6
  181. package/templates/.agents/skills/complete-task/config/verify.en.json +1 -0
  182. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +1 -0
  183. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +17 -0
  184. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +17 -0
  185. package/templates/.agents/skills/create-pr/SKILL.en.md +3 -1
  186. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +3 -1
  187. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +1 -1
  188. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +1 -1
  189. package/templates/.agents/skills/create-release-note/SKILL.en.md +17 -16
  190. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +17 -16
  191. package/templates/.agents/skills/create-task/SKILL.en.md +5 -3
  192. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +5 -3
  193. package/templates/.agents/skills/import-issue/SKILL.en.md +5 -3
  194. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +5 -3
  195. package/templates/.agents/skills/plan-task/SKILL.en.md +8 -5
  196. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +8 -5
  197. package/templates/.agents/skills/post-release/SKILL.en.md +2 -0
  198. package/templates/.agents/skills/post-release/SKILL.zh-CN.md +2 -0
  199. package/templates/.agents/skills/release/SKILL.en.md +16 -10
  200. package/templates/.agents/skills/release/SKILL.zh-CN.md +16 -10
  201. package/templates/.agents/skills/restore-task/SKILL.en.md +4 -1
  202. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +4 -1
  203. package/templates/.agents/skills/review-analysis/SKILL.en.md +7 -4
  204. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +7 -4
  205. package/templates/.agents/skills/review-code/SKILL.en.md +9 -6
  206. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +9 -6
  207. package/templates/.agents/skills/review-plan/SKILL.en.md +7 -4
  208. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +7 -4
  209. package/templates/.agents/skills/review-pr/SKILL.en.md +158 -0
  210. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +158 -0
  211. package/templates/.agents/skills/review-pr/config/verify.en.json +37 -0
  212. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +37 -0
  213. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +65 -0
  214. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +65 -0
  215. package/templates/.agents/skills/review-pr/reference/output-guidance.en.md +18 -0
  216. package/templates/.agents/skills/review-pr/reference/output-guidance.zh-CN.md +18 -0
  217. package/templates/.agents/skills/review-pr/reference/report-template.en.md +85 -0
  218. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +85 -0
  219. package/templates/.agents/skills/run-task/SKILL.en.md +8 -8
  220. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +8 -8
  221. package/templates/.agents/skills/run-task/config/verify.en.json +2 -1
  222. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +2 -1
  223. package/templates/.agents/skills/run-task/reference/host-validation.en.md +20 -0
  224. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +20 -0
  225. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +35 -61
  226. package/templates/.agents/skills/watch-pr/SKILL.en.md +13 -13
  227. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +13 -13
  228. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +27 -6
  229. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +26 -5
  230. package/templates/.agents/templates/task.en.md +1 -1
  231. package/templates/.agents/templates/task.zh-CN.md +1 -1
  232. package/templates/.agents/workflows/bug-fix.en.yaml +3 -3
  233. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +3 -3
  234. package/templates/.agents/workflows/code-review.en.yaml +1 -1
  235. package/templates/.agents/workflows/code-review.zh-CN.yaml +1 -1
  236. package/templates/.agents/workflows/feature-development.en.yaml +4 -4
  237. package/templates/.agents/workflows/feature-development.zh-CN.yaml +4 -4
  238. package/templates/.agents/workflows/refactoring.en.yaml +3 -3
  239. package/templates/.agents/workflows/refactoring.zh-CN.yaml +3 -3
  240. package/templates/.claude/commands/post-release.en.md +1 -0
  241. package/templates/.claude/commands/post-release.zh-CN.md +1 -0
  242. package/templates/.claude/commands/review-pr.en.md +8 -0
  243. package/templates/.claude/commands/review-pr.zh-CN.md +8 -0
  244. package/templates/.gemini/commands/_project_/review-pr.en.toml +10 -0
  245. package/templates/.gemini/commands/_project_/review-pr.zh-CN.toml +10 -0
  246. package/templates/.opencode/commands/post-release.en.md +2 -0
  247. package/templates/.opencode/commands/post-release.zh-CN.md +2 -0
  248. package/templates/.opencode/commands/review-pr.en.md +11 -0
  249. package/templates/.opencode/commands/review-pr.zh-CN.md +11 -0
  250. package/dist/lib/agent-clients/adapters/gemini-cli.js +0 -64
  251. package/lib/agent-clients/adapters/gemini-cli.ts +0 -65
  252. package/templates/.gemini/commands/_project_/analyze-task.en.toml +0 -10
  253. package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +0 -10
  254. package/templates/.gemini/commands/_project_/archive-tasks.en.toml +0 -10
  255. package/templates/.gemini/commands/_project_/archive-tasks.zh-CN.toml +0 -10
  256. package/templates/.gemini/commands/_project_/block-task.en.toml +0 -10
  257. package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +0 -10
  258. package/templates/.gemini/commands/_project_/cancel-task.en.toml +0 -10
  259. package/templates/.gemini/commands/_project_/cancel-task.zh-CN.toml +0 -10
  260. package/templates/.gemini/commands/_project_/check-task.en.toml +0 -10
  261. package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +0 -10
  262. package/templates/.gemini/commands/_project_/close-codescan.en.toml +0 -8
  263. package/templates/.gemini/commands/_project_/close-codescan.zh-CN.toml +0 -8
  264. package/templates/.gemini/commands/_project_/close-dependabot.en.toml +0 -8
  265. package/templates/.gemini/commands/_project_/close-dependabot.zh-CN.toml +0 -8
  266. package/templates/.gemini/commands/_project_/code-task.en.toml +0 -10
  267. package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +0 -10
  268. package/templates/.gemini/commands/_project_/commit.en.toml +0 -10
  269. package/templates/.gemini/commands/_project_/commit.zh-CN.toml +0 -10
  270. package/templates/.gemini/commands/_project_/complete-manual-validation.en.toml +0 -10
  271. package/templates/.gemini/commands/_project_/complete-manual-validation.zh-CN.toml +0 -10
  272. package/templates/.gemini/commands/_project_/complete-task.en.toml +0 -10
  273. package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +0 -10
  274. package/templates/.gemini/commands/_project_/create-pr.en.toml +0 -10
  275. package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +0 -10
  276. package/templates/.gemini/commands/_project_/create-release-note.en.toml +0 -8
  277. package/templates/.gemini/commands/_project_/create-release-note.zh-CN.toml +0 -8
  278. package/templates/.gemini/commands/_project_/create-task.en.toml +0 -8
  279. package/templates/.gemini/commands/_project_/create-task.zh-CN.toml +0 -8
  280. package/templates/.gemini/commands/_project_/import-codescan.en.toml +0 -8
  281. package/templates/.gemini/commands/_project_/import-codescan.zh-CN.toml +0 -8
  282. package/templates/.gemini/commands/_project_/import-dependabot.en.toml +0 -8
  283. package/templates/.gemini/commands/_project_/import-dependabot.zh-CN.toml +0 -8
  284. package/templates/.gemini/commands/_project_/import-issue.en.toml +0 -8
  285. package/templates/.gemini/commands/_project_/import-issue.zh-CN.toml +0 -8
  286. package/templates/.gemini/commands/_project_/init-labels.en.toml +0 -8
  287. package/templates/.gemini/commands/_project_/init-labels.zh-CN.toml +0 -8
  288. package/templates/.gemini/commands/_project_/init-milestones.en.toml +0 -10
  289. package/templates/.gemini/commands/_project_/init-milestones.zh-CN.toml +0 -10
  290. package/templates/.gemini/commands/_project_/plan-task.en.toml +0 -10
  291. package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +0 -10
  292. package/templates/.gemini/commands/_project_/post-release.en.toml +0 -6
  293. package/templates/.gemini/commands/_project_/post-release.zh-CN.toml +0 -6
  294. package/templates/.gemini/commands/_project_/refine-title.en.toml +0 -8
  295. package/templates/.gemini/commands/_project_/refine-title.zh-CN.toml +0 -8
  296. package/templates/.gemini/commands/_project_/release.en.toml +0 -8
  297. package/templates/.gemini/commands/_project_/release.zh-CN.toml +0 -8
  298. package/templates/.gemini/commands/_project_/restore-task.en.toml +0 -8
  299. package/templates/.gemini/commands/_project_/restore-task.zh-CN.toml +0 -8
  300. package/templates/.gemini/commands/_project_/review-analysis.en.toml +0 -10
  301. package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +0 -10
  302. package/templates/.gemini/commands/_project_/review-code.en.toml +0 -10
  303. package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +0 -10
  304. package/templates/.gemini/commands/_project_/review-plan.en.toml +0 -10
  305. package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +0 -10
  306. package/templates/.gemini/commands/_project_/run-task.en.toml +0 -8
  307. package/templates/.gemini/commands/_project_/run-task.zh-CN.toml +0 -8
  308. package/templates/.gemini/commands/_project_/test-integration.en.toml +0 -6
  309. package/templates/.gemini/commands/_project_/test-integration.zh-CN.toml +0 -6
  310. package/templates/.gemini/commands/_project_/test.en.toml +0 -6
  311. package/templates/.gemini/commands/_project_/test.zh-CN.toml +0 -6
  312. package/templates/.gemini/commands/_project_/update-agent-infra.en.toml +0 -6
  313. package/templates/.gemini/commands/_project_/update-agent-infra.zh-CN.toml +0 -6
  314. package/templates/.gemini/commands/_project_/upgrade-dependency.en.toml +0 -8
  315. package/templates/.gemini/commands/_project_/upgrade-dependency.zh-CN.toml +0 -8
  316. package/templates/.gemini/commands/_project_/watch-pr.en.toml +0 -10
  317. package/templates/.gemini/commands/_project_/watch-pr.zh-CN.toml +0 -10
  318. package/templates/.gemini/settings.json +0 -3
@@ -150,9 +150,10 @@ function runOptionalDemo(cwd: string, run: CommandRunner = command): DemoResult
150
150
  return { status: 'recorded', reasonCode: null, message: null, outputPath };
151
151
  }
152
152
 
153
- function git(cwd: string, args: string[], run: CommandRunner = command): string | null {
153
+ function git(cwd: string, args: string[], run: CommandRunner = command, trim = true): string | null {
154
154
  const result = run(cwd, 'git', args);
155
- return result.status === 0 ? String(result.stdout).trim() : null;
155
+ const stdout = String(result.stdout);
156
+ return result.status === 0 ? (trim ? stdout.trim() : stdout) : null;
156
157
  }
157
158
 
158
159
  function inspectLocalReleaseFacts(cwd: string, version: string, run: CommandRunner = command) {
@@ -228,9 +229,15 @@ async function inspectFacts(cwd: string, version: string): Promise<ReleaseFacts>
228
229
  };
229
230
  }
230
231
 
231
- function changedPaths(cwd: string): string[] {
232
- const output = git(cwd, ['status', '--porcelain=v1']) || '';
233
- return output.split('\n').filter(Boolean).map((line) => line.slice(3)).filter((value, index, all) => all.indexOf(value) === index);
232
+ function parsePorcelainPath(record: string): string {
233
+ const match = /^.. (.+)$/.exec(record);
234
+ if (!match) throw new Error('Invalid git status --porcelain=v1 record');
235
+ return match[1]!;
236
+ }
237
+
238
+ function changedPaths(cwd: string, run: CommandRunner = command): string[] {
239
+ const output = git(cwd, ['status', '--porcelain=v1'], run, false) || '';
240
+ return output.split(/\r?\n/).filter(Boolean).map(parsePorcelainPath).filter((value, index, all) => all.indexOf(value) === index);
234
241
  }
235
242
 
236
243
  function updateReleaseMetadata(cwd: string, version: string): void {
@@ -336,5 +343,5 @@ async function releaseWorkflow(args: string[] = []): Promise<void> {
336
343
  process.stdout.write(`${JSON.stringify({ ...pushed, demo, snapshot: releaseSnapshot(version, await inspectFacts(cwd, version)) })}\n`); process.exitCode = pushed.status === 'failed' ? 1 : pushed.status === 'degraded' ? 2 : 0;
337
344
  }
338
345
 
339
- export { computeDemoInputDigest, inspectFacts, inspectLocalReleaseFacts, inspectPostWorktree, releaseSmokeStatus, releaseWorkflow, runOptionalDemo };
346
+ export { changedPaths, computeDemoInputDigest, inspectFacts, inspectLocalReleaseFacts, inspectPostWorktree, releaseSmokeStatus, releaseWorkflow, runOptionalDemo };
340
347
  export type { CommandRunner, DemoResult };
@@ -0,0 +1,55 @@
1
+ import { applyActivityAppendIntent } from '../task/activity-intent.ts';
2
+ import type { ActivityAppendIntent } from '../task/activity-intent.ts';
3
+
4
+ const USAGE = `Usage: agent-infra-internal task-activity <task-ref> append --step <step> --agent <agent> --note <note> [--artifact <canonical.md>] [--dry-run]
5
+ `;
6
+ const FLAGS: Record<string, string> = {
7
+ '--step': 'step',
8
+ '--agent': 'agent',
9
+ '--note': 'note',
10
+ '--artifact': 'artifact'
11
+ };
12
+
13
+ function usageFailure(message: string): void {
14
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'ACTIVITY_PAYLOAD_INVALID', message } })}\n`);
15
+ process.stderr.write(USAGE);
16
+ process.exitCode = 1;
17
+ }
18
+
19
+ function taskActivity(args: string[] = []): void {
20
+ if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
21
+ const [taskRef, kind] = args;
22
+ if (!taskRef || taskRef.startsWith('--') || !kind || kind !== 'append') {
23
+ usageFailure('task ref and the append intent are required');
24
+ return;
25
+ }
26
+ const values: Record<string, unknown> = { kind, taskRef };
27
+ const seen = new Set<string>();
28
+ for (let index = 2; index < args.length; index += 1) {
29
+ const flag = args[index]!;
30
+ if (flag === '--dry-run') {
31
+ if (seen.has(flag)) { usageFailure(`duplicate option '${flag}'`); return; }
32
+ seen.add(flag);
33
+ values.dryRun = true;
34
+ continue;
35
+ }
36
+ const key = FLAGS[flag];
37
+ if (!key) { usageFailure(`unknown option '${flag}'`); return; }
38
+ if (seen.has(flag)) { usageFailure(`duplicate option '${flag}'`); return; }
39
+ const value = args[++index];
40
+ if (value === undefined || value.startsWith('--')) { usageFailure(`option '${flag}' requires a value`); return; }
41
+ seen.add(flag);
42
+ values[key] = value;
43
+ }
44
+ const allowed = new Set(['kind', 'taskRef', 'dryRun', 'step', 'agent', 'note', 'artifact']);
45
+ const unexpected = Object.keys(values).find((key) => !allowed.has(key));
46
+ if (unexpected) { usageFailure(`append does not accept '${unexpected}'`); return; }
47
+ for (const key of ['step', 'agent', 'note']) {
48
+ if (values[key] === undefined) { usageFailure(`append requires '${key}'`); return; }
49
+ }
50
+ const result = applyActivityAppendIntent(values as ActivityAppendIntent);
51
+ process.stdout.write(`${JSON.stringify(result)}\n`);
52
+ if (result.status === 'failed') process.exitCode = 1;
53
+ }
54
+
55
+ export { taskActivity };
@@ -1,7 +1,8 @@
1
+ import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.ts';
1
2
  import { applyTaskEvent, eventCatalog } from '../task/events.ts';
2
3
  import type { TaskEventRequest, Verdict } from '../task/events.ts';
3
4
 
4
- const USAGE = `Usage: agent-infra-internal task-event <N | TASK-id> <event> --agent <agent> [event options] [--dry-run]
5
+ const USAGE = `Usage: agent-infra-internal task-event <N | TASK-id> <event> --agent <agent> [event options] [--orchestrated] [--dry-run]
5
6
 
6
7
  Apply one closed-set task lifecycle event and print a structured JSON result.
7
8
  Events: ${eventCatalog.join(', ')}
@@ -29,6 +30,10 @@ function taskEvent(args: string[] = []): void {
29
30
  const seen = new Set<string>();
30
31
  for (let index = 2; index < args.length; index += 1) {
31
32
  const flag = args[index]!;
33
+ if (flag === '--orchestrated') {
34
+ if (seen.has(flag)) { usageFailure(`duplicate option '${flag}'`); return; }
35
+ seen.add(flag); request.orchestrated = true; continue;
36
+ }
32
37
  if (flag === '--dry-run') {
33
38
  if (seen.has(flag)) { usageFailure(`duplicate option '${flag}'`); return; }
34
39
  seen.add(flag); request.dryRun = true; continue;
@@ -43,6 +48,9 @@ function taskEvent(args: string[] = []): void {
43
48
  else if (key === 'verdict') request.verdict = value as Verdict;
44
49
  else (request as Record<string, unknown>)[key] = value;
45
50
  }
51
+ const agent = normalizeAgentToken(String(request.agent ?? ''));
52
+ if (!agent) { usageFailure(`invalid --agent '${request.agent}': ${AGENT_USAGE_HINT}`); return; }
53
+ request.agent = agent;
46
54
  const result = applyTaskEvent(request);
47
55
  process.stdout.write(`${JSON.stringify(result)}\n`);
48
56
  if (result.status === 'failed') process.exitCode = 1;
@@ -1,3 +1,4 @@
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';
3
4
 
@@ -33,6 +34,9 @@ function taskLifecycle(args: string[] = []): void {
33
34
  seen.add(flag);
34
35
  values[key] = key === 'alertNumber' || key === 'issueNumber' ? Number(value) : value;
35
36
  }
37
+ const agent = normalizeAgentToken(String(values.agent ?? ''));
38
+ if (!agent) { usageFailure(`invalid --agent '${values.agent}': ${AGENT_USAGE_HINT}`); return; }
39
+ values.agent = agent;
36
40
  const result = applyTaskLifecycle(values as TaskLifecycleRequest);
37
41
  process.stdout.write(`${JSON.stringify(result)}\n`);
38
42
  if (result.status === 'failed') process.exitCode = 1;
@@ -1,3 +1,4 @@
1
+ import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.ts';
1
2
  import {
2
3
  activateMatchingOrchestrationDelegation,
3
4
  activateOrchestrationDelegation,
@@ -11,6 +12,7 @@ import {
11
12
  sealOrchestrationDelegation,
12
13
  statusOrchestration
13
14
  } from '../task/orchestration.ts';
15
+ import { isAgentClientId } from '../agent-clients/types.ts';
14
16
  import type { AgentClientId } from '../agent-clients/types.ts';
15
17
 
16
18
  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';
@@ -43,8 +45,11 @@ function taskOrchestration(args: string[] = []): void {
43
45
  for (let index = 2; index < args.length; index += 1) {
44
46
  const flag = args[index]!;
45
47
  if (![
46
- '--max-steps', '--client', '--requested-model', '--parent-id', '--before-fingerprint',
47
- '--native-agent', '--child-id', '--spawn-mode', '--actual-model', '--fallback-reason',
48
+ '--max-steps', '--executor-model', '--executor-reasoning-effort',
49
+ '--reviewer-model', '--reviewer-reasoning-effort',
50
+ '--client', '--requested-model', '--requested-reasoning-effort', '--parent-id', '--before-fingerprint',
51
+ '--native-agent', '--child-id', '--spawn-mode', '--actual-model', '--actual-reasoning-effort',
52
+ '--model-fallback-reason', '--reasoning-effort-fallback-reason',
48
53
  '--exit-code', '--after-fingerprint', '--changed-paths', '--code', '--message', '--recoverable', '--agent'
49
54
  ].includes(flag)) {
50
55
  usageFailure(`unknown option '${flag}'`);
@@ -63,13 +68,41 @@ function taskOrchestration(args: string[] = []): void {
63
68
  values[flag] = value;
64
69
  }
65
70
  const requireValues = (flags: string[]) => flags.find((flag) => values[flag] === undefined);
71
+ if (values['--client'] !== undefined && !isAgentClientId(values['--client'])) {
72
+ usageFailure(`unknown client '${values['--client']}'`);
73
+ return;
74
+ }
66
75
  let result;
67
76
  if (intent === 'begin-or-resume') {
77
+ const missing = requireValues(['--client']);
78
+ if (missing) { usageFailure(`intent 'begin-or-resume' requires '${missing}'`); return; }
68
79
  const maxSteps = values['--max-steps'] === undefined ? undefined : Number(values['--max-steps']);
69
80
  if (maxSteps !== undefined && (!Number.isInteger(maxSteps) || maxSteps < 1)) {
70
81
  usageFailure('--max-steps must be a positive integer'); return;
71
82
  }
72
- result = beginOrResumeOrchestration(taskRef!, { maxSteps });
83
+ const policyFlags = [
84
+ '--executor-model', '--executor-reasoning-effort',
85
+ '--reviewer-model', '--reviewer-reasoning-effort'
86
+ ];
87
+ const hasAnyPolicy = policyFlags.some((flag) => values[flag] !== undefined);
88
+ if (hasAnyPolicy && policyFlags.some((flag) => values[flag] === undefined)) {
89
+ usageFailure('explicit model policy requires executor/reviewer model and reasoning effort');
90
+ return;
91
+ }
92
+ result = beginOrResumeOrchestration(taskRef!, {
93
+ maxSteps,
94
+ client: values['--client'] as AgentClientId,
95
+ modelPolicy: hasAnyPolicy ? {
96
+ executor: {
97
+ model: values['--executor-model']!,
98
+ reasoningEffort: values['--executor-reasoning-effort']!
99
+ },
100
+ reviewer: {
101
+ model: values['--reviewer-model']!,
102
+ reasoningEffort: values['--reviewer-reasoning-effort']!
103
+ }
104
+ } : undefined
105
+ });
73
106
  } else if (intent === 'route') {
74
107
  result = routeOrchestration(taskRef!);
75
108
  } else if (intent === 'status') {
@@ -79,7 +112,8 @@ function taskOrchestration(args: string[] = []): void {
79
112
  if (missing) { usageFailure(`intent 'prepare' requires '${missing}'`); return; }
80
113
  result = prepareOrchestrationDelegation(taskRef!, {
81
114
  client: values['--client'] as AgentClientId,
82
- requestedModel: values['--requested-model']
115
+ requestedModel: values['--requested-model'],
116
+ requestedReasoningEffort: values['--requested-reasoning-effort']
83
117
  });
84
118
  } else if (intent === 'hook-start') {
85
119
  const missing = requireValues([
@@ -90,7 +124,10 @@ function taskOrchestration(args: string[] = []): void {
90
124
  const event = {
91
125
  nativeAgent: values['--native-agent']!, childId: values['--child-id']!,
92
126
  parentId: values['--parent-id']!, spawnMode: values['--spawn-mode']!,
93
- actualModel: values['--actual-model'], modelFallbackReason: values['--fallback-reason']
127
+ actualModel: values['--actual-model'],
128
+ actualReasoningEffort: values['--actual-reasoning-effort'],
129
+ modelFallbackReason: values['--model-fallback-reason'],
130
+ reasoningEffortFallbackReason: values['--reasoning-effort-fallback-reason']
94
131
  };
95
132
  result = taskRef === 'auto'
96
133
  ? activateMatchingOrchestrationDelegation(values['--client'] as AgentClientId, event)
@@ -116,7 +153,9 @@ function taskOrchestration(args: string[] = []): void {
116
153
  } else if (intent === 'stage-completed') {
117
154
  const missing = requireValues(['--agent']);
118
155
  if (missing) { usageFailure(`intent 'stage-completed' requires '${missing}'`); return; }
119
- result = completeCommitOrchestrationStage(taskRef!, values['--agent']!);
156
+ const agent = normalizeAgentToken(values['--agent']!);
157
+ if (!agent) { usageFailure(`invalid --agent '${values['--agent']}': ${AGENT_USAGE_HINT}`); return; }
158
+ result = completeCommitOrchestrationStage(taskRef!, agent);
120
159
  } else if (intent === 'advance') {
121
160
  result = advanceOrchestration(taskRef!);
122
161
  } 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 };
@@ -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;