@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
@@ -12,8 +12,8 @@ const DEFAULT_DEPENDENCIES = {
12
12
  syncComment: syncPlatformComment,
13
13
  addWarning: applyWorkflowWarningIntent
14
14
  };
15
- function verifyCreatedTask(repoRoot, taskId) {
16
- const verification = verifyTaskEvent({ taskRef: taskId, event: 'create-task.completed' }, { repoRoot });
15
+ async function verifyCreatedTask(repoRoot, taskId) {
16
+ const verification = await verifyTaskEvent({ taskRef: taskId, event: 'create-task.completed' }, { repoRoot });
17
17
  if (verification.status === 'pass') {
18
18
  return { operation: { name: 'task:verify', status: 'pass', reasonCode: null }, error: null };
19
19
  }
@@ -42,7 +42,7 @@ function issueFromTask(repoRoot, taskId) {
42
42
  const match = /^issue_number:\s*(\d+)\s*$/m.exec(content);
43
43
  return match ? { number: Number(match[1]), url: '' } : null;
44
44
  }
45
- function createTask(value, options) {
45
+ async function createTask(value, options) {
46
46
  const dependencies = { ...DEFAULT_DEPENDENCIES, ...options.dependencies };
47
47
  let candidate;
48
48
  let local;
@@ -65,13 +65,13 @@ function createTask(value, options) {
65
65
  name: 'task:local', status: local.status, reasonCode: null
66
66
  }];
67
67
  let issue = issueFromTask(options.repoRoot, local.task.id);
68
- const created = dependencies.createIssue(local.task.id, { cwd: options.repoRoot, agent: candidate.agent });
68
+ const created = await dependencies.createIssue(local.task.id, { cwd: options.repoRoot, agent: candidate.agent });
69
69
  operations.push(...platformOperations('platform-create', created.operations));
70
70
  if (created.issue)
71
71
  issue = { number: created.issue.number, url: created.issue.url };
72
72
  let platformFailure = created.status === 'failed' || created.status === 'blocked' ? created : null;
73
73
  if (!platformFailure && (created.task.issueNumber || issue)) {
74
- const synced = dependencies.syncIssue(local.task.id, {
74
+ const synced = await dependencies.syncIssue(local.task.id, {
75
75
  cwd: options.repoRoot,
76
76
  agent: candidate.agent,
77
77
  status: 'waiting-for-triage',
@@ -86,7 +86,7 @@ function createTask(value, options) {
86
86
  if (synced.status === 'failed' || synced.status === 'blocked')
87
87
  platformFailure = synced;
88
88
  if (!platformFailure) {
89
- const commented = dependencies.syncComment(local.task.id, { cwd: options.repoRoot, kind: 'task', agent: candidate.agent });
89
+ const commented = await dependencies.syncComment(local.task.id, { cwd: options.repoRoot, kind: 'task', agent: candidate.agent });
90
90
  operations.push(...platformOperations('platform-comment', commented.operations));
91
91
  if (commented.status === 'failed' || commented.status === 'blocked')
92
92
  platformFailure = commented;
@@ -99,7 +99,7 @@ function createTask(value, options) {
99
99
  code: 'ISSUE_CREATE_FAILED', target: 'issue', message: `${error.code}: ${error.message}`,
100
100
  action: 'Fix platform authentication or connectivity, then retry Issue creation for this task.'
101
101
  }, { repoRoot: options.repoRoot });
102
- const verified = verifyCreatedTask(options.repoRoot, local.task.id);
102
+ const verified = await verifyCreatedTask(options.repoRoot, local.task.id);
103
103
  operations.push(verified.operation);
104
104
  if (verified.error)
105
105
  return {
@@ -116,7 +116,7 @@ function createTask(value, options) {
116
116
  error
117
117
  };
118
118
  }
119
- const verified = verifyCreatedTask(options.repoRoot, local.task.id);
119
+ const verified = await verifyCreatedTask(options.repoRoot, local.task.id);
120
120
  operations.push(verified.operation);
121
121
  if (verified.error)
122
122
  return {
@@ -4,6 +4,8 @@ import path from 'node:path';
4
4
  import { isValidAgentInfraVersion, VERSION } from '../version.js';
5
5
  import { loadShortIdByTaskId, mutateShortIdRegistry } from './short-id.js';
6
6
  import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.js';
7
+ import { readDeliveryDefaults, validateBaseRef, validateRemote } from './delivery-target.js';
8
+ import { buildUnboundFact, encodePrDeliveryFact } from './pr-delivery-fact.js';
7
9
  const AGENTS = ['claude', 'codex', 'antigravity', 'opencode', 'cursor'];
8
10
  const TYPES = ['feature', 'bugfix', 'refactor', 'docs', 'chore'];
9
11
  const PRIORITIES = ['Urgent', 'High', 'Medium', 'Low'];
@@ -15,12 +17,15 @@ const TASK_INPUT_KEYS = [
15
17
  function payloadError(message) {
16
18
  throw new Error(`TASK_CREATE_PAYLOAD_INVALID: ${message}`);
17
19
  }
18
- function exactKeys(value, expected, label) {
20
+ function exactKeys(value, expected, label, optional = []) {
19
21
  const actual = Object.keys(value).sort();
20
22
  const wanted = [...expected].sort();
21
- if (actual.length !== wanted.length || actual.some((key, index) => key !== wanted[index])) {
23
+ const allowed = new Set([...expected, ...optional]);
24
+ if (actual.some((key) => !allowed.has(key))) {
22
25
  payloadError(`${label} has unknown or missing fields`);
23
26
  }
27
+ if (expected.some((key) => !actual.includes(key)))
28
+ payloadError(`${label} has unknown or missing fields`);
24
29
  }
25
30
  function cleanString(value, label, maxBytes, oneLine = false) {
26
31
  if (typeof value !== 'string' || value.length === 0 || Buffer.byteLength(value, 'utf8') > maxBytes) {
@@ -43,7 +48,7 @@ function validateTaskCreateCandidate(value) {
43
48
  exactKeys(candidate, [
44
49
  'version', 'idempotencyKey', 'agent', 'title', 'type', 'branchSlug',
45
50
  'priority', 'effort', 'description', 'taskInput'
46
- ], 'candidate');
51
+ ], 'candidate', ['deliveryRemote', 'deliveryBaseRef']);
47
52
  if (candidate.version !== 1)
48
53
  payloadError('version must be 1');
49
54
  const idempotencyKey = cleanString(candidate.idempotencyKey, 'idempotencyKey', 64, true);
@@ -58,6 +63,16 @@ function validateTaskCreateCandidate(value) {
58
63
  payloadError('branchSlug must be lowercase ASCII kebab-case with length 3-64');
59
64
  }
60
65
  const description = cleanString(candidate.description, 'description', 8 * 1024);
66
+ const deliveryRemote = candidate.deliveryRemote === undefined
67
+ ? undefined
68
+ : cleanString(candidate.deliveryRemote, 'deliveryRemote', 200, true);
69
+ const deliveryBaseRef = candidate.deliveryBaseRef === undefined
70
+ ? undefined
71
+ : cleanString(candidate.deliveryBaseRef, 'deliveryBaseRef', 200, true);
72
+ if (deliveryRemote !== undefined && !validateRemote(deliveryRemote))
73
+ payloadError('deliveryRemote is invalid');
74
+ if (deliveryBaseRef !== undefined && !validateBaseRef(deliveryBaseRef))
75
+ payloadError('deliveryBaseRef is invalid');
61
76
  if (!candidate.taskInput || typeof candidate.taskInput !== 'object' || Array.isArray(candidate.taskInput)) {
62
77
  payloadError('taskInput must be an object');
63
78
  }
@@ -79,6 +94,8 @@ function validateTaskCreateCandidate(value) {
79
94
  priority: enumValue(candidate.priority, PRIORITIES, 'priority'),
80
95
  effort: enumValue(candidate.effort, EFFORTS, 'effort'),
81
96
  description,
97
+ ...(deliveryRemote === undefined ? {} : { deliveryRemote }),
98
+ ...(deliveryBaseRef === undefined ? {} : { deliveryBaseRef }),
82
99
  taskInput
83
100
  };
84
101
  }
@@ -94,6 +111,8 @@ function canonicalTaskCreateCandidate(candidate) {
94
111
  priority: valid.priority,
95
112
  effort: valid.effort,
96
113
  description: valid.description,
114
+ deliveryRemote: valid.deliveryRemote ?? null,
115
+ deliveryBaseRef: valid.deliveryBaseRef ?? null,
97
116
  taskInput: Object.fromEntries(TASK_INPUT_KEYS.map((key) => [key, valid.taskInput[key]]))
98
117
  });
99
118
  }
@@ -145,7 +164,11 @@ function renderTask(params) {
145
164
  'target_date:',
146
165
  'current_step: requirement-analysis',
147
166
  `assigned_to: ${candidate.agent}`,
148
- 'pr_status: pending',
167
+ `pr_delivery_fact: ${JSON.stringify(encodePrDeliveryFact(buildUnboundFact()))}`,
168
+ `delivery_remote: ${candidate.deliveryRemote ?? params.delivery.remote}`,
169
+ `delivery_base_ref: ${candidate.deliveryBaseRef ?? params.delivery.baseRef}`,
170
+ 'checkpoint_commit:',
171
+ 'delivery_remote_head:',
149
172
  `task_create_key_digest: ${params.keyDigest}`,
150
173
  `task_create_candidate_digest: ${params.candidateDigest}`,
151
174
  '---'
@@ -175,7 +198,10 @@ function readProject(repoRoot) {
175
198
  if (typeof config.project !== 'string' || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(config.project)) {
176
199
  throw new Error('TASK_CREATE_CONFIG_INVALID: project is missing or invalid');
177
200
  }
178
- return config.project;
201
+ const delivery = readDeliveryDefaults(repoRoot);
202
+ if (!delivery.ok)
203
+ throw new Error(`TASK_CREATE_CONFIG_INVALID: ${delivery.message}`);
204
+ return { project: config.project, delivery: delivery.value };
179
205
  }
180
206
  function assertRealDirectory(directory, code) {
181
207
  const stat = fs.lstatSync(directory);
@@ -269,7 +295,7 @@ function createLocalTask(value, options) {
269
295
  ensureRealDirectory(path.join(repoRoot, '.agents'), 'TASK_CREATE_WORKSPACE_INVALID');
270
296
  ensureRealDirectory(workspaceRoot, 'TASK_CREATE_WORKSPACE_INVALID');
271
297
  ensureRealDirectory(activeRoot, 'TASK_CREATE_WORKSPACE_INVALID');
272
- const project = readProject(repoRoot);
298
+ const projectConfig = readProject(repoRoot);
273
299
  const canonical = canonicalTaskCreateCandidate(candidate);
274
300
  const candidateDigest = sha256(canonical);
275
301
  const keyDigest = sha256(candidate.idempotencyKey);
@@ -312,7 +338,7 @@ function createLocalTask(value, options) {
312
338
  if (!templateStat.isFile() || templateStat.isSymbolicLink())
313
339
  throw new Error('TASK_CREATE_TEMPLATE_INVALID');
314
340
  const rendered = renderTask({
315
- template: fs.readFileSync(templatePath, 'utf8'), candidate, taskId, project, timestamp,
341
+ template: fs.readFileSync(templatePath, 'utf8'), candidate, taskId, project: projectConfig.project, delivery: projectConfig.delivery, timestamp,
316
342
  agentInfraVersion, keyDigest, candidateDigest
317
343
  });
318
344
  const temporary = path.join(workspaceRoot, `.task-create.tmp.${process.pid}.${randomUUID()}`);
@@ -1,6 +1,7 @@
1
1
  import { isValidAgentInfraVersion } from '../version.js';
2
2
  import { parseTypedTaskFrontmatter } from './frontmatter.js';
3
3
  import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, validateLedgerRows } from './ledger.js';
4
+ import { parseInvalidationDocument } from './invalidation.js';
4
5
  function validateCurrentTaskContract(content) {
5
6
  let metadata;
6
7
  try {
@@ -29,7 +30,10 @@ function validateCurrentTaskContract(content) {
29
30
  const invalid = validateLedgerRows(ledger.rows);
30
31
  if (invalid)
31
32
  return { ok: false, code: 'TASK_CURRENT_CONTRACT_INVALID', message: `${invalid.code}: ${invalid.message}` };
32
- return { ok: true, metadata, ledger };
33
+ const invalidation = parseInvalidationDocument(content);
34
+ if (!invalidation.ok)
35
+ return { ok: false, code: 'TASK_CURRENT_CONTRACT_INVALID', message: `${invalidation.code}: ${invalidation.message}` };
36
+ return { ok: true, metadata, ledger, invalidation: invalidation.document };
33
37
  }
34
38
  export { validateCurrentTaskContract };
35
39
  //# sourceMappingURL=current-contract.js.map
@@ -109,31 +109,8 @@ function resolveDecisionDetail(content, rowId, anchor) {
109
109
  }
110
110
  return { status: 'found', block: matches[0] };
111
111
  }
112
- const INFORMAL_SHORT_HEADING = /^(?:AN|PL|CD|HD)-[1-9]\d*[::]\s*(?:上一轮)?简短复核$/i;
113
- const INFORMAL_SHORT_FRAGMENT = /^简短(?:结论|说明)$/;
114
- function isInformalShortBlock(block) {
115
- if (block.canonical || block.content.length > 600)
116
- return false;
117
- if (!INFORMAL_SHORT_HEADING.test(block.heading))
118
- return false;
119
- const scanned = scanVisibleMarkdown(block.content);
120
- const bodyLines = scanned.lines
121
- .filter((line) => !scanned.headings.some((heading) => heading.start === line.start) && line.text.trim())
122
- .map((line) => line.text);
123
- if (bodyLines.length === 0 || bodyLines.length > 2)
124
- return false;
125
- const fragments = bodyLines.map((line) => line.match(/^\s*[-*]\s+([^\s].*?)\s*$/)?.[1] ?? null);
126
- if (fragments.some((fragment) => fragment === null))
127
- return false;
128
- return fragments.every((fragment) => INFORMAL_SHORT_FRAGMENT.test(fragment));
129
- }
130
- function hasDirectPrecedingAnchor(block, scanned) {
131
- return scanned.anchors.some((anchor) => (anchor.end < block.start
132
- && !scanned.lines.some((line) => line.start > anchor.end && line.start < block.start && line.text.trim())));
133
- }
134
112
  function inspectDecisionDetailDuplicates(content) {
135
113
  const blocks = parseDecisionDetailBlocks(content);
136
- const scanned = scanVisibleMarkdown(content);
137
114
  const grouped = new Map();
138
115
  for (const block of blocks) {
139
116
  const key = block.id.toUpperCase();
@@ -145,15 +122,13 @@ function inspectDecisionDetailDuplicates(content) {
145
122
  for (const group of grouped.values()) {
146
123
  if (group.length < 2)
147
124
  continue;
148
- const canonical = group.filter((block) => block.canonical);
149
- const repairable = canonical.length === 1 && group.every((block) => (block.canonical || (!hasDirectPrecedingAnchor(block, scanned) && isInformalShortBlock(block))));
150
- duplicates.push({ id: canonical[0]?.id ?? group[0].id, blocks: group, repairable });
125
+ duplicates.push({ id: group[0].id, blocks: group });
151
126
  }
152
127
  if (duplicates.length === 0)
153
128
  return { ok: true, blocks };
154
129
  const summary = duplicates.map((duplicate) => {
155
130
  const types = duplicate.blocks.map((block) => block.canonical ? 'canonical' : 'informal').join(', ');
156
- return `${duplicate.id} (${duplicate.blocks.length} blocks: ${types}${duplicate.repairable ? '; safe repair available' : ''})`;
131
+ return `${duplicate.id} (${duplicate.blocks.length} blocks: ${types})`;
157
132
  }).join(', ');
158
133
  return {
159
134
  ok: false,
@@ -163,26 +138,6 @@ function inspectDecisionDetailDuplicates(content) {
163
138
  duplicates
164
139
  };
165
140
  }
166
- function repairDecisionDetailDuplicates(content) {
167
- const inspection = inspectDecisionDetailDuplicates(content);
168
- if (inspection.ok)
169
- return { ok: true, changed: false, content };
170
- const unsafe = inspection.duplicates.filter((duplicate) => !duplicate.repairable);
171
- if (unsafe.length > 0) {
172
- return {
173
- ok: false,
174
- code: 'DECISION_DETAIL_AMBIGUOUS',
175
- message: `Cannot safely repair duplicate decision detail ids: ${unsafe.map((duplicate) => duplicate.id).join(', ')}`,
176
- content
177
- };
178
- }
179
- const removals = inspection.duplicates.flatMap((duplicate) => duplicate.blocks.filter((block) => !block.canonical));
180
- let repaired = content;
181
- for (const block of removals.sort((left, right) => right.start - left.start)) {
182
- repaired = repaired.slice(0, block.start) + repaired.slice(block.end);
183
- }
184
- return { ok: true, changed: repaired !== content, content: repaired };
185
- }
186
141
  const FIELD_KEYS = {
187
142
  '为什么现在要决定': 'why', 'why decide now': 'why', 'why a decision is needed now': 'why',
188
143
  '要决定什么': 'decision', 'what to decide': 'decision', 'what needs a decision': 'decision',
@@ -259,5 +214,5 @@ function normalizeDecisionDetailForDisplay(block) {
259
214
  ordered.push(byKey.get('implementation'));
260
215
  return [body.slice(heading.start, heading.end).trim(), ...ordered].join('\n\n').trim();
261
216
  }
262
- export { inspectDecisionDetailDuplicates, normalizeDecisionDetailForDisplay, parseDecisionDetailBlocks, parseDecisionEvidence, repairDecisionDetailDuplicates, resolveDecisionDetail };
217
+ export { inspectDecisionDetailDuplicates, normalizeDecisionDetailForDisplay, parseDecisionDetailBlocks, parseDecisionEvidence, resolveDecisionDetail, scanVisibleMarkdown };
263
218
  //# sourceMappingURL=decision-details.js.map
@@ -0,0 +1,97 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { execFileSync } from 'node:child_process';
4
+ const REMOTE_RE = /^(?!-)(?!.*\.\.)(?!.*[~^:?*\\\s])[A-Za-z0-9._/-]+$/;
5
+ const REF_RE = /^(?!-)(?!.*\.\.)(?!.*(?:^|\/)\.)(?!.*[~^:?*\\\s])[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*$/;
6
+ function validateRemote(value) {
7
+ return typeof value === 'string' && value.length > 0 && REMOTE_RE.test(value);
8
+ }
9
+ function validateBaseRef(value) {
10
+ return typeof value === 'string' && value.length > 0 && !value.startsWith('refs/') && REF_RE.test(value);
11
+ }
12
+ function invalid(field, value) {
13
+ return { ok: false, code: 'DELIVERY_TARGET_INVALID', message: `${field} is invalid: ${String(value ?? '')}` };
14
+ }
15
+ function bindDeliveryTarget(input) {
16
+ const remote = input.existing?.remote ?? input.explicit?.remote ?? input.defaults?.remote;
17
+ const baseRef = input.existing?.baseRef ?? input.explicit?.baseRef ?? input.defaults?.baseRef;
18
+ if (input.existing?.remote !== undefined && input.explicit?.remote !== undefined && input.existing.remote !== input.explicit.remote) {
19
+ return { ok: false, code: 'DELIVERY_TARGET_CONFLICT', message: 'Explicit delivery remote does not match the task binding' };
20
+ }
21
+ if (input.existing?.baseRef !== undefined && input.explicit?.baseRef !== undefined && input.existing.baseRef !== input.explicit.baseRef) {
22
+ return { ok: false, code: 'DELIVERY_TARGET_CONFLICT', message: 'Explicit delivery base ref does not match the task binding' };
23
+ }
24
+ if (!validateRemote(remote))
25
+ return invalid('delivery remote', remote);
26
+ if (!validateBaseRef(baseRef))
27
+ return invalid('delivery base ref', baseRef);
28
+ return { ok: true, value: { remote, baseRef } };
29
+ }
30
+ function readDeliveryDefaults(repoRoot) {
31
+ try {
32
+ const configPath = path.join(repoRoot, '.agents', '.airc.json');
33
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
34
+ if (!config.delivery || typeof config.delivery !== 'object' || Array.isArray(config.delivery)) {
35
+ return { ok: false, code: 'DELIVERY_CONFIG_INVALID', message: 'delivery config must declare remote and baseRef' };
36
+ }
37
+ const delivery = config.delivery;
38
+ if (typeof delivery.remote !== 'string' || typeof delivery.baseRef !== 'string') {
39
+ return { ok: false, code: 'DELIVERY_CONFIG_INVALID', message: 'delivery config must declare remote and baseRef' };
40
+ }
41
+ return bindDeliveryTarget({
42
+ defaults: {
43
+ remote: delivery.remote,
44
+ baseRef: delivery.baseRef
45
+ }
46
+ });
47
+ }
48
+ catch (error) {
49
+ return { ok: false, code: 'DELIVERY_CONFIG_INVALID', message: error instanceof Error ? error.message : String(error) };
50
+ }
51
+ }
52
+ function resolveDeliveryTarget(repoRoot, existing = {}, explicit = {}) {
53
+ const defaults = readDeliveryDefaults(repoRoot);
54
+ if (!defaults.ok)
55
+ return defaults;
56
+ return bindDeliveryTarget({ defaults: defaults.value, existing, explicit });
57
+ }
58
+ function gitText(repoRoot, args) {
59
+ return execFileSync('git', [...args], {
60
+ cwd: repoRoot,
61
+ encoding: 'utf8',
62
+ stdio: ['ignore', 'pipe', 'pipe']
63
+ }).trim();
64
+ }
65
+ function resolveTargetHead(repoRoot, target) {
66
+ try {
67
+ const output = gitText(repoRoot, ['ls-remote', '--refs', target.remote, `refs/heads/${target.baseRef}`]);
68
+ const head = output.split(/\s+/)[0] ?? '';
69
+ if (!/^[a-f0-9]{40}$/i.test(head)) {
70
+ return { ok: false, code: 'DELIVERY_TARGET_UNAVAILABLE', message: `Delivery target ${target.remote}/${target.baseRef} is unavailable` };
71
+ }
72
+ try {
73
+ gitText(repoRoot, ['cat-file', '-e', `${head}^{commit}`]);
74
+ }
75
+ catch {
76
+ return { ok: false, code: 'DELIVERY_TARGET_OBJECT_MISSING', message: `Delivery target commit ${head} is not available locally` };
77
+ }
78
+ return { ok: true, value: target, head };
79
+ }
80
+ catch (error) {
81
+ return { ok: false, code: 'DELIVERY_TARGET_UNAVAILABLE', message: error instanceof Error ? error.message : String(error) };
82
+ }
83
+ }
84
+ function resolveDiffBase(repoRoot, reviewedHead, targetHead) {
85
+ try {
86
+ const diffBase = gitText(repoRoot, ['merge-base', reviewedHead, targetHead]);
87
+ if (!/^[a-f0-9]{40}$/i.test(diffBase)) {
88
+ return { ok: false, code: 'DELIVERY_DIFF_BASE_UNAVAILABLE', message: 'Git returned an invalid diff base' };
89
+ }
90
+ return { ok: true, diffBase };
91
+ }
92
+ catch (error) {
93
+ return { ok: false, code: 'DELIVERY_DIFF_BASE_UNAVAILABLE', message: error instanceof Error ? error.message : String(error) };
94
+ }
95
+ }
96
+ export { bindDeliveryTarget, readDeliveryDefaults, resolveDeliveryTarget, resolveTargetHead, resolveDiffBase, validateBaseRef, validateRemote };
97
+ //# sourceMappingURL=delivery-target.js.map
@@ -0,0 +1,153 @@
1
+ import fs from 'node:fs';
2
+ import { spawnSync } from 'node:child_process';
3
+ import path from 'node:path';
4
+ import { parseTaskFrontmatter } from './frontmatter.js';
5
+ import { resolveTaskRef } from './resolve-ref.js';
6
+ import { resolveDeliveryTarget, resolveDiffBase, resolveTargetHead, validateBaseRef, validateRemote } from './delivery-target.js';
7
+ import { extractReviewBaseline, extractReviewDiffBase, extractReviewTargetHead, extractReviewedHead, findAuthoritativeReviewCodeArtifact } from './review-fingerprint.js';
8
+ import { captureTaskWriteMetadata, writeTask } from './write.js';
9
+ import { withRepositoryMutationLock, withTaskExecutionLock } from './task-execution-lock.js';
10
+ function classifyDeliveryState(localHead, remoteHead, lastDelivered) {
11
+ if (remoteHead === null)
12
+ return { state: 'absent', shouldPush: true };
13
+ if (remoteHead === localHead)
14
+ return { state: 'same', shouldPush: false };
15
+ if (lastDelivered && remoteHead === lastDelivered)
16
+ return { state: 'known-old', shouldPush: true };
17
+ return { state: 'unknown-drift', shouldPush: false };
18
+ }
19
+ function git(cwd, args) {
20
+ const result = spawnSync('git', [...args], { cwd, encoding: 'utf8' });
21
+ return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };
22
+ }
23
+ function gitValue(cwd, args) {
24
+ const result = git(cwd, args);
25
+ return result.status === 0 ? result.stdout.trim() : null;
26
+ }
27
+ function validateBranch(cwd, branch) {
28
+ return git(cwd, ['check-ref-format', `refs/heads/${branch}`]).status === 0;
29
+ }
30
+ function validateReviewTargetCompatibility(repoRoot, taskDir, target, reviewedHead) {
31
+ const artifact = findAuthoritativeReviewCodeArtifact(taskDir);
32
+ if (!artifact.ok || !artifact.path)
33
+ return { ok: false, code: 'DELIVERY_REVIEW_REQUIRED', message: 'A current review-code artifact is required before delivery' };
34
+ let content;
35
+ try {
36
+ content = fs.readFileSync(artifact.path, 'utf8');
37
+ }
38
+ catch (error) {
39
+ return { ok: false, code: 'DELIVERY_REVIEW_REQUIRED', message: error instanceof Error ? error.message : String(error) };
40
+ }
41
+ const savedReviewedHead = extractReviewedHead(content) || extractReviewBaseline(content);
42
+ const savedTargetHead = extractReviewTargetHead(content);
43
+ const savedDiffBase = extractReviewDiffBase(content);
44
+ if (!savedReviewedHead || !savedTargetHead || !savedDiffBase) {
45
+ return { ok: false, code: 'DELIVERY_REVIEW_TARGET_INVALID', message: 'review-code must save reviewed head, target head, and diff base before delivery' };
46
+ }
47
+ if (savedReviewedHead !== reviewedHead) {
48
+ return { ok: false, code: 'DELIVERY_REVIEW_REQUIRED', message: 'review-code reviewed head does not match last_reviewed_commit' };
49
+ }
50
+ const saved = resolveDiffBase(repoRoot, reviewedHead, savedTargetHead);
51
+ if (!saved.ok || saved.diffBase !== savedDiffBase) {
52
+ return { ok: false, code: 'DELIVERY_REVIEW_TARGET_INVALID', message: saved.ok ? 'saved review diff base does not match saved target head' : saved.message };
53
+ }
54
+ const currentTarget = resolveTargetHead(repoRoot, target);
55
+ if (!currentTarget.ok)
56
+ return { ok: false, code: currentTarget.code, message: currentTarget.message };
57
+ const current = resolveDiffBase(repoRoot, reviewedHead, currentTarget.head);
58
+ if (!current.ok)
59
+ return { ok: false, code: current.code, message: current.message };
60
+ if (current.diffBase !== savedDiffBase) {
61
+ return { ok: false, code: 'DELIVERY_REVIEW_TARGET_CHANGED', message: 'current delivery target changed the reviewed diff base; re-run review-code' };
62
+ }
63
+ return { ok: true };
64
+ }
65
+ function failure(taskId, code, message, retryable = false, status = retryable ? 'blocked' : 'failed') {
66
+ return { status, changed: false, taskId, remoteHead: null, localHead: null, state: null, error: { code, message, retryable } };
67
+ }
68
+ function deliverUnlocked(taskId, taskDir, repoRoot, options) {
69
+ let frontmatter;
70
+ try {
71
+ frontmatter = parseTaskFrontmatter(fs.readFileSync(path.join(taskDir, 'task.md'), 'utf8'));
72
+ }
73
+ catch (error) {
74
+ return failure(taskId, 'TASK_CONTEXT_UNREADABLE', error instanceof Error ? error.message : String(error));
75
+ }
76
+ if (frontmatter.status !== 'active')
77
+ return failure(taskId, 'TASK_STATE_INVALID', 'task branch delivery requires an active task');
78
+ const branch = frontmatter.branch ?? '';
79
+ if (!branch)
80
+ return failure(taskId, 'DELIVERY_BRANCH_MISSING', 'task branch is missing');
81
+ if (!validateBranch(repoRoot, branch))
82
+ return failure(taskId, 'DELIVERY_BRANCH_INVALID', 'task branch is invalid');
83
+ if (!frontmatter.delivery_remote || !frontmatter.delivery_base_ref) {
84
+ return failure(taskId, 'DELIVERY_TARGET_MISSING', 'task delivery target is not bound; recreate or repair task metadata before delivery');
85
+ }
86
+ const target = resolveDeliveryTarget(repoRoot, {
87
+ remote: frontmatter.delivery_remote,
88
+ baseRef: frontmatter.delivery_base_ref
89
+ }, {
90
+ ...(options.remote === undefined ? {} : { remote: options.remote }),
91
+ ...(options.baseRef === undefined ? {} : { baseRef: options.baseRef })
92
+ });
93
+ if (!target.ok)
94
+ return failure(taskId, target.code, target.message);
95
+ if (!validateRemote(target.value.remote) || !validateBaseRef(target.value.baseRef))
96
+ return failure(taskId, 'DELIVERY_TARGET_INVALID', 'task delivery target is invalid');
97
+ const localHead = gitValue(repoRoot, ['rev-parse', 'HEAD']);
98
+ if (!localHead)
99
+ return failure(taskId, 'DELIVERY_LOCAL_HEAD_UNAVAILABLE', 'Unable to resolve local HEAD');
100
+ const status = git(repoRoot, ['status', '--porcelain=v1']);
101
+ if (status.status !== 0)
102
+ return failure(taskId, 'DELIVERY_GIT_INSPECT_FAILED', status.stderr.trim() || 'Unable to inspect Git state');
103
+ if (status.stdout.trim())
104
+ return failure(taskId, 'DELIVERY_WORKTREE_DIRTY', 'Working tree must be clean before branch delivery');
105
+ const reviewed = frontmatter.last_reviewed_commit ?? '';
106
+ if (reviewed !== localHead)
107
+ return failure(taskId, 'DELIVERY_REVIEW_REQUIRED', 'Local HEAD must equal last_reviewed_commit before delivery');
108
+ const reviewTarget = validateReviewTargetCompatibility(repoRoot, taskDir, target.value, reviewed);
109
+ if (!reviewTarget.ok)
110
+ return failure(taskId, reviewTarget.code, reviewTarget.message, reviewTarget.code.includes('UNAVAILABLE'), reviewTarget.code.includes('UNAVAILABLE') ? 'blocked' : 'failed');
111
+ const ref = `refs/heads/${branch}`;
112
+ const remoteOutput = git(repoRoot, ['ls-remote', '--refs', target.value.remote, ref]);
113
+ if (remoteOutput.status !== 0)
114
+ return failure(taskId, 'DELIVERY_REMOTE_UNAVAILABLE', remoteOutput.stderr.trim() || 'Unable to inspect the delivery remote', true);
115
+ const remoteHead = remoteOutput.stdout.trim().split(/\s+/)[0] || null;
116
+ const classification = classifyDeliveryState(localHead, remoteHead, frontmatter.delivery_remote_head ?? null);
117
+ if (classification.state === 'unknown-drift')
118
+ return failure(taskId, 'DELIVERY_REMOTE_DRIFT', `Remote branch ${branch} has an unexpected head; refusing to overwrite it`);
119
+ if (options.dryRun)
120
+ return { status: 'planned', changed: classification.shouldPush, taskId, remoteHead, localHead, state: classification.state, error: null };
121
+ if (classification.shouldPush) {
122
+ const args = classification.state === 'known-old'
123
+ ? ['push', `--force-with-lease=${ref}:${frontmatter.delivery_remote_head}`, target.value.remote, `HEAD:${ref}`]
124
+ : ['push', `--force-with-lease=${ref}:`, target.value.remote, `HEAD:${ref}`];
125
+ const pushed = git(repoRoot, args);
126
+ if (pushed.status !== 0)
127
+ return failure(taskId, 'DELIVERY_PUSH_FAILED', pushed.stderr.trim() || 'Task branch delivery was rejected', true, 'blocked');
128
+ }
129
+ const verified = gitValue(repoRoot, ['ls-remote', '--refs', target.value.remote, ref])?.split(/\s+/)[0] ?? null;
130
+ if (verified !== localHead)
131
+ return failure(taskId, 'DELIVERY_REMOTE_VERIFY_FAILED', `Expected remote head ${localHead}, received ${verified ?? 'unavailable'}`, true, 'blocked');
132
+ const written = writeTask({
133
+ taskRef: taskId,
134
+ expectedState: 'active',
135
+ mutations: [{ kind: 'frontmatter', set: { delivery_remote: target.value.remote, delivery_base_ref: target.value.baseRef, delivery_remote_head: localHead, assigned_to: options.agent } }]
136
+ }, { repoRoot, metadataProvider: captureTaskWriteMetadata });
137
+ if (written.status === 'failed')
138
+ return failure(taskId, 'DELIVERY_TASK_SYNC_FAILED', written.error.message, true, 'blocked');
139
+ return { status: classification.shouldPush ? 'applied' : 'no-op', changed: classification.shouldPush || written.changed, taskId, remoteHead: localHead, localHead, state: classification.state, error: null };
140
+ }
141
+ function deliverTaskBranch(taskRef, options) {
142
+ const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
143
+ if (!resolved.ok)
144
+ return failure(resolved.taskId, resolved.code, resolved.message);
145
+ try {
146
+ return withRepositoryMutationLock(resolved.repoRoot, () => withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-delivery', () => deliverUnlocked(resolved.taskId, resolved.taskDir, resolved.repoRoot, options)));
147
+ }
148
+ catch (error) {
149
+ return failure(resolved.taskId, 'DELIVERY_LOCK_FAILED', error instanceof Error ? error.message : String(error), true, 'blocked');
150
+ }
151
+ }
152
+ export { classifyDeliveryState, deliverTaskBranch };
153
+ //# sourceMappingURL=delivery.js.map