@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
@@ -0,0 +1,138 @@
1
+ const REWORK_INTENT_HEADINGS = ['返工意图', 'Rework Intent'];
2
+ const REWORK_INTENT_COLUMNS = [
3
+ 'intent_id', 'finding_id', 'source_artifact', 'source_sha256', 'target',
4
+ 'status', 'declared_at', 'consumed_at'
5
+ ];
6
+ function cells(line) {
7
+ const first = line.indexOf('|');
8
+ const last = line.lastIndexOf('|');
9
+ if (first < 0 || first === last || line.slice(0, first).trim() || line.slice(last + 1).trim())
10
+ return null;
11
+ const inner = line.slice(first + 1, last);
12
+ const result = [];
13
+ let start = 0;
14
+ let escaped = false;
15
+ for (let index = 0; index < inner.length; index += 1) {
16
+ const char = inner[index];
17
+ if (char === '|' && !escaped) {
18
+ result.push(inner.slice(start, index));
19
+ start = index + 1;
20
+ }
21
+ escaped = char === '\\' && !escaped;
22
+ if (char !== '\\')
23
+ escaped = false;
24
+ }
25
+ result.push(inner.slice(start));
26
+ return result.map((cell) => cell.replace(/\\([\\|])/g, '$1').trim());
27
+ }
28
+ function sectionBody(content) {
29
+ const heading = REWORK_INTENT_HEADINGS.map((value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|');
30
+ const match = new RegExp(`^##\\s+(${heading})\\s*$`, 'm').exec(content);
31
+ if (!match)
32
+ return null;
33
+ const start = (match.index ?? 0) + match[0].length;
34
+ const rest = content.slice(start);
35
+ const end = rest.search(/^##\s+/m);
36
+ return rest.slice(0, end < 0 ? rest.length : end);
37
+ }
38
+ function parseReworkIntentDocument(content) {
39
+ const body = sectionBody(content);
40
+ if (body === null)
41
+ return { ok: true, present: false, intents: [] };
42
+ const lines = body.split(/\r?\n/).filter((line) => line.trim());
43
+ const header = lines[0] ? cells(lines[0]) : null;
44
+ const separator = lines[1] ? cells(lines[1]) : null;
45
+ if (!header || !separator || header.length !== REWORK_INTENT_COLUMNS.length || !header.every((value, index) => value === REWORK_INTENT_COLUMNS[index]) || !separator.every((value) => /^:?-{3,}:?$/.test(value))) {
46
+ return { ok: false, code: 'TASK_REWORK_INTENT_INVALID', message: 'rework intent section must contain its canonical table' };
47
+ }
48
+ try {
49
+ const intents = lines.slice(2).map((line) => {
50
+ const values = cells(line);
51
+ if (!values || values.length !== REWORK_INTENT_COLUMNS.length)
52
+ throw new Error('rework intent row has the wrong column count');
53
+ const row = Object.fromEntries(REWORK_INTENT_COLUMNS.map((column, index) => [column, values[index]]));
54
+ if (!/^RI-[1-9]\d*$/.test(row.intent_id))
55
+ throw new Error(`invalid intent id '${row.intent_id}'`);
56
+ if (!/^(AN|PL|CD)-[1-9]\d*$/.test(row.finding_id))
57
+ throw new Error(`invalid finding id '${row.finding_id}'`);
58
+ if (!['analysis', 'plan', 'code'].includes(row.target))
59
+ throw new Error(`invalid rework target '${row.target}'`);
60
+ if (!['pending', 'consumed', 'superseded'].includes(row.status))
61
+ throw new Error(`invalid rework status '${row.status}'`);
62
+ if (!/^[a-f0-9]{64}$/.test(row.source_sha256))
63
+ throw new Error(`invalid source hash for '${row.intent_id}'`);
64
+ if (!row.source_artifact || !row.declared_at)
65
+ throw new Error(`rework intent '${row.intent_id}' has invalid required fields`);
66
+ const terminal = row.status === 'consumed' || row.status === 'superseded';
67
+ if (terminal !== Boolean(row.consumed_at))
68
+ throw new Error(`rework intent '${row.intent_id}' has invalid consumed_at`);
69
+ return {
70
+ intentId: row.intent_id, findingId: row.finding_id, sourceArtifact: row.source_artifact,
71
+ sourceSha256: row.source_sha256, target: row.target,
72
+ status: row.status, declaredAt: row.declared_at, consumedAt: row.consumed_at
73
+ };
74
+ });
75
+ const ids = new Set();
76
+ for (const intent of intents) {
77
+ if (ids.has(intent.intentId))
78
+ throw new Error(`duplicate intent '${intent.intentId}'`);
79
+ ids.add(intent.intentId);
80
+ }
81
+ return { ok: true, present: true, intents };
82
+ }
83
+ catch (error) {
84
+ return { ok: false, code: 'TASK_REWORK_INTENT_INVALID', message: error instanceof Error ? error.message : String(error) };
85
+ }
86
+ }
87
+ function renderReworkIntents(intents) {
88
+ const escape = (value) => value.replace(/\\/g, '\\\\').replace(/\|/g, '\\|').replace(/[\r\n]/g, ' ');
89
+ return [
90
+ `| ${REWORK_INTENT_COLUMNS.join(' | ')} |`,
91
+ `| ${REWORK_INTENT_COLUMNS.map(() => '---').join(' | ')} |`,
92
+ ...intents.map((intent) => `| ${[
93
+ intent.intentId, intent.findingId, intent.sourceArtifact, intent.sourceSha256,
94
+ intent.target, intent.status, intent.declaredAt, intent.consumedAt
95
+ ].map(escape).join(' | ')} |`)
96
+ ].join('\n');
97
+ }
98
+ function upsertReworkIntent(intents, intent) {
99
+ const existing = intents.find((candidate) => candidate.intentId === intent.intentId);
100
+ if (!existing)
101
+ return { changed: true, intents: [...intents, intent] };
102
+ const identity = (value) => [value.intentId, value.findingId, value.sourceArtifact, value.sourceSha256, value.target];
103
+ if (JSON.stringify(identity(existing)) !== JSON.stringify(identity(intent)))
104
+ throw new Error(`intent '${intent.intentId}' identity conflicts with existing state`);
105
+ return { changed: false, intents };
106
+ }
107
+ function consumeReworkIntents(intents, target, sourceHashes, consumedAt) {
108
+ let changed = false;
109
+ const next = intents.map((intent) => {
110
+ if (intent.status !== 'pending'
111
+ || intent.target !== target
112
+ || sourceHashes[intent.sourceArtifact] !== intent.sourceSha256)
113
+ return intent;
114
+ changed = true;
115
+ return { ...intent, status: 'consumed', consumedAt };
116
+ });
117
+ return { changed, intents: next };
118
+ }
119
+ function supersedeReworkIntents(intents, sourceArtifact, sourceSha256, supersededAt) {
120
+ let changed = false;
121
+ const next = intents.map((intent) => {
122
+ if (intent.status !== 'pending' || intent.sourceArtifact !== sourceArtifact || intent.sourceSha256 === sourceSha256)
123
+ return intent;
124
+ changed = true;
125
+ return { ...intent, status: 'superseded', consumedAt: supersededAt };
126
+ });
127
+ return { changed, intents: next };
128
+ }
129
+ function reworkIntentMutation(content, intents) {
130
+ return {
131
+ kind: 'section',
132
+ aliases: REWORK_INTENT_HEADINGS,
133
+ heading: /^##\s+Rework Intent\s*$/m.test(content) ? REWORK_INTENT_HEADINGS[1] : REWORK_INTENT_HEADINGS[0],
134
+ body: renderReworkIntents(intents)
135
+ };
136
+ }
137
+ export { REWORK_INTENT_COLUMNS, REWORK_INTENT_HEADINGS, parseReworkIntentDocument, renderReworkIntents, reworkIntentMutation, consumeReworkIntents, supersedeReworkIntents, upsertReworkIntent };
138
+ //# sourceMappingURL=rework-intent.js.map
@@ -0,0 +1,23 @@
1
+ const TASK_SCOPE_SKILLS = new Set([
2
+ 'analyze-task',
3
+ 'block-task',
4
+ 'cancel-task',
5
+ 'check-task',
6
+ 'code-task',
7
+ 'commit',
8
+ 'complete-manual-validation',
9
+ 'complete-task',
10
+ 'create-pr',
11
+ 'plan-task',
12
+ 'review-analysis',
13
+ 'review-code',
14
+ 'review-plan',
15
+ 'run-manual-validation',
16
+ 'run-task',
17
+ 'watch-pr'
18
+ ]);
19
+ function isTaskScopeSkill(skillName) {
20
+ return TASK_SCOPE_SKILLS.has(skillName);
21
+ }
22
+ export { TASK_SCOPE_SKILLS, isTaskScopeSkill };
23
+ //# sourceMappingURL=skill-scope.js.map
@@ -160,6 +160,25 @@ function withTaskExecutionLock(repoRoot, taskId, ownerName, callback, options =
160
160
  };
161
161
  const serialized = `${JSON.stringify(owner)}\n`;
162
162
  let ownsFixed = false;
163
+ let deferRelease = false;
164
+ const release = () => {
165
+ try {
166
+ unlinkIfPresent(candidate);
167
+ }
168
+ catch {
169
+ // Candidate cleanup is best-effort and must not replace the primary result.
170
+ }
171
+ if (ownsFixed) {
172
+ try {
173
+ const current = parseOwner(fs.readFileSync(fixed, 'utf8'), key);
174
+ if (current.token === token)
175
+ unlinkIfPresent(fixed);
176
+ }
177
+ catch {
178
+ // A missing or replaced fixed lock is not owned by this invocation.
179
+ }
180
+ }
181
+ };
163
182
  try {
164
183
  fs.mkdirSync(lockRoot, { recursive: true });
165
184
  cleanStaleCandidates(lockRoot, key, options.identityMatches ?? processIdentityMatches);
@@ -202,7 +221,12 @@ function withTaskExecutionLock(repoRoot, taskId, ownerName, callback, options =
202
221
  throw new TaskExecutionLockError('ORCHESTRATION_LOCK_BUSY', 'lifecycle task lock could not be acquired after stale recovery', { operation: 'acquire', errno: 'EEXIST', key });
203
222
  }
204
223
  unlinkIfPresent(candidate);
205
- return callback();
224
+ const value = callback();
225
+ if (value && typeof value.then === 'function') {
226
+ deferRelease = true;
227
+ return value.finally(release);
228
+ }
229
+ return value;
206
230
  }
207
231
  catch (error) {
208
232
  if (error instanceof TaskExecutionLockError)
@@ -212,22 +236,8 @@ function withTaskExecutionLock(repoRoot, taskId, ownerName, callback, options =
212
236
  throw new TaskExecutionLockError('ORCHESTRATION_LOCK_FAILED', 'lifecycle task lock operation failed', { operation: ownsFixed ? 'callback' : 'acquire', errno: errno(error), key });
213
237
  }
214
238
  finally {
215
- try {
216
- unlinkIfPresent(candidate);
217
- }
218
- catch {
219
- // Candidate cleanup is best-effort and must not replace the primary result.
220
- }
221
- if (ownsFixed) {
222
- try {
223
- const current = parseOwner(fs.readFileSync(fixed, 'utf8'), key);
224
- if (current.token === token)
225
- unlinkIfPresent(fixed);
226
- }
227
- catch {
228
- // A missing or replaced fixed lock is not owned by this invocation.
229
- }
230
- }
239
+ if (!deferRelease)
240
+ release();
231
241
  }
232
242
  }
233
243
  function withRepositoryMutationLock(repoRoot, callback, options = {}) {
@@ -4,7 +4,7 @@ import path from "node:path";
4
4
  import process from "node:process";
5
5
  import { execFileSync } from "node:child_process";
6
6
  import { fileURLToPath } from "node:url";
7
- import { extractReviewBaseline, extractReviewDiffBase, extractReviewDiffFingerprint, extractReviewedSnapshotTree, findAuthoritativeReviewCodeArtifact, loadPostReviewConfig, parseReviewVerdict, resolvePostReviewGlobs } from "./verification-review.js";
7
+ import { extractReviewBaseline, extractReviewTargetHead, extractReviewedHead, extractReviewDiffBase, extractReviewDiffFingerprint, extractReviewedSnapshotTree, findAuthoritativeReviewCodeArtifact, loadPostReviewConfig, parseReviewVerdict, resolvePostReviewGlobs } from "./verification-review.js";
8
8
  import { check as checkPlatformSync } from "../platform/verification-sync.js";
9
9
  import { check as checkRequiredChecks } from "../platform/verification-required.js";
10
10
  import { inspectPlatformPullRequest } from "../platform/pull-requests.js";
@@ -19,6 +19,9 @@ import { inspectDecisionDetailDuplicates } from "./decision-details.js";
19
19
  import { loadVerificationConfig } from "./verification-config.js";
20
20
  import { snapshotReview } from "../git/review-snapshot.js";
21
21
  import { OrchestrationStateError, readRun } from "./orchestration.js";
22
+ import { resolveDeliveryTarget } from "./delivery-target.js";
23
+ import { readPrDeliveryFact } from "./pr-delivery-fact.js";
24
+ import { validateLocalArtifact } from "./local-artifact-finalization.js";
22
25
  const TASK_ENUMS = {
23
26
  type: ["feature", "bugfix", "refactor", "docs", "chore"],
24
27
  workflow: ["feature-development", "bug-fix", "refactoring"],
@@ -67,7 +70,7 @@ const scriptPath = fileURLToPath(import.meta.url);
67
70
  let repoRoot = path.resolve(path.dirname(scriptPath), "..", "..");
68
71
  const PLATFORM_ADAPTERS = {
69
72
  "platform-sync": checkPlatformSync,
70
- "platform-sync-preflight": (context, shared) => ({ ...checkPlatformSync(context, shared), type: "platform-sync-preflight" }),
73
+ "platform-sync-preflight": async (context, shared) => ({ ...await checkPlatformSync(context, shared), type: "platform-sync-preflight" }),
71
74
  "required-checks": checkRequiredChecks
72
75
  };
73
76
  const OPTIONAL_PLATFORM_CHECKS = new Set(["platform-sync"]);
@@ -84,7 +87,7 @@ const sharedUtils = {
84
87
  parseIssueNumber,
85
88
  parsePrNumber
86
89
  };
87
- function runCheck(type, context, shared) {
90
+ async function runCheck(type, context, shared) {
88
91
  switch (type) {
89
92
  case "task-meta":
90
93
  return checkTaskMeta(context);
@@ -122,7 +125,7 @@ function runCheck(type, context, shared) {
122
125
  }
123
126
  return failResult(type, `Unsupported check type '${type}'.`);
124
127
  }
125
- return adapter(context, shared);
128
+ return await adapter(context, shared);
126
129
  }
127
130
  }
128
131
  }
@@ -176,13 +179,12 @@ function validateCleanCompletionEvidence(run) {
176
179
  || !shaPattern.test(evidence.headTree)
177
180
  || !shaPattern.test(evidence.worktreeTree)
178
181
  || !shaPattern.test(evidence.lastReviewedCommit)
179
- || !Number.isInteger(evidence.prNumber)
180
- || evidence.prNumber <= 0
181
- || !shaPattern.test(evidence.prHead)) {
182
+ || !(evidence.prNumber === null || (Number.isInteger(evidence.prNumber) && evidence.prNumber > 0))
183
+ || !(evidence.prHead === null || shaPattern.test(evidence.prHead))) {
182
184
  return 'Clean completion evidence has an invalid structure';
183
185
  }
184
186
  if (evidence.head !== evidence.lastReviewedCommit
185
- || evidence.head !== evidence.prHead
187
+ || (evidence.prHead !== null && evidence.head !== evidence.prHead)
186
188
  || evidence.headTree !== evidence.worktreeTree) {
187
189
  return 'Clean completion evidence does not bind matching commit and tree identities';
188
190
  }
@@ -251,10 +253,8 @@ function checkOrchestrationEvidence({ taskDir }) {
251
253
  if (evidenceError)
252
254
  return failResult('orchestration-evidence', evidenceError);
253
255
  }
254
- else if (run.status === 'completed' && (run.receipts.length === 0
255
- || run.receipts.at(-1)?.stage !== 'commit'
256
- || run.receipts.at(-1)?.status !== 'consumed')) {
257
- return failResult('orchestration-evidence', 'Completed run requires a final consumed commit receipt');
256
+ else if (run.status === 'completed') {
257
+ return failResult('orchestration-evidence', 'Completed run requires reviewed-head-clean completion evidence');
258
258
  }
259
259
  if (run.pendingDelegation && !['prepared', 'activated', 'stage-completed'].includes(run.pendingDelegation.status)) {
260
260
  return failResult('orchestration-evidence', `Pending receipt has unsafe status '${run.pendingDelegation.status}'`);
@@ -420,7 +420,7 @@ function checkTaskMeta({ taskDir, config }) {
420
420
  const warningSuffix = warnings.length > 0 ? `; warnings: ${warnings.join("; ")}` : "";
421
421
  return passResult("task-meta", `Task metadata valid (${requiredFields.length} required fields checked${warningSuffix})`, warnings);
422
422
  }
423
- function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }) {
423
+ async function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }) {
424
424
  const task = loadTask(taskDir);
425
425
  if (!task.ok)
426
426
  return failResult('required-pr-delivery', task.message);
@@ -434,43 +434,47 @@ function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }) {
434
434
  return failResult('required-pr-delivery', 'Project configuration is invalid');
435
435
  }
436
436
  const flow = projectConfig.prFlow;
437
- const status = String(task.metadata.pr_status || 'pending');
438
- const prNumber = parsePrNumber(task.metadata.pr_number);
437
+ const factRead = readPrDeliveryFact(task.metadata);
438
+ if (factRead.status === 'invalid')
439
+ return failResult('required-pr-delivery', factRead.error.message);
440
+ const fact = factRead.status === 'valid' ? factRead.fact : null;
441
+ const status = fact?.state || 'unbound';
442
+ const prIdentity = fact?.state === 'bound' ? fact.identity.resource : null;
443
+ const prNumber = prIdentity?.kind === 'number' ? prIdentity.value : null;
439
444
  if (flow === 'disabled')
440
445
  return passResult('required-pr-delivery', 'Pull request delivery is disabled by project policy');
441
- if (flow === 'required' && (status !== 'created' || prNumber === null)) {
446
+ if (flow === 'required' && (status !== 'bound' || !prIdentity)) {
442
447
  return failResult('required-pr-delivery', 'Project policy requires a bound pull request before completion');
443
448
  }
444
- if (flow !== 'required' && status === 'pending') {
449
+ if (flow !== 'required' && status === 'unbound') {
445
450
  return failResult('required-pr-delivery', 'Pull request delivery is pending; create a PR or explicitly skip it');
446
451
  }
447
- if (status === 'created' && prNumber === null) {
448
- return failResult('required-pr-delivery', 'Task claims a created pull request without a valid pr_number');
449
- }
450
452
  if (flow === 'required') {
451
453
  if (mode === 'gate') {
452
454
  return passResult('required-pr-delivery', 'Bound pull request shape is valid; merged-state inspection is reserved for hard preflight');
453
455
  }
454
- const inspected = inspectPlatformPullRequest(task.metadata.id, { cwd: repositoryRoot });
456
+ const inspected = await inspectPlatformPullRequest(task.metadata.id, { cwd: repositoryRoot });
455
457
  if (inspected.status === 'blocked') {
456
458
  return blockedResult('required-pr-delivery', inspected.error?.message || 'Unable to inspect the required pull request', inspected.error?.code || 'PR_INSPECTION_BLOCKED');
457
459
  }
458
460
  const pullRequest = inspected.pullRequest;
459
461
  const repository = inspected.platform.repository?.toLowerCase() || '';
460
462
  const taskBranch = String(task.metadata.branch || '').trim();
461
- if (inspected.status !== 'no-op' || !pullRequest || pullRequest.number !== prNumber) {
463
+ const deliveryBaseRef = String(task.metadata.delivery_base_ref || projectConfig.delivery?.baseRef || '').trim();
464
+ if (inspected.status !== 'no-op' || !pullRequest) {
462
465
  return failResult('required-pr-delivery', 'Bound pull request identity could not be verified');
463
466
  }
464
467
  if (!repository
465
468
  || pullRequest.repository.toLowerCase() !== repository
466
469
  || pullRequest.base.repository.toLowerCase() !== repository
467
- || (taskBranch && pullRequest.head.ref !== taskBranch)) {
470
+ || (taskBranch && pullRequest.head.ref !== taskBranch)
471
+ || (deliveryBaseRef && pullRequest.base.ref !== deliveryBaseRef)) {
468
472
  return failResult('required-pr-delivery', 'Bound pull request identity does not match the task');
469
473
  }
470
474
  if (pullRequest.state !== 'closed' || !pullRequest.mergedAt || !pullRequest.mergeCommitSha) {
471
475
  return failResult('required-pr-delivery', 'Project policy requires the bound pull request to be merged');
472
476
  }
473
- return passResult('required-pr-delivery', `Pull request delivery policy satisfied (merged PR #${prNumber})`);
477
+ return passResult('required-pr-delivery', `Pull request delivery policy satisfied (merged PR ${prNumber === null ? 'identity' : `#${prNumber}`})`);
474
478
  }
475
479
  return passResult('required-pr-delivery', `Pull request delivery policy satisfied (${status})`);
476
480
  }
@@ -502,7 +506,7 @@ function loadProjectName() {
502
506
  return "";
503
507
  }
504
508
  }
505
- function checkArtifact({ taskDir, config, artifactFile }) {
509
+ function checkArtifact({ taskDir, config, artifactFile, skillName }) {
506
510
  const resolvedArtifact = resolveArtifactPath(taskDir, config.file_pattern, artifactFile);
507
511
  if (!resolvedArtifact.ok) {
508
512
  return failResult("artifact", resolvedArtifact.message);
@@ -517,6 +521,20 @@ function checkArtifact({ taskDir, config, artifactFile }) {
517
521
  }
518
522
  const content = fs.readFileSync(artifactPath, "utf8");
519
523
  const requiredSections = config.required_sections || [];
524
+ const localFamily = skillName === "analyze-task"
525
+ ? "analysis"
526
+ : skillName === "plan-task" ? "plan" : skillName === "code-task" ? "code" : null;
527
+ if (localFamily) {
528
+ const local = validateLocalArtifact(content, {
529
+ family: localFamily,
530
+ requiredSections: requiredSections.filter((section) => typeof section === "string"),
531
+ requiredPatterns: (config.required_patterns || []).filter((pattern) => typeof pattern === "string")
532
+ });
533
+ if (!local.ok) {
534
+ return failResult("artifact", `${path.basename(artifactPath)} has local structural errors: ${local.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ')}`);
535
+ }
536
+ return passResult("artifact", `${path.basename(artifactPath)} passed (${requiredSections.length} sections)`);
537
+ }
520
538
  const missingSections = requiredSections.filter((section) => !new RegExp(`^##\\s+${escapeRegExp(section)}\\s*$`, "m").test(content));
521
539
  if (missingSections.length > 0) {
522
540
  return failResult("artifact", `${path.basename(artifactPath)} is missing sections: ${missingSections.join(", ")}`);
@@ -900,6 +918,8 @@ function checkManualValidation({ taskDir }) {
900
918
  // 1. Latest review-code artifact; none -> pass (no review, check not applicable).
901
919
  const review = findAuthoritativeReviewCodeArtifact(taskDir);
902
920
  if (!review.ok) {
921
+ if (review.error)
922
+ return failResult("manual-validation", `Review-code artifact is unavailable: ${review.error}`);
903
923
  return passResult("manual-validation", "No review-code artifact; manual validation not applicable");
904
924
  }
905
925
  // 2. Parse the numeric manual-validation count; unparseable/null -> fail closed
@@ -951,9 +971,11 @@ function checkManualValidation({ taskDir }) {
951
971
  }
952
972
  return passResult("manual-validation", `Manual validation completed → ${artifactName}`);
953
973
  }
954
- function checkPostReviewCommit({ taskDir, config }) {
974
+ async function checkPostReviewCommit({ taskDir, config }) {
955
975
  const reviewArtifact = findAuthoritativeReviewCodeArtifact(taskDir);
956
976
  if (!reviewArtifact.ok) {
977
+ if (reviewArtifact.error)
978
+ return failResult("post-review-commit", `Review-code artifact is unavailable: ${reviewArtifact.error}`);
957
979
  return passResult("post-review-commit", "No review-code artifact; check inactive");
958
980
  }
959
981
  let gitRoot;
@@ -966,12 +988,16 @@ function checkPostReviewCommit({ taskDir, config }) {
966
988
  const task = loadTask(taskDir);
967
989
  if (!task.ok)
968
990
  return failResult("post-review-commit", task.message);
991
+ const factRead = readPrDeliveryFact(task.metadata);
992
+ if (factRead.status === 'invalid')
993
+ return failResult("post-review-commit", factRead.error.message);
994
+ const fact = factRead.status === 'valid' ? factRead.fact : null;
969
995
  const lastReviewedCommit = task.ok ? (task.metadata.last_reviewed_commit || "").trim() : "";
970
996
  const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(repoRoot));
971
- const hasPullRequest = Number(task.metadata.pr_number) > 0;
997
+ const hasPullRequest = fact?.state === 'bound';
972
998
  let inspected = null;
973
999
  if (hasPullRequest) {
974
- inspected = inspectPlatformPullRequest(task.metadata.id, { cwd: gitRoot });
1000
+ inspected = await inspectPlatformPullRequest(task.metadata.id, { cwd: gitRoot });
975
1001
  if (!inspected.pullRequest) {
976
1002
  const message = inspected.error?.message || "PR merge snapshot is unavailable";
977
1003
  const code = inspected.error?.code || "PR_INSPECTION_INVALID";
@@ -982,7 +1008,7 @@ function checkPostReviewCommit({ taskDir, config }) {
982
1008
  if (inspected.pullRequest.state === "closed" &&
983
1009
  inspected.pullRequest.mergedAt &&
984
1010
  inspected.pullRequest.mergeCommitSha) {
985
- const relation = resolveMaterializedReviewedHeadRelation({
1011
+ const relation = await resolveMaterializedReviewedHeadRelation({
986
1012
  cwd: gitRoot,
987
1013
  platformType: inspected.platform.type,
988
1014
  lastReviewedCommit,
@@ -1118,34 +1144,59 @@ function checkReviewFact({ taskDir, artifactFile }) {
1118
1144
  if (!resolvedArtifact.ok) {
1119
1145
  return failResult("review-fact", resolvedArtifact.message);
1120
1146
  }
1147
+ const authoritative = findAuthoritativeReviewCodeArtifact(taskDir);
1148
+ if (!authoritative.ok) {
1149
+ return failResult("review-fact", authoritative.error ?? "No active review-code artifact is available");
1150
+ }
1151
+ if (path.basename(resolvedArtifact.path) !== authoritative.fileName) {
1152
+ return failResult("review-fact", `review-code artifact ${path.basename(resolvedArtifact.path)} is not the current active artifact ${authoritative.fileName}; re-run review-code`);
1153
+ }
1121
1154
  const task = loadTask(taskDir);
1122
1155
  if (!task.ok) {
1123
1156
  return failResult("review-fact", task.message);
1124
1157
  }
1125
1158
  const content = fs.readFileSync(resolvedArtifact.path, "utf8");
1126
1159
  const verdict = parseReviewVerdict(content);
1127
- const reviewBaseline = extractReviewBaseline(content);
1160
+ const reviewTargetHead = extractReviewTargetHead(content);
1161
+ const reviewReviewedHead = extractReviewedHead(content);
1128
1162
  const reviewDiffBase = extractReviewDiffBase(content);
1129
1163
  const reviewedFingerprint = extractReviewDiffFingerprint(content);
1130
1164
  const reviewedTree = extractReviewedSnapshotTree(content);
1131
1165
  if (!["通过", "需要修改", "拒绝", "Approved", "Changes Requested", "Rejected"].includes(verdict)) {
1132
1166
  return failResult("review-fact", `Unsupported review verdict '${verdict}'`);
1133
1167
  }
1168
+ const deliveryRemote = String(task.metadata.delivery_remote || "").trim();
1169
+ const deliveryBaseRef = String(task.metadata.delivery_base_ref || "").trim();
1170
+ if (!deliveryRemote || !deliveryBaseRef) {
1171
+ return failResult("review-fact", "Task delivery target is not bound; re-run task branch preparation before review-code");
1172
+ }
1173
+ if (!reviewTargetHead || !reviewReviewedHead || !reviewDiffBase) {
1174
+ return failResult("review-fact", "Review fact must record target head, reviewed head, and diff base");
1175
+ }
1134
1176
  let gitRoot;
1135
1177
  let head;
1136
1178
  let baseline;
1179
+ let targetHead;
1137
1180
  let diffBase;
1138
1181
  try {
1139
1182
  gitRoot = execFileSync("git", ["-C", taskDir, "rev-parse", "--show-toplevel"], { encoding: "utf8" }).trim();
1140
1183
  head = execFileSync("git", ["-C", gitRoot, "rev-parse", "HEAD"], { encoding: "utf8" }).trim();
1141
- baseline = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewBaseline}^{commit}`], { encoding: "utf8" }).trim();
1142
- diffBase = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewDiffBase || reviewBaseline}^{commit}`], { encoding: "utf8" }).trim();
1184
+ const target = resolveDeliveryTarget(gitRoot, { remote: deliveryRemote, baseRef: deliveryBaseRef });
1185
+ if (!target.ok)
1186
+ throw new Error(target.message);
1187
+ const reviewedRef = reviewReviewedHead;
1188
+ baseline = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewedRef}^{commit}`], { encoding: "utf8" }).trim();
1189
+ targetHead = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewTargetHead}^{commit}`], { encoding: "utf8" }).trim();
1190
+ const computed = execFileSync("git", ["-C", gitRoot, "merge-base", baseline, targetHead], { encoding: "utf8" }).trim();
1191
+ diffBase = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewDiffBase}^{commit}`], { encoding: "utf8" }).trim();
1192
+ if (diffBase !== computed)
1193
+ throw new Error('saved review diff base does not match merge-base(reviewed head, target head)');
1143
1194
  }
1144
1195
  catch {
1145
- return blockedResult("review-fact", `Unable to resolve review baseline '${reviewBaseline}' in the task repository; re-run review-code`);
1196
+ return blockedResult("review-fact", `Unable to resolve saved review commits in the task repository; re-run review-code`);
1146
1197
  }
1147
1198
  if (baseline !== head) {
1148
- return failResult("review-fact", `Review baseline ${baseline.slice(0, 8)} does not match current HEAD ${head.slice(0, 8)}; re-run review-code`);
1199
+ return failResult("review-fact", `Reviewed head ${baseline.slice(0, 8)} does not match current HEAD ${head.slice(0, 8)}; re-run review-code`);
1149
1200
  }
1150
1201
  let actualSnapshot;
1151
1202
  try {
@@ -1170,7 +1221,7 @@ function checkReviewFact({ taskDir, artifactFile }) {
1170
1221
  const lastReviewedCommit = String(task.metadata.last_reviewed_commit || "").trim();
1171
1222
  const cleanSnapshot = actualSnapshot.tree === execFileSync("git", ["-C", gitRoot, "rev-parse", `${baseline}^{tree}`], { encoding: "utf8" }).trim();
1172
1223
  if (cleanSnapshot && lastReviewedCommit !== baseline) {
1173
- return failResult("review-fact", `Approved clean review must set task last_reviewed_commit to baseline ${baseline.slice(0, 8)}`);
1224
+ return failResult("review-fact", `Approved clean review must set task last_reviewed_commit to reviewed head ${baseline.slice(0, 8)}`);
1174
1225
  }
1175
1226
  if (!cleanSnapshot && lastReviewedCommit) {
1176
1227
  return failResult("review-fact", "Approved review with uncommitted changes must remain unanchored until commit");
@@ -1377,7 +1428,7 @@ function escapeRegExp(value) {
1377
1428
  function isBlank(value) {
1378
1429
  return value === undefined || value === null || String(value).trim() === "";
1379
1430
  }
1380
- function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: requestedChecks, repositoryRoot }) {
1431
+ async function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: requestedChecks, repositoryRoot }) {
1381
1432
  if (repositoryRoot)
1382
1433
  repoRoot = path.resolve(repositoryRoot);
1383
1434
  else {
@@ -1394,7 +1445,7 @@ function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: reque
1394
1445
  for (const [type, checkConfig] of Object.entries(verifyConfig.checks || {})) {
1395
1446
  if (checkConfig === null)
1396
1447
  continue;
1397
- const result = runCheck(type, {
1448
+ const result = await runCheck(type, {
1398
1449
  mode,
1399
1450
  skillName,
1400
1451
  taskDir: path.resolve(taskDir),
@@ -1417,7 +1468,7 @@ function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: reque
1417
1468
  return { skill: skillName, ...passResult(type, `Check '${type}' is disabled for skill '${skillName}'.`) };
1418
1469
  return {
1419
1470
  skill: skillName,
1420
- ...runCheck(type, {
1471
+ ...await runCheck(type, {
1421
1472
  skillName,
1422
1473
  taskDir: path.resolve(taskDir),
1423
1474
  artifactFile,
@@ -1,3 +1,3 @@
1
- export { extractReviewBaseline, extractReviewDiffBase, extractReviewDiffFingerprint, extractReviewedSnapshotTree, findAuthoritativeReviewCodeArtifact, loadPostReviewConfig, parseReviewVerdict, resolvePostReviewGlobs } from './review-fingerprint.js';
1
+ export { extractReviewBaseline, extractReviewTargetHead, extractReviewedHead, extractReviewDiffBase, extractReviewDiffFingerprint, extractReviewedSnapshotTree, findAuthoritativeReviewCodeArtifact, loadPostReviewConfig, parseReviewVerdict, resolvePostReviewGlobs } from './review-fingerprint.js';
2
2
  export { parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from './ledger.js';
3
3
  //# sourceMappingURL=verification-review.js.map
@@ -41,7 +41,7 @@ function failure(request, code, message, extra = {}) {
41
41
  artifact: request.artifact ?? null, invocations: [], error: { code, message }, ...extra
42
42
  };
43
43
  }
44
- function verifyTaskEvent(request, options = {}) {
44
+ async function verifyTaskEvent(request, options = {}) {
45
45
  const spec = VERIFICATION_CATALOG[request.event];
46
46
  if (!spec)
47
47
  return failure(request, 'VERIFY_EVENT_UNKNOWN', `unknown verification event '${request.event}'`);
@@ -66,7 +66,7 @@ function verifyTaskEvent(request, options = {}) {
66
66
  const invocations = [];
67
67
  const engine = options.engine ?? verifyInProcess;
68
68
  if (spec.mode === 'gate') {
69
- const payload = engine({ mode: 'gate', skillName: spec.skill, taskDir: resolved.taskDir, artifactFile: request.artifact, checks: [], repositoryRoot: resolved.repoRoot });
69
+ const payload = await engine({ mode: 'gate', skillName: spec.skill, taskDir: resolved.taskDir, artifactFile: request.artifact, checks: [], repositoryRoot: resolved.repoRoot });
70
70
  const status = payload.gate;
71
71
  if (status !== 'pass' && allowsManualOverride(options.manualOverride, 'verification-engine', status === 'blocked' ? 'CHECK_BLOCKED' : 'CHECK_FAILED')) {
72
72
  invocations.push({ status: 'pass', exitCode: 0, payload: { ...payload, gate: 'pass', humanOverride: 'human-approved', originalGate: status } });
@@ -79,7 +79,7 @@ function verifyTaskEvent(request, options = {}) {
79
79
  }
80
80
  else {
81
81
  for (const check of spec.checks ?? []) {
82
- const payload = engine({ mode: 'checks', skillName: spec.skill, taskDir: resolved.taskDir, artifactFile: request.artifact, checks: [check], repositoryRoot: resolved.repoRoot });
82
+ const payload = await engine({ mode: 'checks', skillName: spec.skill, taskDir: resolved.taskDir, artifactFile: request.artifact, checks: [check], repositoryRoot: resolved.repoRoot });
83
83
  const status = payload.status;
84
84
  if (status !== 'pass' && allowsManualOverride(options.manualOverride, 'verification-engine', status === 'blocked' ? 'CHECK_BLOCKED' : 'CHECK_FAILED')) {
85
85
  invocations.push({ status: 'pass', exitCode: 0, payload: { ...payload, status: 'pass', humanOverride: 'human-approved', originalStatus: status } });
@@ -38,7 +38,7 @@ function sectionMutation(content) {
38
38
  const english = /^##\s+Activity Log\s*$/m.test(content);
39
39
  return [{
40
40
  kind: 'section', aliases: WORKFLOW_WARNING_HEADINGS, heading: english ? 'Workflow Warnings' : '工作流告警',
41
- body: `| ${WORKFLOW_WARNING_COLUMNS.join(' | ')} |\n|----|------|------|----------|------|--------|--------|---------|--------|-------------|------------|`
41
+ body: `| ${WORKFLOW_WARNING_COLUMNS.join(' | ')} |\n|----|------|------|----------|------|--------|---------|--------|-------------|------------|------------|`
42
42
  }];
43
43
  }
44
44
  function rowMutation(row) {
@@ -6,6 +6,7 @@ import { resolveTaskRef } from './resolve-ref.js';
6
6
  import { allowsManualOverride } from './guard-override.js';
7
7
  import { mutateTableRow, upsertSection } from './sections.js';
8
8
  import { validateCurrentTaskContract } from './current-contract.js';
9
+ import { invalidationBlocks, parseInvalidationDocument } from './invalidation.js';
9
10
  const DEFAULT_FILE_SYSTEM = {
10
11
  readFileSync: (file) => fs.readFileSync(file, 'utf8'),
11
12
  statModeSync: (file) => fs.statSync(file).mode,
@@ -90,6 +91,16 @@ function writeTask(request, options = {}) {
90
91
  if (!contract.ok) {
91
92
  return failure(request, identity, contract.code, contract.message);
92
93
  }
94
+ if (invalidationBlocks(contract.invalidation)
95
+ && options.invalidationContext !== 'source-completion'
96
+ && options.invalidationContext !== 'reconcile') {
97
+ return failure(request, identity, 'TASK_INVALIDATION_BLOCKED', 'task has an incomplete artifact invalidation operation; reconcile it before writing downstream state');
98
+ }
99
+ }
100
+ else {
101
+ const invalidation = parseInvalidationDocument(original);
102
+ if (!invalidation.ok)
103
+ return failure(request, identity, 'TASK_INVALIDATION_INVALID', invalidation.message);
93
104
  }
94
105
  let candidate = original;
95
106
  const operations = [];