@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
@@ -15,7 +15,7 @@ import { inspectLifecycleExecution } from './lifecycle-execution.ts';
15
15
  import { applyLedgerIntent } from './ledger-intents.ts';
16
16
  import { bindPlatformIssue } from '../platform/issues.ts';
17
17
  import { bindPlatformPullRequest } from '../platform/pull-requests.ts';
18
- import type { GitHubClient } from '../platform/github-client.ts';
18
+ import type { PlatformClient } from '../platform/context.ts';
19
19
  import { finalizeReviewSummary } from './review-finalization.ts';
20
20
  import { resolveTaskRef } from './resolve-ref.ts';
21
21
  import { DocumentMutationError, parseTable } from './sections.ts';
@@ -24,6 +24,10 @@ import { verifyTaskEvent } from './verification.ts';
24
24
  import { verifyInProcess } from './verification-engine.ts';
25
25
  import { canonicalTimestamp, writeTask } from './write.ts';
26
26
  import type { TaskFileSystem, TaskWriteMetadata, TaskWriteResult } from './write.ts';
27
+ import { readPrDeliveryFact } from './pr-delivery-fact.ts';
28
+ import { resourceIdentity, resourceIdentityNumber } from '../platform/provider-bridge.ts';
29
+ import type { ResourceIdentity } from '../platform/resource-identity.ts';
30
+ import { taskIssueIdentity } from '../platform/task-identities.ts';
27
31
 
28
32
  type Eligibility = 'eligible' | 'repair-only' | 'runtime-recovery-only' | 'never-overridable';
29
33
  type OutcomeEffect = 'apply-target' | 'retry-same-intent' | 'record-only' | 'no-write';
@@ -95,8 +99,8 @@ type HumanOverrideOptions = Readonly<{
95
99
  probeIssueNumber?: number;
96
100
  probePullRequestNumber?: number;
97
101
  probeStagingDir?: string;
98
- platformClient?: GitHubClient;
99
- effectExecutor?: (capability: ManualOverrideCapability) => OverrideError | null;
102
+ platformClient?: PlatformClient;
103
+ effectExecutor?: (capability: ManualOverrideCapability) => OverrideError | null | Promise<OverrideError | null>;
100
104
  }>;
101
105
 
102
106
  type FailureSnapshot = Readonly<{
@@ -583,7 +587,7 @@ function snapshotEvidence(
583
587
  content: string,
584
588
  frontmatter: Record<string, unknown> | null,
585
589
  producer: ProducerFailure,
586
- resource: Readonly<{ kind: 'issue' | 'pull-request'; number: number }> | null
590
+ resource: Readonly<{ kind: 'issue' | 'pull-request'; identity: ResourceIdentity; number: number | null }> | null
587
591
  ): string {
588
592
  const stableFrontmatter = frontmatter
589
593
  ? Object.fromEntries(Object.entries(frontmatter).filter(([key]) => !['updated_at', 'agent_infra_version', 'status', 'blocked_at', 'completed_at', 'cancelled_at'].includes(key)))
@@ -608,14 +612,22 @@ function resourceForSnapshot(
608
612
  policy: FailurePolicy,
609
613
  options: HumanOverrideOptions,
610
614
  frontmatter: Record<string, unknown> | null
611
- ): Readonly<{ kind: 'issue' | 'pull-request'; number: number }> | null {
615
+ ): Readonly<{ kind: 'issue' | 'pull-request'; identity: ResourceIdentity; number: number | null }> | null {
612
616
  if (policy.producerId === 'platform.issue') {
613
- const number = options.probeIssueNumber ?? toPositiveInteger(frontmatter?.issue_number);
614
- return number === null ? null : { kind: 'issue', number };
617
+ const identity = options.probeIssueNumber !== undefined
618
+ ? resourceIdentity(options.probeIssueNumber)
619
+ : taskIssueIdentity((frontmatter || {}) as Record<string, string | number | boolean | null>) || (() => {
620
+ const number = toPositiveInteger(frontmatter?.issue_number);
621
+ return number === null ? null : resourceIdentity(number);
622
+ })();
623
+ return identity ? { kind: 'issue', identity, number: resourceIdentityNumber(identity) } : null;
615
624
  }
616
625
  if (policy.producerId === 'platform.pull-request') {
617
- const number = options.probePullRequestNumber ?? toPositiveInteger(frontmatter?.pr_number);
618
- return number === null ? null : { kind: 'pull-request', number };
626
+ const fact = frontmatter ? readPrDeliveryFact(frontmatter) : null;
627
+ const identity = options.probePullRequestNumber !== undefined
628
+ ? resourceIdentity(options.probePullRequestNumber)
629
+ : fact?.status === 'valid' && fact.fact.state === 'bound' ? fact.fact.identity.resource : null;
630
+ return identity ? { kind: 'pull-request', identity, number: resourceIdentityNumber(identity) } : null;
619
631
  }
620
632
  return null;
621
633
  }
@@ -692,40 +704,52 @@ function probeNotObserved(policy: FailurePolicy): OverrideError {
692
704
  return error('OVERRIDE_FAILURE_NOT_PRESENT', `producer ${policy.producerId} did not produce ${policy.code}`);
693
705
  }
694
706
 
695
- function probePlatformFailure(
707
+ async function probePlatformFailure(
696
708
  taskRef: string,
697
709
  policy: FailurePolicy,
698
710
  resolved: ProbeTask,
699
711
  options: HumanOverrideOptions
700
- ): ProducerFailure | OverrideError {
712
+ ): Promise<ProducerFailure | OverrideError> {
701
713
  let frontmatter: ReturnType<typeof parseTypedTaskFrontmatter>;
702
714
  try {
703
715
  frontmatter = parseTypedTaskFrontmatter(fs.readFileSync(path.join(resolved.taskDir, 'task.md'), 'utf8'));
704
716
  } catch (cause) {
705
717
  return error('OVERRIDE_DOCUMENT_INVALID', cause instanceof Error ? cause.message : String(cause));
706
718
  }
707
- const issueNumber = options.probeIssueNumber ?? toPositiveInteger(frontmatter.issue_number);
708
- const pullRequestNumber = options.probePullRequestNumber ?? toPositiveInteger(frontmatter.pr_number);
709
- const operation = policy.producerId === 'platform.issue'
710
- ? issueNumber === null
719
+ const issueIdentity = options.probeIssueNumber !== undefined
720
+ ? resourceIdentity(options.probeIssueNumber)
721
+ : taskIssueIdentity(frontmatter) || (() => {
722
+ const number = toPositiveInteger(frontmatter.issue_number);
723
+ return number === null ? null : resourceIdentity(number);
724
+ })();
725
+ const fact = readPrDeliveryFact(frontmatter);
726
+ const pullRequestIdentity = options.probePullRequestNumber !== undefined
727
+ ? resourceIdentity(options.probePullRequestNumber)
728
+ : fact.status === 'valid' && fact.fact.state === 'bound' ? fact.fact.identity.resource : null;
729
+ const token = (identity: ResourceIdentity | null): string | null => identity ? String(identity.value) : null;
730
+ const issueToken = token(issueIdentity);
731
+ const pullRequestToken = token(pullRequestIdentity);
732
+ const operation = await (policy.producerId === 'platform.issue'
733
+ ? issueToken === null
711
734
  ? null
712
735
  : bindPlatformIssue(taskRef, {
713
- issue: issueNumber,
736
+ issue: issueToken,
714
737
  agent: options.probeOperator ?? 'local-operator',
715
738
  dryRun: true,
716
739
  cwd: resolved.repoRoot,
717
740
  ...(options.platformClient ? { client: options.platformClient } : {})
718
741
  })
719
- : pullRequestNumber === null
742
+ : pullRequestToken === null
720
743
  ? null
721
744
  : bindPlatformPullRequest(taskRef, {
722
- pr: pullRequestNumber,
745
+ pr: pullRequestToken,
723
746
  agent: options.probeOperator ?? 'local-operator',
724
747
  dryRun: true,
725
748
  cwd: resolved.repoRoot,
726
749
  ...(options.platformClient ? { client: options.platformClient } : {})
727
- });
728
- if (!operation) return error('OVERRIDE_PROBE_INPUT_MISSING', `${policy.producerId} requires a bound issue or pull request number`);
750
+ })
751
+ );
752
+ if (!operation) return error('OVERRIDE_PROBE_INPUT_MISSING', `${policy.producerId} requires a bound issue or pull request identity`);
729
753
  if (operation.status !== 'failed' && operation.status !== 'blocked') return probeNotObserved(policy);
730
754
  if (!operation.error) return error('OVERRIDE_PROBE_INPUT_MISSING', `${policy.producerId} returned no platform error evidence`);
731
755
  return {
@@ -763,6 +787,9 @@ function probeTaskEventFailure(taskRef: string, policy: FailurePolicy, resolved:
763
787
  event: candidate.event,
764
788
  agent: 'codex',
765
789
  dryRun: true,
790
+ initiator: 'model',
791
+ requestId: `override-probe:${taskRef}:${candidate.event}`,
792
+ reasonCode: 'user-request',
766
793
  ...(candidate.artifact ? { artifact: candidate.artifact } : {})
767
794
  }, { repoRoot: resolved.repoRoot, lockAlreadyHeld: true });
768
795
  const matched = probeResult(policy, result, resolved.state);
@@ -771,8 +798,8 @@ function probeTaskEventFailure(taskRef: string, policy: FailurePolicy, resolved:
771
798
  return probeNotObserved(policy);
772
799
  }
773
800
 
774
- function probeVerificationFailure(taskRef: string, policy: FailurePolicy, resolved: ProbeTask): ProducerFailure | OverrideError {
775
- const result = verifyTaskEvent(
801
+ async function probeVerificationFailure(taskRef: string, policy: FailurePolicy, resolved: ProbeTask): Promise<ProducerFailure | OverrideError> {
802
+ const result = await verifyTaskEvent(
776
803
  {
777
804
  taskRef,
778
805
  event: 'review-code.completed',
@@ -792,12 +819,12 @@ function latestArtifact(taskDir: string, family: string): string | undefined {
792
819
  ));
793
820
  candidates.sort((a, b) => {
794
821
  const round = (name: string) => Number(/-r(\d+)\.md$/.exec(name)?.[1] ?? 1);
795
- return round(b) - round(a);
796
- });
822
+ return round(b) - round(a);
823
+ });
797
824
  return candidates[0];
798
825
  }
799
826
 
800
- function probeVerificationEngineFailure(policy: FailurePolicy, resolved: ProbeTask): ProducerFailure | OverrideError {
827
+ async function probeVerificationEngineFailure(policy: FailurePolicy, resolved: ProbeTask): Promise<ProducerFailure | OverrideError> {
801
828
  const candidates = [
802
829
  { skillName: 'review-code', family: 'review-code' },
803
830
  { skillName: 'review-plan', family: 'review-plan' },
@@ -811,7 +838,7 @@ function probeVerificationEngineFailure(policy: FailurePolicy, resolved: ProbeTa
811
838
  const artifactFile = candidate.family ? latestArtifact(resolved.taskDir, candidate.family) : undefined;
812
839
  if (candidate.family && !artifactFile) continue;
813
840
  try {
814
- const payload = verifyInProcess({
841
+ const payload = await verifyInProcess({
815
842
  mode: 'gate',
816
843
  skillName: candidate.skillName,
817
844
  taskDir: resolved.taskDir,
@@ -835,12 +862,12 @@ function probeVerificationEngineFailure(policy: FailurePolicy, resolved: ProbeTa
835
862
  return probeNotObserved(policy);
836
863
  }
837
864
 
838
- function probeGenericFailure(
865
+ async function probeGenericFailure(
839
866
  taskRef: string,
840
867
  policy: FailurePolicy,
841
868
  resolved: ProbeTask,
842
869
  options: HumanOverrideOptions = {}
843
- ): ProducerFailure | OverrideError {
870
+ ): Promise<ProducerFailure | OverrideError> {
844
871
  switch (policy.producerId) {
845
872
  case 'task.resolve':
846
873
  return probeNotObserved(policy);
@@ -849,9 +876,9 @@ function probeGenericFailure(
849
876
  case 'task-event':
850
877
  return probeTaskEventFailure(taskRef, policy, resolved);
851
878
  case 'task-verify':
852
- return probeVerificationFailure(taskRef, policy, resolved);
879
+ return await probeVerificationFailure(taskRef, policy, resolved);
853
880
  case 'verification-engine':
854
- return probeVerificationEngineFailure(policy, resolved);
881
+ return await probeVerificationEngineFailure(policy, resolved);
855
882
  case 'activity-intent':
856
883
  return probeResult(policy, applyPrReviewActivityIntent({
857
884
  kind: 'pr-review-start', taskRef, agent: 'codex', artifact: 'pr-review.md', head: '0'.repeat(40), dryRun: true
@@ -886,7 +913,7 @@ function probeGenericFailure(
886
913
  }
887
914
  case 'platform.issue':
888
915
  case 'platform.pull-request':
889
- return probePlatformFailure(taskRef, policy, resolved, options);
916
+ return await probePlatformFailure(taskRef, policy, resolved, options);
890
917
  default:
891
918
  return error('OVERRIDE_PROBE_INPUT_MISSING', `no producer probe is registered for ${policy.producerId}`);
892
919
  }
@@ -896,7 +923,7 @@ function isProducerFailure(value: ProducerFailure | OverrideError): value is Pro
896
923
  return 'observedFacts' in value && 'state' in value && Array.isArray(value.observedFacts);
897
924
  }
898
925
 
899
- function captureFailureSnapshot(taskRef: string, failureIdValue: string, target: string, options: HumanOverrideOptions = {}): FailureSnapshot | OverrideError {
926
+ async function captureFailureSnapshot(taskRef: string, failureIdValue: string, target: string, options: HumanOverrideOptions = {}): Promise<FailureSnapshot | OverrideError> {
900
927
  const policy = policyFor(failureIdValue);
901
928
  if (!policy) return error('OVERRIDE_FAILURE_UNKNOWN', `failure policy '${failureIdValue}' is not registered`);
902
929
  if (!policy.targets.includes(target)) return error('OVERRIDE_TARGET_INVALID', `target '${target}' is not registered for ${failureIdValue}`);
@@ -912,7 +939,7 @@ function captureFailureSnapshot(taskRef: string, failureIdValue: string, target:
912
939
  try { frontmatter = parseTypedTaskFrontmatter(content); } catch { /* probe reports an unconfirmed identity */ }
913
940
  const producer: ProducerFailure | OverrideError = policy.producerId === LIFECYCLE_PRODUCER
914
941
  ? probeLifecycleFailure(taskRef, policy, resolved, options)
915
- : probeGenericFailure(taskRef, policy, resolved, options);
942
+ : await probeGenericFailure(taskRef, policy, resolved, options);
916
943
  if (!isProducerFailure(producer)) return producer;
917
944
  const digest = computeFailureDigest(snapshotEvidence(
918
945
  resolved.taskId,
@@ -981,7 +1008,7 @@ function validateResourceNumbers(request: HumanOverrideRequest): OverrideError |
981
1008
  return null;
982
1009
  }
983
1010
 
984
- function issueHumanOverride(request: HumanOverrideRequest, options: HumanOverrideOptions = {}): HumanOverrideIssueResult {
1011
+ async function issueHumanOverride(request: HumanOverrideRequest, options: HumanOverrideOptions = {}): Promise<HumanOverrideIssueResult> {
985
1012
  const invalid = validateCommon(request);
986
1013
  if (invalid) return failedIssue(invalid.code, invalid.message);
987
1014
  const policy = policyFor(request.failureId);
@@ -1002,7 +1029,7 @@ function issueHumanOverride(request: HumanOverrideRequest, options: HumanOverrid
1002
1029
  const document = readTask(resolved.taskMdPath);
1003
1030
  if ('code' in document) return failedIssue(document.code, document.message, resolved.taskId);
1004
1031
  if (document.frontmatter.id !== resolved.taskId) return failedIssue('OVERRIDE_DOCUMENT_INVALID', 'task frontmatter id does not match resolved task', resolved.taskId);
1005
- const snapshotResult = captureFailureSnapshot(request.taskRef, request.failureId, request.target, {
1032
+ const snapshotResult = await captureFailureSnapshot(request.taskRef, request.failureId, request.target, {
1006
1033
  ...options,
1007
1034
  probeIntent: request.intent,
1008
1035
  probeOperator: request.operator,
@@ -1124,18 +1151,18 @@ function lifecycleRequestFor(
1124
1151
  return { taskRef, intent: 'restore', agent: operator, stagingDir, issueNumber };
1125
1152
  }
1126
1153
 
1127
- function applyOutcomeEffect(
1154
+ async function applyOutcomeEffect(
1128
1155
  request: ConsumeHumanOverrideRequest,
1129
1156
  row: Readonly<Record<string, string>>,
1130
1157
  snapshot: FailureSnapshot,
1131
1158
  outcome: Outcome,
1132
1159
  options: HumanOverrideOptions
1133
- ): OverrideError | null {
1160
+ ): Promise<OverrideError | null> {
1134
1161
  if (outcome.effect === 'no-write' || outcome.effect === 'record-only') return null;
1135
1162
  const intent = outcome.target === 'safe-close' ? 'cancel' : row.intent || request.intent;
1136
1163
  if (!intent && outcome.target === 'continue-local') {
1137
1164
  if (!options.effectExecutor) return error('OVERRIDE_EFFECT_EXECUTOR_MISSING', 'the producer must supply an effect executor for a continue-local outcome');
1138
- return options.effectExecutor({
1165
+ return await options.effectExecutor({
1139
1166
  failureId: request.failureId,
1140
1167
  operator: row.operator ?? 'local-operator',
1141
1168
  reason: row.reason ?? snapshot.message
@@ -1239,7 +1266,7 @@ function snapshotFromTicket(taskId: string, row: Readonly<Record<string, string>
1239
1266
  };
1240
1267
  }
1241
1268
 
1242
- function consumeHumanOverride(request: ConsumeHumanOverrideRequest, options: HumanOverrideOptions = {}): HumanOverrideConsumeResult {
1269
+ async function consumeHumanOverride(request: ConsumeHumanOverrideRequest, options: HumanOverrideOptions = {}): Promise<HumanOverrideConsumeResult> {
1243
1270
  const values = [request.taskRef, request.ticketId, request.failureId, request.target, request.scope];
1244
1271
  if (values.some((value) => !singleLine(value))) {
1245
1272
  return failedConsume('OVERRIDE_PAYLOAD_INVALID', 'consume fields must be non-empty single-line values', request.ticketId || null);
@@ -1275,7 +1302,7 @@ function consumeHumanOverride(request: ConsumeHumanOverrideRequest, options: Hum
1275
1302
  if (isOverrideError(recoverySnapshot)) return failedConsume(recoverySnapshot.code, recoverySnapshot.message, request.ticketId, resolved.taskId);
1276
1303
  snapshot = recoverySnapshot;
1277
1304
  } else {
1278
- const snapshotResult = captureFailureSnapshot(request.taskRef, request.failureId, request.target, {
1305
+ const snapshotResult = await captureFailureSnapshot(request.taskRef, request.failureId, request.target, {
1279
1306
  ...options,
1280
1307
  probeIntent: row.values.intent ? row.values.intent as TaskLifecycleIntent : request.intent,
1281
1308
  probeOperator: row.values.operator,
@@ -1320,7 +1347,7 @@ function consumeHumanOverride(request: ConsumeHumanOverrideRequest, options: Hum
1320
1347
  if (staged.status === 'planned') return failedConsume('OVERRIDE_WRITE_INVALID', 'override writes cannot be planned', request.ticketId, resolved.taskId);
1321
1348
  effectRow = { ...row.values, status: 'consuming', effect: outcome.effect, result: outcome.result, context_id: outcome.contextId, residual: `effect pending: ${outcome.residual}` };
1322
1349
  }
1323
- const effectError = applyOutcomeEffect(request, effectRow, snapshot, outcome, options);
1350
+ const effectError = await applyOutcomeEffect(request, effectRow, snapshot, outcome, options);
1324
1351
  if (effectError) return failedConsume(effectError.code, effectError.message, request.ticketId, resolved.taskId);
1325
1352
  const after = resolveTask(request.taskRef, options);
1326
1353
  if (!after.ok) return failedConsume(after.code, after.message, request.ticketId, after.taskId);
@@ -1356,7 +1383,7 @@ function diagnoseHumanOverride(failure: string, target?: string) {
1356
1383
  };
1357
1384
  }
1358
1385
 
1359
- function diagnoseHumanOverrideForTask(
1386
+ async function diagnoseHumanOverrideForTask(
1360
1387
  taskRef: string,
1361
1388
  failure?: string,
1362
1389
  target?: string,
@@ -1400,12 +1427,12 @@ function diagnoseHumanOverrideForTask(
1400
1427
  error: error('OVERRIDE_FAILURE_UNKNOWN', `failure policy '${failure}' is not registered`)
1401
1428
  };
1402
1429
  }
1403
- const probes = policies
1430
+ const probes = await Promise.all(policies
1404
1431
  .filter((policy) => !target || policy.targets.includes(target))
1405
- .map((policy) => {
1432
+ .map(async (policy) => {
1406
1433
  const producer = policy.producerId === LIFECYCLE_PRODUCER
1407
1434
  ? probeLifecycleFailure(taskRef, policy, resolved, options)
1408
- : probeGenericFailure(taskRef, policy, resolved, options);
1435
+ : await probeGenericFailure(taskRef, policy, resolved, options);
1409
1436
  const observed = isProducerFailure(producer);
1410
1437
  return {
1411
1438
  failureId: policy.id,
@@ -1419,7 +1446,7 @@ function diagnoseHumanOverrideForTask(
1419
1446
  message: observed ? producer.message : producer.message,
1420
1447
  errorCode: observed ? null : producer.code
1421
1448
  };
1422
- });
1449
+ }));
1423
1450
  const blockedBy = probes.filter((probe) => probe.status === 'observed');
1424
1451
  return {
1425
1452
  status: 'ready' as const,
@@ -0,0 +1,86 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ import { parseArtifactReceipts, sha256File } from './artifact-receipts.ts';
5
+ import { invalidationMutation, parseInvalidationDocument, reconcileInvalidation } from './invalidation.ts';
6
+ import { resolveTaskRef } from './resolve-ref.ts';
7
+ import { writeTask } from './write.ts';
8
+ import type { TaskWriteOptions } from './write.ts';
9
+
10
+ type InvalidationCommandOptions = TaskWriteOptions & { now?: () => string; maxTargets?: number; dryRun?: boolean };
11
+ type InvalidationCommandResult = {
12
+ status: 'applied' | 'planned' | 'no-op' | 'failed';
13
+ changed: boolean;
14
+ taskId: string | null;
15
+ processed: number;
16
+ remaining: number;
17
+ error: { code: string; message: string } | null;
18
+ };
19
+
20
+ function reconcileTaskInvalidation(taskRef: string, options: InvalidationCommandOptions = {}): InvalidationCommandResult {
21
+ const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
22
+ if (!resolved.ok) return { status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: 0, error: { code: resolved.code, message: resolved.message } };
23
+ let content: string;
24
+ try { content = fs.readFileSync(resolved.taskMdPath, 'utf8'); }
25
+ catch (error) { return { status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: 0, error: { code: 'TASK_READ_FAILED', message: error instanceof Error ? error.message : String(error) } }; }
26
+ const parsed = parseInvalidationDocument(content);
27
+ if (!parsed.ok) return { status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: 0, error: { code: parsed.code, message: parsed.message } };
28
+ if (!parsed.present) return { status: 'no-op', changed: false, taskId: resolved.taskId, processed: 0, remaining: 0, error: null };
29
+ const beforePending = parsed.document.targets.filter((target) => target.status !== 'completed').length;
30
+ let receipts;
31
+ try { receipts = parseArtifactReceipts(content).rows; }
32
+ catch (error) {
33
+ if (parsed.document.targets.some((target) => target.status !== 'completed' && target.targetKind === 'receipt')) {
34
+ return {
35
+ status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: beforePending,
36
+ error: { code: 'INVALIDATION_TARGET_HASH_CONFLICT', message: error instanceof Error ? error.message : String(error) }
37
+ };
38
+ }
39
+ receipts = [];
40
+ }
41
+ for (const target of parsed.document.targets) {
42
+ if (target.status === 'completed') continue;
43
+ if (target.targetKind === 'receipt') {
44
+ const receipt = receipts.find((candidate) => candidate.output === target.targetArtifact);
45
+ if (!receipt || receipt.inputSha256 !== target.targetSha256) {
46
+ return {
47
+ status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: beforePending,
48
+ error: { code: 'INVALIDATION_TARGET_HASH_CONFLICT', message: `invalidation receipt target '${target.targetArtifact}' changed before reconcile` }
49
+ };
50
+ }
51
+ continue;
52
+ }
53
+ const targetPath = path.join(resolved.taskDir, target.targetArtifact);
54
+ try {
55
+ const stat = fs.lstatSync(targetPath);
56
+ if (!stat.isFile() || stat.isSymbolicLink() || sha256File(targetPath) !== target.targetSha256) {
57
+ return {
58
+ status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: beforePending,
59
+ error: { code: 'INVALIDATION_TARGET_HASH_CONFLICT', message: `invalidation target '${target.targetArtifact}' changed before reconcile` }
60
+ };
61
+ }
62
+ } catch {
63
+ return {
64
+ status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: beforePending,
65
+ error: { code: 'INVALIDATION_TARGET_HASH_CONFLICT', message: `invalidation target '${target.targetArtifact}' is unavailable before reconcile` }
66
+ };
67
+ }
68
+ }
69
+ const reconciled = reconcileInvalidation(parsed.document, (options.now ?? (() => new Date().toISOString()))(), options.maxTargets);
70
+ if (!reconciled.ok) return { status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: beforePending, error: { code: reconciled.code, message: reconciled.message } };
71
+ if (!reconciled.changed) return { status: 'no-op', changed: false, taskId: resolved.taskId, processed: 0, remaining: beforePending, error: null };
72
+ const result = writeTask({
73
+ taskRef, expectedState: resolved.state, dryRun: options.dryRun,
74
+ mutations: [invalidationMutation(content, reconciled.document)]
75
+ }, { ...options, invalidationContext: 'reconcile', taskLocation: { repoRoot: resolved.repoRoot, taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, state: resolved.state } });
76
+ if (result.status === 'failed') return { status: 'failed', changed: false, taskId: resolved.taskId, processed: beforePending - reconciled.document.targets.filter((target) => target.status !== 'completed').length, remaining: reconciled.document.targets.filter((target) => target.status !== 'completed').length, error: result.error };
77
+ return {
78
+ status: result.status, changed: result.changed, taskId: resolved.taskId,
79
+ processed: beforePending - reconciled.document.targets.filter((target) => target.status !== 'completed').length,
80
+ remaining: reconciled.document.targets.filter((target) => target.status !== 'completed').length,
81
+ error: null
82
+ };
83
+ }
84
+
85
+ export { reconcileTaskInvalidation };
86
+ export type { InvalidationCommandOptions, InvalidationCommandResult };