@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
@@ -36,7 +36,6 @@ type DecisionDetailResolution =
36
36
  type DecisionDetailDuplicate = {
37
37
  id: string;
38
38
  blocks: DecisionDetailBlock[];
39
- repairable: boolean;
40
39
  };
41
40
 
42
41
  type DecisionDetailInspection =
@@ -49,15 +48,6 @@ type DecisionDetailInspection =
49
48
  duplicates: DecisionDetailDuplicate[];
50
49
  };
51
50
 
52
- type DecisionDetailRepair =
53
- | { ok: true; changed: boolean; content: string }
54
- | {
55
- ok: false;
56
- code: 'DECISION_DETAIL_AMBIGUOUS';
57
- message: string;
58
- content: string;
59
- };
60
-
61
51
  const DECISION_ID = /^(AN|PL|CD|HD)-[1-9]\d*(?=$|[\s::])/i;
62
52
  const HEADING = /^ {0,3}(#{1,6})[ \t]+(.+?)\s*$/;
63
53
  const FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})(.*)$/;
@@ -172,32 +162,8 @@ function resolveDecisionDetail(content: string, rowId: string, anchor: string):
172
162
  return { status: 'found', block: matches[0]! };
173
163
  }
174
164
 
175
- const INFORMAL_SHORT_HEADING = /^(?:AN|PL|CD|HD)-[1-9]\d*[::]\s*(?:上一轮)?简短复核$/i;
176
- const INFORMAL_SHORT_FRAGMENT = /^简短(?:结论|说明)$/;
177
-
178
- function isInformalShortBlock(block: DecisionDetailBlock): boolean {
179
- if (block.canonical || block.content.length > 600) return false;
180
- if (!INFORMAL_SHORT_HEADING.test(block.heading)) return false;
181
- const scanned = scanVisibleMarkdown(block.content);
182
- const bodyLines = scanned.lines
183
- .filter((line) => !scanned.headings.some((heading) => heading.start === line.start) && line.text.trim())
184
- .map((line) => line.text);
185
- if (bodyLines.length === 0 || bodyLines.length > 2) return false;
186
- const fragments = bodyLines.map((line) => line.match(/^\s*[-*]\s+([^\s].*?)\s*$/)?.[1] ?? null);
187
- if (fragments.some((fragment) => fragment === null)) return false;
188
- return fragments.every((fragment) => INFORMAL_SHORT_FRAGMENT.test(fragment!));
189
- }
190
-
191
- function hasDirectPrecedingAnchor(block: DecisionDetailBlock, scanned: VisibleMarkdown): boolean {
192
- return scanned.anchors.some((anchor) => (
193
- anchor.end < block.start
194
- && !scanned.lines.some((line) => line.start > anchor.end && line.start < block.start && line.text.trim())
195
- ));
196
- }
197
-
198
165
  function inspectDecisionDetailDuplicates(content: string): DecisionDetailInspection {
199
166
  const blocks = parseDecisionDetailBlocks(content);
200
- const scanned = scanVisibleMarkdown(content);
201
167
  const grouped = new Map<string, DecisionDetailBlock[]>();
202
168
  for (const block of blocks) {
203
169
  const key = block.id.toUpperCase();
@@ -208,16 +174,12 @@ function inspectDecisionDetailDuplicates(content: string): DecisionDetailInspect
208
174
  const duplicates: DecisionDetailDuplicate[] = [];
209
175
  for (const group of grouped.values()) {
210
176
  if (group.length < 2) continue;
211
- const canonical = group.filter((block) => block.canonical);
212
- const repairable = canonical.length === 1 && group.every((block) => (
213
- block.canonical || (!hasDirectPrecedingAnchor(block, scanned) && isInformalShortBlock(block))
214
- ));
215
- duplicates.push({ id: canonical[0]?.id ?? group[0]!.id, blocks: group, repairable });
177
+ duplicates.push({ id: group[0]!.id, blocks: group });
216
178
  }
217
179
  if (duplicates.length === 0) return { ok: true, blocks };
218
180
  const summary = duplicates.map((duplicate) => {
219
181
  const types = duplicate.blocks.map((block) => block.canonical ? 'canonical' : 'informal').join(', ');
220
- return `${duplicate.id} (${duplicate.blocks.length} blocks: ${types}${duplicate.repairable ? '; safe repair available' : ''})`;
182
+ return `${duplicate.id} (${duplicate.blocks.length} blocks: ${types})`;
221
183
  }).join(', ');
222
184
  return {
223
185
  ok: false,
@@ -228,26 +190,6 @@ function inspectDecisionDetailDuplicates(content: string): DecisionDetailInspect
228
190
  };
229
191
  }
230
192
 
231
- function repairDecisionDetailDuplicates(content: string): DecisionDetailRepair {
232
- const inspection = inspectDecisionDetailDuplicates(content);
233
- if (inspection.ok) return { ok: true, changed: false, content };
234
- const unsafe = inspection.duplicates.filter((duplicate) => !duplicate.repairable);
235
- if (unsafe.length > 0) {
236
- return {
237
- ok: false,
238
- code: 'DECISION_DETAIL_AMBIGUOUS',
239
- message: `Cannot safely repair duplicate decision detail ids: ${unsafe.map((duplicate) => duplicate.id).join(', ')}`,
240
- content
241
- };
242
- }
243
- const removals = inspection.duplicates.flatMap((duplicate) => duplicate.blocks.filter((block) => !block.canonical));
244
- let repaired = content;
245
- for (const block of removals.sort((left, right) => right.start - left.start)) {
246
- repaired = repaired.slice(0, block.start) + repaired.slice(block.end);
247
- }
248
- return { ok: true, changed: repaired !== content, content: repaired };
249
- }
250
-
251
193
  type FieldKey = 'decision' | 'why' | 'impact' | 'risk' | 'analogy' | 'recommend' | 'reason' | 'implementation';
252
194
 
253
195
  const FIELD_KEYS: Record<string, FieldKey> = {
@@ -328,13 +270,15 @@ export {
328
270
  normalizeDecisionDetailForDisplay,
329
271
  parseDecisionDetailBlocks,
330
272
  parseDecisionEvidence,
331
- repairDecisionDetailDuplicates,
332
- resolveDecisionDetail
273
+ resolveDecisionDetail,
274
+ scanVisibleMarkdown
333
275
  };
334
276
  export type {
335
277
  DecisionDetailBlock,
336
278
  DecisionDetailDuplicate,
337
279
  DecisionDetailInspection,
338
- DecisionDetailRepair,
339
- DecisionDetailResolution
280
+ DecisionDetailResolution,
281
+ SourceLine,
282
+ VisibleHeading,
283
+ VisibleMarkdown
340
284
  };
@@ -0,0 +1,130 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { execFileSync } from 'node:child_process';
4
+
5
+ export type DeliveryTarget = Readonly<{
6
+ remote: string;
7
+ baseRef: string;
8
+ }>;
9
+
10
+ export type DeliveryTargetBindingInput = Readonly<{
11
+ defaults?: Partial<DeliveryTarget>;
12
+ existing?: Partial<DeliveryTarget>;
13
+ explicit?: Partial<DeliveryTarget>;
14
+ }>;
15
+
16
+ export type DeliveryTargetResult =
17
+ | { ok: true; value: DeliveryTarget }
18
+ | { ok: false; code: string; message: string };
19
+
20
+ export type DiffBaseResult =
21
+ | { ok: true; diffBase: string }
22
+ | { ok: false; code: string; message: string };
23
+
24
+ const REMOTE_RE = /^(?!-)(?!.*\.\.)(?!.*[~^:?*\\\s])[A-Za-z0-9._/-]+$/;
25
+ const REF_RE = /^(?!-)(?!.*\.\.)(?!.*(?:^|\/)\.)(?!.*[~^:?*\\\s])[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*$/;
26
+
27
+ function validateRemote(value: unknown): value is string {
28
+ return typeof value === 'string' && value.length > 0 && REMOTE_RE.test(value);
29
+ }
30
+
31
+ function validateBaseRef(value: unknown): value is string {
32
+ return typeof value === 'string' && value.length > 0 && !value.startsWith('refs/') && REF_RE.test(value);
33
+ }
34
+
35
+ function invalid(field: string, value: unknown): DeliveryTargetResult {
36
+ return { ok: false, code: 'DELIVERY_TARGET_INVALID', message: `${field} is invalid: ${String(value ?? '')}` };
37
+ }
38
+
39
+ function bindDeliveryTarget(input: DeliveryTargetBindingInput): DeliveryTargetResult {
40
+ const remote = input.existing?.remote ?? input.explicit?.remote ?? input.defaults?.remote;
41
+ const baseRef = input.existing?.baseRef ?? input.explicit?.baseRef ?? input.defaults?.baseRef;
42
+ if (input.existing?.remote !== undefined && input.explicit?.remote !== undefined && input.existing.remote !== input.explicit.remote) {
43
+ return { ok: false, code: 'DELIVERY_TARGET_CONFLICT', message: 'Explicit delivery remote does not match the task binding' };
44
+ }
45
+ if (input.existing?.baseRef !== undefined && input.explicit?.baseRef !== undefined && input.existing.baseRef !== input.explicit.baseRef) {
46
+ return { ok: false, code: 'DELIVERY_TARGET_CONFLICT', message: 'Explicit delivery base ref does not match the task binding' };
47
+ }
48
+ if (!validateRemote(remote)) return invalid('delivery remote', remote);
49
+ if (!validateBaseRef(baseRef)) return invalid('delivery base ref', baseRef);
50
+ return { ok: true, value: { remote, baseRef } };
51
+ }
52
+
53
+ function readDeliveryDefaults(repoRoot: string): DeliveryTargetResult {
54
+ try {
55
+ const configPath = path.join(repoRoot, '.agents', '.airc.json');
56
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8')) as Record<string, unknown>;
57
+ if (!config.delivery || typeof config.delivery !== 'object' || Array.isArray(config.delivery)) {
58
+ return { ok: false, code: 'DELIVERY_CONFIG_INVALID', message: 'delivery config must declare remote and baseRef' };
59
+ }
60
+ const delivery = config.delivery as Record<string, unknown>;
61
+ if (typeof delivery.remote !== 'string' || typeof delivery.baseRef !== 'string') {
62
+ return { ok: false, code: 'DELIVERY_CONFIG_INVALID', message: 'delivery config must declare remote and baseRef' };
63
+ }
64
+ return bindDeliveryTarget({
65
+ defaults: {
66
+ remote: delivery.remote,
67
+ baseRef: delivery.baseRef
68
+ }
69
+ });
70
+ } catch (error) {
71
+ return { ok: false, code: 'DELIVERY_CONFIG_INVALID', message: error instanceof Error ? error.message : String(error) };
72
+ }
73
+ }
74
+
75
+ function resolveDeliveryTarget(
76
+ repoRoot: string,
77
+ existing: Partial<DeliveryTarget> = {},
78
+ explicit: Partial<DeliveryTarget> = {}
79
+ ): DeliveryTargetResult {
80
+ const defaults = readDeliveryDefaults(repoRoot);
81
+ if (!defaults.ok) return defaults;
82
+ return bindDeliveryTarget({ defaults: defaults.value, existing, explicit });
83
+ }
84
+
85
+ function gitText(repoRoot: string, args: readonly string[]): string {
86
+ return execFileSync('git', [...args], {
87
+ cwd: repoRoot,
88
+ encoding: 'utf8',
89
+ stdio: ['ignore', 'pipe', 'pipe']
90
+ }).trim();
91
+ }
92
+
93
+ function resolveTargetHead(repoRoot: string, target: DeliveryTarget): DeliveryTargetResult & { head?: string } {
94
+ try {
95
+ const output = gitText(repoRoot, ['ls-remote', '--refs', target.remote, `refs/heads/${target.baseRef}`]);
96
+ const head = output.split(/\s+/)[0] ?? '';
97
+ if (!/^[a-f0-9]{40}$/i.test(head)) {
98
+ return { ok: false, code: 'DELIVERY_TARGET_UNAVAILABLE', message: `Delivery target ${target.remote}/${target.baseRef} is unavailable` };
99
+ }
100
+ try { gitText(repoRoot, ['cat-file', '-e', `${head}^{commit}`]); }
101
+ catch {
102
+ return { ok: false, code: 'DELIVERY_TARGET_OBJECT_MISSING', message: `Delivery target commit ${head} is not available locally` };
103
+ }
104
+ return { ok: true, value: target, head };
105
+ } catch (error) {
106
+ return { ok: false, code: 'DELIVERY_TARGET_UNAVAILABLE', message: error instanceof Error ? error.message : String(error) };
107
+ }
108
+ }
109
+
110
+ function resolveDiffBase(repoRoot: string, reviewedHead: string, targetHead: string): DiffBaseResult {
111
+ try {
112
+ const diffBase = gitText(repoRoot, ['merge-base', reviewedHead, targetHead]);
113
+ if (!/^[a-f0-9]{40}$/i.test(diffBase)) {
114
+ return { ok: false, code: 'DELIVERY_DIFF_BASE_UNAVAILABLE', message: 'Git returned an invalid diff base' };
115
+ }
116
+ return { ok: true, diffBase };
117
+ } catch (error) {
118
+ return { ok: false, code: 'DELIVERY_DIFF_BASE_UNAVAILABLE', message: error instanceof Error ? error.message : String(error) };
119
+ }
120
+ }
121
+
122
+ export {
123
+ bindDeliveryTarget,
124
+ readDeliveryDefaults,
125
+ resolveDeliveryTarget,
126
+ resolveTargetHead,
127
+ resolveDiffBase,
128
+ validateBaseRef,
129
+ validateRemote
130
+ };
@@ -0,0 +1,160 @@
1
+ import fs from 'node:fs';
2
+ import { spawnSync } from 'node:child_process';
3
+ import path from 'node:path';
4
+
5
+ import { parseTaskFrontmatter } from './frontmatter.ts';
6
+ import { resolveTaskRef } from './resolve-ref.ts';
7
+ import { resolveDeliveryTarget, resolveDiffBase, resolveTargetHead, validateBaseRef, validateRemote } from './delivery-target.ts';
8
+ import { extractReviewBaseline, extractReviewDiffBase, extractReviewTargetHead, extractReviewedHead, findAuthoritativeReviewCodeArtifact } from './review-fingerprint.ts';
9
+ import { captureTaskWriteMetadata, writeTask } from './write.ts';
10
+ import { withRepositoryMutationLock, withTaskExecutionLock } from './task-execution-lock.ts';
11
+
12
+ export type DeliveryState = 'absent' | 'same' | 'known-old' | 'unknown-drift';
13
+
14
+ export type DeliveryClassification = Readonly<{
15
+ state: DeliveryState;
16
+ shouldPush: boolean;
17
+ }>;
18
+
19
+ export type TaskBranchDeliveryResult = Readonly<{
20
+ status: 'applied' | 'no-op' | 'failed' | 'blocked' | 'planned';
21
+ changed: boolean;
22
+ taskId: string | null;
23
+ remoteHead: string | null;
24
+ localHead: string | null;
25
+ state: DeliveryState | null;
26
+ error: { code: string; message: string; retryable: boolean } | null;
27
+ }>;
28
+
29
+ function classifyDeliveryState(localHead: string, remoteHead: string | null, lastDelivered: string | null): DeliveryClassification {
30
+ if (remoteHead === null) return { state: 'absent', shouldPush: true };
31
+ if (remoteHead === localHead) return { state: 'same', shouldPush: false };
32
+ if (lastDelivered && remoteHead === lastDelivered) return { state: 'known-old', shouldPush: true };
33
+ return { state: 'unknown-drift', shouldPush: false };
34
+ }
35
+
36
+ function git(cwd: string, args: readonly string[]): { status: number | null; stdout: string; stderr: string } {
37
+ const result = spawnSync('git', [...args], { cwd, encoding: 'utf8' });
38
+ return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };
39
+ }
40
+
41
+ function gitValue(cwd: string, args: readonly string[]): string | null {
42
+ const result = git(cwd, args);
43
+ return result.status === 0 ? result.stdout.trim() : null;
44
+ }
45
+
46
+ function validateBranch(cwd: string, branch: string): boolean {
47
+ return git(cwd, ['check-ref-format', `refs/heads/${branch}`]).status === 0;
48
+ }
49
+
50
+ function validateReviewTargetCompatibility(
51
+ repoRoot: string,
52
+ taskDir: string,
53
+ target: { remote: string; baseRef: string },
54
+ reviewedHead: string
55
+ ): { ok: true } | { ok: false; code: string; message: string } {
56
+ const artifact = findAuthoritativeReviewCodeArtifact(taskDir);
57
+ if (!artifact.ok || !artifact.path) return { ok: false, code: 'DELIVERY_REVIEW_REQUIRED', message: 'A current review-code artifact is required before delivery' };
58
+ let content: string;
59
+ try { content = fs.readFileSync(artifact.path, 'utf8'); }
60
+ catch (error) { return { ok: false, code: 'DELIVERY_REVIEW_REQUIRED', message: error instanceof Error ? error.message : String(error) }; }
61
+ const savedReviewedHead = extractReviewedHead(content) || extractReviewBaseline(content);
62
+ const savedTargetHead = extractReviewTargetHead(content);
63
+ const savedDiffBase = extractReviewDiffBase(content);
64
+ if (!savedReviewedHead || !savedTargetHead || !savedDiffBase) {
65
+ return { ok: false, code: 'DELIVERY_REVIEW_TARGET_INVALID', message: 'review-code must save reviewed head, target head, and diff base before delivery' };
66
+ }
67
+ if (savedReviewedHead !== reviewedHead) {
68
+ return { ok: false, code: 'DELIVERY_REVIEW_REQUIRED', message: 'review-code reviewed head does not match last_reviewed_commit' };
69
+ }
70
+ const saved = resolveDiffBase(repoRoot, reviewedHead, savedTargetHead);
71
+ if (!saved.ok || saved.diffBase !== savedDiffBase) {
72
+ return { ok: false, code: 'DELIVERY_REVIEW_TARGET_INVALID', message: saved.ok ? 'saved review diff base does not match saved target head' : saved.message };
73
+ }
74
+ const currentTarget = resolveTargetHead(repoRoot, target);
75
+ if (!currentTarget.ok) return { ok: false, code: currentTarget.code, message: currentTarget.message };
76
+ const current = resolveDiffBase(repoRoot, reviewedHead, currentTarget.head!);
77
+ if (!current.ok) return { ok: false, code: current.code, message: current.message };
78
+ if (current.diffBase !== savedDiffBase) {
79
+ return { ok: false, code: 'DELIVERY_REVIEW_TARGET_CHANGED', message: 'current delivery target changed the reviewed diff base; re-run review-code' };
80
+ }
81
+ return { ok: true };
82
+ }
83
+
84
+ function failure(taskId: string | null, code: string, message: string, retryable = false, status: 'failed' | 'blocked' = retryable ? 'blocked' : 'failed'): TaskBranchDeliveryResult {
85
+ return { status, changed: false, taskId, remoteHead: null, localHead: null, state: null, error: { code, message, retryable } };
86
+ }
87
+
88
+ function deliverUnlocked(
89
+ taskId: string,
90
+ taskDir: string,
91
+ repoRoot: string,
92
+ options: { agent: string; remote?: string; baseRef?: string; dryRun?: boolean }
93
+ ): TaskBranchDeliveryResult {
94
+ let frontmatter: ReturnType<typeof parseTaskFrontmatter>;
95
+ try { frontmatter = parseTaskFrontmatter(fs.readFileSync(path.join(taskDir, 'task.md'), 'utf8')); }
96
+ catch (error) { return failure(taskId, 'TASK_CONTEXT_UNREADABLE', error instanceof Error ? error.message : String(error)); }
97
+ if (frontmatter.status !== 'active') return failure(taskId, 'TASK_STATE_INVALID', 'task branch delivery requires an active task');
98
+ const branch = frontmatter.branch ?? '';
99
+ if (!branch) return failure(taskId, 'DELIVERY_BRANCH_MISSING', 'task branch is missing');
100
+ if (!validateBranch(repoRoot, branch)) return failure(taskId, 'DELIVERY_BRANCH_INVALID', 'task branch is invalid');
101
+ if (!frontmatter.delivery_remote || !frontmatter.delivery_base_ref) {
102
+ return failure(taskId, 'DELIVERY_TARGET_MISSING', 'task delivery target is not bound; recreate or repair task metadata before delivery');
103
+ }
104
+ const target = resolveDeliveryTarget(repoRoot, {
105
+ remote: frontmatter.delivery_remote,
106
+ baseRef: frontmatter.delivery_base_ref
107
+ }, {
108
+ ...(options.remote === undefined ? {} : { remote: options.remote }),
109
+ ...(options.baseRef === undefined ? {} : { baseRef: options.baseRef })
110
+ });
111
+ if (!target.ok) return failure(taskId, target.code, target.message);
112
+ if (!validateRemote(target.value.remote) || !validateBaseRef(target.value.baseRef)) return failure(taskId, 'DELIVERY_TARGET_INVALID', 'task delivery target is invalid');
113
+ const localHead = gitValue(repoRoot, ['rev-parse', 'HEAD']);
114
+ if (!localHead) return failure(taskId, 'DELIVERY_LOCAL_HEAD_UNAVAILABLE', 'Unable to resolve local HEAD');
115
+ const status = git(repoRoot, ['status', '--porcelain=v1']);
116
+ if (status.status !== 0) return failure(taskId, 'DELIVERY_GIT_INSPECT_FAILED', status.stderr.trim() || 'Unable to inspect Git state');
117
+ if (status.stdout.trim()) return failure(taskId, 'DELIVERY_WORKTREE_DIRTY', 'Working tree must be clean before branch delivery');
118
+ const reviewed = frontmatter.last_reviewed_commit ?? '';
119
+ if (reviewed !== localHead) return failure(taskId, 'DELIVERY_REVIEW_REQUIRED', 'Local HEAD must equal last_reviewed_commit before delivery');
120
+ const reviewTarget = validateReviewTargetCompatibility(repoRoot, taskDir, target.value, reviewed);
121
+ if (!reviewTarget.ok) return failure(taskId, reviewTarget.code, reviewTarget.message, reviewTarget.code.includes('UNAVAILABLE'), reviewTarget.code.includes('UNAVAILABLE') ? 'blocked' : 'failed');
122
+ const ref = `refs/heads/${branch}`;
123
+ const remoteOutput = git(repoRoot, ['ls-remote', '--refs', target.value.remote, ref]);
124
+ if (remoteOutput.status !== 0) return failure(taskId, 'DELIVERY_REMOTE_UNAVAILABLE', remoteOutput.stderr.trim() || 'Unable to inspect the delivery remote', true);
125
+ const remoteHead = remoteOutput.stdout.trim().split(/\s+/)[0] || null;
126
+ const classification = classifyDeliveryState(localHead, remoteHead, frontmatter.delivery_remote_head ?? null);
127
+ if (classification.state === 'unknown-drift') return failure(taskId, 'DELIVERY_REMOTE_DRIFT', `Remote branch ${branch} has an unexpected head; refusing to overwrite it`);
128
+ if (options.dryRun) return { status: 'planned', changed: classification.shouldPush, taskId, remoteHead, localHead, state: classification.state, error: null };
129
+ if (classification.shouldPush) {
130
+ const args = classification.state === 'known-old'
131
+ ? ['push', `--force-with-lease=${ref}:${frontmatter.delivery_remote_head}`, target.value.remote, `HEAD:${ref}`]
132
+ : ['push', `--force-with-lease=${ref}:`, target.value.remote, `HEAD:${ref}`];
133
+ const pushed = git(repoRoot, args);
134
+ if (pushed.status !== 0) return failure(taskId, 'DELIVERY_PUSH_FAILED', pushed.stderr.trim() || 'Task branch delivery was rejected', true, 'blocked');
135
+ }
136
+ const verified = gitValue(repoRoot, ['ls-remote', '--refs', target.value.remote, ref])?.split(/\s+/)[0] ?? null;
137
+ if (verified !== localHead) return failure(taskId, 'DELIVERY_REMOTE_VERIFY_FAILED', `Expected remote head ${localHead}, received ${verified ?? 'unavailable'}`, true, 'blocked');
138
+ const written = writeTask({
139
+ taskRef: taskId,
140
+ expectedState: 'active',
141
+ mutations: [{ kind: 'frontmatter', set: { delivery_remote: target.value.remote, delivery_base_ref: target.value.baseRef, delivery_remote_head: localHead, assigned_to: options.agent } }]
142
+ }, { repoRoot, metadataProvider: captureTaskWriteMetadata });
143
+ if (written.status === 'failed') return failure(taskId, 'DELIVERY_TASK_SYNC_FAILED', written.error.message, true, 'blocked');
144
+ return { status: classification.shouldPush ? 'applied' : 'no-op', changed: classification.shouldPush || written.changed, taskId, remoteHead: localHead, localHead, state: classification.state, error: null };
145
+ }
146
+
147
+ function deliverTaskBranch(taskRef: string, options: { repoRoot?: string; agent: string; remote?: string; baseRef?: string; dryRun?: boolean }): TaskBranchDeliveryResult {
148
+ const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
149
+ if (!resolved.ok) return failure(resolved.taskId, resolved.code, resolved.message);
150
+ try {
151
+ return withRepositoryMutationLock(resolved.repoRoot, () => withTaskExecutionLock(
152
+ resolved.repoRoot, resolved.taskId, 'task-delivery',
153
+ () => deliverUnlocked(resolved.taskId, resolved.taskDir, resolved.repoRoot, options)
154
+ ));
155
+ } catch (error) {
156
+ return failure(resolved.taskId, 'DELIVERY_LOCK_FAILED', error instanceof Error ? error.message : String(error), true, 'blocked');
157
+ }
158
+ }
159
+
160
+ export { classifyDeliveryState, deliverTaskBranch };