@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,7 @@
1
1
  import { execFileSync, spawnSync } from "node:child_process";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
2
5
  const SHA_PATTERN = /^[0-9a-f]{40}$/i;
3
6
  function git(cwd, args) {
4
7
  return execFileSync("git", args, {
@@ -29,6 +32,103 @@ function isAncestor(gitRoot, ancestor, descendant) {
29
32
  return { status: "no" };
30
33
  return { status: "error" };
31
34
  }
35
+ function blocked(message) {
36
+ return { status: "blocked", code: "PR_MERGE_GIT_EVIDENCE_UNAVAILABLE", message };
37
+ }
38
+ function resolveUniqueMergeBase(gitRoot, reviewedHead, squashParent) {
39
+ const result = spawnSync("git", ["merge-base", "--all", reviewedHead, squashParent], {
40
+ cwd: gitRoot,
41
+ encoding: "utf8",
42
+ stdio: ["ignore", "pipe", "pipe"]
43
+ });
44
+ if (result.error || result.status === null || result.status > 1) {
45
+ return { status: "blocked", relation: blocked("Unable to compute the reviewed PR merge base") };
46
+ }
47
+ const candidates = result.stdout.trim() === "" ? [] : result.stdout.trim().split(/\s+/);
48
+ if (result.status === 1 || candidates.length !== 1) {
49
+ return {
50
+ status: "failed",
51
+ relation: {
52
+ status: "failed",
53
+ code: "PR_MERGE_TOPOLOGY_INVALID",
54
+ message: "Reviewed head and squash parent do not have a unique merge base"
55
+ }
56
+ };
57
+ }
58
+ const [candidate] = candidates;
59
+ if (!candidate || !SHA_PATTERN.test(candidate)) {
60
+ return { status: "blocked", relation: blocked("Git returned an invalid reviewed PR merge base") };
61
+ }
62
+ return { status: "ok", mergeBase: candidate };
63
+ }
64
+ function compareReplayedTree(input) {
65
+ const { gitRoot, mergeBase, reviewedHead, squashParent, squashCommit } = input;
66
+ let tempDir;
67
+ let relation = null;
68
+ try {
69
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "agent-infra-merge-equivalence-"));
70
+ const env = { ...process.env, GIT_INDEX_FILE: path.join(tempDir, "index") };
71
+ const readTree = spawnSync("git", ["read-tree", squashParent], {
72
+ cwd: gitRoot, env, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"]
73
+ });
74
+ if (readTree.error || readTree.status !== 0) {
75
+ relation = blocked("Unable to initialize isolated squash merge evidence");
76
+ }
77
+ else {
78
+ const patchResult = spawnSync("git", ["diff", "--no-renames", "--binary", "--full-index", mergeBase, reviewedHead], { cwd: gitRoot, env, encoding: "utf8", maxBuffer: 32 * 1024 * 1024, stdio: ["ignore", "pipe", "pipe"] });
79
+ if (patchResult.error || patchResult.status !== 0) {
80
+ relation = blocked("Unable to generate the reviewed PR patch");
81
+ }
82
+ else if (patchResult.stdout !== "") {
83
+ const applyResult = spawnSync("git", ["apply", "--cached", "--3way", "--binary", "-q"], {
84
+ cwd: gitRoot,
85
+ env,
86
+ encoding: "utf8",
87
+ input: patchResult.stdout,
88
+ maxBuffer: 32 * 1024 * 1024,
89
+ stdio: ["pipe", "pipe", "pipe"]
90
+ });
91
+ if (applyResult.status === 1) {
92
+ relation = {
93
+ status: "failed",
94
+ code: "PR_MERGE_CONTENT_MISMATCH",
95
+ message: "Reviewed PR patch cannot be replayed without conflicts, so content equivalence cannot be established"
96
+ };
97
+ }
98
+ else if (applyResult.error || applyResult.status !== 0) {
99
+ relation = blocked("Unable to replay the reviewed PR patch");
100
+ }
101
+ }
102
+ if (relation === null) {
103
+ const compareResult = spawnSync("git", ["diff", "--cached", "--quiet", "--no-ext-diff", squashCommit, "--"], { cwd: gitRoot, env, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
104
+ if (compareResult.status === 1) {
105
+ relation = {
106
+ status: "failed",
107
+ code: "PR_MERGE_CONTENT_MISMATCH",
108
+ message: "Replayed reviewed PR content differs from the squash merge tree"
109
+ };
110
+ }
111
+ else if (compareResult.error || compareResult.status !== 0) {
112
+ relation = blocked("Unable to compare replayed PR content with the squash merge tree");
113
+ }
114
+ }
115
+ }
116
+ }
117
+ catch {
118
+ relation = blocked("Unable to create isolated squash merge evidence");
119
+ }
120
+ finally {
121
+ if (tempDir) {
122
+ try {
123
+ fs.rmSync(tempDir, { recursive: true, force: true });
124
+ }
125
+ catch {
126
+ relation = blocked("Unable to clean up isolated squash merge evidence");
127
+ }
128
+ }
129
+ }
130
+ return relation;
131
+ }
32
132
  export function resolveReviewedHeadRelation(input) {
33
133
  const { gitRoot, comparisonHead, lastReviewedCommit, pullRequest } = input;
34
134
  if (comparisonHead === lastReviewedCommit &&
@@ -64,12 +164,22 @@ export function resolveReviewedHeadRelation(input) {
64
164
  if (parents.length !== 2) {
65
165
  return { status: "failed", code: "PR_MERGE_TOPOLOGY_INVALID", message: "PR merge commit is not a single-parent squash commit" };
66
166
  }
67
- const diffArgs = ["diff", "--no-renames", "--binary", "--full-index"];
68
- const reviewedDiff = git(gitRoot, [...diffArgs, pullRequest.base.sha, pullRequest.head.sha]);
69
- const mergedDiff = git(gitRoot, [...diffArgs, `${pullRequest.mergeCommitSha}^`, pullRequest.mergeCommitSha]);
70
- if (reviewedDiff !== mergedDiff) {
71
- return { status: "failed", code: "PR_MERGE_CONTENT_MISMATCH", message: "Squash merge content differs from the reviewed PR changes" };
167
+ const squashParent = parents[1];
168
+ if (!squashParent) {
169
+ return { status: "failed", code: "PR_MERGE_TOPOLOGY_INVALID", message: "PR merge commit is not a single-parent squash commit" };
72
170
  }
171
+ const mergeBase = resolveUniqueMergeBase(gitRoot, pullRequest.head.sha, squashParent);
172
+ if (mergeBase.status !== "ok")
173
+ return mergeBase.relation;
174
+ const replayFailure = compareReplayedTree({
175
+ gitRoot,
176
+ mergeBase: mergeBase.mergeBase,
177
+ reviewedHead: pullRequest.head.sha,
178
+ squashParent,
179
+ squashCommit: pullRequest.mergeCommitSha
180
+ });
181
+ if (replayFailure)
182
+ return replayFailure;
73
183
  }
74
184
  catch {
75
185
  return { status: "blocked", code: "PR_MERGE_GIT_EVIDENCE_UNAVAILABLE", message: "Unable to verify PR merge topology or content" };
@@ -17,21 +17,14 @@ function classifyRequiredChecks(required) {
17
17
  return { state: 'pending', required };
18
18
  return { state: 'passed', required };
19
19
  }
20
- async function watchRequiredChecks(options) {
21
- const now = options.now || (() => performance.now());
22
- const sleep = options.sleep || ((delay) => new Promise((resolve) => setTimeout(resolve, delay)));
23
- const started = now();
24
- while (true) {
25
- if (options.signal?.aborted)
26
- return { state: 'cancelled', required: [] };
27
- const snapshot = await options.inspect();
28
- if (snapshot.state !== 'pending')
29
- return snapshot;
30
- const elapsed = now() - started;
31
- if (elapsed >= options.deadlineMs)
32
- return { state: 'timed-out', required: snapshot.required };
33
- await sleep(Math.min(options.intervalMs, options.deadlineMs - elapsed));
34
- }
20
+ function classifyPullRequestReadiness(input) {
21
+ if (input.mergeability === 'conflicting')
22
+ return { state: 'conflicting', headSha: input.headSha };
23
+ if (input.checks.state === 'failed' || input.checks.state === 'cancelled')
24
+ return { state: 'checks-failed', headSha: input.headSha };
25
+ if (input.mergeability === 'unknown' || input.checks.state === 'pending')
26
+ return { state: 'pending', headSha: input.headSha };
27
+ return { state: 'ready', headSha: input.headSha };
35
28
  }
36
29
  function parseRunJobIdentity(detailsUrl) {
37
30
  try {
@@ -122,6 +115,9 @@ function inspectRequiredChecks(taskRef, options = {}) {
122
115
  const base = resolvedTask(taskRef, options);
123
116
  if (!base.ok)
124
117
  return base.output;
118
+ return inspectChecksForResolvedTask(base, options);
119
+ }
120
+ function inspectChecksForResolvedTask(base, options) {
125
121
  const repository = base.context.platform.repository;
126
122
  const inspected = inspectPlatformRequiredChecks(base.context.platform.type, {
127
123
  cwd: base.resolved.repoRoot,
@@ -157,33 +153,60 @@ function inspectRequiredChecks(taskRef, options = {}) {
157
153
  }
158
154
  });
159
155
  }
160
- async function watchPlatformChecks(taskRef, options) {
161
- let last = null;
162
- const watched = await watchRequiredChecks({
163
- intervalMs: options.intervalSeconds * 1000,
164
- deadlineMs: options.deadlineSeconds * 1000,
165
- signal: options.signal,
166
- now: options.now,
167
- sleep: options.sleep,
168
- inspect: async () => {
169
- last = inspectRequiredChecks(taskRef, options);
170
- if (last.checks.state === 'pending' && last.error?.code === 'REQUIRED_CHECKS_PENDING')
171
- return last.checks;
172
- return last.checks;
156
+ function inspectPullRequestReadiness(taskRef, options = {}) {
157
+ const base = resolvedTask(taskRef, options);
158
+ if (!base.ok)
159
+ return base.output;
160
+ const checked = inspectChecksForResolvedTask(base, options);
161
+ const classifiedCodes = new Set(['REQUIRED_CHECKS_PENDING', 'REQUIRED_CHECKS_FAILED', 'REQUIRED_CHECKS_CANCELLED']);
162
+ if (checked.error && !classifiedCodes.has(checked.error.code))
163
+ return checked;
164
+ const readiness = classifyPullRequestReadiness({
165
+ headSha: base.pullRequest.head.sha,
166
+ mergeability: base.pullRequest.mergeability?.state ?? 'unknown',
167
+ checks: checked.checks
168
+ });
169
+ const status = readiness.state === 'ready' ? 'no-op'
170
+ : readiness.state === 'conflicting' || readiness.state === 'checks-failed' ? 'failed' : 'blocked';
171
+ return checksResult(status, {
172
+ ...checked,
173
+ status,
174
+ changed: false,
175
+ readiness,
176
+ error: status === 'no-op' ? null : {
177
+ code: readiness.state === 'conflicting' ? 'PR_MERGE_CONFLICT'
178
+ : readiness.state === 'checks-failed' ? 'REQUIRED_CHECKS_FAILED' : 'PR_READINESS_PENDING',
179
+ message: `Pull request readiness is ${readiness.state}`,
180
+ retryable: readiness.state === 'pending'
173
181
  }
174
182
  });
175
- if (!last)
176
- return checksResult('blocked', { checks: watched, error: { code: 'REQUIRED_CHECKS_UNAVAILABLE', message: 'No checks snapshot was produced', retryable: true } });
177
- const snapshot = last;
178
- if (watched.state === 'timed-out' || watched.state === 'cancelled')
179
- return checksResult('blocked', {
180
- ...snapshot,
181
- status: 'blocked',
182
- changed: false,
183
- checks: watched,
184
- error: { code: watched.state === 'timed-out' ? 'REQUIRED_CHECKS_TIMEOUT' : 'REQUIRED_CHECKS_CANCELLED', message: `Required checks ${watched.state}`, retryable: watched.state === 'timed-out' }
185
- });
186
- return { ...snapshot, checks: watched };
183
+ }
184
+ async function watchPullRequestReadiness(taskRef, options) {
185
+ const now = options.now || (() => performance.now());
186
+ const sleep = options.sleep || ((delay) => new Promise((resolve) => setTimeout(resolve, delay)));
187
+ const started = now();
188
+ let last = null;
189
+ while (true) {
190
+ if (options.signal?.aborted)
191
+ return checksResult('blocked', {
192
+ ...last,
193
+ status: 'blocked', changed: false,
194
+ readiness: { state: 'cancelled', headSha: last?.pullRequest?.head.sha ?? '' },
195
+ error: { code: 'PR_READINESS_CANCELLED', message: 'Pull request readiness watch was cancelled', retryable: false }
196
+ });
197
+ last = inspectPullRequestReadiness(taskRef, options);
198
+ if (last.readiness?.state !== 'pending' || last.error?.code !== 'PR_READINESS_PENDING')
199
+ return last;
200
+ const elapsed = now() - started;
201
+ if (elapsed >= options.deadlineSeconds * 1000)
202
+ return checksResult('blocked', {
203
+ ...last,
204
+ status: 'blocked', changed: false,
205
+ readiness: { state: 'timed-out', headSha: last.pullRequest?.head.sha ?? '' },
206
+ error: { code: 'PR_READINESS_TIMEOUT', message: 'Pull request readiness watch timed out', retryable: true }
207
+ });
208
+ await sleep(Math.min(options.intervalSeconds * 1000, options.deadlineSeconds * 1000 - elapsed));
209
+ }
187
210
  }
188
211
  function resolvePlatformCheckRun(taskRef, options) {
189
212
  const base = resolvedTask(taskRef, options);
@@ -240,5 +263,5 @@ function fetchPlatformCheckLogs(taskRef, options) {
240
263
  logs: { runId: options.run, ...(options.job ? { jobId: options.job } : {}), text: fetched.value }, error: null
241
264
  });
242
265
  }
243
- export { classifyRequiredChecks, fetchCheckLogText, fetchPlatformCheckLogs, inspectRequiredChecks, parseRunJobIdentity, resolvePlatformCheckRun, resolveRunCandidate, watchPlatformChecks, watchRequiredChecks };
266
+ export { classifyPullRequestReadiness, classifyRequiredChecks, fetchCheckLogText, fetchPlatformCheckLogs, inspectRequiredChecks, inspectPullRequestReadiness, parseRunJobIdentity, resolvePlatformCheckRun, resolveRunCandidate, watchPullRequestReadiness };
244
267
  //# sourceMappingURL=pr-checks.js.map
@@ -0,0 +1,166 @@
1
+ import { createGitHubClient } from './github-client.js';
2
+ import { resolvePlatformContext } from './context.js';
3
+ import { platformResult } from './types.js';
4
+ const REVIEW_EVENTS = ['COMMENT', 'APPROVE', 'REQUEST_CHANGES'];
5
+ // Marker-safe scope: a task id (`TASK-YYYYMMDD-HHMMSS`) or a bare PR number
6
+ // (`pr{N}`). Any other value (e.g. one containing `\r\n` or `-->`) would break
7
+ // the first-line marker idempotency contract of `reviewMarker` (PL-6).
8
+ const REVIEW_SCOPE_PATTERN = /^(?:pr\d+|TASK-\d{8}-\d{6})$/;
9
+ export function reviewMarker(identity) {
10
+ return `<!-- review-pr:${identity.scope}:r${identity.round} -->`;
11
+ }
12
+ export function reviewedCommitMarker(sha) {
13
+ return `<!-- reviewed-commit: ${sha} -->`;
14
+ }
15
+ function normalizeBody(body) {
16
+ return String(body || '').replace(/\r\n/g, '\n').replace(/\n+$/, '\n');
17
+ }
18
+ function firstLine(body) {
19
+ return normalizeBody(String(body || '')).split('\n', 1)[0] || '';
20
+ }
21
+ function hasUsableContext(context) {
22
+ return (context.status === 'no-op' || context.status === 'degraded') && context.platform.repository !== null;
23
+ }
24
+ function invalidPrNumber(prNumber) {
25
+ return !Number.isInteger(prNumber) || prNumber <= 0;
26
+ }
27
+ export function listPrReviews(prNumber, options = {}) {
28
+ const client = options.client || createGitHubClient();
29
+ const context = resolvePlatformContext({ cwd: options.cwd || process.cwd(), client });
30
+ if (!hasUsableContext(context)) {
31
+ return { ...platformResult(context.status, { platform: context.platform, capabilities: context.capabilities, error: context.error }), reviews: [] };
32
+ }
33
+ const repository = context.platform.repository;
34
+ if (invalidPrNumber(prNumber)) {
35
+ return {
36
+ ...platformResult('failed', {
37
+ platform: context.platform, capabilities: context.capabilities,
38
+ error: { code: 'PR_NUMBER_INVALID', message: 'PR number must be positive', retryable: false }
39
+ }),
40
+ reviews: []
41
+ };
42
+ }
43
+ const fetched = client.json(['api', '--paginate', '--slurp', `repos/${repository}/pulls/${prNumber}/reviews?per_page=100`], { cwd: options.cwd || process.cwd() });
44
+ if (!fetched.ok) {
45
+ return {
46
+ ...platformResult(fetched.error.retryable ? 'blocked' : 'failed', {
47
+ platform: context.platform, capabilities: context.capabilities,
48
+ resource: { kind: 'pull-request', number: prNumber }, error: fetched.error
49
+ }),
50
+ reviews: []
51
+ };
52
+ }
53
+ const flat = (fetched.value || []).flatMap((entry) => Array.isArray(entry) ? entry : [entry]);
54
+ const reviews = flat
55
+ .map((review) => ({
56
+ id: review.id ?? 0,
57
+ commitId: review.commit_id ?? '',
58
+ body: review.body ?? '',
59
+ url: review.html_url ?? ''
60
+ }))
61
+ .filter((review) => review.body !== '');
62
+ return {
63
+ ...platformResult('no-op', {
64
+ platform: context.platform, capabilities: context.capabilities,
65
+ resource: { kind: 'pull-request', number: prNumber }, error: null
66
+ }),
67
+ reviews
68
+ };
69
+ }
70
+ export function publishPrReview(options) {
71
+ const client = options.client || createGitHubClient();
72
+ const context = resolvePlatformContext({ cwd: options.cwd || process.cwd(), client });
73
+ if (!hasUsableContext(context)) {
74
+ return platformResult(context.status, { platform: context.platform, capabilities: context.capabilities, error: context.error });
75
+ }
76
+ const repository = context.platform.repository;
77
+ if (invalidPrNumber(options.prNumber)) {
78
+ return platformResult('failed', {
79
+ platform: context.platform, capabilities: context.capabilities,
80
+ error: { code: 'PR_NUMBER_INVALID', message: 'PR number must be positive', retryable: false }
81
+ });
82
+ }
83
+ if (!REVIEW_EVENTS.includes(options.event)) {
84
+ return platformResult('failed', {
85
+ platform: context.platform, capabilities: context.capabilities,
86
+ resource: { kind: 'pull-request', number: options.prNumber },
87
+ error: { code: 'REVIEW_EVENT_INVALID', message: `review event must be one of ${REVIEW_EVENTS.join('|')}`, retryable: false }
88
+ });
89
+ }
90
+ if (!REVIEW_SCOPE_PATTERN.test(options.identity.scope) || !/^[0-9a-f]{7,40}$/i.test(options.identity.commitSha)) {
91
+ return platformResult('failed', {
92
+ platform: context.platform, capabilities: context.capabilities,
93
+ resource: { kind: 'pull-request', number: options.prNumber },
94
+ error: { code: 'REVIEW_IDENTITY_INVALID', message: 'review scope must be a task id or pr{N}; commitSha is required', retryable: false }
95
+ });
96
+ }
97
+ const marker = reviewMarker(options.identity);
98
+ const listed = listPrReviews(options.prNumber, { cwd: options.cwd, client });
99
+ if (listed.status === 'failed' || listed.status === 'blocked')
100
+ return listed;
101
+ const existing = listed.reviews.find((review) => firstLine(review.body) === marker) ?? null;
102
+ if (existing) {
103
+ if (existing.commitId === options.identity.commitSha) {
104
+ return platformResult('no-op', {
105
+ platform: context.platform, capabilities: context.capabilities,
106
+ resource: { kind: 'pull-request', number: options.prNumber },
107
+ operations: [{ name: 'review:publish', status: 'no-op', reasonCode: null }], error: null
108
+ });
109
+ }
110
+ return platformResult('failed', {
111
+ platform: context.platform, capabilities: context.capabilities,
112
+ resource: { kind: 'pull-request', number: options.prNumber },
113
+ operations: [{ name: 'review:publish', status: 'failed', reasonCode: 'REVIEW_MARKER_CONFLICT' }],
114
+ error: { code: 'REVIEW_MARKER_CONFLICT', message: 'A review with the same marker targets a different commit; start a new round', retryable: false }
115
+ });
116
+ }
117
+ const wrappedBody = [
118
+ marker,
119
+ reviewedCommitMarker(options.identity.commitSha),
120
+ '',
121
+ String(options.body || '').replace(/\r?\n/g, '\n').replace(/\n+$/, ''),
122
+ ''
123
+ ].join('\n');
124
+ if (options.dryRun) {
125
+ return platformResult('planned', {
126
+ platform: context.platform, capabilities: context.capabilities,
127
+ resource: { kind: 'pull-request', number: options.prNumber },
128
+ operations: [{ name: 'review:publish', status: 'planned', reasonCode: null }], error: null
129
+ });
130
+ }
131
+ const posted = client.json(['api', `repos/${repository}/pulls/${options.prNumber}/reviews`, '-X', 'POST', '--input', '-'], {
132
+ cwd: options.cwd || process.cwd(),
133
+ method: 'POST',
134
+ input: JSON.stringify({ commit_id: options.identity.commitSha, body: wrappedBody, event: options.event })
135
+ });
136
+ if (!posted.ok) {
137
+ if (posted.error.retryable) {
138
+ const reconciled = listPrReviews(options.prNumber, { cwd: options.cwd, client });
139
+ const found = reconciled.reviews.find((review) => firstLine(review.body) === marker);
140
+ if (found) {
141
+ return platformResult('applied', {
142
+ changed: true, platform: context.platform, capabilities: context.capabilities,
143
+ resource: { kind: 'pull-request', number: options.prNumber },
144
+ operations: [{ name: 'review:publish', status: 'applied', reasonCode: 'CREATE_RECONCILED' }], error: null
145
+ });
146
+ }
147
+ return platformResult('blocked', {
148
+ platform: context.platform, capabilities: context.capabilities,
149
+ resource: { kind: 'pull-request', number: options.prNumber },
150
+ operations: [{ name: 'review:publish', status: 'failed', reasonCode: 'REVIEW_CREATE_OUTCOME_UNKNOWN' }],
151
+ error: { code: 'REVIEW_CREATE_OUTCOME_UNKNOWN', message: posted.error.message, retryable: true }
152
+ });
153
+ }
154
+ return platformResult('failed', {
155
+ platform: context.platform, capabilities: context.capabilities,
156
+ resource: { kind: 'pull-request', number: options.prNumber },
157
+ operations: [{ name: 'review:publish', status: 'failed', reasonCode: posted.error.code }], error: posted.error
158
+ });
159
+ }
160
+ return platformResult('applied', {
161
+ changed: true, platform: context.platform, capabilities: context.capabilities,
162
+ resource: { kind: 'pull-request', number: options.prNumber },
163
+ operations: [{ name: 'review:publish', status: 'applied', reasonCode: null }], error: null
164
+ });
165
+ }
166
+ //# sourceMappingURL=pr-review.js.map