@fitlab-ai/agent-infra 0.9.1 → 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 (476) hide show
  1. package/README.md +24 -11
  2. package/README.zh-CN.md +24 -11
  3. package/bin/cli.ts +12 -0
  4. package/dist/bin/cli.js +14 -0
  5. package/dist/bin/internal-cli.js +30 -0
  6. package/dist/lib/agent-client.js +163 -0
  7. package/dist/lib/agent-clients/adapter.js +337 -0
  8. package/dist/lib/agent-clients/adapters/antigravity-cli.js +64 -0
  9. package/dist/lib/agent-clients/adapters/claude-code.js +71 -0
  10. package/dist/lib/agent-clients/adapters/codex-sandbox.js +210 -0
  11. package/dist/lib/agent-clients/adapters/codex.js +63 -0
  12. package/dist/lib/agent-clients/adapters/index.js +20 -0
  13. package/dist/lib/agent-clients/adapters/opencode.js +73 -0
  14. package/dist/lib/agent-clients/config.js +215 -0
  15. package/dist/lib/agent-clients/custom-tuis.js +99 -0
  16. package/dist/lib/agent-clients/invocation.js +9 -0
  17. package/dist/lib/agent-clients/next-steps.js +47 -0
  18. package/dist/lib/agent-clients/project-assets.js +45 -0
  19. package/dist/lib/agent-clients/reconcile.js +236 -0
  20. package/dist/lib/agent-clients/registry.js +78 -0
  21. package/dist/lib/agent-clients/schema.js +75 -0
  22. package/dist/lib/agent-clients/tokens.js +49 -0
  23. package/dist/lib/agent-clients/types.js +29 -0
  24. package/dist/lib/builtin-tuis.js +9 -14
  25. package/dist/lib/defaults.json +85 -73
  26. package/dist/lib/git/review-snapshot.js +25 -10
  27. package/dist/lib/git/reviewed-commit-equivalence.js +110 -0
  28. package/dist/lib/git/workflow.js +54 -1
  29. package/dist/lib/init.js +47 -91
  30. package/dist/lib/internal/agent-client.js +174 -0
  31. package/dist/lib/internal/git-workflow.js +7 -2
  32. package/dist/lib/internal/platform-checks.js +3 -3
  33. package/dist/lib/internal/platform-comment.js +29 -2
  34. package/dist/lib/internal/platform-issue.js +7 -0
  35. package/dist/lib/internal/platform-pr-review.js +132 -0
  36. package/dist/lib/internal/platform-pr.js +20 -2
  37. package/dist/lib/internal/platform-release-notes.js +52 -16
  38. package/dist/lib/internal/pr-review-grade.js +140 -0
  39. package/dist/lib/internal/release-workflow.js +82 -20
  40. package/dist/lib/internal/task-activity.js +73 -0
  41. package/dist/lib/internal/task-event.js +17 -1
  42. package/dist/lib/internal/task-lifecycle.js +7 -0
  43. package/dist/lib/internal/task-orchestration.js +196 -0
  44. package/dist/lib/internal/task-review.js +70 -0
  45. package/dist/lib/merge.js +2 -1
  46. package/dist/lib/platform/adapters.js +45 -1
  47. package/dist/lib/platform/change-request-git-evidence.js +113 -0
  48. package/dist/lib/platform/completion-backfill.js +122 -0
  49. package/dist/lib/platform/issue-comments.js +3 -2
  50. package/dist/lib/platform/merged-pr-equivalence.js +156 -16
  51. package/dist/lib/platform/pr-checks.js +101 -50
  52. package/dist/lib/platform/pr-review.js +166 -0
  53. package/dist/lib/platform/pull-requests.js +432 -7
  54. package/dist/lib/platform/release-notes.js +85 -3
  55. package/dist/lib/platform/releases.js +1 -1
  56. package/dist/lib/platform/verification-required.js +8 -10
  57. package/dist/lib/pr-review/evidence-grading.js +229 -0
  58. package/dist/lib/prompt.js +15 -3
  59. package/dist/lib/release/channels.js +4 -1
  60. package/dist/lib/release/workflow.js +4 -2
  61. package/dist/lib/remove-dir.js +25 -0
  62. package/dist/lib/run/tui.js +11 -7
  63. package/dist/lib/sandbox/agent-client-reconciler.js +234 -0
  64. package/dist/lib/sandbox/clipboard/linux.js +2 -1
  65. package/dist/lib/sandbox/commands/create.js +76 -200
  66. package/dist/lib/sandbox/commands/enter.js +17 -1
  67. package/dist/lib/sandbox/commands/prune.js +2 -2
  68. package/dist/lib/sandbox/commands/rm.js +3 -2
  69. package/dist/lib/sandbox/commands/show.js +1 -1
  70. package/dist/lib/sandbox/config.js +21 -4
  71. package/dist/lib/sandbox/constants.js +3 -0
  72. package/dist/lib/sandbox/dockerfile.js +2 -1
  73. package/dist/lib/sandbox/managed-fs.js +10 -5
  74. package/dist/lib/sandbox/recovery.js +52 -36
  75. package/dist/lib/sandbox/shell.js +1 -1
  76. package/dist/lib/sandbox/tool-types.js +8 -0
  77. package/dist/lib/sandbox/tools.js +2 -126
  78. package/dist/lib/task/activity-intent.js +101 -0
  79. package/dist/lib/task/artifact-lifecycle.js +3 -50
  80. package/dist/lib/task/commands/decisions.js +50 -20
  81. package/dist/lib/task/commands/log.js +15 -14
  82. package/dist/lib/task/delegation-receipts.js +128 -0
  83. package/dist/lib/task/events.js +146 -8
  84. package/dist/lib/task/finalization-artifacts.js +35 -0
  85. package/dist/lib/task/lifecycle-execution.js +46 -0
  86. package/dist/lib/task/orchestration.js +784 -0
  87. package/dist/lib/task/review-artifacts.js +143 -59
  88. package/dist/lib/task/review-finalization.js +186 -0
  89. package/dist/lib/task/review-fingerprint.js +4 -0
  90. package/dist/lib/task/task-execution-lock.js +231 -0
  91. package/dist/lib/task/verification-checks.js +2 -1
  92. package/dist/lib/task/verification-engine.js +372 -28
  93. package/dist/lib/task/verification-review.js +1 -1
  94. package/dist/lib/task/verification.js +5 -2
  95. package/dist/lib/task/workspace-snapshot.js +46 -0
  96. package/dist/lib/update.js +42 -161
  97. package/lib/agent-client.ts +214 -0
  98. package/lib/agent-clients/adapter.ts +534 -0
  99. package/lib/agent-clients/adapters/antigravity-cli.ts +65 -0
  100. package/lib/agent-clients/adapters/claude-code.ts +79 -0
  101. package/lib/agent-clients/adapters/codex-sandbox.ts +245 -0
  102. package/lib/agent-clients/adapters/codex.ts +67 -0
  103. package/lib/agent-clients/adapters/index.ts +27 -0
  104. package/lib/agent-clients/adapters/opencode.ts +75 -0
  105. package/lib/agent-clients/config.ts +323 -0
  106. package/lib/agent-clients/custom-tuis.ts +149 -0
  107. package/lib/agent-clients/invocation.ts +19 -0
  108. package/lib/agent-clients/next-steps.ts +85 -0
  109. package/lib/agent-clients/project-assets.ts +96 -0
  110. package/lib/agent-clients/reconcile.ts +325 -0
  111. package/lib/agent-clients/registry.ts +154 -0
  112. package/lib/agent-clients/schema.ts +80 -0
  113. package/lib/agent-clients/tokens.ts +53 -0
  114. package/lib/agent-clients/types.ts +92 -0
  115. package/lib/benchmark/schemas/v1.0.0/case-manifest.schema.json +120 -0
  116. package/lib/benchmark/schemas/v1.0.0/common.schema.json +109 -0
  117. package/lib/benchmark/schemas/v1.0.0/grader-result.schema.json +160 -0
  118. package/lib/benchmark/schemas/v1.0.0/run-manifest.schema.json +122 -0
  119. package/lib/benchmark/schemas/v1.0.0/subject.schema.json +227 -0
  120. package/lib/builtin-tuis.ts +16 -15
  121. package/lib/defaults.json +24 -12
  122. package/lib/git/review-snapshot.ts +39 -9
  123. package/lib/git/reviewed-commit-equivalence.ts +135 -0
  124. package/lib/git/workflow.ts +66 -2
  125. package/lib/init.ts +53 -121
  126. package/lib/internal/agent-client.ts +186 -0
  127. package/lib/internal/git-workflow.ts +6 -2
  128. package/lib/internal/platform-checks.ts +4 -4
  129. package/lib/internal/platform-comment.ts +17 -2
  130. package/lib/internal/platform-issue.ts +4 -0
  131. package/lib/internal/platform-pr-review.ts +104 -0
  132. package/lib/internal/platform-pr.ts +14 -1
  133. package/lib/internal/platform-release-notes.ts +59 -16
  134. package/lib/internal/pr-review-grade.ts +130 -0
  135. package/lib/internal/release-workflow.ts +79 -20
  136. package/lib/internal/task-activity.ts +55 -0
  137. package/lib/internal/task-event.ts +9 -1
  138. package/lib/internal/task-lifecycle.ts +4 -0
  139. package/lib/internal/task-orchestration.ts +171 -0
  140. package/lib/internal/task-review.ts +70 -0
  141. package/lib/merge.ts +2 -1
  142. package/lib/platform/adapters.ts +169 -3
  143. package/lib/platform/change-request-git-evidence.ts +159 -0
  144. package/lib/platform/completion-backfill.ts +134 -0
  145. package/lib/platform/issue-comments.ts +3 -2
  146. package/lib/platform/merged-pr-equivalence.ts +178 -19
  147. package/lib/platform/pr-checks.ts +121 -66
  148. package/lib/platform/pr-review.ts +201 -0
  149. package/lib/platform/pull-requests.ts +529 -27
  150. package/lib/platform/release-notes.ts +100 -4
  151. package/lib/platform/releases.ts +1 -1
  152. package/lib/platform/verification-required.ts +12 -10
  153. package/lib/pr-review/evidence-grading.ts +318 -0
  154. package/lib/prompt.ts +16 -3
  155. package/lib/release/channels.ts +4 -1
  156. package/lib/release/workflow.ts +4 -3
  157. package/lib/remove-dir.ts +28 -0
  158. package/lib/run/tui.ts +12 -5
  159. package/lib/sandbox/agent-client-reconciler.ts +378 -0
  160. package/lib/sandbox/clipboard/linux.ts +2 -1
  161. package/lib/sandbox/commands/create.ts +111 -212
  162. package/lib/sandbox/commands/enter.ts +23 -1
  163. package/lib/sandbox/commands/prune.ts +2 -2
  164. package/lib/sandbox/commands/rm.ts +3 -2
  165. package/lib/sandbox/commands/show.ts +1 -1
  166. package/lib/sandbox/config.ts +31 -4
  167. package/lib/sandbox/constants.ts +6 -0
  168. package/lib/sandbox/dockerfile.ts +2 -1
  169. package/lib/sandbox/managed-fs.ts +18 -5
  170. package/lib/sandbox/recovery.ts +98 -67
  171. package/lib/sandbox/shell.ts +1 -1
  172. package/lib/sandbox/tool-types.ts +143 -0
  173. package/lib/sandbox/tools.ts +5 -157
  174. package/lib/server/server.schema.json +2 -2
  175. package/lib/task/activity-intent.ts +128 -0
  176. package/lib/task/artifact-lifecycle.ts +3 -39
  177. package/lib/task/commands/decisions.ts +53 -20
  178. package/lib/task/commands/log.ts +15 -14
  179. package/lib/task/delegation-receipts.ts +199 -0
  180. package/lib/task/events.ts +164 -11
  181. package/lib/task/finalization-artifacts.ts +58 -0
  182. package/lib/task/lifecycle-execution.ts +106 -0
  183. package/lib/task/orchestration.ts +1022 -0
  184. package/lib/task/review-artifacts.ts +201 -69
  185. package/lib/task/review-finalization.ts +306 -0
  186. package/lib/task/review-fingerprint.ts +5 -0
  187. package/lib/task/task-execution-lock.ts +296 -0
  188. package/lib/task/verification-checks.ts +2 -1
  189. package/lib/task/verification-engine.ts +424 -28
  190. package/lib/task/verification-review.ts +1 -0
  191. package/lib/task/verification.ts +8 -3
  192. package/lib/task/workspace-snapshot.ts +57 -0
  193. package/lib/update.ts +48 -184
  194. package/package.json +4 -4
  195. package/templates/.agents/QUICKSTART.en.md +25 -8
  196. package/templates/.agents/QUICKSTART.zh-CN.md +25 -8
  197. package/templates/.agents/README.en.md +29 -25
  198. package/templates/.agents/README.zh-CN.md +29 -25
  199. package/templates/.agents/hooks/lifecycle-delegation.js +75 -0
  200. package/templates/.agents/rules/README.en.md +2 -0
  201. package/templates/.agents/rules/README.zh-CN.md +2 -0
  202. package/templates/.agents/rules/commit-and-pr.en.md +1 -0
  203. package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -0
  204. package/templates/.agents/rules/create-issue.github.en.md +4 -2
  205. package/templates/.agents/rules/create-issue.github.zh-CN.md +4 -2
  206. package/templates/.agents/rules/human-decision-context.en.md +14 -12
  207. package/templates/.agents/rules/human-decision-context.zh-CN.md +14 -12
  208. package/templates/.agents/rules/issue-fields.github.en.md +3 -1
  209. package/templates/.agents/rules/issue-fields.github.zh-CN.md +3 -1
  210. package/templates/.agents/rules/issue-pr-commands.en.md +5 -3
  211. package/templates/.agents/rules/issue-pr-commands.github.en.md +5 -3
  212. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +5 -3
  213. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +5 -3
  214. package/templates/.agents/rules/issue-sync.github.en.md +7 -3
  215. package/templates/.agents/rules/issue-sync.github.zh-CN.md +8 -4
  216. package/templates/.agents/rules/lifecycle-orchestration.en.md +24 -0
  217. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +24 -0
  218. package/templates/.agents/rules/milestone-inference.github.en.md +4 -2
  219. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +4 -2
  220. package/templates/.agents/rules/next-step-output.en.md +18 -0
  221. package/templates/.agents/rules/next-step-output.zh-CN.md +18 -0
  222. package/templates/.agents/rules/no-mid-flow-questions.en.md +19 -0
  223. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +19 -0
  224. package/templates/.agents/rules/pr-checks-commands.en.md +3 -3
  225. package/templates/.agents/rules/pr-checks-commands.github.en.md +2 -2
  226. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +2 -2
  227. package/templates/.agents/rules/pr-checks-commands.zh-CN.md +3 -3
  228. package/templates/.agents/rules/pr-sync.en.md +3 -1
  229. package/templates/.agents/rules/pr-sync.github.en.md +11 -1
  230. package/templates/.agents/rules/pr-sync.github.zh-CN.md +11 -1
  231. package/templates/.agents/rules/pr-sync.zh-CN.md +3 -1
  232. package/templates/.agents/rules/release-commands.en.md +1 -1
  233. package/templates/.agents/rules/release-commands.github.en.md +21 -5
  234. package/templates/.agents/rules/release-commands.github.zh-CN.md +21 -5
  235. package/templates/.agents/rules/release-commands.zh-CN.md +1 -1
  236. package/templates/.agents/rules/review-handshake.en.md +4 -4
  237. package/templates/.agents/rules/review-handshake.zh-CN.md +4 -4
  238. package/templates/.agents/rules/review-method.en.md +113 -0
  239. package/templates/.agents/rules/review-method.zh-CN.md +98 -0
  240. package/templates/.agents/rules/task-management.en.md +11 -0
  241. package/templates/.agents/rules/task-management.zh-CN.md +11 -0
  242. package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -12
  243. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +15 -12
  244. package/templates/.agents/skills/block-task/SKILL.en.md +11 -9
  245. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +11 -9
  246. package/templates/.agents/skills/cancel-task/SKILL.en.md +10 -8
  247. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +11 -9
  248. package/templates/.agents/skills/check-task/SKILL.en.md +16 -16
  249. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -16
  250. package/templates/.agents/skills/close-codescan/SKILL.en.md +7 -5
  251. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +7 -5
  252. package/templates/.agents/skills/close-dependabot/SKILL.en.md +7 -5
  253. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +7 -5
  254. package/templates/.agents/skills/code-task/SKILL.en.md +10 -7
  255. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +13 -10
  256. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +14 -16
  257. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +14 -16
  258. package/templates/.agents/skills/code-task/reference/output-template.en.md +3 -3
  259. package/templates/.agents/skills/code-task/reference/output-template.zh-CN.md +3 -3
  260. package/templates/.agents/skills/commit/SKILL.en.md +13 -1
  261. package/templates/.agents/skills/commit/SKILL.zh-CN.md +13 -1
  262. package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -1
  263. package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -1
  264. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
  265. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
  266. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  267. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  268. package/templates/.agents/skills/commit/reference/task-status-update.en.md +24 -28
  269. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +24 -28
  270. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +6 -4
  271. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +6 -4
  272. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +1 -1
  273. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
  274. package/templates/.agents/skills/complete-task/SKILL.en.md +23 -8
  275. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +23 -8
  276. package/templates/.agents/skills/complete-task/config/verify.en.json +1 -0
  277. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +1 -0
  278. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +17 -0
  279. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +17 -0
  280. package/templates/.agents/skills/create-pr/SKILL.en.md +13 -11
  281. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +13 -11
  282. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +1 -1
  283. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +1 -1
  284. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +3 -3
  285. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +3 -3
  286. package/templates/.agents/skills/create-release-note/SKILL.en.md +17 -16
  287. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +17 -16
  288. package/templates/.agents/skills/create-task/SKILL.en.md +16 -14
  289. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +16 -14
  290. package/templates/.agents/skills/import-codescan/SKILL.en.md +5 -5
  291. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +5 -5
  292. package/templates/.agents/skills/import-dependabot/SKILL.en.md +5 -5
  293. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +5 -5
  294. package/templates/.agents/skills/import-issue/SKILL.en.md +10 -8
  295. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +10 -8
  296. package/templates/.agents/skills/init-labels/SKILL.en.md +4 -4
  297. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +4 -4
  298. package/templates/.agents/skills/init-milestones/SKILL.en.md +4 -4
  299. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +4 -4
  300. package/templates/.agents/skills/plan-task/SKILL.en.md +13 -10
  301. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +13 -10
  302. package/templates/.agents/skills/post-release/SKILL.en.md +2 -0
  303. package/templates/.agents/skills/post-release/SKILL.zh-CN.md +2 -0
  304. package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
  305. package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
  306. package/templates/.agents/skills/release/SKILL.en.md +16 -10
  307. package/templates/.agents/skills/release/SKILL.zh-CN.md +16 -10
  308. package/templates/.agents/skills/restore-task/SKILL.en.md +4 -1
  309. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +4 -1
  310. package/templates/.agents/skills/review-analysis/SKILL.en.md +18 -4
  311. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +19 -5
  312. package/templates/.agents/skills/review-analysis/config/verify.en.json +6 -0
  313. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +6 -0
  314. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +13 -15
  315. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +13 -15
  316. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +51 -5
  317. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +52 -6
  318. package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +25 -22
  319. package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +25 -22
  320. package/templates/.agents/skills/review-code/SKILL.en.md +35 -12
  321. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +35 -12
  322. package/templates/.agents/skills/review-code/config/verify.en.json +7 -0
  323. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +7 -0
  324. package/templates/.agents/skills/review-code/reference/concurrency-risks.en.md +25 -0
  325. package/templates/.agents/skills/review-code/reference/concurrency-risks.zh-CN.md +25 -0
  326. package/templates/.agents/skills/review-code/reference/cross-platform-risks.en.md +27 -0
  327. package/templates/.agents/skills/review-code/reference/cross-platform-risks.zh-CN.md +27 -0
  328. package/templates/.agents/skills/review-code/reference/documentation-antipatterns.en.md +13 -0
  329. package/templates/.agents/skills/review-code/reference/documentation-antipatterns.zh-CN.md +13 -0
  330. package/templates/.agents/skills/review-code/reference/migration-risks.en.md +25 -0
  331. package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +25 -0
  332. package/templates/.agents/skills/review-code/reference/output-templates.en.md +22 -24
  333. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +22 -24
  334. package/templates/.agents/skills/review-code/reference/report-template.en.md +54 -7
  335. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +54 -7
  336. package/templates/.agents/skills/review-code/reference/review-criteria.en.md +29 -24
  337. package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +29 -24
  338. package/templates/.agents/skills/review-code/reference/security-risks.en.md +25 -0
  339. package/templates/.agents/skills/review-code/reference/security-risks.zh-CN.md +25 -0
  340. package/templates/.agents/skills/review-plan/SKILL.en.md +18 -4
  341. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +19 -5
  342. package/templates/.agents/skills/review-plan/config/verify.en.json +6 -0
  343. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +6 -0
  344. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +13 -15
  345. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +13 -15
  346. package/templates/.agents/skills/review-plan/reference/report-template.en.md +61 -5
  347. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +61 -5
  348. package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +21 -24
  349. package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +21 -24
  350. package/templates/.agents/skills/review-pr/SKILL.en.md +158 -0
  351. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +158 -0
  352. package/templates/.agents/skills/review-pr/config/verify.en.json +37 -0
  353. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +37 -0
  354. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +65 -0
  355. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +65 -0
  356. package/templates/.agents/skills/review-pr/reference/output-guidance.en.md +18 -0
  357. package/templates/.agents/skills/review-pr/reference/output-guidance.zh-CN.md +18 -0
  358. package/templates/.agents/skills/review-pr/reference/report-template.en.md +85 -0
  359. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +85 -0
  360. package/templates/.agents/skills/run-task/SKILL.en.md +22 -0
  361. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +22 -0
  362. package/templates/.agents/skills/run-task/config/verify.en.json +10 -0
  363. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +10 -0
  364. package/templates/.agents/skills/run-task/reference/host-validation.en.md +20 -0
  365. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +20 -0
  366. package/templates/.agents/skills/test/SKILL.en.md +4 -4
  367. package/templates/.agents/skills/test/SKILL.zh-CN.md +4 -4
  368. package/templates/.agents/skills/test-integration/SKILL.en.md +4 -4
  369. package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +4 -4
  370. package/templates/.agents/skills/update-agent-infra/SKILL.en.md +5 -5
  371. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +5 -5
  372. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +664 -246
  373. package/templates/.agents/skills/upgrade-dependency/SKILL.en.md +4 -4
  374. package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +4 -4
  375. package/templates/.agents/skills/watch-pr/SKILL.en.md +21 -21
  376. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +21 -21
  377. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +27 -6
  378. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +26 -5
  379. package/templates/.agents/templates/task.en.md +1 -1
  380. package/templates/.agents/templates/task.zh-CN.md +1 -1
  381. package/templates/.agents/workflows/bug-fix.en.yaml +3 -3
  382. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +3 -3
  383. package/templates/.agents/workflows/code-review.en.yaml +1 -1
  384. package/templates/.agents/workflows/code-review.zh-CN.yaml +1 -1
  385. package/templates/.agents/workflows/feature-development.en.yaml +4 -4
  386. package/templates/.agents/workflows/feature-development.zh-CN.yaml +4 -4
  387. package/templates/.agents/workflows/refactoring.en.yaml +3 -3
  388. package/templates/.agents/workflows/refactoring.zh-CN.yaml +3 -3
  389. package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +6 -0
  390. package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +6 -0
  391. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +6 -0
  392. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +6 -0
  393. package/templates/.claude/commands/post-release.en.md +1 -0
  394. package/templates/.claude/commands/post-release.zh-CN.md +1 -0
  395. package/templates/.claude/commands/review-pr.en.md +8 -0
  396. package/templates/.claude/commands/review-pr.zh-CN.md +8 -0
  397. package/templates/.claude/commands/run-task.en.md +8 -0
  398. package/templates/.claude/commands/run-task.zh-CN.md +8 -0
  399. package/templates/.claude/settings.json +24 -0
  400. package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +3 -0
  401. package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +3 -0
  402. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +3 -0
  403. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +3 -0
  404. package/templates/.gemini/commands/_project_/review-pr.en.toml +10 -0
  405. package/templates/.gemini/commands/_project_/review-pr.zh-CN.toml +10 -0
  406. package/templates/.opencode/commands/post-release.en.md +2 -0
  407. package/templates/.opencode/commands/post-release.zh-CN.md +2 -0
  408. package/templates/.opencode/commands/review-pr.en.md +11 -0
  409. package/templates/.opencode/commands/review-pr.zh-CN.md +11 -0
  410. package/templates/.opencode/commands/run-task.en.md +11 -0
  411. package/templates/.opencode/commands/run-task.zh-CN.md +11 -0
  412. package/templates/.gemini/commands/_project_/analyze-task.en.toml +0 -10
  413. package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +0 -10
  414. package/templates/.gemini/commands/_project_/archive-tasks.en.toml +0 -10
  415. package/templates/.gemini/commands/_project_/archive-tasks.zh-CN.toml +0 -10
  416. package/templates/.gemini/commands/_project_/block-task.en.toml +0 -10
  417. package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +0 -10
  418. package/templates/.gemini/commands/_project_/cancel-task.en.toml +0 -10
  419. package/templates/.gemini/commands/_project_/cancel-task.zh-CN.toml +0 -10
  420. package/templates/.gemini/commands/_project_/check-task.en.toml +0 -10
  421. package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +0 -10
  422. package/templates/.gemini/commands/_project_/close-codescan.en.toml +0 -8
  423. package/templates/.gemini/commands/_project_/close-codescan.zh-CN.toml +0 -8
  424. package/templates/.gemini/commands/_project_/close-dependabot.en.toml +0 -8
  425. package/templates/.gemini/commands/_project_/close-dependabot.zh-CN.toml +0 -8
  426. package/templates/.gemini/commands/_project_/code-task.en.toml +0 -10
  427. package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +0 -10
  428. package/templates/.gemini/commands/_project_/commit.en.toml +0 -10
  429. package/templates/.gemini/commands/_project_/commit.zh-CN.toml +0 -10
  430. package/templates/.gemini/commands/_project_/complete-manual-validation.en.toml +0 -10
  431. package/templates/.gemini/commands/_project_/complete-manual-validation.zh-CN.toml +0 -10
  432. package/templates/.gemini/commands/_project_/complete-task.en.toml +0 -10
  433. package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +0 -10
  434. package/templates/.gemini/commands/_project_/create-pr.en.toml +0 -10
  435. package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +0 -10
  436. package/templates/.gemini/commands/_project_/create-release-note.en.toml +0 -8
  437. package/templates/.gemini/commands/_project_/create-release-note.zh-CN.toml +0 -8
  438. package/templates/.gemini/commands/_project_/create-task.en.toml +0 -8
  439. package/templates/.gemini/commands/_project_/create-task.zh-CN.toml +0 -8
  440. package/templates/.gemini/commands/_project_/import-codescan.en.toml +0 -8
  441. package/templates/.gemini/commands/_project_/import-codescan.zh-CN.toml +0 -8
  442. package/templates/.gemini/commands/_project_/import-dependabot.en.toml +0 -8
  443. package/templates/.gemini/commands/_project_/import-dependabot.zh-CN.toml +0 -8
  444. package/templates/.gemini/commands/_project_/import-issue.en.toml +0 -8
  445. package/templates/.gemini/commands/_project_/import-issue.zh-CN.toml +0 -8
  446. package/templates/.gemini/commands/_project_/init-labels.en.toml +0 -8
  447. package/templates/.gemini/commands/_project_/init-labels.zh-CN.toml +0 -8
  448. package/templates/.gemini/commands/_project_/init-milestones.en.toml +0 -10
  449. package/templates/.gemini/commands/_project_/init-milestones.zh-CN.toml +0 -10
  450. package/templates/.gemini/commands/_project_/plan-task.en.toml +0 -10
  451. package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +0 -10
  452. package/templates/.gemini/commands/_project_/post-release.en.toml +0 -6
  453. package/templates/.gemini/commands/_project_/post-release.zh-CN.toml +0 -6
  454. package/templates/.gemini/commands/_project_/refine-title.en.toml +0 -8
  455. package/templates/.gemini/commands/_project_/refine-title.zh-CN.toml +0 -8
  456. package/templates/.gemini/commands/_project_/release.en.toml +0 -8
  457. package/templates/.gemini/commands/_project_/release.zh-CN.toml +0 -8
  458. package/templates/.gemini/commands/_project_/restore-task.en.toml +0 -8
  459. package/templates/.gemini/commands/_project_/restore-task.zh-CN.toml +0 -8
  460. package/templates/.gemini/commands/_project_/review-analysis.en.toml +0 -10
  461. package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +0 -10
  462. package/templates/.gemini/commands/_project_/review-code.en.toml +0 -10
  463. package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +0 -10
  464. package/templates/.gemini/commands/_project_/review-plan.en.toml +0 -10
  465. package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +0 -10
  466. package/templates/.gemini/commands/_project_/test-integration.en.toml +0 -6
  467. package/templates/.gemini/commands/_project_/test-integration.zh-CN.toml +0 -6
  468. package/templates/.gemini/commands/_project_/test.en.toml +0 -6
  469. package/templates/.gemini/commands/_project_/test.zh-CN.toml +0 -6
  470. package/templates/.gemini/commands/_project_/update-agent-infra.en.toml +0 -6
  471. package/templates/.gemini/commands/_project_/update-agent-infra.zh-CN.toml +0 -6
  472. package/templates/.gemini/commands/_project_/upgrade-dependency.en.toml +0 -8
  473. package/templates/.gemini/commands/_project_/upgrade-dependency.zh-CN.toml +0 -8
  474. package/templates/.gemini/commands/_project_/watch-pr.en.toml +0 -10
  475. package/templates/.gemini/commands/_project_/watch-pr.zh-CN.toml +0 -10
  476. package/templates/.gemini/settings.json +0 -3
@@ -1,39 +1,32 @@
1
1
  import fs from 'node:fs';
2
+ import { execFileSync } from 'node:child_process';
2
3
 
3
4
  import { parseTaskFrontmatter } from '../task/frontmatter.ts';
4
5
  import { resolveTaskRef } from '../task/resolve-ref.ts';
5
6
  import { extractSection } from '../task/sections.ts';
6
7
  import { captureTaskWriteMetadata, writeTask } from '../task/write.ts';
7
- import { resolvePlatformContext } from './context.ts';
8
+ import {
9
+ inspectPlatformChangeRequest,
10
+ inspectPlatformIssueClosingChangeRequests,
11
+ registerPlatformCapabilities
12
+ } from './adapters.ts';
13
+ import type { PlatformChangeRequestSnapshot } from './adapters.ts';
14
+ import { parseGitHubRemote, resolvePlatformContext } from './context.ts';
8
15
  import { createGitHubClient } from './github-client.ts';
9
16
  import type { GitHubClient } from './github-client.ts';
10
17
  import { inspectPlatformIssue } from './issues.ts';
11
18
  import { planPullRequestMetadata } from './pull-request-metadata.ts';
12
19
  import { platformResult } from './types.ts';
13
20
  import type { PlatformOperation, PlatformResult } from './types.ts';
21
+ import { inspectCompletionArtifacts } from '../task/finalization-artifacts.ts';
14
22
 
15
- type PullRequestSnapshot = {
16
- repository: string;
17
- number: number;
18
- nodeId: string;
19
- url: string;
20
- state: 'open' | 'closed';
21
- title: string;
22
- body: string;
23
- draft: boolean;
24
- head: { repository: string; ref: string; sha: string };
25
- base: { repository: string; ref: string; sha: string };
26
- mergedAt: string | null;
27
- mergeCommitSha: string | null;
28
- labels: string[];
29
- assignees: string[];
30
- milestone: string | null;
31
- };
23
+ type PullRequestSnapshot = PlatformChangeRequestSnapshot;
32
24
 
33
25
  type PullRequestResult = PlatformResult & {
34
26
  task: { id: string | null; issueNumber: number | null; prNumber: number | null };
35
27
  pullRequest: PullRequestSnapshot | null;
36
28
  };
29
+ type InspectionOptions = { cwd?: string; client?: unknown };
37
30
  type SharedOptions = { cwd?: string; client?: GitHubClient };
38
31
  type CreateOptions = SharedOptions & {
39
32
  agent: string;
@@ -46,6 +39,18 @@ type CreateOptions = SharedOptions & {
46
39
  };
47
40
  type BindOptions = SharedOptions & { agent: string; pr: number; dryRun?: boolean };
48
41
  type SyncOptions = SharedOptions & { agent: string; metadata?: boolean; closingIssue?: boolean; dryRun?: boolean };
42
+ type ResolveExternalOptions = SharedOptions & { agent: string; pr?: number; dryRun?: boolean };
43
+ type ExternalPullRequestSelection =
44
+ | { status: 'normal'; candidates: PullRequestSnapshot[]; eligible: [] }
45
+ | { status: 'selected'; source: 'unique' | 'explicit'; selected: PullRequestSnapshot; candidates: PullRequestSnapshot[]; eligible: PullRequestSnapshot[] }
46
+ | { status: 'failed'; code: string; message: string; candidates: PullRequestSnapshot[]; eligible: PullRequestSnapshot[] };
47
+ type ExternalPullRequestResult = PullRequestResult & {
48
+ mode: 'normal' | 'external' | null;
49
+ authorization: 'unique' | 'explicit' | null;
50
+ candidates: PullRequestSnapshot[];
51
+ eligible: PullRequestSnapshot[];
52
+ selected: PullRequestSnapshot | null;
53
+ };
49
54
 
50
55
  type RemotePullRequest = {
51
56
  number?: number;
@@ -63,6 +68,36 @@ type RemotePullRequest = {
63
68
  labels?: Array<string | { name?: string }>;
64
69
  assignees?: Array<{ login?: string }>;
65
70
  milestone?: { title?: string } | null;
71
+ mergeable?: boolean | null;
72
+ mergeable_state?: string | null;
73
+ };
74
+
75
+ type ClosingPullRequestNode = {
76
+ number?: number;
77
+ id?: string;
78
+ url?: string;
79
+ state?: string;
80
+ title?: string;
81
+ body?: string | null;
82
+ isDraft?: boolean;
83
+ headRefName?: string;
84
+ headRefOid?: string;
85
+ headRepository?: { nameWithOwner?: string } | null;
86
+ baseRefName?: string;
87
+ baseRefOid?: string;
88
+ baseRepository?: { nameWithOwner?: string } | null;
89
+ mergedAt?: string | null;
90
+ mergeCommit?: { oid?: string } | null;
91
+ labels?: { nodes?: Array<{ name?: string }> };
92
+ assignees?: { nodes?: Array<{ login?: string }> };
93
+ milestone?: { title?: string } | null;
94
+ };
95
+
96
+ type ClosingPullRequestPage = {
97
+ data?: { repository?: { issue?: { closedByPullRequestsReferences?: {
98
+ nodes?: ClosingPullRequestNode[];
99
+ pageInfo?: { hasNextPage?: boolean; endCursor?: string | null };
100
+ } } } };
66
101
  };
67
102
 
68
103
  function result(
@@ -80,12 +115,33 @@ function result(
80
115
  };
81
116
  }
82
117
 
118
+ function externalResult(
119
+ base: PullRequestResult,
120
+ overrides: Partial<ExternalPullRequestResult> = {}
121
+ ): ExternalPullRequestResult {
122
+ return {
123
+ ...base,
124
+ mode: null,
125
+ authorization: null,
126
+ candidates: [],
127
+ eligible: [],
128
+ selected: null,
129
+ ...overrides
130
+ };
131
+ }
132
+
83
133
  function normalizePullRequest(remote: RemotePullRequest, repository: string): PullRequestSnapshot | null {
84
134
  const number = Number(remote.number);
85
135
  const headRepository = remote.head?.repo?.full_name;
86
136
  const baseRepository = remote.base?.repo?.full_name;
87
137
  if (!Number.isInteger(number) || number <= 0 || !remote.node_id || !remote.html_url ||
88
138
  !remote.head?.ref || !remote.head.sha || !headRepository || !remote.base?.ref || !baseRepository) return null;
139
+ const mergeabilityDetail = remote.mergeable_state?.trim().toLowerCase() || null;
140
+ const mergeability = remote.mergeable === false
141
+ ? { state: 'conflicting' as const, detail: mergeabilityDetail }
142
+ : remote.mergeable === true && mergeabilityDetail !== 'dirty'
143
+ ? { state: 'mergeable' as const, detail: mergeabilityDetail }
144
+ : { state: 'unknown' as const, detail: mergeabilityDetail };
89
145
  return {
90
146
  repository,
91
147
  number,
@@ -101,10 +157,151 @@ function normalizePullRequest(remote: RemotePullRequest, repository: string): Pu
101
157
  mergeCommitSha: remote.merge_commit_sha || null,
102
158
  labels: (remote.labels || []).map((label) => typeof label === 'string' ? label : label.name || '').filter(Boolean).sort(),
103
159
  assignees: (remote.assignees || []).map((assignee) => assignee.login || '').filter(Boolean).sort(),
104
- milestone: remote.milestone?.title || null
160
+ milestone: remote.milestone?.title || null,
161
+ mergeability
105
162
  };
106
163
  }
107
164
 
165
+ function normalizeClosingPullRequest(node: ClosingPullRequestNode, repository: string): PullRequestSnapshot | null {
166
+ return normalizePullRequest({
167
+ number: node.number,
168
+ node_id: node.id,
169
+ html_url: node.url,
170
+ state: node.state === 'OPEN' ? 'open' : 'closed',
171
+ title: node.title,
172
+ body: node.body,
173
+ draft: node.isDraft,
174
+ head: { ref: node.headRefName, sha: node.headRefOid, repo: node.headRepository ? { full_name: node.headRepository.nameWithOwner } : null },
175
+ base: { ref: node.baseRefName, sha: node.baseRefOid, repo: node.baseRepository ? { full_name: node.baseRepository.nameWithOwner } : null },
176
+ merged_at: node.mergedAt,
177
+ merge_commit_sha: node.mergeCommit?.oid,
178
+ labels: node.labels?.nodes,
179
+ assignees: node.assignees?.nodes,
180
+ milestone: node.milestone
181
+ }, repository);
182
+ }
183
+
184
+ function repositoryKey(repository: string): string {
185
+ return repository.trim().toLowerCase();
186
+ }
187
+
188
+ function identitySignature(pullRequest: PullRequestSnapshot): string {
189
+ return [
190
+ pullRequest.repository, pullRequest.number, pullRequest.nodeId, pullRequest.url,
191
+ pullRequest.head.repository, pullRequest.head.ref, pullRequest.head.sha,
192
+ pullRequest.base.repository, pullRequest.base.ref, pullRequest.base.sha,
193
+ pullRequest.mergedAt || '', pullRequest.mergeCommitSha || ''
194
+ ].join('|');
195
+ }
196
+
197
+ function hasCompleteExternalIdentity(pullRequest: PullRequestSnapshot): boolean {
198
+ const required = [
199
+ pullRequest.repository, pullRequest.nodeId, pullRequest.url,
200
+ pullRequest.head.repository, pullRequest.head.ref, pullRequest.head.sha,
201
+ pullRequest.base.repository, pullRequest.base.ref, pullRequest.base.sha
202
+ ];
203
+ return Number.isInteger(pullRequest.number) && pullRequest.number > 0 &&
204
+ required.every((value) => Boolean(value?.trim())) &&
205
+ Boolean(pullRequest.mergedAt) === Boolean(pullRequest.mergeCommitSha);
206
+ }
207
+
208
+ function selectExternalPullRequest(
209
+ candidates: PullRequestSnapshot[],
210
+ repository: string,
211
+ existingPrNumber: number | null,
212
+ explicitPrNumber: number | null
213
+ ): ExternalPullRequestSelection {
214
+ const invalid = candidates.find((candidate) => !hasCompleteExternalIdentity(candidate));
215
+ if (invalid) return {
216
+ status: 'failed', code: 'PR_IDENTITY_INVALID',
217
+ message: `Closing PR #${invalid.number} lacks required identity`, candidates, eligible: []
218
+ };
219
+ const byNumber = new Map<number, string>();
220
+ for (const candidate of candidates) {
221
+ const signature = identitySignature(candidate);
222
+ const prior = byNumber.get(candidate.number);
223
+ if (prior && prior !== signature) return {
224
+ status: 'failed', code: 'PR_IDENTITY_INVALID',
225
+ message: `Closing PR #${candidate.number} has conflicting identities`, candidates, eligible: []
226
+ };
227
+ byNumber.set(candidate.number, signature);
228
+ }
229
+ const unique = candidates.filter((candidate, index) =>
230
+ candidates.findIndex((other) => other.number === candidate.number) === index
231
+ );
232
+ const wantedRepository = repositoryKey(repository);
233
+ const eligible = unique.filter((candidate) =>
234
+ repositoryKey(candidate.repository) === wantedRepository &&
235
+ repositoryKey(candidate.base.repository) === wantedRepository &&
236
+ Boolean(candidate.mergedAt && candidate.mergeCommitSha)
237
+ );
238
+ if (explicitPrNumber !== null) {
239
+ const selected = unique.find((candidate) => candidate.number === explicitPrNumber);
240
+ if (!selected) return { status: 'failed', code: 'PR_NOT_FOUND', message: `PR #${explicitPrNumber} is not a closing PR`, candidates, eligible };
241
+ if (!eligible.some((candidate) => candidate.number === explicitPrNumber)) {
242
+ return { status: 'failed', code: 'PR_IDENTITY_INVALID', message: `PR #${explicitPrNumber} is not an eligible merged PR`, candidates, eligible };
243
+ }
244
+ if (existingPrNumber !== null && existingPrNumber !== explicitPrNumber) {
245
+ return { status: 'failed', code: 'PR_BIND_CONFLICT', message: `Task is already bound to PR #${existingPrNumber}`, candidates, eligible };
246
+ }
247
+ return { status: 'selected', source: 'explicit', selected, candidates, eligible };
248
+ }
249
+ if (existingPrNumber !== null && eligible.length === 1 && existingPrNumber !== eligible[0]!.number) {
250
+ return { status: 'failed', code: 'PR_BIND_CONFLICT', message: `Task is already bound to PR #${existingPrNumber}`, candidates, eligible };
251
+ }
252
+ if (eligible.length === 0) return { status: 'normal', candidates, eligible: [] };
253
+ if (eligible.length > 1) return {
254
+ status: 'failed', code: 'PR_IDENTITY_AMBIGUOUS',
255
+ message: 'Multiple eligible merged closing pull requests were found', candidates, eligible
256
+ };
257
+ return { status: 'selected', source: 'unique', selected: eligible[0]!, candidates, eligible };
258
+ }
259
+
260
+ const CLOSING_PULL_REQUESTS_QUERY = `query($owner:String!,$name:String!,$issue:Int!,$cursor:String){repository(owner:$owner,name:$name){issue(number:$issue){closedByPullRequestsReferences(first:100,after:$cursor){nodes{number id url state title body isDraft headRefName headRefOid headRepository{nameWithOwner} baseRefName baseRefOid baseRepository{nameWithOwner} mergedAt mergeCommit{oid} labels(first:100){nodes{name}} assignees(first:100){nodes{login}} milestone{title}} pageInfo{hasNextPage endCursor}}}}}`;
261
+
262
+ function inspectGitHubIssueClosingChangeRequests(
263
+ client: GitHubClient,
264
+ repository: string,
265
+ issueNumber: number,
266
+ cwd: string
267
+ ) {
268
+ const [owner, name] = repository.split('/');
269
+ if (!owner || !name || !Number.isInteger(issueNumber) || issueNumber <= 0) return {
270
+ ok: false as const,
271
+ error: { code: 'PR_IDENTITY_INVALID', message: 'Repository or Issue identity is invalid', retryable: false }
272
+ };
273
+ const candidates: PullRequestSnapshot[] = [];
274
+ let cursor: string | null = null;
275
+ for (;;) {
276
+ const args = [
277
+ 'api', 'graphql', '-f', `query=${CLOSING_PULL_REQUESTS_QUERY}`,
278
+ '-F', `owner=${owner}`, '-F', `name=${name}`, '-F', `issue=${issueNumber}`
279
+ ];
280
+ if (cursor) args.push('-F', `cursor=${cursor}`);
281
+ const response = client.json<ClosingPullRequestPage>(args, { cwd });
282
+ if (!response.ok) return response;
283
+ const connection = response.value?.data?.repository?.issue?.closedByPullRequestsReferences;
284
+ if (!connection || !Array.isArray(connection.nodes) || !connection.pageInfo) return {
285
+ ok: false as const,
286
+ error: { code: 'PR_IDENTITY_INVALID', message: 'Closing pull request response is incomplete', retryable: false }
287
+ };
288
+ for (const node of connection.nodes) {
289
+ const normalized = normalizeClosingPullRequest(node, repository);
290
+ if (!normalized) return {
291
+ ok: false as const,
292
+ error: { code: 'PR_IDENTITY_INVALID', message: 'Closing pull request identity is incomplete', retryable: false }
293
+ };
294
+ candidates.push(normalized);
295
+ }
296
+ if (!connection.pageInfo.hasNextPage) return { ok: true as const, value: candidates };
297
+ if (!connection.pageInfo.endCursor || connection.pageInfo.endCursor === cursor) return {
298
+ ok: false as const,
299
+ error: { code: 'PR_IDENTITY_INVALID', message: 'Closing pull request pagination cursor is invalid', retryable: false }
300
+ };
301
+ cursor = connection.pageInfo.endCursor;
302
+ }
303
+ }
304
+
108
305
  function expectedHead(repository: string, head: string): { repository: string; ref: string } {
109
306
  const colon = head.indexOf(':');
110
307
  if (colon === -1) return { repository, ref: head };
@@ -126,7 +323,7 @@ function selectPullRequest(remotes: RemotePullRequest[], repository: string, hea
126
323
  return { status: matches.length === 0 ? 'missing' : 'ambiguous', pullRequest: null };
127
324
  }
128
325
 
129
- function resolvedContext(taskRef: string, options: SharedOptions) {
326
+ function resolvedContext(taskRef: string, options: InspectionOptions) {
130
327
  const resolved = resolveTaskRef(taskRef, options.cwd ? { repoRoot: options.cwd } : {});
131
328
  if (!resolved.ok) return { ok: false as const, output: result('failed', resolved.taskId, null, null, {
132
329
  error: { code: resolved.code, message: resolved.message, retryable: false }
@@ -137,7 +334,7 @@ function resolvedContext(taskRef: string, options: SharedOptions) {
137
334
  const pr = Number(frontmatter.pr_number);
138
335
  const issueNumber = Number.isInteger(issue) && issue > 0 ? issue : null;
139
336
  const prNumber = Number.isInteger(pr) && pr > 0 ? pr : null;
140
- const client = options.client || createGitHubClient();
337
+ const client = (options.client as GitHubClient | undefined) || createGitHubClient();
141
338
  const context = resolvePlatformContext({ cwd: resolved.repoRoot, client });
142
339
  const usable = (context.status === 'no-op' || context.status === 'degraded') && context.platform.repository;
143
340
  if (!usable) return { ok: false as const, output: result(context.status, resolved.taskId, issueNumber, prNumber, {
@@ -155,6 +352,116 @@ function inspectGitHubPullRequest(client: GitHubClient, repository: string, numb
155
352
  : { ok: false as const, error: { code: 'PR_IDENTITY_INVALID', message: 'Remote resource is not a valid pull request', retryable: false } };
156
353
  }
157
354
 
355
+ function configuredGitRemotes(cwd: string): Array<{ name: string; url: string; repository: string }> {
356
+ try {
357
+ return execFileSync('git', ['remote'], {
358
+ cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe']
359
+ }).split(/\r?\n/).filter(Boolean).flatMap((name) => {
360
+ try {
361
+ const url = execFileSync('git', ['config', '--get', `remote.${name}.url`], {
362
+ cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe']
363
+ }).trim();
364
+ const repository = parseGitHubRemote(url);
365
+ return repository ? [{ name, url, repository }] : [];
366
+ } catch {
367
+ return [];
368
+ }
369
+ });
370
+ } catch {
371
+ return [];
372
+ }
373
+ }
374
+
375
+ function rewriteGitHubRemote(remote: string, repository: string): string | null {
376
+ const match = remote.trim().match(
377
+ /^(https?:\/\/github\.com\/|ssh:\/\/(?:git@)?github\.com\/|git@github\.com:)[^/\s]+\/[^/\s]+(?:\.git)?$/i
378
+ );
379
+ return match ? `${match[1]}${repository}.git` : null;
380
+ }
381
+
382
+ function resolveGitHubChangeRequestGitEvidence({
383
+ cwd,
384
+ repository,
385
+ pullRequest
386
+ }: {
387
+ cwd: string;
388
+ repository: string;
389
+ pullRequest: PullRequestSnapshot;
390
+ }) {
391
+ if (
392
+ pullRequest.repository !== repository ||
393
+ pullRequest.base.repository !== repository ||
394
+ pullRequest.number <= 0
395
+ ) {
396
+ return {
397
+ ok: false as const,
398
+ error: {
399
+ code: 'PR_MERGE_EVIDENCE_SOURCE_UNAVAILABLE',
400
+ message: 'Pull request repository identity is inconsistent',
401
+ retryable: false
402
+ }
403
+ };
404
+ }
405
+ const reviewedHeadRef = `refs/pull/${pullRequest.number}/head`;
406
+ const targetHeadRef = `refs/heads/${pullRequest.base.ref}`;
407
+ const refValid = (ref: string) => {
408
+ try {
409
+ execFileSync('git', ['check-ref-format', ref], {
410
+ cwd, encoding: 'utf8', stdio: ['ignore', 'ignore', 'ignore']
411
+ });
412
+ return true;
413
+ } catch {
414
+ return false;
415
+ }
416
+ };
417
+ if (!refValid(reviewedHeadRef) || !refValid(targetHeadRef)) {
418
+ return {
419
+ ok: false as const,
420
+ error: {
421
+ code: 'PR_MERGE_EVIDENCE_SOURCE_UNAVAILABLE',
422
+ message: 'Pull request Git refs are invalid',
423
+ retryable: false
424
+ }
425
+ };
426
+ }
427
+
428
+ const remotes = configuredGitRemotes(cwd);
429
+ const exact = remotes
430
+ .filter((remote) => remote.repository === repository)
431
+ .sort((left, right) => Number(right.name === 'origin') - Number(left.name === 'origin') ||
432
+ left.name.localeCompare(right.name))[0];
433
+ const origin = remotes.find((remote) => remote.name === 'origin');
434
+ const remoteUrl = exact?.url || (origin ? rewriteGitHubRemote(origin.url, repository) : null);
435
+ if (!remoteUrl) {
436
+ return {
437
+ ok: false as const,
438
+ error: {
439
+ code: 'PR_MERGE_EVIDENCE_SOURCE_UNAVAILABLE',
440
+ message: `No GitHub remote can provide evidence for ${repository}`,
441
+ retryable: false
442
+ }
443
+ };
444
+ }
445
+ return {
446
+ ok: true as const,
447
+ value: { remoteUrl, reviewedHeadRef, targetHeadRef }
448
+ };
449
+ }
450
+
451
+ registerPlatformCapabilities('github', {
452
+ inspectChangeRequest({ client, repository, number, cwd }) {
453
+ return inspectGitHubPullRequest((client as GitHubClient | undefined) || createGitHubClient(), repository, number, cwd);
454
+ },
455
+ inspectIssueClosingChangeRequests({ client, repository, issueNumber, cwd }) {
456
+ return inspectGitHubIssueClosingChangeRequests(
457
+ (client as GitHubClient | undefined) || createGitHubClient(), repository, issueNumber, cwd
458
+ );
459
+ },
460
+ resolveChangeRequestGitEvidence(context) {
461
+ return resolveGitHubChangeRequestGitEvidence(context);
462
+ }
463
+ });
464
+
158
465
  function locatePullRequest(base: ReturnType<typeof resolvedContext> & { ok: true }, head: string, target: string) {
159
466
  const repository = base.context.platform.repository!;
160
467
  const listed = base.client.json<RemotePullRequest[]>([
@@ -171,24 +478,74 @@ function locatePullRequest(base: ReturnType<typeof resolvedContext> & { ok: true
171
478
  } };
172
479
  }
173
480
 
174
- function inspectPlatformPullRequest(taskRef: string, options: SharedOptions = {}): PullRequestResult {
481
+ function inspectPlatformPullRequest(taskRef: string, options: InspectionOptions = {}): PullRequestResult {
175
482
  const base = resolvedContext(taskRef, options);
176
483
  if (!base.ok) return base.output;
177
484
  if (!base.prNumber) return result('no-op', base.resolved.taskId, base.issueNumber, null, {
178
485
  platform: base.context.platform, capabilities: base.context.capabilities,
179
486
  error: { code: 'PR_NOT_LINKED', message: 'Task has no valid pr_number', retryable: false }
180
487
  });
181
- const fetched = inspectGitHubPullRequest(base.client, base.context.platform.repository!, base.prNumber, base.resolved.repoRoot);
182
- if (!fetched.ok) return result(fetched.error.retryable ? 'blocked' : 'failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
183
- platform: base.context.platform, capabilities: base.context.capabilities,
184
- resource: { kind: 'pull-request', number: base.prNumber }, error: fetched.error
488
+ const fetched = inspectPlatformChangeRequest(base.context.platform.type, {
489
+ cwd: base.resolved.repoRoot,
490
+ repository: base.context.platform.repository!,
491
+ number: base.prNumber,
492
+ client: options.client || base.client
185
493
  });
494
+ if (!fetched.ok || !fetched.value) {
495
+ const error = fetched.error || {
496
+ code: 'PR_INSPECTION_INVALID',
497
+ message: 'Platform adapter returned no change-request snapshot',
498
+ retryable: false
499
+ };
500
+ return result(error.retryable ? 'blocked' : 'failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
501
+ platform: base.context.platform, capabilities: base.context.capabilities,
502
+ resource: { kind: 'pull-request', number: base.prNumber }, error
503
+ });
504
+ }
186
505
  return result('no-op', base.resolved.taskId, base.issueNumber, base.prNumber, {
187
506
  platform: base.context.platform, capabilities: base.context.capabilities,
188
507
  resource: { kind: 'pull-request', number: base.prNumber }, pullRequest: fetched.value, error: null
189
508
  });
190
509
  }
191
510
 
511
+ function inspectPlatformPullRequestByNumber(prNumber: number, options: InspectionOptions = {}): PullRequestResult {
512
+ const client = (options.client as GitHubClient | undefined) || createGitHubClient();
513
+ const context = resolvePlatformContext({ cwd: options.cwd || process.cwd(), client });
514
+ const usable = (context.status === 'no-op' || context.status === 'degraded') && context.platform.repository;
515
+ if (!usable) {
516
+ return result(context.status, null, null, null, {
517
+ platform: context.platform, capabilities: context.capabilities, operations: context.operations, error: context.error
518
+ });
519
+ }
520
+ if (!Number.isInteger(prNumber) || prNumber <= 0) {
521
+ return result('failed', null, null, null, {
522
+ platform: context.platform, capabilities: context.capabilities,
523
+ error: { code: 'PR_NUMBER_INVALID', message: 'PR number must be positive', retryable: false }
524
+ });
525
+ }
526
+ const fetched = inspectPlatformChangeRequest(context.platform.type, {
527
+ cwd: options.cwd || process.cwd(),
528
+ repository: context.platform.repository!,
529
+ number: prNumber,
530
+ client
531
+ });
532
+ if (!fetched.ok || !fetched.value) {
533
+ const error = fetched.error || {
534
+ code: 'PR_INSPECTION_INVALID',
535
+ message: 'Platform adapter returned no change-request snapshot',
536
+ retryable: false
537
+ };
538
+ return result(error.retryable ? 'blocked' : 'failed', null, null, prNumber, {
539
+ platform: context.platform, capabilities: context.capabilities,
540
+ resource: { kind: 'pull-request', number: prNumber }, error
541
+ });
542
+ }
543
+ return result('no-op', null, null, prNumber, {
544
+ platform: context.platform, capabilities: context.capabilities,
545
+ resource: { kind: 'pull-request', number: prNumber }, pullRequest: fetched.value, error: null
546
+ });
547
+ }
548
+
192
549
  function appendActivity(content: string, line: string): string {
193
550
  const body = extractSection(content, ['活动日志', 'Activity Log']);
194
551
  return `${body.replace(/\s+$/, '')}${body.trim() ? '\n' : ''}${line}`;
@@ -250,6 +607,146 @@ function bindPlatformPullRequest(taskRef: string, options: BindOptions): PullReq
250
607
  });
251
608
  }
252
609
 
610
+ function externalEvidenceNote(
611
+ issueNumber: number,
612
+ source: 'unique' | 'explicit',
613
+ pullRequest: PullRequestSnapshot
614
+ ): string {
615
+ return [
616
+ `authorization=${source}`,
617
+ externalIdentityEvidenceNote(issueNumber, pullRequest)
618
+ ].join('; ');
619
+ }
620
+
621
+ function externalIdentityEvidenceNote(
622
+ issueNumber: number,
623
+ pullRequest: PullRequestSnapshot
624
+ ): string {
625
+ return [
626
+ `issue=#${issueNumber}`,
627
+ `pr=#${pullRequest.number}`,
628
+ `url=${pullRequest.url}`,
629
+ `base=${pullRequest.base.repository}:${pullRequest.base.ref}@${pullRequest.base.sha}`,
630
+ `head=${pullRequest.head.repository}:${pullRequest.head.ref}@${pullRequest.head.sha}`,
631
+ `mergedAt=${pullRequest.mergedAt}`,
632
+ `mergeCommitSha=${pullRequest.mergeCommitSha}`
633
+ ].join('; ');
634
+ }
635
+
636
+ function resolveExternalPullRequest(taskRef: string, options: ResolveExternalOptions): ExternalPullRequestResult {
637
+ const base = resolvedContext(taskRef, options);
638
+ if (!base.ok) return externalResult(base.output);
639
+ const inventory = inspectCompletionArtifacts(base.resolved.taskId, { repoRoot: base.resolved.repoRoot });
640
+ if (inventory.status === 'failed') return externalResult(result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
641
+ platform: base.context.platform,
642
+ capabilities: base.context.capabilities,
643
+ error: { code: inventory.error?.code || 'ARTIFACT_TOPOLOGY_CONFLICT', message: inventory.error?.message || 'Completion artifact inventory failed', retryable: false }
644
+ }));
645
+ if (inventory.artifacts.length > 0) {
646
+ if (options.pr !== undefined) return externalResult(result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
647
+ platform: base.context.platform,
648
+ capabilities: base.context.capabilities,
649
+ error: { code: 'EXTERNAL_DELIVERY_NOT_APPLICABLE', message: 'External PR selection is only valid when the completion inventory is empty', retryable: false }
650
+ }), { mode: 'normal' });
651
+ return externalResult(result('no-op', base.resolved.taskId, base.issueNumber, base.prNumber, {
652
+ platform: base.context.platform,
653
+ capabilities: base.context.capabilities,
654
+ operations: [{ name: 'external-pr:inventory', status: 'no-op', reasonCode: 'CANONICAL_ARTIFACTS_PRESENT' }],
655
+ error: null
656
+ }), { mode: 'normal' });
657
+ }
658
+ if (!base.issueNumber) return externalResult(result('failed', base.resolved.taskId, null, base.prNumber, {
659
+ platform: base.context.platform,
660
+ capabilities: base.context.capabilities,
661
+ error: { code: 'EXTERNAL_DELIVERY_ISSUE_REQUIRED', message: 'External delivery requires a valid issue_number', retryable: false }
662
+ }));
663
+ const inspected = inspectPlatformIssueClosingChangeRequests(base.context.platform.type, {
664
+ cwd: base.resolved.repoRoot,
665
+ repository: base.context.platform.repository!,
666
+ issueNumber: base.issueNumber,
667
+ client: base.client
668
+ });
669
+ if (!inspected.ok || !inspected.value) {
670
+ const error = inspected.error || { code: 'PR_IDENTITY_INVALID', message: 'Closing PR inspection returned no candidates', retryable: false };
671
+ return externalResult(result(error.retryable ? 'blocked' : 'failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
672
+ platform: base.context.platform, capabilities: base.context.capabilities, error
673
+ }));
674
+ }
675
+ const selected = selectExternalPullRequest(
676
+ inspected.value,
677
+ base.context.platform.repository!,
678
+ base.prNumber,
679
+ options.pr ?? null
680
+ );
681
+ if (selected.status === 'normal') return externalResult(result('no-op', base.resolved.taskId, base.issueNumber, base.prNumber, {
682
+ platform: base.context.platform,
683
+ capabilities: base.context.capabilities,
684
+ operations: [{ name: 'external-pr:select', status: 'no-op', reasonCode: 'NO_ELIGIBLE_CANDIDATE' }],
685
+ error: null
686
+ }), { mode: 'normal', candidates: selected.candidates, eligible: selected.eligible });
687
+ if (selected.status === 'failed') return externalResult(result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
688
+ platform: base.context.platform,
689
+ capabilities: base.context.capabilities,
690
+ error: { code: selected.code, message: selected.message, retryable: false }
691
+ }), { candidates: selected.candidates, eligible: selected.eligible });
692
+
693
+ const note = externalEvidenceNote(base.issueNumber, selected.source, selected.selected);
694
+ const identityNote = externalIdentityEvidenceNote(base.issueNumber, selected.selected);
695
+ const activityEntry = `**Bind External PR** by ${options.agent} — ${note}`;
696
+ const auditLines = base.content.split(/\r?\n/).filter((line) => line.includes('**Bind External PR**'));
697
+ const alreadyAudited = auditLines.some((line) => line.endsWith(identityNote));
698
+ if (auditLines.length > 0 && !alreadyAudited) return externalResult(result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
699
+ platform: base.context.platform,
700
+ capabilities: base.context.capabilities,
701
+ pullRequest: selected.selected,
702
+ error: { code: 'PR_BIND_CONFLICT', message: 'Existing external PR audit evidence conflicts with the selected identity', retryable: false }
703
+ }), { candidates: selected.candidates, eligible: selected.eligible, selected: selected.selected });
704
+ if (alreadyAudited && base.prNumber !== selected.selected.number) return externalResult(result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
705
+ platform: base.context.platform,
706
+ capabilities: base.context.capabilities,
707
+ pullRequest: selected.selected,
708
+ error: { code: 'PR_BIND_CONFLICT', message: 'External PR audit evidence does not match the task binding', retryable: false }
709
+ }), { candidates: selected.candidates, eligible: selected.eligible, selected: selected.selected });
710
+ if (base.prNumber === selected.selected.number && alreadyAudited) {
711
+ return externalResult(result('no-op', base.resolved.taskId, base.issueNumber, base.prNumber, {
712
+ platform: base.context.platform,
713
+ capabilities: base.context.capabilities,
714
+ resource: { kind: 'pull-request', number: selected.selected.number },
715
+ pullRequest: selected.selected,
716
+ operations: [{ name: 'task:bind-external-pr', status: 'no-op', reasonCode: 'EVIDENCE_ALREADY_RECORDED' }],
717
+ error: null
718
+ }), { mode: 'external', authorization: selected.source, candidates: selected.candidates, eligible: selected.eligible, selected: selected.selected });
719
+ }
720
+ const metadata = captureTaskWriteMetadata();
721
+ const write = writeTask({
722
+ taskRef: base.resolved.taskId,
723
+ expectedState: 'active',
724
+ dryRun: options.dryRun,
725
+ mutations: [
726
+ { kind: 'frontmatter', set: { pr_number: selected.selected.number, pr_status: 'created', assigned_to: options.agent } },
727
+ { kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: '活动日志', body: appendActivity(
728
+ base.content, `- ${metadata.timestamp} — ${activityEntry}`
729
+ ) }
730
+ ]
731
+ }, { repoRoot: base.resolved.repoRoot, metadataProvider: () => metadata });
732
+ if (write.status === 'failed') return externalResult(result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
733
+ platform: base.context.platform,
734
+ capabilities: base.context.capabilities,
735
+ pullRequest: selected.selected,
736
+ error: { code: write.error.code, message: write.error.message, retryable: false }
737
+ }), { candidates: selected.candidates, eligible: selected.eligible, selected: selected.selected });
738
+ const operationStatus = options.dryRun ? 'planned' : write.status === 'applied' ? 'applied' : 'no-op';
739
+ return externalResult(result(operationStatus, base.resolved.taskId, base.issueNumber, options.dryRun ? base.prNumber : selected.selected.number, {
740
+ changed: !options.dryRun && write.changed,
741
+ platform: base.context.platform,
742
+ capabilities: base.context.capabilities,
743
+ resource: { kind: 'pull-request', number: selected.selected.number },
744
+ pullRequest: selected.selected,
745
+ operations: [{ name: 'task:bind-external-pr', status: operationStatus, reasonCode: null }],
746
+ error: null
747
+ }), { mode: 'external', authorization: selected.source, candidates: selected.candidates, eligible: selected.eligible, selected: selected.selected });
748
+ }
749
+
253
750
  function createPlatformPullRequest(taskRef: string, options: CreateOptions): PullRequestResult {
254
751
  const base = resolvedContext(taskRef, options);
255
752
  if (!base.ok) return base.output;
@@ -378,9 +875,14 @@ export {
378
875
  bindPlatformPullRequest,
379
876
  createPlatformPullRequest,
380
877
  inspectGitHubPullRequest,
878
+ inspectGitHubIssueClosingChangeRequests,
381
879
  inspectPlatformPullRequest,
880
+ inspectPlatformPullRequestByNumber,
382
881
  normalizePullRequest,
882
+ resolveGitHubChangeRequestGitEvidence,
883
+ resolveExternalPullRequest,
884
+ selectExternalPullRequest,
383
885
  selectPullRequest,
384
886
  syncPlatformPullRequest
385
887
  };
386
- export type { BindOptions, CreateOptions, PullRequestResult, PullRequestSnapshot, SyncOptions };
888
+ export type { BindOptions, CreateOptions, ExternalPullRequestResult, ExternalPullRequestSelection, PullRequestResult, PullRequestSnapshot, ResolveExternalOptions, SyncOptions };