@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
@@ -1,4 +1,6 @@
1
1
  import { spawnSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
2
4
  const defaultRunner = (args, cwd) => {
3
5
  const result = spawnSync('git', [...args], { cwd, encoding: 'utf8' });
4
6
  return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };
@@ -10,6 +12,9 @@ function value(runner, cwd, args, trim = true) {
10
12
  const result = run(runner, cwd, args);
11
13
  return result.status === 0 ? (trim ? result.stdout.trim() : result.stdout.replace(/\n$/, '')) : null;
12
14
  }
15
+ function cleanMessage(message) {
16
+ return message.replace(/(https?:\/\/)[^\s/@:]+(?::[^\s/@]*)?@/gi, '$1***@').trim();
17
+ }
13
18
  function inspectGitWorkflow(cwd, runner = defaultRunner, remoteInput) {
14
19
  const head = value(runner, cwd, ['rev-parse', 'HEAD']);
15
20
  const branch = value(runner, cwd, ['branch', '--show-current']);
@@ -97,5 +102,53 @@ function pushGitRefs(input, runner = defaultRunner) {
97
102
  const failures = operations.filter((item) => item.status === 'failed').length;
98
103
  return { status: failures === 0 ? 'applied' : failures === operations.length ? 'failed' : 'degraded', changed: failures < operations.length, snapshot: inspectGitWorkflow(input.cwd, runner).snapshot, operations, error: failures ? { code: 'GIT_PUSH_PARTIAL', message: `${failures} ref push operation(s) failed` } : null };
99
104
  }
100
- export { commitExplicitPaths, inspectGitWorkflow, pushGitRefs };
105
+ function pushRebasedBranch(input, runner = defaultRunner) {
106
+ const sha = /^[0-9a-f]{40}$/i;
107
+ const refName = /^(?!-)(?!.*\.\.)(?!.*(?:^|\/)\.)(?!.*[~^:?*\[\\\s])(?:[A-Za-z0-9._-]+\/)*[A-Za-z0-9._-]+$/;
108
+ if (!input.remote || !refName.test(input.remote) || !refName.test(input.branch) || !refName.test(input.baseBranch) ||
109
+ !sha.test(input.expectedOldHead) || !sha.test(input.newHead) || !sha.test(input.expectedBaseHead)) {
110
+ return { status: 'failed', changed: false, snapshot: null, operations: [], error: { code: 'GIT_REBASED_INPUT_INVALID', message: 'Remote, branches, and full 40-character SHAs are required' } };
111
+ }
112
+ const snapshot = inspectGitWorkflow(input.cwd, runner).snapshot;
113
+ if (!snapshot)
114
+ return { status: 'failed', changed: false, snapshot: null, operations: [], error: { code: 'GIT_INSPECT_FAILED', message: 'Unable to inspect Git repository' } };
115
+ if (snapshot.branch !== input.branch || snapshot.head !== input.newHead) {
116
+ return { status: 'failed', changed: false, snapshot, operations: [], error: { code: 'GIT_LOCAL_IDENTITY_MISMATCH', message: 'Current branch or HEAD does not match the rebased intent' } };
117
+ }
118
+ const rebasePaths = ['rebase-merge', 'rebase-apply']
119
+ .map((name) => value(runner, input.cwd, ['rev-parse', '--git-path', name]))
120
+ .filter((candidate) => Boolean(candidate));
121
+ if (snapshot.worktree.length > 0 || snapshot.staged.length > 0 ||
122
+ run(runner, input.cwd, ['rev-parse', '-q', '--verify', 'REBASE_HEAD']).status === 0 ||
123
+ rebasePaths.some((candidate) => fs.existsSync(path.isAbsolute(candidate) ? candidate : path.join(input.cwd, candidate)))) {
124
+ return { status: 'failed', changed: false, snapshot, operations: [], error: { code: 'GIT_LOCAL_STATE_UNSAFE', message: 'Working tree must be clean with no rebase in progress' } };
125
+ }
126
+ const remoteRef = `refs/heads/${input.branch}`;
127
+ const baseRef = `refs/heads/${input.baseBranch}`;
128
+ const remoteHead = value(runner, input.cwd, ['ls-remote', '--exit-code', input.remote, remoteRef])?.split(/\s+/)[0] ?? null;
129
+ if (remoteHead !== input.expectedOldHead) {
130
+ return { status: 'failed', changed: false, snapshot, operations: [], error: { code: 'GIT_REMOTE_HEAD_MISMATCH', message: `Expected remote head ${input.expectedOldHead}, received ${remoteHead ?? 'unavailable'}` } };
131
+ }
132
+ const baseHead = value(runner, input.cwd, ['ls-remote', '--exit-code', input.remote, baseRef])?.split(/\s+/)[0] ?? null;
133
+ if (baseHead !== input.expectedBaseHead) {
134
+ return { status: 'failed', changed: false, snapshot, operations: [], error: { code: 'GIT_REMOTE_BASE_MISMATCH', message: `Expected base head ${input.expectedBaseHead}, received ${baseHead ?? 'unavailable'}` } };
135
+ }
136
+ if (run(runner, input.cwd, ['merge-base', '--is-ancestor', input.expectedBaseHead, input.newHead]).status !== 0) {
137
+ return { status: 'failed', changed: false, snapshot, operations: [], error: { code: 'GIT_REBASED_ANCESTOR_MISMATCH', message: 'Rebased head does not contain the expected base head' } };
138
+ }
139
+ const pushed = run(runner, input.cwd, [
140
+ 'push', `--force-with-lease=${remoteRef}:${input.expectedOldHead}`,
141
+ input.remote, `${input.newHead}:${remoteRef}`
142
+ ]);
143
+ if (pushed.status !== 0) {
144
+ const message = cleanMessage(pushed.stderr) || 'Rebased branch push was rejected';
145
+ return { status: 'failed', changed: false, snapshot: inspectGitWorkflow(input.cwd, runner).snapshot, operations: [{ name: 'push-rebased', status: 'failed', ref: input.branch, message }], error: { code: 'GIT_REBASED_PUSH_REJECTED', message } };
146
+ }
147
+ const verified = value(runner, input.cwd, ['ls-remote', '--exit-code', input.remote, remoteRef])?.split(/\s+/)[0] ?? null;
148
+ if (verified !== input.newHead) {
149
+ return { status: 'failed', changed: true, snapshot: inspectGitWorkflow(input.cwd, runner).snapshot, operations: [{ name: 'push-rebased', status: 'failed', ref: input.branch, message: 'Remote ref verification failed' }], error: { code: 'GIT_REBASED_VERIFY_FAILED', message: `Expected pushed head ${input.newHead}, received ${verified ?? 'unavailable'}` } };
150
+ }
151
+ return { status: 'applied', changed: true, snapshot: inspectGitWorkflow(input.cwd, runner).snapshot, operations: [{ name: 'push-rebased', status: 'applied', ref: input.branch }], error: null };
152
+ }
153
+ export { commitExplicitPaths, inspectGitWorkflow, pushGitRefs, pushRebasedBranch };
101
154
  //# sourceMappingURL=workflow.js.map
@@ -3,7 +3,9 @@ import path from 'node:path';
3
3
  import { AgentClientConfigError, normalizeAgentClients } from '../agent-clients/config.js';
4
4
  import { normalizeCustomTUIs } from '../agent-clients/custom-tuis.js';
5
5
  import { renderNextStepCommands } from '../agent-clients/next-steps.js';
6
- const USAGE = 'Usage: agent-infra-internal agent-client next-steps --skill <skill-name> [--task-ref <NN|TASK-id>] [--format text|json]\n';
6
+ import { getAgentClientModelSelection } from '../agent-clients/registry.js';
7
+ import { isAgentClientId } from '../agent-clients/types.js';
8
+ const USAGE = 'Usage: agent-infra-internal agent-client <next-steps|model-selection> [options]\n';
7
9
  function failure(code, message) {
8
10
  process.stdout.write(`${JSON.stringify({
9
11
  status: 'failed',
@@ -25,11 +27,12 @@ function parseArgs(args) {
25
27
  }
26
28
  let skillName;
27
29
  let taskRef;
30
+ let version;
28
31
  let format = 'text';
29
32
  const seen = new Set();
30
33
  for (let index = 1; index < args.length; index += 1) {
31
34
  const flag = args[index];
32
- if (!['--skill', '--task-ref', '--format'].includes(flag)) {
35
+ if (!['--skill', '--task-ref', '--version', '--format'].includes(flag)) {
33
36
  failure('AGENT_CLIENT_PAYLOAD_INVALID', `unknown option '${flag}'`);
34
37
  return null;
35
38
  }
@@ -47,6 +50,8 @@ function parseArgs(args) {
47
50
  skillName = value;
48
51
  if (flag === '--task-ref')
49
52
  taskRef = value;
53
+ if (flag === '--version')
54
+ version = value;
50
55
  if (flag === '--format') {
51
56
  if (value !== 'text' && value !== 'json') {
52
57
  failure('AGENT_CLIENT_PAYLOAD_INVALID', "format must be 'text' or 'json'");
@@ -59,9 +64,60 @@ function parseArgs(args) {
59
64
  failure('AGENT_CLIENT_PAYLOAD_INVALID', "option '--skill' is required");
60
65
  return null;
61
66
  }
62
- return { skillName, ...(taskRef ? { taskRef } : {}), format };
67
+ return {
68
+ skillName,
69
+ ...(taskRef ? { taskRef } : {}),
70
+ ...(version ? { version } : {}),
71
+ format
72
+ };
63
73
  }
64
74
  function agentClient(args = []) {
75
+ if (args[0] === 'model-selection') {
76
+ const values = {};
77
+ const seen = new Set();
78
+ for (let index = 1; index < args.length; index += 1) {
79
+ const flag = args[index];
80
+ if (!['--client', '--format'].includes(flag) || seen.has(flag)) {
81
+ failure('AGENT_CLIENT_PAYLOAD_INVALID', `invalid or duplicate option '${flag}'`);
82
+ return;
83
+ }
84
+ const value = args[++index];
85
+ if (!value || value.startsWith('--')) {
86
+ failure('AGENT_CLIENT_PAYLOAD_INVALID', `option '${flag}' requires a value`);
87
+ return;
88
+ }
89
+ seen.add(flag);
90
+ values[flag] = value;
91
+ }
92
+ const client = values['--client'];
93
+ const format = values['--format'] ?? 'text';
94
+ if (!isAgentClientId(client) || !['text', 'json'].includes(format)) {
95
+ failure('AGENT_CLIENT_PAYLOAD_INVALID', 'model-selection requires a known --client and text|json format');
96
+ return;
97
+ }
98
+ const context = getAgentClientModelSelection(client);
99
+ if (format === 'json') {
100
+ process.stdout.write(`${JSON.stringify({
101
+ status: 'resolved', changed: false, client, context, error: null
102
+ })}\n`);
103
+ return;
104
+ }
105
+ if (context.kind === 'interactive-only') {
106
+ process.stdout.write(`Model selection: interactive-only\nCommand: ${context.command}\n${context.guidance}\n`);
107
+ }
108
+ else {
109
+ process.stdout.write(`Model selection: ${context.completeness} catalog\nSource: ${context.source}\n`);
110
+ for (const model of context.models) {
111
+ const efforts = model.reasoningEfforts?.length
112
+ ? ` (${model.reasoningEfforts.join(', ')})`
113
+ : '';
114
+ process.stdout.write(`- ${model.id}${efforts}\n`);
115
+ }
116
+ if (context.guidance)
117
+ process.stdout.write(`${context.guidance}\n`);
118
+ }
119
+ return;
120
+ }
65
121
  const parsed = parseArgs(args);
66
122
  if (!parsed || process.exitCode)
67
123
  return;
@@ -86,7 +142,8 @@ function agentClient(args = []) {
86
142
  state: clients.state,
87
143
  customTUIs: custom.items,
88
144
  skillName: parsed.skillName,
89
- ...(parsed.taskRef ? { taskRef: parsed.taskRef } : {})
145
+ ...(parsed.taskRef ? { taskRef: parsed.taskRef } : {}),
146
+ ...(parsed.version ? { version: parsed.version } : {})
90
147
  });
91
148
  if (parsed.format === 'json') {
92
149
  process.stdout.write(`${JSON.stringify({
@@ -1,5 +1,5 @@
1
1
  import fs from 'node:fs';
2
- import { commitExplicitPaths, inspectGitWorkflow, pushGitRefs } from '../git/workflow.js';
2
+ import { commitExplicitPaths, inspectGitWorkflow, pushGitRefs, pushRebasedBranch } from '../git/workflow.js';
3
3
  import { compareReviewTrees, snapshotReview } from '../git/review-snapshot.js';
4
4
  import { resolvePostReviewGlobs } from '../task/review-fingerprint.js';
5
5
  function output(value) { process.stdout.write(`${JSON.stringify(value)}\n`); }
@@ -23,6 +23,11 @@ function gitWorkflow(args = []) {
23
23
  const input = inputIndex >= 0 && rest[inputIndex + 1] ? JSON.parse(fs.readFileSync(rest[inputIndex + 1], 'utf8')) : null;
24
24
  result = input ? pushGitRefs({ cwd: cwd ?? process.cwd(), ...input }) : { status: 'failed', changed: false, error: { code: 'GIT_INPUT_REQUIRED', message: '--input JSON file is required' } };
25
25
  }
26
+ else if (action === 'push-rebased') {
27
+ const inputIndex = rest.indexOf('--input');
28
+ const input = inputIndex >= 0 && rest[inputIndex + 1] ? JSON.parse(fs.readFileSync(rest[inputIndex + 1], 'utf8')) : null;
29
+ result = input ? pushRebasedBranch({ cwd: cwd ?? process.cwd(), ...input }) : { status: 'failed', changed: false, error: { code: 'GIT_INPUT_REQUIRED', message: '--input JSON file is required' } };
30
+ }
26
31
  else if (action === 'snapshot' || action === 'compare-trees') {
27
32
  const inputIndex = rest.indexOf('--input');
28
33
  const input = inputIndex >= 0 && rest[inputIndex + 1] ? JSON.parse(fs.readFileSync(rest[inputIndex + 1], 'utf8')) : null;
@@ -1,5 +1,5 @@
1
1
  import path from 'node:path';
2
- import { fetchPlatformCheckLogs, inspectRequiredChecks, resolvePlatformCheckRun, watchPlatformChecks } from '../platform/pr-checks.js';
2
+ import { fetchPlatformCheckLogs, inspectPullRequestReadiness, resolvePlatformCheckRun, watchPullRequestReadiness } from '../platform/pr-checks.js';
3
3
  const USAGE = `Usage: agent-infra-internal platform-checks inspect <task-ref> [--cwd <path>]
4
4
  agent-infra-internal platform-checks watch <task-ref> --interval-seconds <N> --deadline-seconds <N> [--cwd <path>]
5
5
  agent-infra-internal platform-checks resolve-run <task-ref> --check-name <name> [--details-url <url>] [--cwd <path>]
@@ -76,7 +76,7 @@ async function platformChecks(args = []) {
76
76
  return;
77
77
  }
78
78
  if (operation === 'inspect') {
79
- finish(inspectRequiredChecks(taskRef, { cwd }));
79
+ finish(inspectPullRequestReadiness(taskRef, { cwd }));
80
80
  return;
81
81
  }
82
82
  if (operation === 'resolve-run') {
@@ -108,7 +108,7 @@ async function platformChecks(args = []) {
108
108
  process.once('SIGINT', abort);
109
109
  process.once('SIGTERM', abort);
110
110
  try {
111
- finish(await watchPlatformChecks(taskRef, { cwd, intervalSeconds, deadlineSeconds, signal: controller.signal }));
111
+ finish(await watchPullRequestReadiness(taskRef, { cwd, intervalSeconds, deadlineSeconds, signal: controller.signal }));
112
112
  }
113
113
  finally {
114
114
  process.removeListener('SIGINT', abort);
@@ -1,8 +1,11 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
+ import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.js';
3
4
  import { checkPlatformCommentOwner, listPlatformComments, syncPlatformComment } from '../platform/issue-comments.js';
5
+ import { backfillCompletionComments } from '../platform/completion-backfill.js';
4
6
  const USAGE = `Usage: agent-infra-internal platform-comment list --issue <N> [--cwd <path>]
5
7
  agent-infra-internal platform-comment owner <task-ref> [--cwd <path>]
8
+ agent-infra-internal platform-comment backfill <task-ref> --agent <agent> [--cwd <path>]
6
9
  agent-infra-internal platform-comment sync <task-ref> --kind <kind> --agent <agent> [--artifact <file>] [--body-file <path|->] [--status-label <label>] [--backfill] [--cwd <path>]
7
10
  `;
8
11
  function fail(message) {
@@ -50,7 +53,7 @@ function platformComment(args = []) {
50
53
  return;
51
54
  }
52
55
  const operation = args[0];
53
- if (!operation || !['list', 'owner', 'sync'].includes(operation)) {
56
+ if (!operation || !['list', 'owner', 'backfill', 'sync'].includes(operation)) {
54
57
  fail('a valid operation is required');
55
58
  return;
56
59
  }
@@ -89,6 +92,25 @@ function platformComment(args = []) {
89
92
  finish(checkPlatformCommentOwner(taskRef, { cwd }));
90
93
  return;
91
94
  }
95
+ if (operation === 'backfill') {
96
+ const unexpected = Object.keys(parsed.values).find((key) => !['cwd', 'agent'].includes(key));
97
+ if (unexpected) {
98
+ fail(`backfill does not accept '--${unexpected}'`);
99
+ return;
100
+ }
101
+ const agent = parsed.values.agent;
102
+ if (typeof agent !== 'string' || !agent) {
103
+ fail('backfill requires --agent');
104
+ return;
105
+ }
106
+ const normalizedAgent = normalizeAgentToken(agent);
107
+ if (!normalizedAgent) {
108
+ fail(`invalid --agent '${agent}': ${AGENT_USAGE_HINT}`);
109
+ return;
110
+ }
111
+ finish(backfillCompletionComments(taskRef, { cwd, agent: normalizedAgent }));
112
+ return;
113
+ }
92
114
  const kind = parsed.values.kind;
93
115
  const agent = parsed.values.agent;
94
116
  if (!['task', 'artifact', 'summary', 'cancel'].includes(String(kind))) {
@@ -99,6 +121,11 @@ function platformComment(args = []) {
99
121
  fail('sync requires --agent');
100
122
  return;
101
123
  }
124
+ const normalizedAgent = normalizeAgentToken(agent);
125
+ if (!normalizedAgent) {
126
+ fail(`invalid --agent '${agent}': ${AGENT_USAGE_HINT}`);
127
+ return;
128
+ }
102
129
  if (kind === 'artifact' && typeof parsed.values.artifact !== 'string') {
103
130
  fail('artifact sync requires --artifact');
104
131
  return;
@@ -118,7 +145,7 @@ function platformComment(args = []) {
118
145
  }
119
146
  finish(syncPlatformComment(taskRef, {
120
147
  kind: kind,
121
- agent,
148
+ agent: normalizedAgent,
122
149
  artifact: typeof parsed.values.artifact === 'string' ? parsed.values.artifact : undefined,
123
150
  body,
124
151
  backfill: parsed.values.backfill === true,
@@ -1,4 +1,5 @@
1
1
  import path from 'node:path';
2
+ import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.js';
2
3
  import { bindPlatformIssue, createPlatformIssue, inspectPlatformIssue, syncPlatformIssue } from '../platform/issues.js';
3
4
  const USAGE = `Usage: agent-infra-internal platform-issue inspect <task-ref> [--cwd <path>]
4
5
  agent-infra-internal platform-issue create <task-ref> --agent <agent> [--dry-run] [--cwd <path>]
@@ -92,6 +93,12 @@ function platformIssue(args = []) {
92
93
  fail(`${operation} requires --agent`);
93
94
  return;
94
95
  }
96
+ const agent = normalizeAgentToken(values.agent);
97
+ if (!agent) {
98
+ fail(`invalid --agent '${values.agent}': ${AGENT_USAGE_HINT}`);
99
+ return;
100
+ }
101
+ values.agent = agent;
95
102
  if (operation === 'create') {
96
103
  finish(createPlatformIssue(taskRef, { cwd, agent: values.agent, dryRun: values.dryRun === true }));
97
104
  return;
@@ -0,0 +1,132 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { inspectPlatformPullRequestByNumber } from '../platform/pull-requests.js';
4
+ import { listPrReviews, publishPrReview } from '../platform/pr-review.js';
5
+ const USAGE = `Usage: agent-infra-internal platform-pr-review inspect --pr <N> [--cwd <path>]
6
+ agent-infra-internal platform-pr-review list --pr <N> [--cwd <path>]
7
+ agent-infra-internal platform-pr-review publish --pr <N> --scope <taskId|pr{N}> --round <N> --commit <sha> --event <COMMENT|APPROVE|REQUEST_CHANGES> --body-file <path|-> [--dry-run] [--cwd <path>]
8
+ `;
9
+ const BOOLEAN_FLAGS = new Set(['--dry-run']);
10
+ const VALUE_FLAGS = new Set(['--cwd', '--pr', '--scope', '--round', '--commit', '--event', '--body-file']);
11
+ function key(flag) {
12
+ return flag.slice(2).replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
13
+ }
14
+ function fail(message) {
15
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'PR_REVIEW_PAYLOAD_INVALID', message } })}\n`);
16
+ process.stderr.write(USAGE);
17
+ process.exitCode = 1;
18
+ }
19
+ function finish(output) {
20
+ process.stdout.write(`${JSON.stringify(output)}\n`);
21
+ if (output.status === 'failed')
22
+ process.exitCode = 1;
23
+ if (output.status === 'blocked')
24
+ process.exitCode = 2;
25
+ }
26
+ function parse(args, start) {
27
+ const values = {};
28
+ const seen = new Set();
29
+ for (let index = start; index < args.length; index += 1) {
30
+ const flag = args[index];
31
+ if (!BOOLEAN_FLAGS.has(flag) && !VALUE_FLAGS.has(flag))
32
+ return { values, error: `unknown option '${flag}'` };
33
+ if (seen.has(flag))
34
+ return { values, error: `duplicate option '${flag}'` };
35
+ seen.add(flag);
36
+ if (BOOLEAN_FLAGS.has(flag)) {
37
+ values[key(flag)] = true;
38
+ continue;
39
+ }
40
+ const value = args[++index];
41
+ if (value === undefined || value.startsWith('--'))
42
+ return { values, error: `option '${flag}' requires a value` };
43
+ values[key(flag)] = value;
44
+ }
45
+ return { values };
46
+ }
47
+ function readBodyFile(value, cwd) {
48
+ return value === '-' ? fs.readFileSync(0, 'utf8') : fs.readFileSync(path.resolve(cwd, value), 'utf8');
49
+ }
50
+ function platformPrReview(args = []) {
51
+ if (args[0] === '--help' || args[0] === '-h') {
52
+ process.stdout.write(USAGE);
53
+ return;
54
+ }
55
+ const operation = args[0];
56
+ if (!operation || !['inspect', 'list', 'publish'].includes(operation)) {
57
+ fail('a valid operation is required');
58
+ return;
59
+ }
60
+ const parsed = parse(args, 1);
61
+ if (parsed.error) {
62
+ fail(parsed.error);
63
+ return;
64
+ }
65
+ const values = parsed.values;
66
+ const cwd = path.resolve(typeof values.cwd === 'string' ? values.cwd : process.cwd());
67
+ const allowed = {
68
+ inspect: ['cwd', 'pr'],
69
+ list: ['cwd', 'pr'],
70
+ publish: ['cwd', 'pr', 'scope', 'round', 'commit', 'event', 'bodyFile', 'dryRun']
71
+ };
72
+ const unexpected = Object.keys(values).find((name) => !allowed[operation].includes(name));
73
+ if (unexpected) {
74
+ fail(`${operation} does not accept --${unexpected}`);
75
+ return;
76
+ }
77
+ const pr = Number(values.pr);
78
+ if (!Number.isInteger(pr) || pr <= 0) {
79
+ fail(`${operation} requires a positive --pr`);
80
+ return;
81
+ }
82
+ if (operation === 'inspect') {
83
+ finish(inspectPlatformPullRequestByNumber(pr, { cwd }));
84
+ return;
85
+ }
86
+ if (operation === 'list') {
87
+ finish(listPrReviews(pr, { cwd }));
88
+ return;
89
+ }
90
+ const scope = typeof values.scope === 'string' ? values.scope : '';
91
+ const round = Number(values.round);
92
+ const commit = typeof values.commit === 'string' ? values.commit : '';
93
+ const event = values.event;
94
+ if (!scope || !/^(?:pr\d+|TASK-\d{8}-\d{6})$/.test(scope)) {
95
+ fail('publish requires --scope <taskId|pr{N}>');
96
+ return;
97
+ }
98
+ if (!Number.isInteger(round) || round <= 0) {
99
+ fail('publish requires a positive --round');
100
+ return;
101
+ }
102
+ if (!/^[0-9a-f]{7,40}$/i.test(commit)) {
103
+ fail('publish requires --commit <sha>');
104
+ return;
105
+ }
106
+ if (!['COMMENT', 'APPROVE', 'REQUEST_CHANGES'].includes(event)) {
107
+ fail('publish requires --event <COMMENT|APPROVE|REQUEST_CHANGES>');
108
+ return;
109
+ }
110
+ if (typeof values.bodyFile !== 'string') {
111
+ fail('publish requires --body-file');
112
+ return;
113
+ }
114
+ let body;
115
+ try {
116
+ body = readBodyFile(values.bodyFile, cwd);
117
+ }
118
+ catch (error) {
119
+ fail(`unable to read body file: ${error instanceof Error ? error.message : String(error)}`);
120
+ return;
121
+ }
122
+ finish(publishPrReview({
123
+ cwd,
124
+ prNumber: pr,
125
+ identity: { scope, round, commitSha: commit },
126
+ event: event,
127
+ body,
128
+ dryRun: values.dryRun === true
129
+ }));
130
+ }
131
+ export { platformPrReview };
132
+ //# sourceMappingURL=platform-pr-review.js.map
@@ -1,8 +1,10 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { bindPlatformPullRequest, createPlatformPullRequest, inspectPlatformPullRequest, syncPlatformPullRequest } from '../platform/pull-requests.js';
3
+ import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.js';
4
+ import { bindPlatformPullRequest, createPlatformPullRequest, inspectPlatformPullRequest, resolveExternalPullRequest, syncPlatformPullRequest } from '../platform/pull-requests.js';
4
5
  import { summaryContext, syncPullRequestSummary } from '../platform/pr-summary.js';
5
6
  const USAGE = `Usage: agent-infra-internal platform-pr inspect <task-ref> [--cwd <path>]
7
+ agent-infra-internal platform-pr resolve-external <task-ref> --agent <agent> [--pr <N>] [--dry-run] [--cwd <path>]
6
8
  agent-infra-internal platform-pr create <task-ref> --agent <agent> --base <branch> --head <branch> --title-file <path|-> --body-file <path|-> [--draft] [--dry-run] [--cwd <path>]
7
9
  agent-infra-internal platform-pr bind <task-ref> --pr <N> --agent <agent> [--dry-run] [--cwd <path>]
8
10
  agent-infra-internal platform-pr sync <task-ref> --agent <agent> [--metadata] [--closing-issue] [--dry-run] [--cwd <path>]
@@ -56,7 +58,7 @@ function platformPr(args = []) {
56
58
  return;
57
59
  }
58
60
  const operation = args[0];
59
- if (!operation || !['inspect', 'create', 'bind', 'sync', 'summary-context', 'summary-sync'].includes(operation)) {
61
+ if (!operation || !['inspect', 'resolve-external', 'create', 'bind', 'sync', 'summary-context', 'summary-sync'].includes(operation)) {
60
62
  fail('a valid operation is required');
61
63
  return;
62
64
  }
@@ -74,6 +76,7 @@ function platformPr(args = []) {
74
76
  const cwd = path.resolve(typeof values.cwd === 'string' ? values.cwd : process.cwd());
75
77
  const allowed = {
76
78
  inspect: ['cwd'],
79
+ 'resolve-external': ['cwd', 'agent', 'pr', 'dryRun'],
77
80
  create: ['cwd', 'agent', 'base', 'head', 'titleFile', 'bodyFile', 'draft', 'dryRun'],
78
81
  bind: ['cwd', 'agent', 'pr', 'dryRun'],
79
82
  sync: ['cwd', 'agent', 'metadata', 'closingIssue', 'dryRun'],
@@ -97,6 +100,21 @@ function platformPr(args = []) {
97
100
  fail(`${operation} requires --agent`);
98
101
  return;
99
102
  }
103
+ const agent = normalizeAgentToken(values.agent);
104
+ if (!agent) {
105
+ fail(`invalid --agent '${values.agent}': ${AGENT_USAGE_HINT}`);
106
+ return;
107
+ }
108
+ values.agent = agent;
109
+ if (operation === 'resolve-external') {
110
+ const pr = values.pr === undefined ? undefined : Number(values.pr);
111
+ if (pr !== undefined && (!Number.isInteger(pr) || pr <= 0)) {
112
+ fail('resolve-external requires a positive --pr');
113
+ return;
114
+ }
115
+ finish(resolveExternalPullRequest(taskRef, { cwd, agent: values.agent, pr, dryRun: values.dryRun === true }));
116
+ return;
117
+ }
100
118
  if (operation === 'bind') {
101
119
  const pr = Number(values.pr);
102
120
  if (!Number.isInteger(pr) || pr <= 0) {
@@ -1,9 +1,28 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { publishReleaseNotes, releaseNoteContext } from '../platform/release-notes.js';
4
- function option(args, name) {
5
- const index = args.indexOf(name);
6
- return index >= 0 && args[index + 1] ? args[index + 1] : null;
3
+ import { publishReleaseNotes, releaseNoteContext, stageReleaseNotes } from '../platform/release-notes.js';
4
+ function parseOptions(args, valueFlags, switchFlags = []) {
5
+ const values = new Map();
6
+ const switches = new Set();
7
+ for (let index = 0; index < args.length; index += 1) {
8
+ const flag = args[index];
9
+ if (values.has(flag) || switches.has(flag))
10
+ return null;
11
+ if (switchFlags.includes(flag)) {
12
+ switches.add(flag);
13
+ continue;
14
+ }
15
+ if (!valueFlags.includes(flag))
16
+ return null;
17
+ const value = args[++index];
18
+ if (!value || value.startsWith('--'))
19
+ return null;
20
+ values.set(flag, value);
21
+ }
22
+ return { values, switches };
23
+ }
24
+ function invalidInput(message) {
25
+ return { status: 'failed', changed: false, error: { code: 'RELEASE_NOTES_INPUT_INVALID', message, retryable: false } };
7
26
  }
8
27
  function finish(result) {
9
28
  process.stdout.write(`${JSON.stringify(result)}\n`);
@@ -11,21 +30,37 @@ function finish(result) {
11
30
  }
12
31
  function platformReleaseNotes(args = []) {
13
32
  const [action, ...rest] = args;
14
- const cwd = path.resolve(option(rest, '--cwd') || process.cwd());
15
33
  if (action === 'context') {
16
- const historyRaw = option(rest, '--history-limit');
34
+ const parsed = parseOptions(rest, ['--cwd', '--history-limit', '--from-tag', '--to-tag', '--branch']);
35
+ if (!parsed)
36
+ return finish(invalidInput('invalid context options'));
37
+ const cwd = path.resolve(parsed.values.get('--cwd') || process.cwd());
38
+ const historyRaw = parsed.values.get('--history-limit') ?? null;
17
39
  finish(releaseNoteContext({
18
- fromTag: option(rest, '--from-tag') || '',
19
- toTag: option(rest, '--to-tag') || '',
20
- branch: option(rest, '--branch') || '',
40
+ fromTag: parsed.values.get('--from-tag') || '',
41
+ toTag: parsed.values.get('--to-tag') || '',
42
+ branch: parsed.values.get('--branch') || '',
21
43
  historyLimit: historyRaw === null ? undefined : Number(historyRaw)
22
44
  }, { cwd }));
23
45
  return;
24
46
  }
47
+ if (action === 'stage') {
48
+ const parsed = parseOptions(rest, ['--cwd', '--notes-file']);
49
+ if (!parsed)
50
+ return finish(invalidInput('invalid stage options'));
51
+ const notesFile = parsed.values.get('--notes-file');
52
+ if (!notesFile)
53
+ return finish(invalidInput('notes-file is required'));
54
+ finish(stageReleaseNotes({ notesFile }, { cwd: path.resolve(parsed.values.get('--cwd') || process.cwd()) }));
55
+ return;
56
+ }
25
57
  if (action === 'publish') {
26
- const notesPath = option(rest, '--notes-file');
58
+ const parsed = parseOptions(rest, ['--cwd', '--notes-file', '--tag', '--title', '--expected-sha256'], ['--dry-run']);
59
+ if (!parsed)
60
+ return finish(invalidInput('invalid publish options'));
61
+ const notesPath = parsed.values.get('--notes-file');
27
62
  if (!notesPath) {
28
- finish({ status: 'failed', changed: false, error: { code: 'RELEASE_NOTES_INPUT_INVALID', message: 'notes-file is required', retryable: false } });
63
+ finish(invalidInput('notes-file is required'));
29
64
  return;
30
65
  }
31
66
  let resolvedNotesPath = notesPath;
@@ -35,11 +70,12 @@ function platformReleaseNotes(args = []) {
35
70
  }
36
71
  try {
37
72
  finish(publishReleaseNotes({
38
- tag: option(rest, '--tag') || '',
39
- title: option(rest, '--title') || option(rest, '--tag') || '',
73
+ tag: parsed.values.get('--tag') || '',
74
+ title: parsed.values.get('--title') || parsed.values.get('--tag') || '',
40
75
  notesFile: resolvedNotesPath,
41
- dryRun: rest.includes('--dry-run')
42
- }, { cwd }));
76
+ expectedSha256: parsed.values.get('--expected-sha256') || '',
77
+ dryRun: parsed.switches.has('--dry-run')
78
+ }, { cwd: path.resolve(parsed.values.get('--cwd') || process.cwd()) }));
43
79
  }
44
80
  finally {
45
81
  if (notesPath === '-')
@@ -47,7 +83,7 @@ function platformReleaseNotes(args = []) {
47
83
  }
48
84
  return;
49
85
  }
50
- finish({ status: 'failed', changed: false, error: { code: 'RELEASE_NOTES_INPUT_INVALID', message: 'Usage: platform-release-notes context|publish', retryable: false } });
86
+ finish(invalidInput('Usage: platform-release-notes context|stage|publish'));
51
87
  }
52
88
  export { platformReleaseNotes };
53
89
  //# sourceMappingURL=platform-release-notes.js.map