@fitlab-ai/agent-infra 0.9.11 → 0.9.13

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 (356) hide show
  1. package/README.md +13 -13
  2. package/README.zh-CN.md +13 -13
  3. package/dist/bin/internal-cli.js +29 -19
  4. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +71 -10
  5. package/dist/lib/agent-clients/next-steps.js +6 -1
  6. package/dist/lib/decide.js +3 -3
  7. package/dist/lib/defaults.json +4 -0
  8. package/dist/lib/git/workflow.js +43 -1
  9. package/dist/lib/init.js +1 -0
  10. package/dist/lib/internal/git-workflow.js +8 -1
  11. package/dist/lib/internal/platform-checks.js +3 -3
  12. package/dist/lib/internal/platform-comment.js +9 -9
  13. package/dist/lib/internal/platform-context.js +2 -2
  14. package/dist/lib/internal/platform-issue.js +8 -9
  15. package/dist/lib/internal/platform-pr-review.js +10 -10
  16. package/dist/lib/internal/platform-pr.js +68 -23
  17. package/dist/lib/internal/platform-release-notes.js +3 -3
  18. package/dist/lib/internal/pr-review-grade.js +11 -9
  19. package/dist/lib/internal/release-workflow.js +4 -4
  20. package/dist/lib/internal/sandbox-control.js +30 -4
  21. package/dist/lib/internal/task-activity.js +3 -3
  22. package/dist/lib/internal/task-artifact.js +76 -24
  23. package/dist/lib/internal/task-create.js +2 -2
  24. package/dist/lib/internal/task-delivery.js +59 -0
  25. package/dist/lib/internal/task-event.js +6 -3
  26. package/dist/lib/internal/task-finalization.js +2 -2
  27. package/dist/lib/internal/task-invalidation.js +60 -0
  28. package/dist/lib/internal/task-ledger.js +9 -6
  29. package/dist/lib/internal/task-lifecycle.js +2 -2
  30. package/dist/lib/internal/task-override.js +4 -4
  31. package/dist/lib/internal/task-review.js +3 -3
  32. package/dist/lib/internal/task-verify.js +6 -6
  33. package/dist/lib/internal/task-warning.js +3 -3
  34. package/dist/lib/platform/adapters.js +1 -3
  35. package/dist/lib/platform/change-request-git-evidence.js +27 -7
  36. package/dist/lib/platform/completion-backfill.js +6 -5
  37. package/dist/lib/platform/context.js +70 -130
  38. package/dist/lib/platform/github-client.js +8 -2
  39. package/dist/lib/platform/github-provider.js +903 -0
  40. package/dist/lib/platform/in-label-sync.js +143 -0
  41. package/dist/lib/platform/issue-comments.js +94 -41
  42. package/dist/lib/platform/issues.js +335 -189
  43. package/dist/lib/platform/metadata-labels.js +6 -2
  44. package/dist/lib/platform/none-provider.js +28 -0
  45. package/dist/lib/platform/pr-change-report.js +551 -0
  46. package/dist/lib/platform/pr-checks.js +124 -106
  47. package/dist/lib/platform/pr-review.js +88 -72
  48. package/dist/lib/platform/pr-summary.js +523 -49
  49. package/dist/lib/platform/provider-bridge.js +45 -0
  50. package/dist/lib/platform/provider-contract.d.ts +487 -0
  51. package/dist/lib/platform/provider-contract.js +95 -0
  52. package/dist/lib/platform/provider-loader.js +251 -0
  53. package/dist/lib/platform/provider-validation.js +504 -0
  54. package/dist/lib/platform/pull-request-metadata.js +8 -6
  55. package/dist/lib/platform/pull-requests.js +1050 -502
  56. package/dist/lib/platform/release-notes.js +78 -55
  57. package/dist/lib/platform/releases.js +79 -50
  58. package/dist/lib/platform/resource-identity.d.ts +26 -0
  59. package/dist/lib/platform/resource-identity.js +92 -0
  60. package/dist/lib/platform/task-identities.js +31 -0
  61. package/dist/lib/platform/verification-required.js +22 -12
  62. package/dist/lib/platform/verification-sync.js +118 -239
  63. package/dist/lib/pr-review/evidence-grading.js +30 -9
  64. package/dist/lib/run/index.js +63 -23
  65. package/dist/lib/sandbox/config.js +5 -0
  66. package/dist/lib/sandbox/control/client.js +96 -15
  67. package/dist/lib/sandbox/control/executor.js +3 -3
  68. package/dist/lib/sandbox/control/lifecycle.js +29 -7
  69. package/dist/lib/sandbox/control/protocol.js +77 -0
  70. package/dist/lib/sandbox/control/server.js +398 -25
  71. package/dist/lib/sandbox/control/state.js +204 -1
  72. package/dist/lib/server/process-state.js +2 -2
  73. package/dist/lib/server/protocol.js +38 -1
  74. package/dist/lib/task/activity-log.js +8 -1
  75. package/dist/lib/task/artifact-lifecycle.js +35 -7
  76. package/dist/lib/task/capabilities.js +239 -0
  77. package/dist/lib/task/commands/status.js +32 -0
  78. package/dist/lib/task/commit-intent.js +100 -0
  79. package/dist/lib/task/commit-operation.js +207 -102
  80. package/dist/lib/task/control-authority.js +8 -5
  81. package/dist/lib/task/create-service.js +8 -8
  82. package/dist/lib/task/create.js +33 -7
  83. package/dist/lib/task/current-contract.js +5 -1
  84. package/dist/lib/task/decision-details.js +3 -48
  85. package/dist/lib/task/delivery-target.js +97 -0
  86. package/dist/lib/task/delivery.js +153 -0
  87. package/dist/lib/task/events.js +297 -17
  88. package/dist/lib/task/finalization.js +37 -13
  89. package/dist/lib/task/human-override.js +61 -36
  90. package/dist/lib/task/invalidation-command.js +86 -0
  91. package/dist/lib/task/invalidation.js +260 -0
  92. package/dist/lib/task/ledger-intents.js +37 -0
  93. package/dist/lib/task/lifecycle.js +106 -9
  94. package/dist/lib/task/local-artifact-finalization.js +374 -0
  95. package/dist/lib/task/orchestration.js +100 -151
  96. package/dist/lib/task/pr-delivery-fact.js +183 -0
  97. package/dist/lib/task/review-finalization.js +4 -8
  98. package/dist/lib/task/review-fingerprint.js +32 -2
  99. package/dist/lib/task/rework-intent.js +138 -0
  100. package/dist/lib/task/skill-scope.js +23 -0
  101. package/dist/lib/task/task-execution-lock.js +27 -17
  102. package/dist/lib/task/verification-engine.js +89 -38
  103. package/dist/lib/task/verification-review.js +1 -1
  104. package/dist/lib/task/verification.js +3 -3
  105. package/dist/lib/task/workflow-warning-intents.js +1 -1
  106. package/dist/lib/task/write.js +11 -0
  107. package/dist/lib/update.js +9 -0
  108. package/dist/lib/version.js +11 -1
  109. package/dist/lifecycle-build-manifest.json +3 -3
  110. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +105 -10
  111. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +12 -1
  112. package/lib/agent-clients/next-steps.ts +6 -1
  113. package/lib/decide.ts +3 -3
  114. package/lib/defaults.json +4 -0
  115. package/lib/git/workflow.ts +38 -1
  116. package/lib/init.ts +4 -1
  117. package/lib/internal/git-workflow.ts +7 -1
  118. package/lib/internal/platform-checks.ts +3 -3
  119. package/lib/internal/platform-comment.ts +8 -8
  120. package/lib/internal/platform-context.ts +2 -2
  121. package/lib/internal/platform-issue.ts +7 -8
  122. package/lib/internal/platform-pr-review.ts +9 -9
  123. package/lib/internal/platform-pr.ts +53 -21
  124. package/lib/internal/platform-release-notes.ts +3 -3
  125. package/lib/internal/pr-review-grade.ts +10 -8
  126. package/lib/internal/release-workflow.ts +4 -4
  127. package/lib/internal/sandbox-control.ts +27 -3
  128. package/lib/internal/task-activity.ts +3 -3
  129. package/lib/internal/task-artifact.ts +65 -22
  130. package/lib/internal/task-create.ts +2 -2
  131. package/lib/internal/task-delivery.ts +53 -0
  132. package/lib/internal/task-event.ts +6 -3
  133. package/lib/internal/task-finalization.ts +3 -3
  134. package/lib/internal/task-invalidation.ts +39 -0
  135. package/lib/internal/task-ledger.ts +11 -8
  136. package/lib/internal/task-lifecycle.ts +2 -2
  137. package/lib/internal/task-override.ts +6 -6
  138. package/lib/internal/task-review.ts +3 -3
  139. package/lib/internal/task-verify.ts +6 -6
  140. package/lib/internal/task-warning.ts +3 -3
  141. package/lib/platform/adapters.ts +3 -2
  142. package/lib/platform/change-request-git-evidence.ts +36 -9
  143. package/lib/platform/completion-backfill.ts +9 -8
  144. package/lib/platform/context.ts +97 -134
  145. package/lib/platform/github-client.ts +10 -3
  146. package/lib/platform/github-provider.ts +910 -0
  147. package/lib/platform/in-label-sync.ts +208 -0
  148. package/lib/platform/issue-comments.ts +97 -47
  149. package/lib/platform/issues.ts +344 -174
  150. package/lib/platform/metadata-labels.ts +5 -2
  151. package/lib/platform/none-provider.ts +35 -0
  152. package/lib/platform/pr-change-report.ts +645 -0
  153. package/lib/platform/pr-checks.ts +129 -107
  154. package/lib/platform/pr-review.ts +88 -85
  155. package/lib/platform/pr-summary.ts +562 -52
  156. package/lib/platform/provider-bridge.ts +82 -0
  157. package/lib/platform/provider-contract.ts +536 -0
  158. package/lib/platform/provider-loader.ts +307 -0
  159. package/lib/platform/provider-validation.ts +529 -0
  160. package/lib/platform/pull-request-metadata.ts +10 -7
  161. package/lib/platform/pull-requests.ts +1126 -505
  162. package/lib/platform/release-notes.ts +76 -59
  163. package/lib/platform/releases.ts +77 -43
  164. package/lib/platform/resource-identity.ts +121 -0
  165. package/lib/platform/task-identities.ts +40 -0
  166. package/lib/platform/types.ts +4 -2
  167. package/lib/platform/verification-required.ts +21 -13
  168. package/lib/platform/verification-sync.ts +118 -293
  169. package/lib/pr-review/evidence-grading.ts +31 -11
  170. package/lib/run/index.ts +57 -22
  171. package/lib/sandbox/config.ts +7 -0
  172. package/lib/sandbox/control/client.ts +105 -15
  173. package/lib/sandbox/control/executor.ts +4 -4
  174. package/lib/sandbox/control/lifecycle.ts +30 -8
  175. package/lib/sandbox/control/protocol.ts +113 -0
  176. package/lib/sandbox/control/server.ts +431 -23
  177. package/lib/sandbox/control/state.ts +251 -1
  178. package/lib/server/process-state.ts +2 -2
  179. package/lib/server/protocol.ts +36 -1
  180. package/lib/task/activity-log.ts +8 -0
  181. package/lib/task/artifact-lifecycle.ts +34 -8
  182. package/lib/task/capabilities.ts +262 -0
  183. package/lib/task/commands/status.ts +38 -0
  184. package/lib/task/commit-intent.ts +137 -0
  185. package/lib/task/commit-operation.ts +186 -88
  186. package/lib/task/control-authority.ts +11 -8
  187. package/lib/task/create-service.ts +8 -8
  188. package/lib/task/create.ts +34 -9
  189. package/lib/task/current-contract.ts +6 -1
  190. package/lib/task/decision-details.ts +8 -64
  191. package/lib/task/delivery-target.ts +130 -0
  192. package/lib/task/delivery.ts +160 -0
  193. package/lib/task/events.ts +296 -16
  194. package/lib/task/finalization.ts +50 -14
  195. package/lib/task/human-override.ts +73 -46
  196. package/lib/task/invalidation-command.ts +86 -0
  197. package/lib/task/invalidation.ts +332 -0
  198. package/lib/task/ledger-intents.ts +35 -1
  199. package/lib/task/lifecycle.ts +93 -4
  200. package/lib/task/local-artifact-finalization.ts +563 -0
  201. package/lib/task/orchestration.ts +110 -146
  202. package/lib/task/pr-delivery-fact.ts +237 -0
  203. package/lib/task/review-finalization.ts +4 -14
  204. package/lib/task/review-fingerprint.ts +33 -2
  205. package/lib/task/rework-intent.ts +165 -0
  206. package/lib/task/skill-scope.ts +24 -0
  207. package/lib/task/task-execution-lock.ts +23 -14
  208. package/lib/task/verification-engine.ts +95 -43
  209. package/lib/task/verification-review.ts +2 -0
  210. package/lib/task/verification.ts +4 -4
  211. package/lib/task/workflow-warning-intents.ts +1 -1
  212. package/lib/task/write.ts +19 -0
  213. package/lib/update.ts +11 -1
  214. package/lib/version.ts +15 -1
  215. package/package.json +7 -1
  216. package/templates/.agents/rules/README.en.md +4 -2
  217. package/templates/.agents/rules/README.zh-CN.md +4 -2
  218. package/templates/.agents/rules/create-issue.en.md +11 -2
  219. package/templates/.agents/rules/create-issue.zh-CN.md +24 -2
  220. package/templates/.agents/rules/issue-pr-commands.en.md +4 -17
  221. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
  222. package/templates/.agents/rules/issue-sync.en.md +28 -5
  223. package/templates/.agents/rules/issue-sync.zh-CN.md +64 -5
  224. package/templates/.agents/rules/label-milestone-setup.en.md +15 -2
  225. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +15 -2
  226. package/templates/.agents/rules/local-artifact-repair.en.md +53 -0
  227. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +53 -0
  228. package/templates/.agents/rules/milestone-inference.en.md +12 -2
  229. package/templates/.agents/rules/milestone-inference.zh-CN.md +25 -3
  230. package/templates/.agents/rules/pr-sync.en.md +28 -13
  231. package/templates/.agents/rules/pr-sync.zh-CN.md +39 -5
  232. package/templates/.agents/rules/release-commands.en.md +42 -3
  233. package/templates/.agents/rules/release-commands.zh-CN.md +42 -3
  234. package/templates/.agents/rules/security-alerts.en.md +17 -2
  235. package/templates/.agents/rules/security-alerts.zh-CN.md +17 -2
  236. package/templates/.agents/rules/sync-content-generation.en.md +8 -0
  237. package/templates/.agents/rules/sync-content-generation.zh-CN.md +8 -0
  238. package/templates/.agents/rules/task-management.en.md +1 -1
  239. package/templates/.agents/rules/task-management.zh-CN.md +1 -1
  240. package/templates/.agents/rules/task-short-id.en.md +1 -4
  241. package/templates/.agents/rules/task-short-id.zh-CN.md +1 -3
  242. package/templates/.agents/scripts/security-alerts.github.sh +151 -0
  243. package/templates/.agents/scripts/security-alerts.sh +31 -0
  244. package/templates/.agents/skills/analyze-task/SKILL.en.md +14 -3
  245. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +11 -3
  246. package/templates/.agents/skills/check-task/SKILL.en.md +16 -37
  247. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -37
  248. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  249. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  250. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  251. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  252. package/templates/.agents/skills/code-task/SKILL.en.md +32 -10
  253. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +35 -13
  254. package/templates/.agents/skills/code-task/config/verify.en.json +1 -0
  255. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -0
  256. package/templates/.agents/skills/commit/SKILL.en.md +3 -3
  257. package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -3
  258. package/templates/.agents/skills/commit/config/verify.json +1 -1
  259. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +3 -3
  260. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +3 -3
  261. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +2 -0
  262. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +2 -0
  263. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +4 -4
  264. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +4 -4
  265. package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -2
  266. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -2
  267. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +7 -4
  268. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +7 -4
  269. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  270. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  271. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +5 -4
  272. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +5 -4
  273. package/templates/.agents/skills/complete-task/SKILL.en.md +31 -13
  274. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +30 -13
  275. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +2 -2
  276. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +2 -2
  277. package/templates/.agents/skills/create-pr/SKILL.en.md +11 -10
  278. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +11 -11
  279. package/templates/.agents/skills/create-pr/config/verify.json +1 -0
  280. package/templates/.agents/skills/create-pr/reference/change-report.en.md +16 -4
  281. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +16 -4
  282. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +5 -3
  283. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +5 -3
  284. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +1 -1
  285. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +1 -1
  286. package/templates/.agents/skills/create-pr/scripts/change-report.mjs +3 -0
  287. package/templates/.agents/skills/create-task/SKILL.en.md +1 -0
  288. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -0
  289. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  290. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  291. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  292. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  293. package/templates/.agents/skills/init-labels/SKILL.en.md +9 -10
  294. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +9 -10
  295. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +57 -1
  296. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +27 -1
  297. package/templates/.agents/skills/init-milestones/SKILL.en.md +3 -5
  298. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +3 -5
  299. package/templates/.agents/skills/plan-task/SKILL.en.md +14 -3
  300. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +11 -3
  301. package/templates/.agents/skills/review-analysis/SKILL.en.md +6 -5
  302. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +6 -5
  303. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +18 -0
  304. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +18 -0
  305. package/templates/.agents/skills/review-code/SKILL.en.md +10 -9
  306. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +10 -9
  307. package/templates/.agents/skills/review-code/reference/output-templates.en.md +19 -1
  308. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +19 -1
  309. package/templates/.agents/skills/review-code/reference/report-template.en.md +4 -2
  310. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +4 -2
  311. package/templates/.agents/skills/review-plan/SKILL.en.md +6 -5
  312. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +6 -5
  313. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +18 -0
  314. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +18 -0
  315. package/templates/.agents/skills/review-pr/SKILL.en.md +1 -0
  316. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +1 -0
  317. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +2 -2
  318. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +2 -2
  319. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -2
  320. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -2
  321. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  322. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  323. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +4 -0
  324. package/templates/.agents/skills/watch-pr/SKILL.en.md +6 -6
  325. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +6 -6
  326. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +6 -0
  327. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +6 -0
  328. package/templates/.agents/templates/task.en.md +23 -2
  329. package/templates/.agents/templates/task.zh-CN.md +23 -2
  330. package/templates/.agents/workflows/bug-fix.en.yaml +9 -8
  331. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +9 -8
  332. package/templates/.agents/workflows/feature-development.en.yaml +9 -8
  333. package/templates/.agents/workflows/feature-development.zh-CN.yaml +9 -8
  334. package/templates/.agents/workflows/refactoring.en.yaml +9 -8
  335. package/templates/.agents/workflows/refactoring.zh-CN.yaml +9 -8
  336. package/templates/.github/workflows/pr-label.yml +7 -26
  337. package/templates/.agents/rules/create-issue.github.en.md +0 -14
  338. package/templates/.agents/rules/create-issue.github.zh-CN.md +0 -27
  339. package/templates/.agents/rules/issue-pr-commands.github.en.md +0 -34
  340. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +0 -49
  341. package/templates/.agents/rules/issue-sync.github.en.md +0 -40
  342. package/templates/.agents/rules/issue-sync.github.zh-CN.md +0 -76
  343. package/templates/.agents/rules/label-milestone-setup.github.en.md +0 -60
  344. package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +0 -60
  345. package/templates/.agents/rules/milestone-inference.github.en.md +0 -15
  346. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +0 -27
  347. package/templates/.agents/rules/pr-checks-commands.github.en.md +0 -18
  348. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +0 -34
  349. package/templates/.agents/rules/pr-sync.github.en.md +0 -43
  350. package/templates/.agents/rules/pr-sync.github.zh-CN.md +0 -69
  351. package/templates/.agents/rules/release-commands.github.en.md +0 -44
  352. package/templates/.agents/rules/release-commands.github.zh-CN.md +0 -44
  353. package/templates/.agents/rules/security-alerts.github.en.md +0 -43
  354. package/templates/.agents/rules/security-alerts.github.zh-CN.md +0 -43
  355. /package/templates/.agents/rules/{issue-fields.github.en.md → issue-fields.en.md} +0 -0
  356. /package/templates/.agents/rules/{issue-fields.github.zh-CN.md → issue-fields.zh-CN.md} +0 -0
@@ -7,23 +7,28 @@ import {
7
7
  createPlatformPullRequest,
8
8
  inspectPlatformPullRequest,
9
9
  resolveExternalPullRequest,
10
- syncPlatformPullRequest
10
+ skipPlatformPullRequestFact,
11
+ syncPlatformPullRequest,
12
+ syncPlatformPullRequestInLabels
11
13
  } from '../platform/pull-requests.ts';
12
14
  import type { PullRequestResult } from '../platform/pull-requests.ts';
13
- import { summaryContext, syncPullRequestSummary } from '../platform/pr-summary.ts';
15
+ import { reportWrite, summaryContext, syncPullRequestSummary } from '../platform/pr-summary.ts';
14
16
  import type { PlatformResult } from '../platform/types.ts';
15
17
 
16
18
  const USAGE = `Usage: agent-infra-internal platform-pr inspect <task-ref> [--cwd <path>]
17
- agent-infra-internal platform-pr resolve-external <task-ref> --agent <agent> [--pr <N>] [--dry-run] [--cwd <path>]
19
+ agent-infra-internal platform-pr resolve-external <task-ref> --agent <agent> [--pr <token>] [--dry-run] [--cwd <path>]
18
20
  agent-infra-internal platform-pr create <task-ref> --agent <agent> --base <branch> --head <branch> --title-file <path|-> --body-file <path|-> [--draft] [--dry-run] [--cwd <path>]
19
- agent-infra-internal platform-pr bind <task-ref> --pr <N> --agent <agent> [--dry-run] [--cwd <path>]
21
+ agent-infra-internal platform-pr bind <task-ref> --pr <token> --agent <agent> [--dry-run] [--cwd <path>]
22
+ agent-infra-internal platform-pr skip <task-ref> --agent <agent> [--dry-run] [--cwd <path>]
20
23
  agent-infra-internal platform-pr sync <task-ref> --agent <agent> [--metadata] [--closing-issue] --result <pr_created|pr_reused|no_op> [--dry-run] [--cwd <path>]
24
+ agent-infra-internal platform-pr sync-in-labels --pr <N> [--dry-run] [--cwd <path>]
21
25
  agent-infra-internal platform-pr summary-context <task-ref> [--cwd <path>]
22
- agent-infra-internal platform-pr summary-sync <task-ref> --agent <agent> --body-file <path|-> --result <pr_created|pr_reused|no_op> [--dry-run] [--cwd <path>]
26
+ agent-infra-internal platform-pr change-report <task-ref> --agent <agent> --mechanical-file <path> --precheck-file <path> [--dry-run] [--cwd <path>]
27
+ agent-infra-internal platform-pr summary-sync <task-ref> --agent <agent> --body-file <path|-> --change-report-file <path> --result <pr_created|pr_reused|no_op> [--strict] [--dry-run] [--cwd <path>]
23
28
  `;
24
29
 
25
- const BOOLEAN_FLAGS = new Set(['--draft', '--dry-run', '--metadata', '--closing-issue']);
26
- const VALUE_FLAGS = new Set(['--cwd', '--agent', '--base', '--head', '--title-file', '--body-file', '--pr', '--result']);
30
+ const BOOLEAN_FLAGS = new Set(['--draft', '--dry-run', '--metadata', '--closing-issue', '--strict']);
31
+ const VALUE_FLAGS = new Set(['--cwd', '--agent', '--base', '--head', '--title-file', '--body-file', '--change-report-file', '--mechanical-file', '--precheck-file', '--pr', '--result']);
27
32
 
28
33
  function key(flag: string): string {
29
34
  return flag.slice(2).replace(/-([a-z])/g, (_, letter: string) => letter.toUpperCase());
@@ -61,10 +66,22 @@ function readFile(value: string, cwd: string): string {
61
66
  return value === '-' ? fs.readFileSync(0, 'utf8') : fs.readFileSync(path.resolve(cwd, value), 'utf8');
62
67
  }
63
68
 
64
- function platformPr(args: string[] = []): void {
69
+ async function platformPr(args: string[] = []): Promise<void> {
65
70
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
66
71
  const operation = args[0];
67
- if (!operation || !['inspect', 'resolve-external', 'create', 'bind', 'sync', 'summary-context', 'summary-sync'].includes(operation)) { fail('a valid operation is required'); return; }
72
+ if (!operation || !['inspect', 'resolve-external', 'create', 'bind', 'skip', 'sync', 'sync-in-labels', 'summary-context', 'change-report', 'summary-sync'].includes(operation)) { fail('a valid operation is required'); return; }
73
+ if (operation === 'sync-in-labels') {
74
+ const parsed = parse(args, 1);
75
+ if (parsed.error) { fail(parsed.error); return; }
76
+ const values = parsed.values;
77
+ const unexpected = Object.keys(values).find((name) => !['cwd', 'pr', 'dryRun'].includes(name));
78
+ if (unexpected) { fail(`sync-in-labels does not accept --${unexpected}`); return; }
79
+ const pr = Number(values.pr);
80
+ if (!Number.isInteger(pr) || pr <= 0) { fail('sync-in-labels requires a positive --pr'); return; }
81
+ const cwd = path.resolve(typeof values.cwd === 'string' ? values.cwd : process.cwd());
82
+ finish(await syncPlatformPullRequestInLabels(pr, { cwd, dryRun: values.dryRun === true }));
83
+ return;
84
+ }
68
85
  const taskRef = args[1];
69
86
  if (!taskRef || taskRef.startsWith('--')) { fail(`${operation} requires a task ref`); return; }
70
87
  const parsed = parse(args, 2);
@@ -76,46 +93,61 @@ function platformPr(args: string[] = []): void {
76
93
  'resolve-external': ['cwd', 'agent', 'pr', 'dryRun'],
77
94
  create: ['cwd', 'agent', 'base', 'head', 'titleFile', 'bodyFile', 'draft', 'dryRun'],
78
95
  bind: ['cwd', 'agent', 'pr', 'dryRun'],
96
+ skip: ['cwd', 'agent', 'dryRun'],
79
97
  sync: ['cwd', 'agent', 'metadata', 'closingIssue', 'result', 'dryRun'],
98
+ 'sync-in-labels': ['cwd', 'pr', 'dryRun'],
80
99
  'summary-context': ['cwd'],
81
- 'summary-sync': ['cwd', 'agent', 'bodyFile', 'result', 'dryRun']
100
+ 'change-report': ['cwd', 'agent', 'mechanicalFile', 'precheckFile', 'dryRun'],
101
+ 'summary-sync': ['cwd', 'agent', 'bodyFile', 'changeReportFile', 'result', 'dryRun', 'strict']
82
102
  };
83
103
  const unexpected = Object.keys(values).find((name) => !allowed[operation]!.includes(name));
84
104
  if (unexpected) { fail(`${operation} does not accept --${unexpected}`); return; }
85
- if (operation === 'inspect') { finish(inspectPlatformPullRequest(taskRef, { cwd })); return; }
86
- if (operation === 'summary-context') { finish(summaryContext(taskRef, { cwd })); return; }
105
+ if (operation === 'inspect') { finish(await inspectPlatformPullRequest(taskRef, { cwd })); return; }
106
+ if (operation === 'summary-context') { finish(await summaryContext(taskRef, { cwd })); return; }
87
107
  if (typeof values.agent !== 'string' || !values.agent) { fail(`${operation} requires --agent`); return; }
88
108
  const agent = normalizeAgentToken(values.agent);
89
109
  if (!agent) { fail(`invalid --agent '${values.agent}': ${AGENT_USAGE_HINT}`); return; }
90
110
  values.agent = agent;
111
+ if (operation === 'change-report') {
112
+ if (typeof values.mechanicalFile !== 'string' || typeof values.precheckFile !== 'string') { fail('change-report requires --mechanical-file and --precheck-file'); return; }
113
+ finish(await reportWrite(taskRef, {
114
+ cwd, agent: values.agent, mechanicalFile: values.mechanicalFile, precheckFile: values.precheckFile, dryRun: values.dryRun === true
115
+ }));
116
+ return;
117
+ }
118
+ if (operation === 'skip') {
119
+ finish(await skipPlatformPullRequestFact(taskRef, { cwd, agent, dryRun: values.dryRun === true }));
120
+ return;
121
+ }
91
122
  const primaryResult = values.result === undefined ? undefined : values.result;
92
123
  if (primaryResult !== undefined && !['pr_created', 'pr_reused', 'no_op'].includes(primaryResult as string)) {
93
124
  fail('--result must be pr_created, pr_reused, or no_op');
94
125
  return;
95
126
  }
96
127
  if (operation === 'resolve-external') {
97
- const pr = values.pr === undefined ? undefined : Number(values.pr);
98
- if (pr !== undefined && (!Number.isInteger(pr) || pr <= 0)) { fail('resolve-external requires a positive --pr'); return; }
99
- finish(resolveExternalPullRequest(taskRef, { cwd, agent: values.agent, pr, dryRun: values.dryRun === true }));
128
+ const pr = values.pr === undefined ? undefined : values.pr;
129
+ if (pr !== undefined && (typeof pr !== 'string' || !pr)) { fail('resolve-external requires --pr <token>'); return; }
130
+ finish(await resolveExternalPullRequest(taskRef, { cwd, agent: values.agent, pr, dryRun: values.dryRun === true }));
100
131
  return;
101
132
  }
102
133
  if (operation === 'bind') {
103
- const pr = Number(values.pr);
104
- if (!Number.isInteger(pr) || pr <= 0) { fail('bind requires a positive --pr'); return; }
105
- finish(bindPlatformPullRequest(taskRef, { cwd, agent: values.agent, pr, dryRun: values.dryRun === true }));
134
+ const pr = values.pr;
135
+ if (typeof pr !== 'string' || !pr) { fail('bind requires --pr <token>'); return; }
136
+ finish(await bindPlatformPullRequest(taskRef, { cwd, agent: values.agent, pr, dryRun: values.dryRun === true }));
106
137
  return;
107
138
  }
108
139
  if (operation === 'sync') {
109
140
  if (values.metadata !== true && values.closingIssue !== true) { fail('sync requires --metadata or --closing-issue'); return; }
110
141
  if (!primaryResult) { fail('sync requires --result pr_created, pr_reused, or no_op'); return; }
111
- finish(syncPlatformPullRequest(taskRef, { cwd, agent: values.agent, metadata: values.metadata === true, closingIssue: values.closingIssue === true, primaryResult: primaryResult as 'pr_created' | 'pr_reused' | 'no_op', dryRun: values.dryRun === true }));
142
+ finish(await syncPlatformPullRequest(taskRef, { cwd, agent: values.agent, metadata: values.metadata === true, closingIssue: values.closingIssue === true, primaryResult: primaryResult as 'pr_created' | 'pr_reused' | 'no_op', dryRun: values.dryRun === true }));
112
143
  return;
113
144
  }
114
145
  if (operation === 'summary-sync') {
115
146
  if (typeof values.bodyFile !== 'string') { fail('summary-sync requires --body-file'); return; }
147
+ if (typeof values.changeReportFile !== 'string') { fail('summary-sync requires --change-report-file'); return; }
116
148
  if (!primaryResult) { fail('summary-sync requires --result pr_created, pr_reused, or no_op'); return; }
117
149
  try {
118
- finish(syncPullRequestSummary(taskRef, { cwd, agent: values.agent, body: readFile(values.bodyFile, cwd), primaryResult: primaryResult as 'pr_created' | 'pr_reused' | 'no_op', dryRun: values.dryRun === true }));
150
+ finish(await syncPullRequestSummary(taskRef, { cwd, agent: values.agent, body: readFile(values.bodyFile, cwd), changeReportFile: values.changeReportFile, primaryResult: primaryResult as 'pr_created' | 'pr_reused' | 'no_op', dryRun: values.dryRun === true, strict: values.strict === true }));
119
151
  } catch (error) {
120
152
  fail(`unable to read body file: ${error instanceof Error ? error.message : String(error)}`);
121
153
  }
@@ -126,7 +158,7 @@ function platformPr(args: string[] = []): void {
126
158
  return;
127
159
  }
128
160
  try {
129
- finish(createPlatformPullRequest(taskRef, {
161
+ finish(await createPlatformPullRequest(taskRef, {
130
162
  cwd, agent: values.agent, base: values.base, head: values.head,
131
163
  title: readFile(values.titleFile, cwd), body: readFile(values.bodyFile, cwd),
132
164
  draft: values.draft === true, dryRun: values.dryRun === true
@@ -36,14 +36,14 @@ function finish(result: { status: string; [key: string]: unknown }): void {
36
36
  process.exitCode = result.status === 'blocked' ? 2 : result.status === 'failed' ? 1 : 0;
37
37
  }
38
38
 
39
- function platformReleaseNotes(args: string[] = []): void {
39
+ async function platformReleaseNotes(args: string[] = []): Promise<void> {
40
40
  const [action, ...rest] = args;
41
41
  if (action === 'context') {
42
42
  const parsed = parseOptions(rest, ['--cwd', '--history-limit', '--from-tag', '--to-tag', '--branch']);
43
43
  if (!parsed) return finish(invalidInput('invalid context options'));
44
44
  const cwd = path.resolve(parsed.values.get('--cwd') || process.cwd());
45
45
  const historyRaw = parsed.values.get('--history-limit') ?? null;
46
- finish(releaseNoteContext({
46
+ finish(await releaseNoteContext({
47
47
  fromTag: parsed.values.get('--from-tag') || '',
48
48
  toTag: parsed.values.get('--to-tag') || '',
49
49
  branch: parsed.values.get('--branch') || '',
@@ -80,7 +80,7 @@ function platformReleaseNotes(args: string[] = []): void {
80
80
  fs.writeFileSync(resolvedNotesPath, fs.readFileSync(0));
81
81
  }
82
82
  try {
83
- finish(publishReleaseNotes({
83
+ finish(await publishReleaseNotes({
84
84
  tag: parsed.values.get('--tag') || '',
85
85
  title: parsed.values.get('--title') || parsed.values.get('--tag') || '',
86
86
  notesFile: resolvedNotesPath,
@@ -13,7 +13,7 @@ import { inspectPlatformPullRequestByNumber } from '../platform/pull-requests.ts
13
13
  import { verifyInProcess } from '../task/verification-engine.ts';
14
14
 
15
15
  const USAGE = `Usage: agent-infra-internal pr-review-grade decide --input-file <path|-> [--cwd <path>]
16
- agent-infra-internal pr-review-grade resolve-host --pr <N> [--cwd <path>]
16
+ agent-infra-internal pr-review-grade resolve-host --pr <token> [--cwd <path>]
17
17
  agent-infra-internal pr-review-grade verify-artifact --artifact-file <path> [--cwd <path>]
18
18
  `;
19
19
 
@@ -49,7 +49,7 @@ function readInput(value: string, cwd: string): string {
49
49
  return value === '-' ? fs.readFileSync(0, 'utf8') : fs.readFileSync(path.resolve(cwd, value), 'utf8');
50
50
  }
51
51
 
52
- function prReviewGrade(args: string[] = []): void {
52
+ async function prReviewGrade(args: string[] = []): Promise<void> {
53
53
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
54
54
  const operation = args[0];
55
55
  if (!operation || !['decide', 'resolve-host', 'verify-artifact'].includes(operation)) { fail('a valid operation is required'); return; }
@@ -85,9 +85,9 @@ function prReviewGrade(args: string[] = []): void {
85
85
  }
86
86
 
87
87
  if (operation === 'resolve-host') {
88
- const pr = Number(values.pr);
89
- if (!Number.isInteger(pr) || pr <= 0) { fail('resolve-host requires a positive --pr'); return; }
90
- const inspected = inspectPlatformPullRequestByNumber(pr, { cwd });
88
+ const pr = typeof values.pr === 'string' ? values.pr : '';
89
+ if (!pr) { fail('resolve-host requires --pr <token>'); return; }
90
+ const inspected = await inspectPlatformPullRequestByNumber(pr, { cwd });
91
91
  if (!inspected.pullRequest) {
92
92
  finish({
93
93
  status: 'failed', changed: false, host: null, candidates: [], closingIssues: [],
@@ -95,12 +95,14 @@ function prReviewGrade(args: string[] = []): void {
95
95
  }, inspected.status === 'blocked' ? 2 : 1);
96
96
  return;
97
97
  }
98
+ const prNumber = inspected.pullRequest.number;
99
+ const prIdentity = inspected.pullRequest.identity || { kind: 'number' as const, value: prNumber };
98
100
  const closingIssues = extractClosingIssueNumbers(inspected.pullRequest.body);
99
- const candidates = collectHostCandidates({ prNumber: pr, closingIssues, workspaceRoot: cwd });
101
+ const candidates = collectHostCandidates({ prNumber, prIdentity, closingIssues, workspaceRoot: cwd });
100
102
  const host: HostResolution = resolveHostFromCandidates(candidates);
101
103
  finish({
102
104
  status: 'ok', changed: false,
103
- pr: { number: pr, baseSha: inspected.pullRequest.base.sha, headSha: inspected.pullRequest.head.sha, state: inspected.pullRequest.state },
105
+ pr: { number: prNumber, identity: prIdentity, baseSha: inspected.pullRequest.base.sha, headSha: inspected.pullRequest.head.sha, state: inspected.pullRequest.state },
104
106
  closingIssues, candidates, host,
105
107
  taskIssueMatches: deriveTaskIssueMatches(host, closingIssues), error: null
106
108
  });
@@ -111,7 +113,7 @@ function prReviewGrade(args: string[] = []): void {
111
113
  const artifactPath = path.resolve(cwd, values.artifactFile);
112
114
  let result: Record<string, unknown>;
113
115
  try {
114
- result = verifyInProcess({
116
+ result = await verifyInProcess({
115
117
  mode: 'checks',
116
118
  skillName: 'review-pr',
117
119
  taskDir: path.dirname(artifactPath),
@@ -251,7 +251,7 @@ async function inspectFacts(cwd: string, version: string): Promise<ReleaseFacts>
251
251
  const local = inspectLocalReleaseFacts(cwd, version);
252
252
  const remoteBranch = branch ? git(cwd, ['ls-remote', '--heads', 'origin', branch]) : null;
253
253
  const remoteTag = git(cwd, ['ls-remote', '--tags', 'origin', `refs/tags/${tag}`]);
254
- const platform = inspectPlatformRelease(tag, { cwd });
254
+ const platform = await inspectPlatformRelease(tag, { cwd });
255
255
  const npm = await inspectNpmChannel(pkg.name, version);
256
256
  const formulaUrl = `https://raw.githubusercontent.com/${config.org}/homebrew-tap/main/Formula/${config.project}.rb`;
257
257
  const homebrew = await inspectHomebrewChannel(formulaUrl, version);
@@ -262,7 +262,7 @@ async function inspectFacts(cwd: string, version: string): Promise<ReleaseFacts>
262
262
  localTagAncestor: local.localTagAncestor,
263
263
  localTagConflict: local.localTagConflict,
264
264
  remoteBranch: Boolean(remoteBranch && remoteBranch.split(/\s+/)[0] === head), remoteTag: Boolean(remoteTag),
265
- githubRelease: platform.platform.type !== 'github'
265
+ githubRelease: platform.error?.code === 'PLATFORM_CAPABILITY_UNSUPPORTED'
266
266
  ? true
267
267
  : platform.status === 'blocked' ? null : Boolean(platform.release?.published),
268
268
  npm: npm.published, homebrew: homebrew.published, smoke,
@@ -324,7 +324,7 @@ async function releaseWorkflow(args: string[] = []): Promise<void> {
324
324
  }
325
325
  if (action === 'prepare') {
326
326
  if (before.phase !== 'unprepared') {
327
- const milestones = reconcileReleaseMilestones(version, { cwd });
327
+ const milestones = await reconcileReleaseMilestones(version, { cwd });
328
328
  process.stdout.write(`${JSON.stringify({ ...milestones, snapshot: before })}\n`);
329
329
  process.exitCode = milestones.status === 'failed' ? 1 : milestones.status === 'blocked' ? 2 : 0;
330
330
  return;
@@ -344,7 +344,7 @@ async function releaseWorkflow(args: string[] = []): Promise<void> {
344
344
  const committed = commitExplicitPaths({ cwd, paths: changedPaths(cwd), message: `chore: release v${version}` });
345
345
  if (committed.status === 'failed') { process.stdout.write(`${JSON.stringify(committed)}\n`); process.exitCode = 1; return; }
346
346
  const tagged = command(cwd, 'git', ['tag', '-a', `v${version}`, '-m', `Release v${version}`]);
347
- const milestones = tagged.status === 0 ? reconcileReleaseMilestones(version, { cwd }) : null;
347
+ const milestones = tagged.status === 0 ? await reconcileReleaseMilestones(version, { cwd }) : null;
348
348
  const snapshot = releaseSnapshot(version, await inspectFacts(cwd, version));
349
349
  const failed = tagged.status !== 0 || milestones?.status === 'failed';
350
350
  const blocked = milestones?.status === 'blocked';
@@ -1,4 +1,5 @@
1
1
  import {
2
+ recoverSandboxControl,
2
3
  requestSandboxControl,
3
4
  requestSandboxTaskFinalization,
4
5
  requestSandboxTaskControl,
@@ -39,6 +40,11 @@ function finalizationErrorStatus(error: { retryable: boolean; code: string }): F
39
40
  return error.retryable ? 'blocked' : 'failed';
40
41
  }
41
42
 
43
+ function writeClientError(error: SandboxControlClientError): void {
44
+ process.stderr.write(`${error.detail.message}\n`);
45
+ if (error.requestId) process.stderr.write(`SANDBOX_CONTROL_REQUEST_ID: ${error.requestId}\n`);
46
+ }
47
+
42
48
  function sandboxFinalizationClient(args: string[]): void {
43
49
  if (args.length !== 4 || !args[0] || args[1] !== 'complete' || args[2] !== '--agent' || !args[3]) {
44
50
  const error = { code: 'TASK_FINALIZATION_PAYLOAD_INVALID', message: 'task ref, complete intent, and --agent are required', retryable: false };
@@ -60,7 +66,7 @@ function sandboxFinalizationClient(args: string[]): void {
60
66
  } catch (error) {
61
67
  if (!(error instanceof SandboxControlClientError)) throw error;
62
68
  writeFinalizationEnvelope(finalizationErrorStatus(error.detail), error.accepted, error.detail);
63
- process.stderr.write(`${error.detail.message}\n`);
69
+ writeClientError(error);
64
70
  process.exitCode = error.detail.code === 'SANDBOX_CONTROL_RESULT_UNKNOWN' ? 1 : error.detail.retryable ? 2 : 1;
65
71
  return;
66
72
  }
@@ -107,6 +113,24 @@ async function sandboxControl(args: string[]): Promise<void> {
107
113
  await runSandboxControlExecutor(request, nonce);
108
114
  return;
109
115
  }
116
+ if (operation === 'recover') {
117
+ if (rest.length !== 1 || !rest[0]) throw new Error('sandbox-control recover requires <request-id>');
118
+ let response;
119
+ try {
120
+ response = recoverSandboxControl(rest[0]);
121
+ } catch (error) {
122
+ if (!(error instanceof SandboxControlClientError)) throw error;
123
+ writeClientError(error);
124
+ process.exitCode = error.detail.code === 'SANDBOX_CONTROL_RESULT_UNKNOWN' ? 1 : error.detail.retryable ? 75 : 1;
125
+ return;
126
+ }
127
+ process.stdout.write(response.stdout);
128
+ process.stderr.write(response.stderr);
129
+ process.exitCode = response.phase === 'rejected'
130
+ ? response.error?.retryable ? 75 : 1
131
+ : response.exitCode ?? 1;
132
+ return;
133
+ }
110
134
  if (operation === 'client') {
111
135
  const [family = '', ...commandArgs] = rest;
112
136
  if (family === 'task-finalization') {
@@ -126,7 +150,7 @@ async function sandboxControl(args: string[]): Promise<void> {
126
150
  }
127
151
  } catch (error) {
128
152
  if (!(error instanceof SandboxControlClientError)) throw error;
129
- process.stderr.write(`${error.detail.message}\n`);
153
+ writeClientError(error);
130
154
  process.exitCode = error.detail.retryable ? 75 : 1;
131
155
  return;
132
156
  }
@@ -140,7 +164,7 @@ async function sandboxControl(args: string[]): Promise<void> {
140
164
  }
141
165
  return;
142
166
  }
143
- throw new Error('Usage: agent-infra-internal sandbox-control serve --manifest <path> | execute --request <path> --nonce <nonce> | client <family> [args...]');
167
+ throw new Error('Usage: agent-infra-internal sandbox-control serve --manifest <path> | execute --request <path> --nonce <nonce> | client <family> [args...] | recover <request-id>');
144
168
  }
145
169
 
146
170
  export { sandboxControl };
@@ -43,7 +43,7 @@ function usageFailure(message: string): void {
43
43
  process.exitCode = 1;
44
44
  }
45
45
 
46
- function taskActivity(args: string[] = []): void {
46
+ async function taskActivity(args: string[] = []): Promise<void> {
47
47
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
48
48
  const [taskRef, kind] = args;
49
49
  if (!taskRef || taskRef.startsWith('--') || !kind || !OPERATIONS.has(kind)) {
@@ -94,11 +94,11 @@ function taskActivity(args: string[] = []): void {
94
94
  let result;
95
95
  let humanOverride: unknown = null;
96
96
  try {
97
- result = withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-activity.${kind}`, () => {
97
+ result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-activity.${kind}`, async () => {
98
98
  let current = applyPrReviewActivityIntent(values as PrReviewActivityIntent, { lockAlreadyHeld: true });
99
99
  if (current.status !== 'failed' || !values.overrideTicket) return current;
100
100
  if (!values.overrideTarget || !values.overrideScope) { usageFailure('override ticket requires target and scope'); return current; }
101
- const consumed = consumeHumanOverride({
101
+ const consumed = await consumeHumanOverride({
102
102
  taskRef, ticketId: String(values.overrideTicket),
103
103
  failureId: failureId('activity-intent', current.error?.code ?? 'TASK_STATE_MISMATCH'),
104
104
  target: String(values.overrideTarget), scope: String(values.overrideScope)
@@ -1,6 +1,10 @@
1
1
  import { resolveArtifactContext } from '../task/artifact-lifecycle.ts';
2
+ import { finalizeLocalArtifact } from '../task/local-artifact-finalization.ts';
3
+ import type { LocalArtifactFamily } from '../task/local-artifact-finalization.ts';
4
+ import { resolveTaskRef } from '../task/resolve-ref.ts';
5
+ import { loadVerificationConfig } from '../task/verification-config.ts';
2
6
 
3
- const USAGE = `Usage: agent-infra-internal task-artifact <N | TASK-id> inspect --family <family>\n\nInspect one workflow artifact family and print a read-only JSON context.\n`;
7
+ const USAGE = `Usage: agent-infra-internal task-artifact <N | TASK-id> inspect --family <family>\n agent-infra-internal task-artifact <N | TASK-id> finalize-local --family <analysis|plan|code> --artifact <artifact>\n\nInspect workflow artifact context or finalize a local analysis/plan/code artifact without changing task state.\n`;
4
8
 
5
9
  function failUsage(message: string): void {
6
10
  process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'ARTIFACT_PAYLOAD_INVALID', message } })}\n`);
@@ -11,37 +15,76 @@ function failUsage(message: string): void {
11
15
  function taskArtifact(args: string[] = []): void {
12
16
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
13
17
  if (args.length < 2) { failUsage('task ref and operation are required'); return; }
14
- if (args[1] !== 'inspect') { failUsage(`unknown operation '${args[1]}'`); return; }
18
+ const operation = args[1];
19
+ if (operation !== 'inspect' && operation !== 'finalize-local') { failUsage(`unknown operation '${operation}'`); return; }
15
20
  let family = '';
21
+ let artifact = '';
16
22
  const seen = new Set<string>();
17
23
  for (let index = 2; index < args.length; index += 1) {
18
24
  const flag = args[index]!;
19
- if (flag !== '--family') { failUsage(`unknown option '${flag}'`); return; }
25
+ if (flag !== '--family' && flag !== '--artifact') { failUsage(`unknown option '${flag}'`); return; }
20
26
  if (seen.has(flag)) { failUsage(`duplicate option '${flag}'`); return; }
21
27
  const value = args[++index];
22
28
  if (!value || value.startsWith('--')) { failUsage(`option '${flag}' requires a value`); return; }
23
29
  seen.add(flag);
24
- family = value;
30
+ if (flag === '--family') family = value;
31
+ else artifact = value;
25
32
  }
26
33
  if (!family) { failUsage("option '--family' is required"); return; }
27
- const result = resolveArtifactContext(args[0]!, family);
28
- const output = family === 'code' && result.codeMode ? {
29
- ...result,
30
- mode: result.codeMode.mode,
31
- code_max: result.codeMode.codeMax,
32
- rev_max: result.codeMode.reviewMax,
33
- verdict: result.codeMode.verdict,
34
- next_round: result.next?.round ?? null,
35
- next_artifact: result.next?.name ?? null,
36
- review_artifact: result.codeMode.reviewArtifact,
37
- implementation_input: result.codeMode.implementationInput,
38
- decision_id: result.codeMode.decisionId,
39
- decision_evidence: result.codeMode.decisionEvidence,
40
- message: result.codeMode.message
41
- } : result;
42
- process.stdout.write(`${JSON.stringify(output)}\n`);
43
- if (result.status === 'refused') process.exitCode = 1;
44
- else if (result.status === 'failed') process.exitCode = 2;
34
+ if (operation === 'inspect') {
35
+ if (artifact) { failUsage("option '--artifact' is only valid for finalize-local"); return; }
36
+ const result = resolveArtifactContext(args[0]!, family);
37
+ const output = family === 'code' && result.codeMode ? {
38
+ ...result,
39
+ mode: result.codeMode.mode,
40
+ code_max: result.codeMode.codeMax,
41
+ rev_max: result.codeMode.reviewMax,
42
+ verdict: result.codeMode.verdict,
43
+ next_round: result.next?.round ?? null,
44
+ next_artifact: result.next?.name ?? null,
45
+ review_artifact: result.codeMode.reviewArtifact,
46
+ implementation_input: result.codeMode.implementationInput,
47
+ decision_id: result.codeMode.decisionId,
48
+ decision_evidence: result.codeMode.decisionEvidence,
49
+ message: result.codeMode.message
50
+ } : result;
51
+ process.stdout.write(`${JSON.stringify(output)}\n`);
52
+ if (result.status === 'refused') process.exitCode = 1;
53
+ else if (result.status === 'failed') process.exitCode = 2;
54
+ return;
55
+ }
56
+ const resolved = resolveTaskRef(args[0]!);
57
+ const repositoryRoot = resolved.ok ? resolved.repoRoot : process.cwd();
58
+ if (!artifact) { failUsage("option '--artifact' is required"); return; }
59
+ if (family !== 'analysis' && family !== 'plan' && family !== 'code') {
60
+ failUsage("finalize-local only supports 'analysis', 'plan', and 'code'");
61
+ return;
62
+ }
63
+ const skillName = family === 'analysis' ? 'analyze-task' : family === 'plan' ? 'plan-task' : 'code-task';
64
+ let config: { requiredSections?: readonly string[]; requiredPatterns?: readonly string[] } = {};
65
+ try {
66
+ const loaded = loadVerificationConfig(repositoryRoot, skillName);
67
+ const artifactConfig = loaded.checks.artifact;
68
+ if (artifactConfig && typeof artifactConfig === 'object' && !Array.isArray(artifactConfig)) {
69
+ const sections = artifactConfig.required_sections;
70
+ const patterns = artifactConfig.required_patterns;
71
+ config = {
72
+ requiredSections: Array.isArray(sections) ? sections.filter((value): value is string => typeof value === 'string') : undefined,
73
+ requiredPatterns: Array.isArray(patterns) ? patterns.filter((value): value is string => typeof value === 'string') : undefined
74
+ };
75
+ }
76
+ } catch {
77
+ // Isolated fixture repositories may not contain the project's verification config.
78
+ }
79
+ const result = finalizeLocalArtifact({
80
+ taskRef: args[0]!,
81
+ family: family as LocalArtifactFamily,
82
+ artifact,
83
+ repoRoot: repositoryRoot,
84
+ ...config
85
+ });
86
+ process.stdout.write(`${JSON.stringify(result)}\n`);
87
+ if (result.status === 'failed') process.exitCode = 1;
45
88
  }
46
89
 
47
90
  export { taskArtifact };
@@ -18,7 +18,7 @@ function output(result: TaskCreateResult): void {
18
18
  process.exitCode = result.status === 'blocked' ? 2 : result.status === 'failed' ? 1 : 0;
19
19
  }
20
20
 
21
- function taskCreate(args: string[]): void {
21
+ async function taskCreate(args: string[]): Promise<void> {
22
22
  const inputIndex = args.indexOf('--input');
23
23
  const input = inputIndex >= 0 ? args[inputIndex + 1] : undefined;
24
24
  if (!input || args.length !== 2 || inputIndex !== 0) {
@@ -46,7 +46,7 @@ function taskCreate(args: string[]): void {
46
46
  process.exitCode = response.exitCode;
47
47
  return;
48
48
  }
49
- output(createTask(candidate, { repoRoot: process.cwd() }));
49
+ output(await createTask(candidate, { repoRoot: process.cwd() }));
50
50
  } catch (error) {
51
51
  if (error instanceof SandboxControlClientError) {
52
52
  output(failed(error.detail.code, error.detail.message, error.detail.retryable));
@@ -0,0 +1,53 @@
1
+ import path from 'node:path';
2
+
3
+ import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.ts';
4
+ import { deliverTaskBranch } from '../task/delivery.ts';
5
+
6
+ const USAGE = `Usage: agent-infra-internal task-delivery <task-ref> deliver --agent <agent> [--remote <name>] [--base <branch>] [--dry-run] [--cwd <path>]\n`;
7
+
8
+ function taskDelivery(args: string[] = []): void {
9
+ const taskRef = args[0];
10
+ const operation = args[1];
11
+ if (!taskRef || operation !== 'deliver') {
12
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'DELIVERY_PAYLOAD_INVALID', message: 'task ref and deliver operation are required' } })}\n`);
13
+ process.stderr.write(USAGE);
14
+ process.exitCode = 1;
15
+ return;
16
+ }
17
+ let agent = '';
18
+ let remote: string | undefined;
19
+ let baseRef: string | undefined;
20
+ let cwd = process.cwd();
21
+ let dryRun = false;
22
+ for (let index = 2; index < args.length; index += 1) {
23
+ const flag = args[index];
24
+ if (flag === '--dry-run') { dryRun = true; continue; }
25
+ const value = args[++index];
26
+ if (value === undefined || value.startsWith('--')) {
27
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'DELIVERY_PAYLOAD_INVALID', message: `${flag} requires a value` } })}\n`);
28
+ process.exitCode = 1;
29
+ return;
30
+ }
31
+ if (flag === '--agent') agent = value;
32
+ else if (flag === '--remote') remote = value;
33
+ else if (flag === '--base') baseRef = value;
34
+ else if (flag === '--cwd') cwd = path.resolve(value);
35
+ else {
36
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'DELIVERY_PAYLOAD_INVALID', message: `unknown option '${flag}'` } })}\n`);
37
+ process.exitCode = 1;
38
+ return;
39
+ }
40
+ }
41
+ const normalized = normalizeAgentToken(agent);
42
+ if (!normalized) {
43
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'DELIVERY_PAYLOAD_INVALID', message: `invalid --agent '${agent}': ${AGENT_USAGE_HINT}` } })}\n`);
44
+ process.exitCode = 1;
45
+ return;
46
+ }
47
+ const result = deliverTaskBranch(taskRef, { repoRoot: cwd, agent: normalized, remote, baseRef, dryRun });
48
+ process.stdout.write(`${JSON.stringify(result)}\n`);
49
+ if (result.status === 'failed') process.exitCode = 1;
50
+ if (result.status === 'blocked') process.exitCode = 2;
51
+ }
52
+
53
+ export { taskDelivery };
@@ -13,6 +13,9 @@ Events: ${eventCatalog.join(', ')}
13
13
 
14
14
  const FLAGS: Record<string, keyof TaskEventRequest> = {
15
15
  '--agent': 'agent', '--round': 'round', '--question': 'question', '--artifact': 'artifact',
16
+ '--artifact-sha256': 'artifactSha256', '--semantic-digest': 'semanticDigest',
17
+ '--initiator': 'initiator', '--request-id': 'requestId', '--reason-code': 'reasonCode',
18
+ '--source-finding': 'sourceFinding', '--source-artifact': 'sourceArtifact', '--source-sha256': 'sourceSha256',
16
19
  '--fix-for': 'fixFor', '--implementation-input': 'implementationInput',
17
20
  '--verdict': 'verdict', '--blockers': 'blockers', '--major': 'major',
18
21
  '--minor': 'minor', '--manual-validation': 'manualValidation', '--files-modified': 'filesModified',
@@ -27,7 +30,7 @@ function usageFailure(message: string): void {
27
30
  process.exitCode = 1;
28
31
  }
29
32
 
30
- function taskEvent(args: string[] = []): void {
33
+ async function taskEvent(args: string[] = []): Promise<void> {
31
34
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
32
35
  if (args.length < 2) { usageFailure('task ref and event are required'); return; }
33
36
  const request: TaskEventRequest = { taskRef: args[0]!, event: args[1]!, agent: '' };
@@ -66,14 +69,14 @@ function taskEvent(args: string[] = []): void {
66
69
  let result;
67
70
  let humanOverride: unknown = null;
68
71
  try {
69
- result = withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-event.${request.event}`, () => {
72
+ result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-event.${request.event}`, async () => {
70
73
  let current = applyTaskEvent(request, { lockAlreadyHeld: true });
71
74
  const values = request as Record<string, unknown>;
72
75
  if (current.status !== 'failed' || !values.overrideTicket) return current;
73
76
  if (!values.overrideTarget || !values.overrideScope) {
74
77
  return { ...current, humanOverride: { status: 'failed', error: { code: 'OVERRIDE_PAYLOAD_INVALID', message: 'override ticket requires target and scope' } } } as typeof current & { humanOverride: unknown };
75
78
  }
76
- const consumed = consumeHumanOverride({
79
+ const consumed = await consumeHumanOverride({
77
80
  taskRef: request.taskRef,
78
81
  ticketId: String(values.overrideTicket),
79
82
  failureId: failureId('task-event', current.error?.code ?? 'EVENT_TRANSITION_INVALID'),
@@ -14,7 +14,7 @@ function envelope(
14
14
  status: 'completed' | 'failed' | 'blocked' | 'unknown',
15
15
  changed: boolean,
16
16
  accepted: boolean,
17
- result: ReturnType<typeof applyTaskFinalization> | null,
17
+ result: Awaited<ReturnType<typeof applyTaskFinalization>> | null,
18
18
  error: FinalizationError | null
19
19
  ): string {
20
20
  return `${JSON.stringify({ version: 1, status, changed, accepted, result, error })}\n`;
@@ -36,7 +36,7 @@ function parseFailure(error: unknown): string {
36
36
  return message.replace(/^TASK_CONTROL_OPERATION_INVALID: /u, '');
37
37
  }
38
38
 
39
- function taskFinalization(args: string[] = []): void {
39
+ async function taskFinalization(args: string[] = []): Promise<void> {
40
40
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
41
41
 
42
42
  let operation;
@@ -71,7 +71,7 @@ function taskFinalization(args: string[] = []): void {
71
71
  ...operation,
72
72
  request: { ...operation.request, taskRef: resolved.taskId }
73
73
  };
74
- const result = dispatchTaskControlOperation(
74
+ const result = await dispatchTaskControlOperation(
75
75
  createDirectHostExecutionContext({ repoRoot }),
76
76
  boundOperation
77
77
  );