@fitlab-ai/agent-infra 0.9.11 → 0.9.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (356) hide show
  1. package/README.md +13 -13
  2. package/README.zh-CN.md +13 -13
  3. package/dist/bin/internal-cli.js +29 -19
  4. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +71 -10
  5. package/dist/lib/agent-clients/next-steps.js +6 -1
  6. package/dist/lib/decide.js +3 -3
  7. package/dist/lib/defaults.json +4 -0
  8. package/dist/lib/git/workflow.js +43 -1
  9. package/dist/lib/init.js +1 -0
  10. package/dist/lib/internal/git-workflow.js +8 -1
  11. package/dist/lib/internal/platform-checks.js +3 -3
  12. package/dist/lib/internal/platform-comment.js +9 -9
  13. package/dist/lib/internal/platform-context.js +2 -2
  14. package/dist/lib/internal/platform-issue.js +8 -9
  15. package/dist/lib/internal/platform-pr-review.js +10 -10
  16. package/dist/lib/internal/platform-pr.js +68 -23
  17. package/dist/lib/internal/platform-release-notes.js +3 -3
  18. package/dist/lib/internal/pr-review-grade.js +11 -9
  19. package/dist/lib/internal/release-workflow.js +4 -4
  20. package/dist/lib/internal/sandbox-control.js +30 -4
  21. package/dist/lib/internal/task-activity.js +3 -3
  22. package/dist/lib/internal/task-artifact.js +76 -24
  23. package/dist/lib/internal/task-create.js +2 -2
  24. package/dist/lib/internal/task-delivery.js +59 -0
  25. package/dist/lib/internal/task-event.js +6 -3
  26. package/dist/lib/internal/task-finalization.js +2 -2
  27. package/dist/lib/internal/task-invalidation.js +60 -0
  28. package/dist/lib/internal/task-ledger.js +9 -6
  29. package/dist/lib/internal/task-lifecycle.js +2 -2
  30. package/dist/lib/internal/task-override.js +4 -4
  31. package/dist/lib/internal/task-review.js +3 -3
  32. package/dist/lib/internal/task-verify.js +6 -6
  33. package/dist/lib/internal/task-warning.js +3 -3
  34. package/dist/lib/platform/adapters.js +1 -3
  35. package/dist/lib/platform/change-request-git-evidence.js +27 -7
  36. package/dist/lib/platform/completion-backfill.js +6 -5
  37. package/dist/lib/platform/context.js +70 -130
  38. package/dist/lib/platform/github-client.js +8 -2
  39. package/dist/lib/platform/github-provider.js +903 -0
  40. package/dist/lib/platform/in-label-sync.js +143 -0
  41. package/dist/lib/platform/issue-comments.js +94 -41
  42. package/dist/lib/platform/issues.js +335 -189
  43. package/dist/lib/platform/metadata-labels.js +6 -2
  44. package/dist/lib/platform/none-provider.js +28 -0
  45. package/dist/lib/platform/pr-change-report.js +551 -0
  46. package/dist/lib/platform/pr-checks.js +124 -106
  47. package/dist/lib/platform/pr-review.js +88 -72
  48. package/dist/lib/platform/pr-summary.js +523 -49
  49. package/dist/lib/platform/provider-bridge.js +45 -0
  50. package/dist/lib/platform/provider-contract.d.ts +487 -0
  51. package/dist/lib/platform/provider-contract.js +95 -0
  52. package/dist/lib/platform/provider-loader.js +251 -0
  53. package/dist/lib/platform/provider-validation.js +504 -0
  54. package/dist/lib/platform/pull-request-metadata.js +8 -6
  55. package/dist/lib/platform/pull-requests.js +1050 -502
  56. package/dist/lib/platform/release-notes.js +78 -55
  57. package/dist/lib/platform/releases.js +79 -50
  58. package/dist/lib/platform/resource-identity.d.ts +26 -0
  59. package/dist/lib/platform/resource-identity.js +92 -0
  60. package/dist/lib/platform/task-identities.js +31 -0
  61. package/dist/lib/platform/verification-required.js +22 -12
  62. package/dist/lib/platform/verification-sync.js +118 -239
  63. package/dist/lib/pr-review/evidence-grading.js +30 -9
  64. package/dist/lib/run/index.js +63 -23
  65. package/dist/lib/sandbox/config.js +5 -0
  66. package/dist/lib/sandbox/control/client.js +96 -15
  67. package/dist/lib/sandbox/control/executor.js +3 -3
  68. package/dist/lib/sandbox/control/lifecycle.js +29 -7
  69. package/dist/lib/sandbox/control/protocol.js +77 -0
  70. package/dist/lib/sandbox/control/server.js +398 -25
  71. package/dist/lib/sandbox/control/state.js +204 -1
  72. package/dist/lib/server/process-state.js +2 -2
  73. package/dist/lib/server/protocol.js +38 -1
  74. package/dist/lib/task/activity-log.js +8 -1
  75. package/dist/lib/task/artifact-lifecycle.js +35 -7
  76. package/dist/lib/task/capabilities.js +239 -0
  77. package/dist/lib/task/commands/status.js +32 -0
  78. package/dist/lib/task/commit-intent.js +100 -0
  79. package/dist/lib/task/commit-operation.js +207 -102
  80. package/dist/lib/task/control-authority.js +8 -5
  81. package/dist/lib/task/create-service.js +8 -8
  82. package/dist/lib/task/create.js +33 -7
  83. package/dist/lib/task/current-contract.js +5 -1
  84. package/dist/lib/task/decision-details.js +3 -48
  85. package/dist/lib/task/delivery-target.js +97 -0
  86. package/dist/lib/task/delivery.js +153 -0
  87. package/dist/lib/task/events.js +297 -17
  88. package/dist/lib/task/finalization.js +37 -13
  89. package/dist/lib/task/human-override.js +61 -36
  90. package/dist/lib/task/invalidation-command.js +86 -0
  91. package/dist/lib/task/invalidation.js +260 -0
  92. package/dist/lib/task/ledger-intents.js +37 -0
  93. package/dist/lib/task/lifecycle.js +106 -9
  94. package/dist/lib/task/local-artifact-finalization.js +374 -0
  95. package/dist/lib/task/orchestration.js +100 -151
  96. package/dist/lib/task/pr-delivery-fact.js +183 -0
  97. package/dist/lib/task/review-finalization.js +4 -8
  98. package/dist/lib/task/review-fingerprint.js +32 -2
  99. package/dist/lib/task/rework-intent.js +138 -0
  100. package/dist/lib/task/skill-scope.js +23 -0
  101. package/dist/lib/task/task-execution-lock.js +27 -17
  102. package/dist/lib/task/verification-engine.js +89 -38
  103. package/dist/lib/task/verification-review.js +1 -1
  104. package/dist/lib/task/verification.js +3 -3
  105. package/dist/lib/task/workflow-warning-intents.js +1 -1
  106. package/dist/lib/task/write.js +11 -0
  107. package/dist/lib/update.js +9 -0
  108. package/dist/lib/version.js +11 -1
  109. package/dist/lifecycle-build-manifest.json +3 -3
  110. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +105 -10
  111. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +12 -1
  112. package/lib/agent-clients/next-steps.ts +6 -1
  113. package/lib/decide.ts +3 -3
  114. package/lib/defaults.json +4 -0
  115. package/lib/git/workflow.ts +38 -1
  116. package/lib/init.ts +4 -1
  117. package/lib/internal/git-workflow.ts +7 -1
  118. package/lib/internal/platform-checks.ts +3 -3
  119. package/lib/internal/platform-comment.ts +8 -8
  120. package/lib/internal/platform-context.ts +2 -2
  121. package/lib/internal/platform-issue.ts +7 -8
  122. package/lib/internal/platform-pr-review.ts +9 -9
  123. package/lib/internal/platform-pr.ts +53 -21
  124. package/lib/internal/platform-release-notes.ts +3 -3
  125. package/lib/internal/pr-review-grade.ts +10 -8
  126. package/lib/internal/release-workflow.ts +4 -4
  127. package/lib/internal/sandbox-control.ts +27 -3
  128. package/lib/internal/task-activity.ts +3 -3
  129. package/lib/internal/task-artifact.ts +65 -22
  130. package/lib/internal/task-create.ts +2 -2
  131. package/lib/internal/task-delivery.ts +53 -0
  132. package/lib/internal/task-event.ts +6 -3
  133. package/lib/internal/task-finalization.ts +3 -3
  134. package/lib/internal/task-invalidation.ts +39 -0
  135. package/lib/internal/task-ledger.ts +11 -8
  136. package/lib/internal/task-lifecycle.ts +2 -2
  137. package/lib/internal/task-override.ts +6 -6
  138. package/lib/internal/task-review.ts +3 -3
  139. package/lib/internal/task-verify.ts +6 -6
  140. package/lib/internal/task-warning.ts +3 -3
  141. package/lib/platform/adapters.ts +3 -2
  142. package/lib/platform/change-request-git-evidence.ts +36 -9
  143. package/lib/platform/completion-backfill.ts +9 -8
  144. package/lib/platform/context.ts +97 -134
  145. package/lib/platform/github-client.ts +10 -3
  146. package/lib/platform/github-provider.ts +910 -0
  147. package/lib/platform/in-label-sync.ts +208 -0
  148. package/lib/platform/issue-comments.ts +97 -47
  149. package/lib/platform/issues.ts +344 -174
  150. package/lib/platform/metadata-labels.ts +5 -2
  151. package/lib/platform/none-provider.ts +35 -0
  152. package/lib/platform/pr-change-report.ts +645 -0
  153. package/lib/platform/pr-checks.ts +129 -107
  154. package/lib/platform/pr-review.ts +88 -85
  155. package/lib/platform/pr-summary.ts +562 -52
  156. package/lib/platform/provider-bridge.ts +82 -0
  157. package/lib/platform/provider-contract.ts +536 -0
  158. package/lib/platform/provider-loader.ts +307 -0
  159. package/lib/platform/provider-validation.ts +529 -0
  160. package/lib/platform/pull-request-metadata.ts +10 -7
  161. package/lib/platform/pull-requests.ts +1126 -505
  162. package/lib/platform/release-notes.ts +76 -59
  163. package/lib/platform/releases.ts +77 -43
  164. package/lib/platform/resource-identity.ts +121 -0
  165. package/lib/platform/task-identities.ts +40 -0
  166. package/lib/platform/types.ts +4 -2
  167. package/lib/platform/verification-required.ts +21 -13
  168. package/lib/platform/verification-sync.ts +118 -293
  169. package/lib/pr-review/evidence-grading.ts +31 -11
  170. package/lib/run/index.ts +57 -22
  171. package/lib/sandbox/config.ts +7 -0
  172. package/lib/sandbox/control/client.ts +105 -15
  173. package/lib/sandbox/control/executor.ts +4 -4
  174. package/lib/sandbox/control/lifecycle.ts +30 -8
  175. package/lib/sandbox/control/protocol.ts +113 -0
  176. package/lib/sandbox/control/server.ts +431 -23
  177. package/lib/sandbox/control/state.ts +251 -1
  178. package/lib/server/process-state.ts +2 -2
  179. package/lib/server/protocol.ts +36 -1
  180. package/lib/task/activity-log.ts +8 -0
  181. package/lib/task/artifact-lifecycle.ts +34 -8
  182. package/lib/task/capabilities.ts +262 -0
  183. package/lib/task/commands/status.ts +38 -0
  184. package/lib/task/commit-intent.ts +137 -0
  185. package/lib/task/commit-operation.ts +186 -88
  186. package/lib/task/control-authority.ts +11 -8
  187. package/lib/task/create-service.ts +8 -8
  188. package/lib/task/create.ts +34 -9
  189. package/lib/task/current-contract.ts +6 -1
  190. package/lib/task/decision-details.ts +8 -64
  191. package/lib/task/delivery-target.ts +130 -0
  192. package/lib/task/delivery.ts +160 -0
  193. package/lib/task/events.ts +296 -16
  194. package/lib/task/finalization.ts +50 -14
  195. package/lib/task/human-override.ts +73 -46
  196. package/lib/task/invalidation-command.ts +86 -0
  197. package/lib/task/invalidation.ts +332 -0
  198. package/lib/task/ledger-intents.ts +35 -1
  199. package/lib/task/lifecycle.ts +93 -4
  200. package/lib/task/local-artifact-finalization.ts +563 -0
  201. package/lib/task/orchestration.ts +110 -146
  202. package/lib/task/pr-delivery-fact.ts +237 -0
  203. package/lib/task/review-finalization.ts +4 -14
  204. package/lib/task/review-fingerprint.ts +33 -2
  205. package/lib/task/rework-intent.ts +165 -0
  206. package/lib/task/skill-scope.ts +24 -0
  207. package/lib/task/task-execution-lock.ts +23 -14
  208. package/lib/task/verification-engine.ts +95 -43
  209. package/lib/task/verification-review.ts +2 -0
  210. package/lib/task/verification.ts +4 -4
  211. package/lib/task/workflow-warning-intents.ts +1 -1
  212. package/lib/task/write.ts +19 -0
  213. package/lib/update.ts +11 -1
  214. package/lib/version.ts +15 -1
  215. package/package.json +7 -1
  216. package/templates/.agents/rules/README.en.md +4 -2
  217. package/templates/.agents/rules/README.zh-CN.md +4 -2
  218. package/templates/.agents/rules/create-issue.en.md +11 -2
  219. package/templates/.agents/rules/create-issue.zh-CN.md +24 -2
  220. package/templates/.agents/rules/issue-pr-commands.en.md +4 -17
  221. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
  222. package/templates/.agents/rules/issue-sync.en.md +28 -5
  223. package/templates/.agents/rules/issue-sync.zh-CN.md +64 -5
  224. package/templates/.agents/rules/label-milestone-setup.en.md +15 -2
  225. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +15 -2
  226. package/templates/.agents/rules/local-artifact-repair.en.md +53 -0
  227. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +53 -0
  228. package/templates/.agents/rules/milestone-inference.en.md +12 -2
  229. package/templates/.agents/rules/milestone-inference.zh-CN.md +25 -3
  230. package/templates/.agents/rules/pr-sync.en.md +28 -13
  231. package/templates/.agents/rules/pr-sync.zh-CN.md +39 -5
  232. package/templates/.agents/rules/release-commands.en.md +42 -3
  233. package/templates/.agents/rules/release-commands.zh-CN.md +42 -3
  234. package/templates/.agents/rules/security-alerts.en.md +17 -2
  235. package/templates/.agents/rules/security-alerts.zh-CN.md +17 -2
  236. package/templates/.agents/rules/sync-content-generation.en.md +8 -0
  237. package/templates/.agents/rules/sync-content-generation.zh-CN.md +8 -0
  238. package/templates/.agents/rules/task-management.en.md +1 -1
  239. package/templates/.agents/rules/task-management.zh-CN.md +1 -1
  240. package/templates/.agents/rules/task-short-id.en.md +1 -4
  241. package/templates/.agents/rules/task-short-id.zh-CN.md +1 -3
  242. package/templates/.agents/scripts/security-alerts.github.sh +151 -0
  243. package/templates/.agents/scripts/security-alerts.sh +31 -0
  244. package/templates/.agents/skills/analyze-task/SKILL.en.md +14 -3
  245. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +11 -3
  246. package/templates/.agents/skills/check-task/SKILL.en.md +16 -37
  247. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -37
  248. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  249. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  250. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  251. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  252. package/templates/.agents/skills/code-task/SKILL.en.md +32 -10
  253. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +35 -13
  254. package/templates/.agents/skills/code-task/config/verify.en.json +1 -0
  255. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -0
  256. package/templates/.agents/skills/commit/SKILL.en.md +3 -3
  257. package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -3
  258. package/templates/.agents/skills/commit/config/verify.json +1 -1
  259. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +3 -3
  260. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +3 -3
  261. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +2 -0
  262. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +2 -0
  263. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +4 -4
  264. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +4 -4
  265. package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -2
  266. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -2
  267. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +7 -4
  268. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +7 -4
  269. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  270. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  271. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +5 -4
  272. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +5 -4
  273. package/templates/.agents/skills/complete-task/SKILL.en.md +31 -13
  274. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +30 -13
  275. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +2 -2
  276. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +2 -2
  277. package/templates/.agents/skills/create-pr/SKILL.en.md +11 -10
  278. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +11 -11
  279. package/templates/.agents/skills/create-pr/config/verify.json +1 -0
  280. package/templates/.agents/skills/create-pr/reference/change-report.en.md +16 -4
  281. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +16 -4
  282. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +5 -3
  283. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +5 -3
  284. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +1 -1
  285. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +1 -1
  286. package/templates/.agents/skills/create-pr/scripts/change-report.mjs +3 -0
  287. package/templates/.agents/skills/create-task/SKILL.en.md +1 -0
  288. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -0
  289. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  290. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  291. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  292. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  293. package/templates/.agents/skills/init-labels/SKILL.en.md +9 -10
  294. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +9 -10
  295. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +57 -1
  296. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +27 -1
  297. package/templates/.agents/skills/init-milestones/SKILL.en.md +3 -5
  298. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +3 -5
  299. package/templates/.agents/skills/plan-task/SKILL.en.md +14 -3
  300. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +11 -3
  301. package/templates/.agents/skills/review-analysis/SKILL.en.md +6 -5
  302. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +6 -5
  303. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +18 -0
  304. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +18 -0
  305. package/templates/.agents/skills/review-code/SKILL.en.md +10 -9
  306. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +10 -9
  307. package/templates/.agents/skills/review-code/reference/output-templates.en.md +19 -1
  308. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +19 -1
  309. package/templates/.agents/skills/review-code/reference/report-template.en.md +4 -2
  310. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +4 -2
  311. package/templates/.agents/skills/review-plan/SKILL.en.md +6 -5
  312. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +6 -5
  313. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +18 -0
  314. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +18 -0
  315. package/templates/.agents/skills/review-pr/SKILL.en.md +1 -0
  316. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +1 -0
  317. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +2 -2
  318. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +2 -2
  319. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -2
  320. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -2
  321. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  322. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  323. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +4 -0
  324. package/templates/.agents/skills/watch-pr/SKILL.en.md +6 -6
  325. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +6 -6
  326. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +6 -0
  327. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +6 -0
  328. package/templates/.agents/templates/task.en.md +23 -2
  329. package/templates/.agents/templates/task.zh-CN.md +23 -2
  330. package/templates/.agents/workflows/bug-fix.en.yaml +9 -8
  331. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +9 -8
  332. package/templates/.agents/workflows/feature-development.en.yaml +9 -8
  333. package/templates/.agents/workflows/feature-development.zh-CN.yaml +9 -8
  334. package/templates/.agents/workflows/refactoring.en.yaml +9 -8
  335. package/templates/.agents/workflows/refactoring.zh-CN.yaml +9 -8
  336. package/templates/.github/workflows/pr-label.yml +7 -26
  337. package/templates/.agents/rules/create-issue.github.en.md +0 -14
  338. package/templates/.agents/rules/create-issue.github.zh-CN.md +0 -27
  339. package/templates/.agents/rules/issue-pr-commands.github.en.md +0 -34
  340. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +0 -49
  341. package/templates/.agents/rules/issue-sync.github.en.md +0 -40
  342. package/templates/.agents/rules/issue-sync.github.zh-CN.md +0 -76
  343. package/templates/.agents/rules/label-milestone-setup.github.en.md +0 -60
  344. package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +0 -60
  345. package/templates/.agents/rules/milestone-inference.github.en.md +0 -15
  346. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +0 -27
  347. package/templates/.agents/rules/pr-checks-commands.github.en.md +0 -18
  348. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +0 -34
  349. package/templates/.agents/rules/pr-sync.github.en.md +0 -43
  350. package/templates/.agents/rules/pr-sync.github.zh-CN.md +0 -69
  351. package/templates/.agents/rules/release-commands.github.en.md +0 -44
  352. package/templates/.agents/rules/release-commands.github.zh-CN.md +0 -44
  353. package/templates/.agents/rules/security-alerts.github.en.md +0 -43
  354. package/templates/.agents/rules/security-alerts.github.zh-CN.md +0 -43
  355. /package/templates/.agents/rules/{issue-fields.github.en.md → issue-fields.en.md} +0 -0
  356. /package/templates/.agents/rules/{issue-fields.github.zh-CN.md → issue-fields.zh-CN.md} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { execFileSync } from 'node:child_process';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
- import { randomUUID } from 'node:crypto';
4
+ import { createHash, randomUUID } from 'node:crypto';
5
5
  import { buildProcessTreeStopCommand } from '../../server/process-control.ts';
6
6
  import { getProcessIdentityState } from '../../server/process-state.ts';
7
7
  import type { ProcessIdentity, ProcessIdentityProbe } from '../../server/process-state.ts';
@@ -9,8 +9,20 @@ import type {
9
9
  SandboxControlExecution,
10
10
  SandboxControlLease,
11
11
  SandboxControlManifest,
12
+ SandboxControlPayload,
13
+ SandboxControlReservation,
14
+ SandboxControlResultEvidence,
12
15
  SandboxControlStatus
13
16
  } from './protocol.ts';
17
+ import {
18
+ parseSandboxControlResultEvidence,
19
+ parseSandboxControlPayload,
20
+ parseSandboxControlReservation,
21
+ SANDBOX_CONTROL_MAX_RESPONSE_BYTES,
22
+ SANDBOX_CONTROL_MAX_LOGICAL_RECORDS,
23
+ SANDBOX_CONTROL_MAX_TERMINAL_RECORD_BYTES,
24
+ SANDBOX_CONTROL_RESERVATION_BYTES
25
+ } from './protocol.ts';
14
26
 
15
27
  export const SANDBOX_CONTROL_AUDIT_MAX_BYTES = 1024 * 1024;
16
28
  export const SANDBOX_CONTROL_EXECUTION_STOP_MS = 2_000;
@@ -31,11 +43,249 @@ export function atomicWriteJson(filePath: string, value: unknown, mode = 0o600,
31
43
  }
32
44
  }
33
45
 
46
+ export function sandboxControlEncodedJsonBytes(value: unknown): number {
47
+ return Buffer.byteLength(`${JSON.stringify(value)}\n`, 'utf8');
48
+ }
49
+
50
+ export function atomicWriteJsonNoReplace(
51
+ filePath: string,
52
+ value: unknown,
53
+ mode = 0o600,
54
+ createParent = true
55
+ ): void {
56
+ atomicCreateJson(filePath, value, 'SANDBOX_CONTROL_TERMINAL_ALREADY_EXISTS', mode, createParent);
57
+ }
58
+
59
+ function atomicCreateJson(
60
+ filePath: string,
61
+ value: unknown,
62
+ duplicateCode: string,
63
+ mode = 0o600,
64
+ createParent = true
65
+ ): void {
66
+ if (createParent) fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
67
+ const temporary = path.join(path.dirname(filePath), `.${path.basename(filePath)}.${process.pid}.${randomUUID()}.tmp`);
68
+ try {
69
+ fs.writeFileSync(temporary, `${JSON.stringify(value)}\n`, { mode, flag: 'wx' });
70
+ try {
71
+ fs.linkSync(temporary, filePath);
72
+ } catch (error) {
73
+ if ((error as NodeJS.ErrnoException).code === 'EEXIST') {
74
+ throw new Error(duplicateCode);
75
+ }
76
+ throw error;
77
+ }
78
+ } finally {
79
+ fs.rmSync(temporary, { force: true });
80
+ }
81
+ }
82
+
34
83
  export function readJsonFile(filePath: string): unknown {
35
84
  assertRegularFile(filePath);
36
85
  return JSON.parse(fs.readFileSync(filePath, 'utf8'));
37
86
  }
38
87
 
88
+ export function resultEvidencePath(manifest: SandboxControlManifest, requestId: string): string {
89
+ if (!/^[a-f0-9-]{16,64}$/u.test(requestId)) throw new Error('SANDBOX_CONTROL_RESULT_EVIDENCE_INVALID');
90
+ return path.join(manifest.processingDir, requestId, 'result.json');
91
+ }
92
+
93
+ export function payloadPath(manifest: SandboxControlManifest, requestId: string): string {
94
+ if (!/^[a-f0-9-]{16,64}$/u.test(requestId)) throw new Error('SANDBOX_CONTROL_PAYLOAD_INVALID');
95
+ return path.join(manifest.channelDir, 'responses', `${requestId}.payload.json`);
96
+ }
97
+
98
+ export function reservationPath(manifest: SandboxControlManifest, requestId: string): string {
99
+ if (!/^[a-f0-9-]{16,64}$/u.test(requestId)) throw new Error('SANDBOX_CONTROL_RESERVATION_INVALID');
100
+ return path.join(manifest.processingDir, requestId, 'reservation.json');
101
+ }
102
+
103
+ export function readSandboxControlResultEvidence(filePath: string): SandboxControlResultEvidence {
104
+ assertRegularFile(filePath);
105
+ const raw = fs.readFileSync(filePath, 'utf8');
106
+ if (Buffer.byteLength(raw, 'utf8') > SANDBOX_CONTROL_MAX_TERMINAL_RECORD_BYTES) {
107
+ throw new Error('SANDBOX_CONTROL_RESULT_EVIDENCE_TOO_LARGE');
108
+ }
109
+ try {
110
+ return parseSandboxControlResultEvidence(JSON.parse(raw));
111
+ } catch (error) {
112
+ if (error instanceof Error && error.message === 'SANDBOX_CONTROL_RESULT_EVIDENCE_INVALID') throw error;
113
+ throw new Error('SANDBOX_CONTROL_RESULT_EVIDENCE_INVALID');
114
+ }
115
+ }
116
+
117
+ export function sanitizeSandboxControlOutput(manifest: SandboxControlManifest, output: string): string {
118
+ return manifest.token.length === 0 ? output : output.split(manifest.token).join('[REDACTED]');
119
+ }
120
+
121
+ export function sanitizeSandboxControlResult(
122
+ manifest: SandboxControlManifest,
123
+ result: Readonly<{ exitCode: number; stdout: string; stderr: string }>
124
+ ): { exitCode: number; stdout: string; stderr: string } {
125
+ return {
126
+ exitCode: result.exitCode,
127
+ stdout: sanitizeSandboxControlOutput(manifest, result.stdout),
128
+ stderr: sanitizeSandboxControlOutput(manifest, result.stderr)
129
+ };
130
+ }
131
+
132
+ export function writeSandboxControlResultEvidence(
133
+ manifest: SandboxControlManifest,
134
+ requestId: string,
135
+ result: Readonly<{ exitCode: number; stdout: string; stderr: string }>
136
+ ): SandboxControlResultEvidence {
137
+ const normalized = sanitizeSandboxControlResult(manifest, result);
138
+ const stdout = normalized.stdout;
139
+ const stderr = normalized.stderr;
140
+ if (!/^[a-f0-9-]{16,64}$/u.test(requestId)
141
+ || !Number.isSafeInteger(result.exitCode)
142
+ || Buffer.byteLength(stdout, 'utf8') + Buffer.byteLength(stderr, 'utf8') > SANDBOX_CONTROL_MAX_RESPONSE_BYTES) {
143
+ throw new Error('SANDBOX_CONTROL_RESULT_EVIDENCE_INVALID');
144
+ }
145
+ const evidence: SandboxControlResultEvidence = {
146
+ version: 1,
147
+ id: requestId,
148
+ generation: manifest.generation,
149
+ exitCode: result.exitCode,
150
+ stdoutBytes: Buffer.byteLength(stdout, 'utf8'),
151
+ stderrBytes: Buffer.byteLength(stderr, 'utf8'),
152
+ stdoutSha256: createHash('sha256').update(stdout, 'utf8').digest('hex'),
153
+ stderrSha256: createHash('sha256').update(stderr, 'utf8').digest('hex'),
154
+ captureState: 'metadata-only'
155
+ };
156
+ if (sandboxControlEncodedJsonBytes(evidence) > SANDBOX_CONTROL_MAX_TERMINAL_RECORD_BYTES) {
157
+ throw new Error('SANDBOX_CONTROL_RESULT_EVIDENCE_TOO_LARGE');
158
+ }
159
+ atomicCreateJson(
160
+ resultEvidencePath(manifest, requestId), evidence,
161
+ 'SANDBOX_CONTROL_RESULT_EVIDENCE_ALREADY_EXISTS'
162
+ );
163
+ return readSandboxControlResultEvidence(resultEvidencePath(manifest, requestId));
164
+ }
165
+
166
+ export function writeSandboxControlPayload(
167
+ manifest: SandboxControlManifest,
168
+ requestId: string,
169
+ result: Readonly<{ stdout: string; stderr: string }>
170
+ ): SandboxControlPayload {
171
+ const payload = createSandboxControlPayload(manifest, requestId, result);
172
+ atomicCreateJson(payloadPath(manifest, requestId), payload, 'SANDBOX_CONTROL_PAYLOAD_ALREADY_EXISTS');
173
+ return readSandboxControlPayload(payloadPath(manifest, requestId));
174
+ }
175
+
176
+ export function createSandboxControlPayload(
177
+ manifest: SandboxControlManifest,
178
+ requestId: string,
179
+ result: Readonly<{ stdout: string; stderr: string }>
180
+ ): SandboxControlPayload {
181
+ const stdout = sanitizeSandboxControlOutput(manifest, result.stdout);
182
+ const stderr = sanitizeSandboxControlOutput(manifest, result.stderr);
183
+ const payload: SandboxControlPayload = {
184
+ version: 1,
185
+ id: requestId,
186
+ generation: manifest.generation,
187
+ stdout,
188
+ stderr,
189
+ stdoutBytes: Buffer.byteLength(stdout, 'utf8'),
190
+ stderrBytes: Buffer.byteLength(stderr, 'utf8'),
191
+ stdoutSha256: createHash('sha256').update(stdout, 'utf8').digest('hex'),
192
+ stderrSha256: createHash('sha256').update(stderr, 'utf8').digest('hex')
193
+ };
194
+ if (payload.stdoutBytes + payload.stderrBytes > SANDBOX_CONTROL_MAX_RESPONSE_BYTES) {
195
+ throw new Error('SANDBOX_CONTROL_PAYLOAD_TOO_LARGE');
196
+ }
197
+ if (sandboxControlEncodedJsonBytes(payload) > SANDBOX_CONTROL_MAX_RESPONSE_BYTES) {
198
+ throw new Error('SANDBOX_CONTROL_PAYLOAD_TOO_LARGE');
199
+ }
200
+ return payload;
201
+ }
202
+
203
+ export function readSandboxControlPayload(filePath: string): SandboxControlPayload {
204
+ assertRegularFile(filePath);
205
+ const raw = fs.readFileSync(filePath, 'utf8');
206
+ if (Buffer.byteLength(raw, 'utf8') > SANDBOX_CONTROL_MAX_RESPONSE_BYTES) {
207
+ throw new Error('SANDBOX_CONTROL_PAYLOAD_TOO_LARGE');
208
+ }
209
+ try {
210
+ return parseSandboxControlPayload(JSON.parse(raw));
211
+ } catch {
212
+ throw new Error('SANDBOX_CONTROL_PAYLOAD_INVALID');
213
+ }
214
+ }
215
+
216
+ export function writeSandboxControlReservation(
217
+ manifest: SandboxControlManifest,
218
+ requestId: string,
219
+ usage: Readonly<{ logicalRecords: number; bytes: number }>,
220
+ now = Date.now()
221
+ ): SandboxControlReservation {
222
+ if (usage.logicalRecords >= SANDBOX_CONTROL_MAX_LOGICAL_RECORDS
223
+ || usage.bytes + SANDBOX_CONTROL_RESERVATION_BYTES > SANDBOX_CONTROL_MAX_RESPONSE_BYTES) {
224
+ throw new Error('SANDBOX_CONTROL_CAPACITY_EXHAUSTED');
225
+ }
226
+ const reservation: SandboxControlReservation = {
227
+ version: 1,
228
+ id: requestId,
229
+ generation: manifest.generation,
230
+ logicalRecords: 1,
231
+ bytes: SANDBOX_CONTROL_RESERVATION_BYTES,
232
+ createdAt: now
233
+ };
234
+ atomicCreateJson(reservationPath(manifest, requestId), reservation, 'SANDBOX_CONTROL_RESERVATION_ALREADY_EXISTS');
235
+ return parseSandboxControlReservation(readJsonFile(reservationPath(manifest, requestId)));
236
+ }
237
+
238
+ export function readSandboxControlReservation(filePath: string): SandboxControlReservation {
239
+ return parseSandboxControlReservation(readJsonFile(filePath));
240
+ }
241
+
242
+ export function sandboxControlGenerationUsage(manifest: SandboxControlManifest): { logicalRecords: number; bytes: number } {
243
+ const records = new Map<string, { baseBytes: number; payloadBytes: number; logical: boolean }>();
244
+ const responsesDir = path.join(manifest.channelDir, 'responses');
245
+ if (fs.existsSync(responsesDir)) {
246
+ for (const entry of fs.readdirSync(responsesDir, { withFileTypes: true })) {
247
+ if (!entry.isFile()) continue;
248
+ const terminal = entry.name.match(/^([a-f0-9-]{16,64})\.json$/u);
249
+ const accepted = entry.name.match(/^([a-f0-9-]{16,64})\.accepted\.json$/u);
250
+ const payload = entry.name.match(/^([a-f0-9-]{16,64})\.payload\.json$/u);
251
+ if (!terminal && !accepted && !payload) continue;
252
+ const id = (terminal ?? accepted ?? payload)![1]!;
253
+ const previous = records.get(id) ?? { baseBytes: 0, payloadBytes: 0, logical: false };
254
+ const fileBytes = fs.statSync(path.join(responsesDir, entry.name)).size;
255
+ if (payload) previous.payloadBytes += fileBytes;
256
+ else previous.baseBytes += fileBytes;
257
+ previous.logical ||= Boolean(terminal || accepted);
258
+ records.set(id, previous);
259
+ }
260
+ }
261
+ if (fs.existsSync(manifest.processingDir)) {
262
+ for (const entry of fs.readdirSync(manifest.processingDir, { withFileTypes: true })) {
263
+ if (!entry.isDirectory() || !/^[a-f0-9-]{16,64}$/u.test(entry.name)) continue;
264
+ const resultPath = resultEvidencePath(manifest, entry.name);
265
+ const filePath = reservationPath(manifest, entry.name);
266
+ const previous = records.get(entry.name) ?? { baseBytes: 0, payloadBytes: 0, logical: false };
267
+ if (fs.existsSync(resultPath)) {
268
+ const result = readSandboxControlResultEvidence(resultPath);
269
+ if (result.id !== entry.name || result.generation !== manifest.generation) {
270
+ throw new Error('SANDBOX_CONTROL_RESULT_EVIDENCE_INVALID');
271
+ }
272
+ previous.baseBytes += fs.statSync(resultPath).size;
273
+ previous.logical = true;
274
+ }
275
+ if (fs.existsSync(filePath)) {
276
+ const reservation = readSandboxControlReservation(filePath);
277
+ previous.baseBytes = Math.max(previous.baseBytes, reservation.bytes);
278
+ previous.logical = true;
279
+ }
280
+ records.set(entry.name, previous);
281
+ }
282
+ }
283
+ return {
284
+ logicalRecords: [...records.values()].filter((record) => record.logical).length,
285
+ bytes: [...records.values()].reduce((total, record) => total + record.baseBytes + record.payloadBytes, 0)
286
+ };
287
+ }
288
+
39
289
  export function statusPath(manifest: SandboxControlManifest): string {
40
290
  return path.join(manifest.publicStatusDir, 'status.json');
41
291
  }
@@ -85,8 +85,8 @@ export function isProcessAlive(pid: number, platform: NodeJS.Platform = process.
85
85
  }
86
86
  }
87
87
 
88
- function parseDarwinStartTime(output: string): number | null {
89
- const match = output.trim().match(/^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat) ([A-Z][a-z]{2}) (\d{1,2}) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/);
88
+ export function parseDarwinStartTime(output: string): number | null {
89
+ const match = output.trim().match(/^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat) ([A-Z][a-z]{2})\s+(\d{1,2}) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/);
90
90
  if (!match) return null;
91
91
  const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
92
92
  const month = months.indexOf(match[1]!);
@@ -20,6 +20,27 @@ function taskSubcommand(subcommand: string): string {
20
20
  return subcommand === 'list' ? 'ls' : subcommand;
21
21
  }
22
22
 
23
+ function splitRunArguments(args: readonly string[]): { hostArgs: string[]; skillArgs: string[] } {
24
+ const hostArgs: string[] = [];
25
+ const skillArgs: string[] = [];
26
+ for (let i = 0; i < args.length; i += 1) {
27
+ const arg = args[i] as string;
28
+ if (arg === '--tui') {
29
+ hostArgs.push(arg);
30
+ const value = args[i + 1];
31
+ if (value !== undefined) {
32
+ hostArgs.push(value);
33
+ i += 1;
34
+ }
35
+ } else if (arg === '--recreate') {
36
+ hostArgs.push(arg);
37
+ } else {
38
+ skillArgs.push(arg);
39
+ }
40
+ }
41
+ return { hostArgs, skillArgs };
42
+ }
43
+
23
44
  export function commandHelp(): string {
24
45
  return [
25
46
  `agent-infra ${VERSION}`,
@@ -88,7 +109,21 @@ export function parseCommand(text: string): CommandPlan {
88
109
  if (command === '/run') {
89
110
  const spec = getSkillRunSpec(subcommand);
90
111
  if (!spec) return { kind: 'error', message: `Unknown skill: ${subcommand}` };
91
- return { kind: 'ai', role: spec.role, argv: ['run', subcommand, ...rest] };
112
+ if (spec.kind === 'create') {
113
+ return { kind: 'ai', role: spec.role, argv: ['run', '--skill', subcommand, ...rest] };
114
+ }
115
+ const [taskRef, ...skillArgs] = rest;
116
+ if (!taskRef) return { kind: 'error', message: '/run task skills require a task-ref' };
117
+ const { hostArgs, skillArgs: forwardedSkillArgs } = splitRunArguments(skillArgs);
118
+ return {
119
+ kind: 'ai',
120
+ role: spec.role,
121
+ argv: [
122
+ 'run', '--skill', subcommand, '--task', taskRef,
123
+ ...hostArgs,
124
+ ...(forwardedSkillArgs.length > 0 ? ['--', ...forwardedSkillArgs] : [])
125
+ ]
126
+ };
92
127
  }
93
128
 
94
129
  return { kind: 'error', message: `Unknown command: ${command}` };
@@ -5,6 +5,7 @@ const STARTED_SUFFIX_RE = /\s*\[started\]\s*$/;
5
5
  const ABORTED_SUFFIX_RE = /\s*\[aborted\]\s*$/;
6
6
  const ATTEMPT_RE = /(?:^|;\s*)attempt=([A-Za-z0-9-]{8,64})(?:;|$)/;
7
7
  const COMMIT_STARTED_RE = /^started; attempt=([A-Za-z0-9-]{8,64}); baseline=([a-f0-9]{40,64}); agent=([a-z-]+)$/;
8
+ const LIFECYCLE_STEP_RE = /^(?:Complete Manual Validation|(?:Analyze Task|Review Analysis|Plan Task|Review Plan|Code Task|Review Code|Run Manual Validation) \(Round [1-9]\d*(?:(?:, fix for review-code(?:-r[2-9]|-r[1-9]\d+)?\.md)|(?:, decision II-[1-9]\d*))?\))$/;
8
9
 
9
10
  type LogEntry = { time: string; step: string; agent: string; note: string };
10
11
  type StepRow = { step: string; agent: string; started: string; done: string; note: string; attempt?: string };
@@ -93,9 +94,16 @@ function startedBackedRows(rows: StepRow[]): StepRow[] {
93
94
  return rows.filter((row) => row.started !== '');
94
95
  }
95
96
 
97
+ function hasOpenLifecycleExecution(content: string): boolean {
98
+ const section = locateActivityLog(content);
99
+ if (!section) return false;
100
+ return pairEntries(section.entries).some((row) => row.done === '' && LIFECYCLE_STEP_RE.test(row.step));
101
+ }
102
+
96
103
  export {
97
104
  activityAttempt,
98
105
  appendActivityEntry,
106
+ hasOpenLifecycleExecution,
99
107
  commitAttemptStartedNote,
100
108
  locateActivityLog,
101
109
  pairEntries,
@@ -8,6 +8,8 @@ import { parseImplementationInputs, selectPendingImplementationInput } from './i
8
8
  import { parseVerdict } from './review-artifacts.ts';
9
9
  import { extractSection, findSectionHeading } from './sections.ts';
10
10
  import { receiptForOutput, sha256File } from './artifact-receipts.ts';
11
+ import { isArtifactInvalidated, parseInvalidationDocument } from './invalidation.ts';
12
+ import type { InvalidationDocument } from './invalidation.ts';
11
13
 
12
14
  const artifactFamilyCatalog = [
13
15
  { family: 'analysis', sectionAliases: ['分析', 'Analysis'], heading: '分析', labels: ['需求分析报告', 'Requirements Analysis'] },
@@ -47,7 +49,7 @@ type ArtifactErrorCode =
47
49
  | 'ARTIFACT_REFERENCE_INVALID' | 'ARTIFACT_PATH_INVALID'
48
50
  | 'ARTIFACT_IDENTITY_INVALID' | 'ARTIFACT_NOT_FOUND'
49
51
  | 'ARTIFACT_NOT_REGULAR' | 'ARTIFACT_NOT_READABLE' | 'ARTIFACT_VERDICT_INVALID'
50
- | 'ARTIFACT_MODE_REFUSED';
52
+ | 'ARTIFACT_MODE_REFUSED' | 'ARTIFACT_INVALIDATION_INVALID';
51
53
  type ArtifactError = { code: ArtifactErrorCode; message: string };
52
54
  type ArtifactInventoryResult = {
53
55
  status: 'ready' | 'failed';
@@ -154,7 +156,23 @@ function inspectArtifactDirectory(
154
156
  taskId: identity.taskId ?? null, taskDir, taskState: identity.taskState ?? null
155
157
  });
156
158
  }
159
+ let invalidation: InvalidationDocument = { operations: [], targets: [] };
160
+ try {
161
+ const taskContent = fs.readFileSync(path.join(taskDir, 'task.md'), 'utf8');
162
+ const parsed = parseInvalidationDocument(taskContent);
163
+ if (!parsed.ok) {
164
+ return failure(requestRef, family, { code: 'ARTIFACT_INVALIDATION_INVALID', message: parsed.message }, {
165
+ taskId: identity.taskId ?? null, taskDir, taskState: identity.taskState ?? null
166
+ });
167
+ }
168
+ invalidation = parsed.document;
169
+ } catch (error) {
170
+ return failure(requestRef, family, { code: 'ARTIFACT_INVALIDATION_INVALID', message: String(error) }, {
171
+ taskId: identity.taskId ?? null, taskDir, taskState: identity.taskState ?? null
172
+ });
173
+ }
157
174
  const artifacts: ArtifactIdentity[] = [];
175
+ const knownArtifacts: ArtifactIdentity[] = [];
158
176
  const diagnostics: ArtifactDiagnostic[] = [];
159
177
  for (const entry of entries) {
160
178
  const parsed = parseArtifactName(entry.name);
@@ -184,17 +202,20 @@ function inspectArtifactDirectory(
184
202
  diagnostics.push(diagnostic('FILESYSTEM_RACE', family, entry.name, `artifact is not readable: ${entry.name}`));
185
203
  continue;
186
204
  }
187
- artifacts.push({ ...parsed, path: abs, size: stat.size, mtimeMs: stat.mtimeMs });
205
+ const identity = { ...parsed, path: abs, size: stat.size, mtimeMs: stat.mtimeMs };
206
+ knownArtifacts.push(identity);
207
+ if (!isArtifactInvalidated(invalidation, family, entry.name)) artifacts.push(identity);
188
208
  } catch (error) {
189
209
  diagnostics.push(diagnostic('FILESYSTEM_RACE', family, entry.name, String(error)));
190
210
  }
191
211
  }
192
212
  artifacts.sort((left, right) => left.round - right.round);
193
- const rounds = new Set(artifacts.map((item) => item.round));
194
- if (artifacts.length > 0 && !rounds.has(1)) diagnostics.push(diagnostic('MISSING_BASE', family, null, `${family}.md is missing`));
195
- const max = artifacts.at(-1)?.round ?? 0;
213
+ knownArtifacts.sort((left, right) => left.round - right.round);
214
+ const knownRounds = new Set(knownArtifacts.map((item) => item.round));
215
+ if (knownArtifacts.length > 0 && !knownRounds.has(1)) diagnostics.push(diagnostic('MISSING_BASE', family, null, `${family}.md is missing`));
216
+ const max = knownArtifacts.at(-1)?.round ?? 0;
196
217
  for (let round = 1; round <= max; round += 1) {
197
- if (!rounds.has(round)) diagnostics.push(diagnostic('ROUND_GAP', family, null, `${artifactName(family, round)} is missing`));
218
+ if (!knownRounds.has(round)) diagnostics.push(diagnostic('ROUND_GAP', family, null, `${artifactName(family, round)} is missing`));
198
219
  }
199
220
  const latest = artifacts.at(-1) ?? null;
200
221
  const reviewedInput = family.startsWith('review-') && latest
@@ -230,6 +251,11 @@ function resolveReviewedInput(
230
251
  const stat = fs.lstatSync(abs);
231
252
  if (!stat.isFile() || stat.isSymbolicLink()) throw new Error('referenced input is not a regular file');
232
253
  const taskContent = fs.readFileSync(path.join(taskDir, 'task.md'), 'utf8');
254
+ const invalidation = parseInvalidationDocument(taskContent);
255
+ if (!invalidation.ok) throw new Error(invalidation.message);
256
+ if (isArtifactInvalidated(invalidation.document, expectedFamily, parsed.name)) {
257
+ throw new Error(`${parsed.name} is invalidated`);
258
+ }
233
259
  const receipt = receiptForOutput(taskContent, review.name);
234
260
  if (!receipt) throw new Error(`receipt for ${review.name} is missing`);
235
261
  const expectedEvent = reviewEventName(review.family);
@@ -482,9 +508,9 @@ function buildArtifactLinkSection(content: string, artifact: ArtifactIdentity):
482
508
  const label = english
483
509
  ? `${spec.labels[1]} (Round ${artifact.round})`
484
510
  : `${spec.labels[0]}(Round ${artifact.round})`;
485
- const link = `[${label}](${artifact.name})`;
511
+ const link = `${label}:\`${artifact.name}\``;
486
512
  let body = extractSection(content, aliases);
487
- if (body.includes(`](${artifact.name})`)) return { aliases, heading, body };
513
+ if (body.includes(link)) return { aliases, heading, body };
488
514
  const placeholders = new Set([
489
515
  '[分析阶段的发现。哪些文件受影响?范围是什么?]',
490
516
  '[Findings from the analysis phase. Which files are affected? What is the scope?]',