@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
@@ -1,4 +1,5 @@
1
1
  import fs from 'node:fs';
2
+ import path from 'node:path';
2
3
 
3
4
  import { appendActivityEntry, locateActivityLog, pairEntries, startedBackedRows } from './activity-log.ts';
4
5
  import {
@@ -12,7 +13,7 @@ import {
12
13
  validateCompletedArtifact
13
14
  } from './artifact-lifecycle.ts';
14
15
  import type { ArtifactContextResult, ArtifactErrorCode, ArtifactFamily, ArtifactIdentity } from './artifact-lifecycle.ts';
15
- import { ArtifactReceiptError, sha256File, upsertArtifactReceipt } from './artifact-receipts.ts';
16
+ import { ArtifactReceiptError, parseArtifactReceipts, sha256File, upsertArtifactReceipt } from './artifact-receipts.ts';
16
17
  import type { ArtifactReceipt } from './artifact-receipts.ts';
17
18
  import { parseTypedTaskFrontmatter } from './frontmatter.ts';
18
19
  import {
@@ -33,6 +34,20 @@ import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-
33
34
  import { captureTaskWriteMetadata, writeTask } from './write.ts';
34
35
  import type { TaskOperationSummary, TaskWriteErrorCode, TaskWriteOptions } from './write.ts';
35
36
  import { allowsManualOverride } from './guard-override.ts';
37
+ import {
38
+ LOCAL_ARTIFACT_REQUIRED_PATTERNS,
39
+ LOCAL_ARTIFACT_REQUIRED_SECTIONS,
40
+ consumeLocalArtifactFinalizationIntent,
41
+ readLocalArtifactFinalizationIntent,
42
+ validateLocalArtifact
43
+ } from './local-artifact-finalization.ts';
44
+ import type { LocalArtifactFamily, LocalArtifactFinalizationIntent } from './local-artifact-finalization.ts';
45
+ import { loadVerificationConfig } from './verification-config.ts';
46
+ import { buildLifecycleFacts, canStart } from './capabilities.ts';
47
+ import type { ExplicitTrigger, LifecycleAction, TriggerInitiator, TriggerReason } from './capabilities.ts';
48
+ import { createInvalidationOperation, invalidationMutation, parseInvalidationDocument, targetIdFor, upsertInvalidation } from './invalidation.ts';
49
+ import type { InvalidationTargetKind } from './invalidation.ts';
50
+ import { consumeReworkIntents, parseReworkIntentDocument, reworkIntentMutation, supersedeReworkIntents } from './rework-intent.ts';
36
51
 
37
52
  const eventCatalog = [
38
53
  'analyze.started', 'analyze.awaiting-input', 'analyze.completed',
@@ -48,6 +63,7 @@ type TaskEventName = (typeof eventCatalog)[number];
48
63
  type Verdict = 'approved' | 'changes-requested' | 'rejected';
49
64
  type TaskEventErrorCode =
50
65
  | 'EVENT_UNKNOWN' | 'EVENT_PAYLOAD_INVALID' | 'EVENT_TRANSITION_INVALID'
66
+ | 'EVENT_TRIGGER_REQUIRED'
51
67
  | 'EVENT_LOG_MISSING' | 'EVENT_START_MISSING' | 'EVENT_ALREADY_COMPLETED'
52
68
  | 'EVENT_LOG_CONFLICT' | 'EVENT_ARTIFACT_CONFLICT' | 'EVENT_FINDING_COUNT_MISMATCH'
53
69
  | 'EVENT_VERDICT_INVALID'
@@ -56,7 +72,10 @@ type TaskEventErrorCode =
56
72
  type TaskEventRequest = {
57
73
  taskRef: string; event: TaskEventName | string; agent: string; dryRun?: boolean; orchestrated?: boolean;
58
74
  overrideTicket?: string; overrideTarget?: string; overrideScope?: string;
75
+ initiator?: TriggerInitiator; requestId?: string; reasonCode?: TriggerReason;
76
+ sourceFinding?: string; sourceArtifact?: string; sourceSha256?: string;
59
77
  round?: number; question?: number; artifact?: string; fixFor?: string; implementationInput?: string;
78
+ artifactSha256?: string; semanticDigest?: string;
60
79
  verdict?: Verdict; blockers?: number; major?: number; minor?: number;
61
80
  manualValidation?: number; filesModified?: number; testsPassed?: number;
62
81
  summaryResult?: string;
@@ -77,19 +96,19 @@ type TaskEventResult = {
77
96
  operations: readonly TaskOperationSummary[]; error: TaskEventError | null;
78
97
  };
79
98
 
80
- const BASE_FIELDS = new Set(['taskRef', 'event', 'agent', 'dryRun', 'overrideTicket', 'overrideTarget', 'overrideScope']);
99
+ const BASE_FIELDS = new Set(['taskRef', 'event', 'agent', 'dryRun', 'overrideTicket', 'overrideTarget', 'overrideScope', 'initiator', 'requestId', 'reasonCode', 'sourceFinding', 'sourceArtifact', 'sourceSha256']);
81
100
  const SCHEMAS: Record<TaskEventName, { required?: string[]; optional?: string[] }> = {
82
101
  'analyze.started': { optional: ['round'] },
83
102
  'analyze.awaiting-input': { required: ['question'] },
84
- 'analyze.completed': { required: ['artifact'], optional: ['round', 'orchestrated'] },
103
+ 'analyze.completed': { required: ['artifact', 'artifactSha256', 'semanticDigest'], optional: ['round', 'orchestrated'] },
85
104
  'review-analysis.started': { optional: ['round'] },
86
105
  'review-analysis.completed': { required: ['artifact', 'verdict', 'blockers', 'major', 'minor', 'manualValidation'], optional: ['round', 'orchestrated'] },
87
106
  'plan.started': { optional: ['round'] },
88
- 'plan.completed': { required: ['artifact'], optional: ['round', 'orchestrated'] },
107
+ 'plan.completed': { required: ['artifact', 'artifactSha256', 'semanticDigest'], optional: ['round', 'orchestrated'] },
89
108
  'review-plan.started': { optional: ['round'] },
90
109
  'review-plan.completed': { required: ['artifact', 'verdict', 'blockers', 'major', 'minor', 'manualValidation'], optional: ['round', 'orchestrated'] },
91
110
  'code.started': { optional: ['round', 'fixFor', 'implementationInput'] },
92
- 'code.completed': { required: ['artifact'], optional: ['round', 'fixFor', 'implementationInput', 'filesModified', 'testsPassed', 'blockers', 'major', 'minor', 'manualValidation', 'orchestrated'] },
111
+ 'code.completed': { required: ['artifact', 'artifactSha256', 'semanticDigest'], optional: ['round', 'fixFor', 'implementationInput', 'filesModified', 'testsPassed', 'blockers', 'major', 'minor', 'manualValidation', 'orchestrated'] },
93
112
  'review-code.started': { optional: ['round'] },
94
113
  'review-code.completed': { required: ['artifact', 'verdict', 'blockers', 'major', 'minor', 'manualValidation'], optional: ['round', 'orchestrated'] },
95
114
  'manual-validation.started': { optional: ['round'] },
@@ -98,6 +117,30 @@ const SCHEMAS: Record<TaskEventName, { required?: string[]; optional?: string[]
98
117
  'validation-run.completed': { required: ['artifact'], optional: ['round'] }
99
118
  };
100
119
 
120
+ function localArtifactValidationConfig(repoRoot: string, family: LocalArtifactFamily) {
121
+ const fallback = {
122
+ requiredSections: LOCAL_ARTIFACT_REQUIRED_SECTIONS[family],
123
+ requiredPatterns: LOCAL_ARTIFACT_REQUIRED_PATTERNS
124
+ };
125
+ const skillName = family === 'analysis' ? 'analyze-task' : family === 'plan' ? 'plan-task' : 'code-task';
126
+ try {
127
+ const artifact = loadVerificationConfig(repoRoot, skillName).checks.artifact;
128
+ if (!artifact || typeof artifact !== 'object' || Array.isArray(artifact)) return fallback;
129
+ const sections = artifact.required_sections;
130
+ const patterns = artifact.required_patterns;
131
+ return {
132
+ requiredSections: Array.isArray(sections)
133
+ ? sections.filter((value): value is string => typeof value === 'string')
134
+ : fallback.requiredSections,
135
+ requiredPatterns: Array.isArray(patterns)
136
+ ? patterns.filter((value): value is string => typeof value === 'string')
137
+ : fallback.requiredPatterns
138
+ };
139
+ } catch {
140
+ return fallback;
141
+ }
142
+ }
143
+
101
144
  function validateTaskEventRequest(request: TaskEventRequest): TaskEventError | null {
102
145
  if (!eventCatalog.includes(request.event as TaskEventName)) return { code: 'EVENT_UNKNOWN', message: `unknown task event '${request.event}'` };
103
146
  if (!request.taskRef || !request.agent) return { code: 'EVENT_PAYLOAD_INVALID', message: 'taskRef and agent are required' };
@@ -113,6 +156,13 @@ function validateTaskEventRequest(request: TaskEventRequest): TaskEventError | n
113
156
  if (value !== undefined && (!Number.isInteger(value) || value < (key === 'round' || key === 'question' ? 1 : 0))) return { code: 'EVENT_PAYLOAD_INVALID', message: `'${key}' must be a ${key === 'round' || key === 'question' ? 'positive' : 'non-negative'} integer` };
114
157
  }
115
158
  if (request.verdict && !['approved', 'changes-requested', 'rejected'].includes(request.verdict)) return { code: 'EVENT_PAYLOAD_INVALID', message: 'verdict is invalid' };
159
+ if (request.initiator && !['human', 'model', 'orchestrator'].includes(request.initiator)) return { code: 'EVENT_PAYLOAD_INVALID', message: 'initiator is invalid' };
160
+ if (request.requestId !== undefined && (!request.requestId.trim() || /[\r\n]/.test(request.requestId))) return { code: 'EVENT_PAYLOAD_INVALID', message: 'requestId must be a non-empty single line' };
161
+ if (request.reasonCode && !['user-request', 'new-requirement', 'upstream-fact-doubt', 'review-finding', 'retry', 'validation-rerun'].includes(request.reasonCode)) return { code: 'EVENT_PAYLOAD_INVALID', message: 'reasonCode is invalid' };
162
+ for (const [name, value] of [['sourceFinding', request.sourceFinding], ['sourceArtifact', request.sourceArtifact], ['sourceSha256', request.sourceSha256]] as const) {
163
+ if (value !== undefined && (!value.trim() || /[\r\n]/.test(value))) return { code: 'EVENT_PAYLOAD_INVALID', message: `${name} must be a non-empty single line` };
164
+ }
165
+ if (request.sourceSha256 !== undefined && !/^[a-f0-9]{64}$/.test(request.sourceSha256)) return { code: 'EVENT_PAYLOAD_INVALID', message: 'sourceSha256 must be a sha256 digest' };
116
166
  if (request.event === 'code.completed') {
117
167
  const fix = request.fixFor !== undefined || ['blockers', 'major', 'minor', 'manualValidation'].some((key) => request[key as keyof TaskEventRequest] !== undefined);
118
168
  const modeRequired = fix ? ['fixFor', 'blockers', 'major', 'minor', 'manualValidation'] : ['filesModified', 'testsPassed'];
@@ -121,20 +171,27 @@ function validateTaskEventRequest(request: TaskEventRequest): TaskEventError | n
121
171
  }
122
172
  if (request.fixFor && !/^review-code(?:-r(?:[2-9]|[1-9]\d+))?\.md$/.test(request.fixFor)) return { code: 'EVENT_PAYLOAD_INVALID', message: 'fixFor must reference a canonical review-code artifact' };
123
173
  if (request.implementationInput && !/^II-[1-9]\d*$/.test(request.implementationInput)) return { code: 'EVENT_PAYLOAD_INVALID', message: 'implementationInput must be a canonical II-N id' };
174
+ if (request.artifactSha256 !== undefined && !/^[0-9a-f]{64}$/i.test(request.artifactSha256)) return { code: 'EVENT_PAYLOAD_INVALID', message: 'artifactSha256 must be a 64-character hexadecimal digest' };
175
+ if (request.semanticDigest !== undefined && !/^[0-9a-f]{64}$/i.test(request.semanticDigest)) return { code: 'EVENT_PAYLOAD_INVALID', message: 'semanticDigest must be a 64-character hexadecimal digest' };
124
176
  if (request.fixFor && request.implementationInput) return { code: 'EVENT_PAYLOAD_INVALID', message: 'fixFor and implementationInput are mutually exclusive' };
125
177
  if (request.summaryResult !== undefined && (!request.summaryResult.trim() || /[\r\n]/.test(request.summaryResult))) return { code: 'EVENT_PAYLOAD_INVALID', message: 'summaryResult must be a non-empty single line' };
178
+ if (request.event !== 'analyze.awaiting-input' && /\.(?:started|completed)$/.test(request.event)) {
179
+ if (!request.initiator || !request.requestId || !request.reasonCode) {
180
+ return { code: 'EVENT_TRIGGER_REQUIRED', message: `${request.event} requires --initiator, --request-id, and --reason-code` };
181
+ }
182
+ }
126
183
  return null;
127
184
  }
128
185
 
129
186
  const FAMILY = {
130
- analyze: { artifact: 'analysis', started: ['requirement-analysis', 'requirement-analysis-review', 'code'], completed: ['requirement-analysis', 'requirement-analysis-review', 'code'], target: 'requirement-analysis', label: 'Analyze Task' },
131
- 'review-analysis': { artifact: 'review-analysis', started: ['requirement-analysis', 'requirement-analysis-review'], completed: ['requirement-analysis', 'requirement-analysis-review'], target: 'requirement-analysis-review', label: 'Review Analysis' },
132
- plan: { artifact: 'plan', started: ['requirement-analysis-review', 'technical-design-review', 'commit'], completed: ['requirement-analysis-review', 'technical-design-review', 'commit'], target: 'technical-design', label: 'Plan Task' },
133
- 'review-plan': { artifact: 'review-plan', started: ['technical-design', 'technical-design-review'], completed: ['technical-design', 'technical-design-review'], target: 'technical-design-review', label: 'Review Plan' },
134
- code: { artifact: 'code', started: ['technical-design-review', 'code-review'], completed: ['technical-design-review', 'code-review'], target: 'code', label: 'Code Task' },
135
- 'review-code': { artifact: 'review-code', started: ['code', 'code-review', 'commit'], completed: ['code', 'code-review', 'commit'], target: 'code-review', label: 'Review Code' },
136
- 'manual-validation': { artifact: 'manual-validation', started: ['code-review', 'commit'], completed: ['code-review', 'commit'], target: null, label: 'Complete Manual Validation' },
137
- 'validation-run': { artifact: 'validation-run', started: ['code-review', 'commit'], completed: ['code-review', 'commit'], target: null, label: 'Run Manual Validation' }
187
+ analyze: { artifact: 'analysis', target: 'requirement-analysis', label: 'Analyze Task' },
188
+ 'review-analysis': { artifact: 'review-analysis', target: 'requirement-analysis-review', label: 'Review Analysis' },
189
+ plan: { artifact: 'plan', target: 'technical-design', label: 'Plan Task' },
190
+ 'review-plan': { artifact: 'review-plan', target: 'technical-design-review', label: 'Review Plan' },
191
+ code: { artifact: 'code', target: 'code', label: 'Code Task' },
192
+ 'review-code': { artifact: 'review-code', target: 'code-review', label: 'Review Code' },
193
+ 'manual-validation': { artifact: 'manual-validation', target: null, label: 'Complete Manual Validation' },
194
+ 'validation-run': { artifact: 'validation-run', target: null, label: 'Run Manual Validation' }
138
195
  } as const;
139
196
  type EventFamily = keyof typeof FAMILY;
140
197
 
@@ -290,6 +347,126 @@ function reviewInputFamily(family: EventFamily): ArtifactFamily {
290
347
  return family === 'review-analysis' ? 'analysis' : family === 'review-plan' ? 'plan' : 'code';
291
348
  }
292
349
 
350
+ function lifecycleAction(family: EventFamily): LifecycleAction {
351
+ return family === 'analyze' ? 'analysis' : family;
352
+ }
353
+
354
+ function eventTrigger(request: TaskEventRequest, family: EventFamily): ExplicitTrigger {
355
+ return {
356
+ initiator: request.initiator ?? (request.orchestrated ? 'orchestrator' : request.agent === 'human' ? 'human' : 'model'),
357
+ requestId: request.requestId ?? `${request.taskRef}:${request.event}:${request.round ?? 1}`,
358
+ requestedAction: lifecycleAction(family),
359
+ reasonCode: request.reasonCode ?? (request.fixFor || request.implementationInput ? 'review-finding' : 'user-request'),
360
+ ...(request.sourceFinding ? { sourceFinding: request.sourceFinding } : {}),
361
+ ...(request.sourceArtifact ? { sourceArtifact: request.sourceArtifact } : {}),
362
+ ...(request.sourceSha256 ? { sourceSha256: request.sourceSha256 } : {}),
363
+ ...(request.implementationInput ? { implementationInput: request.implementationInput } : {}),
364
+ explicitRequest: request.requestId !== undefined || request.reasonCode !== undefined || request.initiator !== undefined || request.orchestrated === true
365
+ };
366
+ }
367
+
368
+ function invalidationMutationForCompletion(
369
+ content: string,
370
+ taskDir: string,
371
+ family: EventFamily,
372
+ artifact: ArtifactIdentity,
373
+ timestamp: string
374
+ ): { mutation: ReturnType<typeof invalidationMutation> | null } | { error: string } {
375
+ if (!['analyze', 'plan', 'code'].includes(family)) return { mutation: null };
376
+ const parsed = parseInvalidationDocument(content);
377
+ if (!parsed.ok) return { error: parsed.message };
378
+ const downstream: Record<'analyze' | 'plan' | 'code', readonly string[]> = {
379
+ analyze: ['review-analysis', 'plan', 'review-plan', 'code', 'review-code'],
380
+ plan: ['review-plan', 'code', 'review-code'],
381
+ code: ['review-code']
382
+ };
383
+ const sourceFamily = family as 'analyze' | 'plan' | 'code';
384
+ let receipts: readonly ArtifactReceipt[] = [];
385
+ try {
386
+ receipts = parseArtifactReceipts(content).rows;
387
+ } catch (error) {
388
+ return { error: error instanceof Error ? error.message : String(error) };
389
+ }
390
+ const targets = downstream[sourceFamily].flatMap((targetFamily: string) => {
391
+ const names = fs.readdirSync(taskDir).filter((name) => {
392
+ const pattern = targetFamily === 'review-analysis' ? /^review-analysis(?:-r\d+)?\.md$/
393
+ : targetFamily === 'review-plan' ? /^review-plan(?:-r\d+)?\.md$/
394
+ : targetFamily === 'review-code' ? /^review-code(?:-r\d+)?\.md$/
395
+ : new RegExp(`^${targetFamily}(?:-r\\d+)?\\.md$`);
396
+ return pattern.test(name);
397
+ });
398
+ return names.flatMap((name) => {
399
+ try {
400
+ const stat = fs.lstatSync(path.join(taskDir, name));
401
+ if (!stat.isFile() || stat.isSymbolicLink()) return [];
402
+ const targetRound = parseArtifactName(name)?.round ?? 1;
403
+ const targetSha256 = sha256File(path.join(taskDir, name));
404
+ const shapes: Array<{ targetKind: InvalidationTargetKind; targetFamily: string; targetArtifact: string; targetRound: number; targetSha256: string }> = [
405
+ { targetKind: 'artifact', targetFamily, targetArtifact: name, targetRound, targetSha256 }
406
+ ];
407
+ const receipt = receipts.find((candidate) => candidate.output === name);
408
+ if (receipt) shapes.push({
409
+ targetKind: 'receipt', targetFamily, targetArtifact: name, targetRound,
410
+ targetSha256: receipt.inputSha256
411
+ });
412
+ if (targetFamily.startsWith('review-')) {
413
+ shapes.push({ targetKind: 'approval', targetFamily, targetArtifact: name, targetRound, targetSha256 });
414
+ }
415
+ if (targetFamily === 'review-code') {
416
+ shapes.push({ targetKind: 'reviewed-snapshot', targetFamily, targetArtifact: name, targetRound, targetSha256 });
417
+ }
418
+ return shapes.map((targetShape) => ({
419
+ ...targetShape,
420
+ targetId: targetIdFor('pending', targetShape), operationId: 'pending', status: 'pending' as const,
421
+ reasonCode: 'upstream-replaced', updatedAt: timestamp
422
+ }));
423
+ } catch (error) {
424
+ throw new Error(`cannot inspect invalidation target '${name}': ${error instanceof Error ? error.message : String(error)}`);
425
+ }
426
+ });
427
+ });
428
+ if (targets.length === 0) return { mutation: null };
429
+ const source = {
430
+ sourceFamily: lifecycleAction(family), sourceArtifact: artifact.name,
431
+ sourceRound: parseArtifactName(artifact.name)?.round ?? 1, sourceSha256: sha256File(artifact.path),
432
+ createdAt: timestamp, updatedAt: timestamp
433
+ };
434
+ const operation = createInvalidationOperation(source);
435
+ const normalizedTargets = targets.map((target: (typeof targets)[number]) => ({
436
+ ...target, operationId: operation.operationId,
437
+ targetId: targetIdFor(operation.operationId, target)
438
+ }));
439
+ const operationWithTotal = createInvalidationOperation(source, normalizedTargets);
440
+ const next = upsertInvalidation(parsed.document, operationWithTotal, normalizedTargets);
441
+ if (!next.ok) return { error: next.message };
442
+ return { mutation: next.changed ? invalidationMutation(content, next.document) : null };
443
+ }
444
+
445
+ function reworkIntentMutationForCompletion(
446
+ content: string,
447
+ taskDir: string,
448
+ family: EventFamily,
449
+ artifact: ArtifactIdentity,
450
+ timestamp: string
451
+ ): { mutation: ReturnType<typeof reworkIntentMutation> | null } | { error: string } {
452
+ const parsed = parseReworkIntentDocument(content);
453
+ if (!parsed.ok) return { error: parsed.message };
454
+ const hash = sha256File(artifact.path);
455
+ let next = parsed.intents;
456
+ if (family === 'analyze' || family === 'plan' || family === 'code') {
457
+ const hashes = Object.fromEntries(fs.readdirSync(taskDir).flatMap((name) => {
458
+ if (!/^review-(?:analysis|plan|code)(?:-r\d+)?\.md$/.test(name)) return [];
459
+ try { return [[name, sha256File(path.join(taskDir, name))]]; }
460
+ catch { return []; }
461
+ }));
462
+ next = consumeReworkIntents(next, family === 'analyze' ? 'analysis' : family, hashes, timestamp).intents;
463
+ }
464
+ if (family === 'review-analysis' || family === 'review-plan' || family === 'review-code') {
465
+ next = supersedeReworkIntents(next, artifact.name, hash, timestamp).intents;
466
+ }
467
+ return { mutation: JSON.stringify(next) === JSON.stringify(parsed.intents) ? null : reworkIntentMutation(content, next) };
468
+ }
469
+
293
470
  function buildCompletionReceipt(
294
471
  taskDir: string,
295
472
  family: EventFamily,
@@ -407,6 +584,7 @@ function applyTaskEventUnlocked(request: TaskEventRequest, options: TaskEventOpt
407
584
  const completedRows = matchingRows.filter((item) => item.done);
408
585
  const row = manual ? openRows.at(-1) : matchingRows[0];
409
586
  let completedArtifact: ArtifactIdentity | null = null;
587
+ let localFinalizationIntent: LocalArtifactFinalizationIntent | null = null;
410
588
  if (eventIdentity.phase === 'started' && row) {
411
589
  if (row.agent !== normalized.agent) return failed(normalized, { code: 'EVENT_LOG_CONFLICT', message: 'open started event has a different agent' }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
412
590
  return successNoOp(normalized, resolved.taskId, resolved.taskMdPath, currentStep, eventIdentity, row.started, frontmatter, artifactContext);
@@ -420,13 +598,81 @@ function applyTaskEventUnlocked(request: TaskEventRequest, options: TaskEventOpt
420
598
  const validated = validateCompletedArtifact(resolved.taskDir, FAMILY[eventIdentity.family].artifact, normalized.artifact!, normalized.round);
421
599
  if (!validated.ok) return failed(normalized, validated.error, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
422
600
  completedArtifact = validated.artifact;
601
+ if (eventIdentity.family === 'analyze' || eventIdentity.family === 'plan' || eventIdentity.family === 'code') {
602
+ const localFamily = eventIdentity.family === 'analyze'
603
+ ? 'analysis'
604
+ : eventIdentity.family === 'plan' ? 'plan' : 'code';
605
+ let artifactContent: string;
606
+ try { artifactContent = fs.readFileSync(completedArtifact.path, 'utf8'); }
607
+ catch (error) {
608
+ return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: `cannot read ${completedArtifact.name}: ${String(error)}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
609
+ }
610
+ const validationConfig = localArtifactValidationConfig(resolved.repoRoot, localFamily);
611
+ const local = validateLocalArtifact(artifactContent, {
612
+ family: localFamily,
613
+ requiredSections: validationConfig.requiredSections,
614
+ requiredPatterns: validationConfig.requiredPatterns
615
+ });
616
+ if (!local.ok) {
617
+ return failed(normalized, {
618
+ code: 'EVENT_ARTIFACT_CONFLICT',
619
+ message: `LOCAL_ARTIFACT_INVALID: ${local.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ')}`
620
+ }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
621
+ }
622
+ const actualSha256 = sha256File(completedArtifact.path);
623
+ if (actualSha256 !== normalized.artifactSha256) {
624
+ return failed(normalized, {
625
+ code: 'EVENT_ARTIFACT_CONFLICT',
626
+ message: `artifact SHA-256 does not match finalizer result for ${completedArtifact.name}`
627
+ }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
628
+ }
629
+ if (local.semanticDigest !== normalized.semanticDigest) {
630
+ return failed(normalized, {
631
+ code: 'EVENT_ARTIFACT_CONFLICT',
632
+ message: `semantic digest does not match finalizer result for ${completedArtifact.name}`
633
+ }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
634
+ }
635
+ try {
636
+ localFinalizationIntent = readLocalArtifactFinalizationIntent(
637
+ resolved.repoRoot, resolved.taskId, localFamily, completedArtifact.name
638
+ );
639
+ } catch (error) {
640
+ return failed(normalized, {
641
+ code: 'EVENT_ARTIFACT_CONFLICT',
642
+ message: `cannot read local finalizer provenance for ${completedArtifact.name}: ${error instanceof Error ? error.message : String(error)}`
643
+ }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
644
+ }
645
+ if (!localFinalizationIntent || !['passed', 'consumed'].includes(localFinalizationIntent.state)) {
646
+ return failed(normalized, {
647
+ code: 'EVENT_ARTIFACT_CONFLICT',
648
+ message: `local finalizer provenance is missing or incomplete for ${completedArtifact.name}`
649
+ }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
650
+ }
651
+ if (localFinalizationIntent.artifactSha256 !== actualSha256 || localFinalizationIntent.semanticDigest !== local.semanticDigest) {
652
+ return failed(normalized, {
653
+ code: 'EVENT_ARTIFACT_CONFLICT',
654
+ message: `local finalizer provenance does not match ${completedArtifact.name}`
655
+ }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
656
+ }
657
+ }
423
658
  }
424
659
  if (eventIdentity.phase === 'waiting' && section.entries.some((entry) => entry.step === eventIdentity.action && entry.note === eventIdentity.note)) {
425
660
  const existing = section.entries.find((entry) => entry.step === eventIdentity.action && entry.note === eventIdentity.note)!;
426
661
  return successNoOp(normalized, resolved.taskId, resolved.taskMdPath, currentStep, eventIdentity, existing.time, frontmatter, artifactContext);
427
662
  }
428
- const allowed = FAMILY[eventIdentity.family][eventIdentity.phase === 'started' ? 'started' : 'completed'];
429
- if (!(allowed as readonly string[]).includes(currentStep) && !allowsManualOverride(options.manualOverride, 'task-event', 'EVENT_TRANSITION_INVALID')) return failed(normalized, { code: 'EVENT_TRANSITION_INVALID', message: `${normalized.event} is not allowed from '${currentStep}'` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
663
+ if (eventIdentity.phase === 'started') {
664
+ const trigger = eventTrigger(normalized, eventIdentity.family);
665
+ const facts = buildLifecycleFacts(resolved.taskDir, content, resolved.state);
666
+ if (!facts.ok) return failed(normalized, { code: 'EVENT_TRANSITION_INVALID', message: `${facts.code}: ${facts.message}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
667
+ const capability = canStart(lifecycleAction(eventIdentity.family), facts.facts, trigger);
668
+ const capabilityOverride = capability.reasonCode === 'TASK_NOT_ACTIVE'
669
+ ? stateOverride
670
+ : allowsManualOverride(options.manualOverride, 'task-event', 'EVENT_TRANSITION_INVALID');
671
+ if (!capability.allowed && !capabilityOverride) {
672
+ const code = capability.reasonCode === 'INVALIDATION_INCOMPLETE' ? 'TASK_INVALIDATION_BLOCKED' : 'EVENT_TRANSITION_INVALID';
673
+ return failed(normalized, { code, message: `${capability.reasonCode}: ${capability.evidence.join(', ')}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
674
+ }
675
+ }
430
676
  const findingCountError = validateReviewFindingCounts(
431
677
  normalized,
432
678
  content,
@@ -460,12 +706,24 @@ function applyTaskEventUnlocked(request: TaskEventRequest, options: TaskEventOpt
460
706
  try { metadata = (options.metadataProvider ?? captureTaskWriteMetadata)(); }
461
707
  catch (error) { return failed(normalized, { code: 'METADATA_CAPTURE_FAILED', message: String(error) }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath }); }
462
708
  let completionReceipt: ArtifactReceipt | null = null;
709
+ let completionInvalidation: ReturnType<typeof invalidationMutation> | null = null;
710
+ let completionRework: ReturnType<typeof reworkIntentMutation> | null = null;
463
711
  if (eventIdentity.phase === 'completed' && completedArtifact) {
464
712
  const receipt = buildCompletionReceipt(resolved.taskDir, eventIdentity.family, completedArtifact, metadata.timestamp, frontmatter);
465
713
  if (receipt && !receipt.ok) {
466
714
  return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: receipt.message }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
467
715
  }
468
716
  completionReceipt = receipt?.receipt ?? null;
717
+ try {
718
+ const invalidation = invalidationMutationForCompletion(content, resolved.taskDir, eventIdentity.family, completedArtifact, metadata.timestamp);
719
+ if ('error' in invalidation) return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: invalidation.error }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
720
+ completionInvalidation = invalidation.mutation;
721
+ const rework = reworkIntentMutationForCompletion(content, resolved.taskDir, eventIdentity.family, completedArtifact, metadata.timestamp);
722
+ if ('error' in rework) return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: rework.error }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
723
+ completionRework = rework.mutation;
724
+ } catch (error) {
725
+ return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: error instanceof Error ? error.message : String(error) }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
726
+ }
469
727
  }
470
728
  const step = eventIdentity.phase === 'started' || eventIdentity.target === null ? currentStep : eventIdentity.target;
471
729
  const logStep = eventIdentity.phase === 'started' ? `${eventIdentity.action} [started]` : eventIdentity.action;
@@ -513,6 +771,8 @@ function applyTaskEventUnlocked(request: TaskEventRequest, options: TaskEventOpt
513
771
  return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
514
772
  }
515
773
  }
774
+ if (completionInvalidation) mutations.push(completionInvalidation);
775
+ if (completionRework) mutations.push(completionRework);
516
776
  if (eventIdentity.phase === 'completed' && normalized.implementationInput) {
517
777
  let implementationRows;
518
778
  try {
@@ -531,7 +791,27 @@ function applyTaskEventUnlocked(request: TaskEventRequest, options: TaskEventOpt
531
791
  });
532
792
  }
533
793
  mutations.push({ kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: section.heading, body });
534
- const result = writeTask({ taskRef: normalized.taskRef, expectedState: stateOverride ? resolved.state : 'active', dryRun: normalized.dryRun, mutations }, { ...options, metadataProvider: () => metadata });
794
+ if (!normalized.dryRun && localFinalizationIntent && completedArtifact && localFinalizationIntent.state === 'passed') {
795
+ try {
796
+ localFinalizationIntent = consumeLocalArtifactFinalizationIntent(resolved.repoRoot, localFinalizationIntent);
797
+ } catch (error) {
798
+ return failed(normalized, {
799
+ code: 'EVENT_ARTIFACT_CONFLICT',
800
+ message: `local finalizer provenance could not be consumed before task write for ${completedArtifact.name}: ${error instanceof Error ? error.message : String(error)}`
801
+ }, {
802
+ taskId: resolved.taskId,
803
+ taskMdPath: resolved.taskMdPath,
804
+ fromStep: currentStep,
805
+ toStep: step,
806
+ action: eventIdentity.action,
807
+ phase: eventIdentity.phase,
808
+ artifactContext
809
+ });
810
+ }
811
+ }
812
+ const sourceCompletion = eventIdentity.phase === 'completed'
813
+ && ['analyze', 'plan', 'code'].includes(eventIdentity.family);
814
+ const result = writeTask({ taskRef: normalized.taskRef, expectedState: stateOverride ? resolved.state : 'active', dryRun: normalized.dryRun, mutations }, { ...options, invalidationContext: sourceCompletion ? 'source-completion' : 'standard', metadataProvider: () => metadata });
535
815
  if (result.status === 'failed') return failed(normalized, result.error, { taskId: result.taskId, taskMdPath: result.taskMdPath, fromStep: currentStep, toStep: step, action: eventIdentity.action, phase: eventIdentity.phase, timestamp: result.timestamp, agentInfraVersion: result.agentInfraVersion, operations: result.operations, artifactContext });
536
816
  if (!normalized.dryRun && orchestrationCompletion) {
537
817
  try {
@@ -55,6 +55,7 @@ type TaskFinalizationRequest = Readonly<{
55
55
 
56
56
  type TaskFinalizationOptions = Readonly<{
57
57
  repoRoot: string;
58
+ controlBinding?: Readonly<{ generation: string; requestId: string }>;
58
59
  metadataProvider?: TaskLifecycleOptions['metadataProvider'];
59
60
  lifecycle?: typeof applyTaskLifecycle;
60
61
  commentSync?: typeof syncPlatformComment;
@@ -73,6 +74,7 @@ type TaskFinalizationReceipt = Readonly<{
73
74
  verification: FinalizationStepState;
74
75
  warningProjection: WarningProjectionState;
75
76
  warnings: readonly FinalizationWarning[];
77
+ controlBinding?: Readonly<{ generation: string; requestId: string }>;
76
78
  updatedAt: string;
77
79
  lastError: FinalizationError | null;
78
80
  }>;
@@ -146,7 +148,7 @@ function failed(
146
148
  };
147
149
  }
148
150
 
149
- function emptyReceipt(taskId: string): TaskFinalizationReceipt {
151
+ function emptyReceipt(taskId: string, controlBinding?: Readonly<{ generation: string; requestId: string }>): TaskFinalizationReceipt {
150
152
  return {
151
153
  version: RECEIPT_VERSION,
152
154
  taskId,
@@ -158,6 +160,7 @@ function emptyReceipt(taskId: string): TaskFinalizationReceipt {
158
160
  verification: 'pending',
159
161
  warningProjection: 'done',
160
162
  warnings: [],
163
+ ...(controlBinding ? { controlBinding } : {}),
161
164
  updatedAt: now(),
162
165
  lastError: null
163
166
  };
@@ -182,6 +185,7 @@ function validWarning(value: unknown): value is FinalizationWarning {
182
185
  function validateReceipt(value: unknown, taskId: string): TaskFinalizationReceipt {
183
186
  if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('receipt must be an object');
184
187
  const receipt = value as Record<string, unknown>;
188
+ const controlBinding = receipt.controlBinding as Record<string, unknown> | null | undefined;
185
189
  const states = ['pending', 'done', 'skipped'];
186
190
  if (
187
191
  receipt.version !== RECEIPT_VERSION || receipt.taskId !== taskId || receipt.intent !== 'complete'
@@ -194,6 +198,10 @@ function validateReceipt(value: unknown, taskId: string): TaskFinalizationReceip
194
198
  || !Array.isArray(receipt.warnings) || receipt.warnings.some((warning) => !validWarning(warning))
195
199
  || typeof receipt.updatedAt !== 'string'
196
200
  || (receipt.lastError !== null && (typeof receipt.lastError !== 'object' || Array.isArray(receipt.lastError)))
201
+ || (receipt.controlBinding !== undefined && (!controlBinding || typeof controlBinding !== 'object'
202
+ || Array.isArray(controlBinding)
203
+ || typeof controlBinding.generation !== 'string' || controlBinding.generation.length === 0
204
+ || typeof controlBinding.requestId !== 'string' || !/^[a-f0-9-]{16,64}$/u.test(controlBinding.requestId)))
197
205
  ) throw new Error('receipt schema is invalid');
198
206
  return receipt as TaskFinalizationReceipt;
199
207
  }
@@ -205,6 +213,18 @@ function readReceipt(repoRoot: string, taskId: string): TaskFinalizationReceipt
205
213
  return validateReceipt(value, taskId);
206
214
  }
207
215
 
216
+ function readTaskFinalizationReceipt(repoRoot: string, taskId: string): TaskFinalizationReceipt | null {
217
+ return readReceipt(path.resolve(repoRoot), taskId);
218
+ }
219
+
220
+ function controlBindingMatches(
221
+ receipt: TaskFinalizationReceipt,
222
+ binding: Readonly<{ generation: string; requestId: string }>
223
+ ): boolean {
224
+ return receipt.controlBinding?.generation === binding.generation
225
+ && receipt.controlBinding.requestId === binding.requestId;
226
+ }
227
+
208
228
  function writeReceipt(repoRoot: string, receipt: TaskFinalizationReceipt): void {
209
229
  const directory = finalizationRoot(repoRoot);
210
230
  fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
@@ -486,14 +506,14 @@ function reconcileWarningProjection(repoRoot: string, taskId: string, receipt: T
486
506
  catch { return receipt; }
487
507
  }
488
508
 
489
- function syncPendingTaskComment(input: {
509
+ async function syncPendingTaskComment(input: {
490
510
  repoRoot: string;
491
511
  taskId: string;
492
512
  agent: string;
493
513
  receipt: TaskFinalizationReceipt;
494
514
  commentSync: typeof syncPlatformComment;
495
515
  consumedCapabilities: Set<string>;
496
- }): TaskCommentSyncOutcome {
516
+ }): Promise<TaskCommentSyncOutcome> {
497
517
  const { repoRoot, taskId, agent, commentSync, consumedCapabilities } = input;
498
518
  let receipt = input.receipt;
499
519
  if (receipt.taskComment !== 'pending') {
@@ -505,7 +525,7 @@ function syncPendingTaskComment(input: {
505
525
  };
506
526
  }
507
527
  try {
508
- const result = commentSync(taskId, { kind: 'task', agent, cwd: repoRoot });
528
+ const result = await commentSync(taskId, { kind: 'task', agent, cwd: repoRoot });
509
529
  const step = commentStep(result);
510
530
  if (result.status === 'applied' || result.status === 'no-op') {
511
531
  const skipped = result.error?.code === 'ISSUE_NOT_LINKED';
@@ -569,11 +589,11 @@ function terminalResult(
569
589
  };
570
590
  }
571
591
 
572
- function applyUnderLock(
592
+ async function applyUnderLock(
573
593
  request: TaskFinalizationRequest,
574
594
  taskId: string,
575
595
  options: TaskFinalizationOptions
576
- ): TaskFinalizationResult {
596
+ ): Promise<TaskFinalizationResult> {
577
597
  const repoRoot = path.resolve(options.repoRoot);
578
598
  const lifecycle = options.lifecycle ?? applyTaskLifecycle;
579
599
  const commentSync = options.commentSync ?? syncPlatformComment;
@@ -583,16 +603,27 @@ function applyUnderLock(
583
603
  try {
584
604
  const file = receiptPath(repoRoot, taskId);
585
605
  const existed = fs.existsSync(file);
586
- receipt = readReceipt(repoRoot, taskId) ?? emptyReceipt(taskId);
606
+ receipt = readReceipt(repoRoot, taskId) ?? emptyReceipt(taskId, options.controlBinding);
587
607
  if (!existed) writeReceipt(repoRoot, receipt);
588
608
  } catch (error) {
589
609
  return failed(taskId, errorOf(error, 'TASK_FINALIZATION_RECEIPT_INVALID'));
590
610
  }
611
+ if (options.controlBinding && !controlBindingMatches(receipt, options.controlBinding)) {
612
+ const error: FinalizationError = {
613
+ code: 'TASK_FINALIZATION_CONTROL_BINDING_CONFLICT',
614
+ message: 'finalization receipt belongs to a different sandbox request or generation',
615
+ retryable: false
616
+ };
617
+ return failed(taskId, error, {
618
+ completedSteps: completedSteps(receipt),
619
+ pendingSteps: pendingSteps(receipt)
620
+ });
621
+ }
591
622
 
592
623
  const preflightState = resolveTaskRef(taskId, { repoRoot });
593
624
  if (options.preflight && preflightState.ok && preflightState.state === 'active') {
594
625
  try {
595
- const preflight = options.preflight(
626
+ const preflight = await options.preflight(
596
627
  { taskRef: taskId, event: 'complete-task.preflight' },
597
628
  { repoRoot }
598
629
  );
@@ -668,7 +699,7 @@ function applyUnderLock(
668
699
 
669
700
  let taskComment: TaskFinalizationStep | null = null;
670
701
  receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
671
- const initialComment = syncPendingTaskComment({
702
+ const initialComment = await syncPendingTaskComment({
672
703
  repoRoot, taskId, agent: request.agent, receipt, commentSync, consumedCapabilities
673
704
  });
674
705
  receipt = initialComment.receipt;
@@ -684,7 +715,7 @@ function applyUnderLock(
684
715
  if (receipt.verification !== 'pending') {
685
716
  verification = { status: 'no-op', changed: false, error: null };
686
717
  } else {
687
- const result = verify(
718
+ const result = await verify(
688
719
  { taskRef: taskId, event: 'complete-task.completed' },
689
720
  { repoRoot }
690
721
  );
@@ -695,7 +726,7 @@ function applyUnderLock(
695
726
  scope: 'verification', operation: 'succeeded'
696
727
  }, consumedCapabilities);
697
728
  receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
698
- const finalComment = syncPendingTaskComment({
729
+ const finalComment = await syncPendingTaskComment({
699
730
  repoRoot, taskId, agent: request.agent, receipt, commentSync, consumedCapabilities
700
731
  });
701
732
  receipt = finalComment.receipt;
@@ -729,7 +760,7 @@ function applyUnderLock(
729
760
  return terminalResult(taskId, receipt, { lifecycle: lifecycleResult, taskComment, verification }, changed);
730
761
  }
731
762
 
732
- function applyTaskFinalization(request: TaskFinalizationRequest, options: TaskFinalizationOptions): TaskFinalizationResult {
763
+ async function applyTaskFinalization(request: TaskFinalizationRequest, options: TaskFinalizationOptions): Promise<TaskFinalizationResult> {
733
764
  if (request.intent !== 'complete' || !request.taskRef || !request.agent) {
734
765
  return failed(null, { code: 'TASK_FINALIZATION_PAYLOAD_INVALID', message: 'complete finalization requires taskRef and agent', retryable: false });
735
766
  }
@@ -737,7 +768,7 @@ function applyTaskFinalization(request: TaskFinalizationRequest, options: TaskFi
737
768
  const resolved = resolveTaskRef(request.taskRef, { repoRoot });
738
769
  if (!resolved.ok) return failed(resolved.taskId, { code: resolved.code, message: resolved.message, retryable: false });
739
770
  try {
740
- return withTaskExecutionLock(repoRoot, resolved.taskId, 'task-finalization.complete', () => applyUnderLock(request, resolved.taskId, options));
771
+ return await withTaskExecutionLock(repoRoot, resolved.taskId, 'task-finalization.complete', () => applyUnderLock(request, resolved.taskId, options));
741
772
  } catch (error) {
742
773
  const detail = error instanceof TaskExecutionLockError
743
774
  ? { code: error.code, message: error.message, retryable: error.code === 'ORCHESTRATION_LOCK_BUSY' }
@@ -746,7 +777,12 @@ function applyTaskFinalization(request: TaskFinalizationRequest, options: TaskFi
746
777
  }
747
778
  }
748
779
 
749
- export { applyFinalizationReceiptMutation, applyTaskFinalization, issueCapability as createFinalizationCapability };
780
+ export {
781
+ applyFinalizationReceiptMutation,
782
+ applyTaskFinalization,
783
+ issueCapability as createFinalizationCapability,
784
+ readTaskFinalizationReceipt
785
+ };
750
786
  export type {
751
787
  FinalizationError,
752
788
  FinalizationCapability,