@fitlab-ai/agent-infra 0.8.5 → 0.9.0

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 (425) hide show
  1. package/bin/cli.ts +2 -2
  2. package/dist/bin/cli.js +2 -2
  3. package/dist/bin/internal-cli.js +98 -0
  4. package/dist/lib/decide.js +81 -90
  5. package/dist/lib/defaults.json +1 -0
  6. package/dist/lib/git/review-snapshot.js +79 -0
  7. package/dist/lib/git/workflow.js +101 -0
  8. package/dist/lib/internal/git-workflow.js +42 -0
  9. package/dist/lib/internal/platform-checks.js +119 -0
  10. package/dist/lib/internal/platform-comment.js +129 -0
  11. package/dist/lib/internal/platform-context.js +46 -0
  12. package/dist/lib/internal/platform-issue.js +142 -0
  13. package/dist/lib/internal/platform-pr.js +146 -0
  14. package/dist/lib/internal/release-workflow.js +217 -0
  15. package/dist/lib/internal/task-artifact.js +67 -0
  16. package/dist/lib/internal/task-context.js +43 -0
  17. package/dist/lib/internal/task-event.js +70 -0
  18. package/dist/lib/internal/task-ledger.js +114 -0
  19. package/dist/lib/internal/task-lifecycle.js +58 -0
  20. package/dist/lib/internal/task-short-id.js +83 -0
  21. package/dist/lib/internal/task-snapshot.js +47 -0
  22. package/dist/lib/internal/task-verify.js +50 -0
  23. package/dist/lib/internal/task-warning.js +74 -0
  24. package/dist/lib/platform/adapters.js +14 -0
  25. package/dist/lib/platform/context.js +146 -0
  26. package/dist/lib/platform/github-client.js +124 -0
  27. package/dist/lib/platform/issue-comments.js +409 -0
  28. package/dist/lib/platform/issue-metadata.js +183 -0
  29. package/dist/lib/platform/issues.js +617 -0
  30. package/dist/lib/platform/metadata-labels.js +28 -0
  31. package/dist/lib/platform/pr-checks.js +216 -0
  32. package/dist/lib/platform/pr-summary.js +88 -0
  33. package/dist/lib/platform/pull-request-metadata.js +38 -0
  34. package/dist/lib/platform/pull-requests.js +338 -0
  35. package/dist/lib/platform/releases.js +82 -0
  36. package/dist/lib/platform/types.js +22 -0
  37. package/dist/lib/platform/verification-required.js +78 -0
  38. package/dist/lib/platform/verification-sync.js +1014 -0
  39. package/dist/lib/platform/verification.js +6 -0
  40. package/dist/lib/release/channels.js +31 -0
  41. package/dist/lib/release/workflow.js +32 -0
  42. package/dist/lib/render.js +3 -2
  43. package/dist/lib/run/index.js +24 -7
  44. package/dist/lib/sandbox/capture.js +25 -3
  45. package/dist/lib/sandbox/commands/create.js +36 -22
  46. package/dist/lib/sandbox/commands/enter.js +34 -11
  47. package/dist/lib/sandbox/commands/list-running.js +10 -8
  48. package/dist/lib/sandbox/commands/show.js +2 -2
  49. package/dist/lib/sandbox/commands/start.js +53 -15
  50. package/dist/lib/sandbox/index.js +6 -6
  51. package/dist/lib/sandbox/mounts.js +36 -0
  52. package/dist/lib/sandbox/recovery.js +562 -0
  53. package/dist/lib/sandbox/task-resolver.js +5 -1
  54. package/dist/lib/sandbox/tools.js +19 -0
  55. package/dist/lib/server/protocol.js +5 -5
  56. package/dist/lib/task/activity-log.js +61 -0
  57. package/dist/lib/task/artifact-lifecycle.js +427 -0
  58. package/dist/lib/task/command-options.js +30 -0
  59. package/dist/lib/task/commands/cat.js +36 -6
  60. package/dist/lib/task/commands/decisions.js +80 -46
  61. package/dist/lib/task/commands/files.js +21 -7
  62. package/dist/lib/task/commands/grep.js +55 -7
  63. package/dist/lib/task/commands/issue-body.js +23 -14
  64. package/dist/lib/task/commands/log.js +27 -70
  65. package/dist/lib/task/commands/show.js +20 -7
  66. package/dist/lib/task/commands/status.js +18 -8
  67. package/dist/lib/task/decision-intents.js +154 -0
  68. package/dist/lib/task/decision-items.js +53 -0
  69. package/dist/lib/task/events.js +318 -0
  70. package/dist/lib/task/frontmatter.js +159 -1
  71. package/dist/lib/task/implementation-inputs.js +117 -0
  72. package/dist/lib/task/index.js +12 -9
  73. package/dist/lib/task/issue-form.js +19 -6
  74. package/dist/lib/task/ledger-intents.js +185 -0
  75. package/dist/lib/task/ledger.js +65 -35
  76. package/dist/lib/task/lifecycle.js +484 -0
  77. package/dist/lib/task/resolve-ref.js +152 -32
  78. package/dist/lib/task/review-artifacts.js +101 -0
  79. package/dist/lib/task/review-fingerprint.js +46 -0
  80. package/dist/lib/task/sections.js +358 -4
  81. package/dist/lib/task/short-id.js +292 -7
  82. package/dist/lib/task/snapshot.js +95 -0
  83. package/dist/lib/task/verification-checks.js +8 -0
  84. package/dist/lib/task/verification-config.js +14 -0
  85. package/dist/lib/task/verification-engine.js +906 -0
  86. package/dist/lib/task/verification-review.js +3 -0
  87. package/dist/lib/task/verification-types.js +2 -0
  88. package/dist/lib/task/verification.js +113 -0
  89. package/dist/lib/task/workflow-warning-intents.js +131 -0
  90. package/dist/lib/task/workflow-warnings.js +10 -78
  91. package/dist/lib/task/write.js +241 -0
  92. package/lib/decide.ts +57 -97
  93. package/lib/defaults.json +1 -0
  94. package/lib/git/review-snapshot.ts +73 -0
  95. package/lib/git/workflow.ts +101 -0
  96. package/lib/internal/git-workflow.ts +37 -0
  97. package/lib/internal/platform-checks.ts +101 -0
  98. package/lib/internal/platform-comment.ts +99 -0
  99. package/lib/internal/platform-context.ts +33 -0
  100. package/lib/internal/platform-issue.ts +116 -0
  101. package/lib/internal/platform-pr.ts +119 -0
  102. package/lib/internal/release-workflow.ts +186 -0
  103. package/lib/internal/task-artifact.ts +47 -0
  104. package/lib/internal/task-context.ts +35 -0
  105. package/lib/internal/task-event.ts +51 -0
  106. package/lib/internal/task-ledger.ts +86 -0
  107. package/lib/internal/task-lifecycle.ts +41 -0
  108. package/lib/internal/task-short-id.ts +55 -0
  109. package/lib/internal/task-snapshot.ts +32 -0
  110. package/lib/internal/task-verify.ts +33 -0
  111. package/lib/internal/task-warning.ts +50 -0
  112. package/lib/platform/adapters.ts +30 -0
  113. package/lib/platform/context.ts +164 -0
  114. package/lib/platform/github-client.ts +146 -0
  115. package/lib/platform/issue-comments.ts +479 -0
  116. package/lib/platform/issue-metadata.ts +250 -0
  117. package/lib/platform/issues.ts +691 -0
  118. package/lib/platform/metadata-labels.ts +33 -0
  119. package/lib/platform/pr-checks.ts +246 -0
  120. package/lib/platform/pr-summary.ts +90 -0
  121. package/lib/platform/pull-request-metadata.ts +69 -0
  122. package/lib/platform/pull-requests.ts +380 -0
  123. package/lib/platform/releases.ts +71 -0
  124. package/lib/platform/types.ts +74 -0
  125. package/lib/platform/verification-required.ts +83 -0
  126. package/{runtime/platform-adapters/platform-sync.github.js → lib/platform/verification-sync.ts} +198 -367
  127. package/lib/platform/verification.ts +11 -0
  128. package/lib/release/channels.ts +30 -0
  129. package/lib/release/workflow.ts +31 -0
  130. package/lib/render.ts +3 -2
  131. package/lib/run/index.ts +25 -7
  132. package/lib/sandbox/capture.ts +29 -3
  133. package/lib/sandbox/commands/create.ts +43 -25
  134. package/lib/sandbox/commands/enter.ts +38 -11
  135. package/lib/sandbox/commands/list-running.ts +10 -8
  136. package/lib/sandbox/commands/show.ts +2 -2
  137. package/lib/sandbox/commands/start.ts +50 -16
  138. package/lib/sandbox/index.ts +6 -6
  139. package/lib/sandbox/mounts.ts +55 -0
  140. package/lib/sandbox/recovery.ts +828 -0
  141. package/lib/sandbox/task-resolver.ts +5 -1
  142. package/lib/sandbox/tools.ts +31 -0
  143. package/lib/server/protocol.ts +5 -5
  144. package/lib/task/activity-log.ts +62 -0
  145. package/lib/task/artifact-lifecycle.ts +484 -0
  146. package/lib/task/command-options.ts +32 -0
  147. package/lib/task/commands/cat.ts +22 -9
  148. package/lib/task/commands/decisions.ts +49 -47
  149. package/lib/task/commands/files.ts +14 -6
  150. package/lib/task/commands/grep.ts +34 -7
  151. package/lib/task/commands/issue-body.ts +16 -16
  152. package/lib/task/commands/log.ts +17 -70
  153. package/lib/task/commands/show.ts +14 -6
  154. package/lib/task/commands/status.ts +17 -7
  155. package/lib/task/decision-intents.ts +163 -0
  156. package/lib/task/decision-items.ts +64 -0
  157. package/lib/task/events.ts +320 -0
  158. package/lib/task/frontmatter.ts +202 -2
  159. package/lib/task/implementation-inputs.ts +137 -0
  160. package/lib/task/index.ts +12 -9
  161. package/lib/task/issue-form.ts +20 -6
  162. package/lib/task/ledger-intents.ts +201 -0
  163. package/lib/task/ledger.ts +77 -31
  164. package/lib/task/lifecycle.ts +458 -0
  165. package/lib/task/resolve-ref.ts +197 -36
  166. package/{templates/.agents/scripts/lib/review-artifacts.js → lib/task/review-artifacts.ts} +11 -12
  167. package/{templates/.agents/scripts/lib/post-review-commit.js → lib/task/review-fingerprint.ts} +17 -12
  168. package/lib/task/sections.ts +486 -4
  169. package/lib/task/short-id.ts +403 -9
  170. package/lib/task/snapshot.ts +143 -0
  171. package/lib/task/verification-checks.ts +9 -0
  172. package/lib/task/verification-config.ts +20 -0
  173. package/{templates/.agents/scripts/validate-artifact.js → lib/task/verification-engine.ts} +199 -406
  174. package/lib/task/verification-review.ts +9 -0
  175. package/lib/task/verification-types.ts +29 -0
  176. package/lib/task/verification.ts +156 -0
  177. package/lib/task/workflow-warning-intents.ts +142 -0
  178. package/lib/task/workflow-warnings.ts +10 -78
  179. package/lib/task/write.ts +468 -0
  180. package/package.json +4 -2
  181. package/templates/.agents/README.en.md +4 -3
  182. package/templates/.agents/README.zh-CN.md +4 -3
  183. package/templates/.agents/rules/README.en.md +6 -5
  184. package/templates/.agents/rules/README.zh-CN.md +6 -5
  185. package/templates/.agents/rules/create-issue.en.md +1 -1
  186. package/templates/.agents/rules/create-issue.github.en.md +5 -184
  187. package/templates/.agents/rules/create-issue.github.zh-CN.md +12 -178
  188. package/templates/.agents/rules/create-issue.zh-CN.md +1 -1
  189. package/templates/.agents/rules/human-decision-context.en.md +36 -0
  190. package/templates/.agents/rules/human-decision-context.zh-CN.md +36 -0
  191. package/templates/.agents/rules/issue-fields.github.en.md +4 -148
  192. package/templates/.agents/rules/issue-fields.github.zh-CN.md +9 -144
  193. package/templates/.agents/rules/issue-pr-commands.en.md +43 -3
  194. package/templates/.agents/rules/issue-pr-commands.github.en.md +15 -220
  195. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +23 -213
  196. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +45 -3
  197. package/templates/.agents/rules/issue-sync.en.md +1 -1
  198. package/templates/.agents/rules/issue-sync.github.en.md +14 -301
  199. package/templates/.agents/rules/issue-sync.github.zh-CN.md +36 -287
  200. package/templates/.agents/rules/issue-sync.zh-CN.md +1 -1
  201. package/templates/.agents/rules/milestone-inference.en.md +1 -1
  202. package/templates/.agents/rules/milestone-inference.github.en.md +7 -119
  203. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +8 -108
  204. package/templates/.agents/rules/milestone-inference.zh-CN.md +1 -1
  205. package/templates/.agents/rules/next-step-output.en.md +12 -11
  206. package/templates/.agents/rules/next-step-output.zh-CN.md +12 -11
  207. package/templates/.agents/rules/no-mid-flow-questions.en.md +3 -3
  208. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +3 -3
  209. package/templates/.agents/rules/pr-checks-commands.en.md +16 -3
  210. package/templates/.agents/rules/pr-checks-commands.github.en.md +10 -54
  211. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +19 -47
  212. package/templates/.agents/rules/pr-checks-commands.zh-CN.md +30 -3
  213. package/templates/.agents/rules/pr-sync.en.md +30 -3
  214. package/templates/.agents/rules/pr-sync.github.en.md +12 -115
  215. package/templates/.agents/rules/pr-sync.github.zh-CN.md +26 -104
  216. package/templates/.agents/rules/pr-sync.zh-CN.md +43 -3
  217. package/templates/.agents/rules/review-handshake.en.md +8 -5
  218. package/templates/.agents/rules/review-handshake.zh-CN.md +8 -5
  219. package/templates/.agents/rules/task-management.en.md +11 -2
  220. package/templates/.agents/rules/task-management.zh-CN.md +11 -3
  221. package/templates/.agents/rules/task-short-id.en.md +25 -29
  222. package/templates/.agents/rules/task-short-id.zh-CN.md +20 -23
  223. package/templates/.agents/scripts/lib/agent-infra-package.js +1 -9
  224. package/templates/.agents/scripts/task-short-id.js +71 -533
  225. package/templates/.agents/skills/analyze-task/SKILL.en.md +22 -55
  226. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +26 -59
  227. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -3
  228. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -3
  229. package/templates/.agents/skills/block-task/SKILL.en.md +21 -47
  230. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +23 -47
  231. package/templates/.agents/skills/block-task/config/verify.json +1 -2
  232. package/templates/.agents/skills/cancel-task/SKILL.en.md +16 -45
  233. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +16 -45
  234. package/templates/.agents/skills/cancel-task/config/verify.json +1 -2
  235. package/templates/.agents/skills/check-task/SKILL.en.md +6 -3
  236. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +6 -3
  237. package/templates/.agents/skills/close-codescan/SKILL.en.md +6 -24
  238. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +6 -24
  239. package/templates/.agents/skills/close-dependabot/SKILL.en.md +6 -24
  240. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +6 -24
  241. package/templates/.agents/skills/code-task/SKILL.en.md +22 -35
  242. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +28 -44
  243. package/templates/.agents/skills/code-task/config/verify.en.json +3 -3
  244. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +3 -3
  245. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +13 -9
  246. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +13 -9
  247. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +1 -1
  248. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +1 -1
  249. package/templates/.agents/skills/code-task/reference/report-template.en.md +11 -1
  250. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +11 -1
  251. package/templates/.agents/skills/commit/SKILL.en.md +13 -11
  252. package/templates/.agents/skills/commit/SKILL.zh-CN.md +13 -11
  253. package/templates/.agents/skills/commit/config/verify.json +1 -2
  254. package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -11
  255. package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -11
  256. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +4 -8
  257. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +4 -8
  258. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +6 -18
  259. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +5 -17
  260. package/templates/.agents/skills/commit/reference/task-status-update.en.md +13 -0
  261. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +13 -0
  262. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +13 -36
  263. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +13 -36
  264. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -3
  265. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -3
  266. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +10 -54
  267. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +10 -79
  268. package/templates/.agents/skills/complete-task/SKILL.en.md +59 -63
  269. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +59 -63
  270. package/templates/.agents/skills/complete-task/config/verify.en.json +11 -7
  271. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +11 -7
  272. package/templates/.agents/skills/create-pr/SKILL.en.md +19 -44
  273. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +19 -43
  274. package/templates/.agents/skills/create-pr/config/verify.json +1 -2
  275. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +8 -12
  276. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +7 -11
  277. package/templates/.agents/skills/create-task/SKILL.en.md +12 -13
  278. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +12 -13
  279. package/templates/.agents/skills/create-task/config/verify.json +1 -2
  280. package/templates/.agents/skills/import-codescan/SKILL.en.md +2 -2
  281. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +2 -2
  282. package/templates/.agents/skills/import-codescan/config/verify.json +1 -2
  283. package/templates/.agents/skills/import-dependabot/SKILL.en.md +2 -2
  284. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +2 -2
  285. package/templates/.agents/skills/import-dependabot/config/verify.json +1 -2
  286. package/templates/.agents/skills/import-issue/SKILL.en.md +9 -13
  287. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +10 -14
  288. package/templates/.agents/skills/import-issue/config/verify.json +1 -2
  289. package/templates/.agents/skills/plan-task/SKILL.en.md +17 -42
  290. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +22 -49
  291. package/templates/.agents/skills/plan-task/config/verify.en.json +1 -3
  292. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -3
  293. package/templates/.agents/skills/post-release/SKILL.en.md +11 -81
  294. package/templates/.agents/skills/post-release/SKILL.zh-CN.md +8 -78
  295. package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
  296. package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
  297. package/templates/.agents/skills/release/SKILL.en.md +16 -163
  298. package/templates/.agents/skills/release/SKILL.zh-CN.md +15 -162
  299. package/templates/.agents/skills/restore-task/SKILL.en.md +11 -29
  300. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +11 -29
  301. package/templates/.agents/skills/restore-task/config/verify.json +1 -2
  302. package/templates/.agents/skills/review-analysis/SKILL.en.md +13 -25
  303. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +13 -33
  304. package/templates/.agents/skills/review-analysis/config/verify.en.json +3 -4
  305. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +3 -4
  306. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +9 -12
  307. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +9 -12
  308. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +9 -2
  309. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +9 -2
  310. package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +7 -0
  311. package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +7 -0
  312. package/templates/.agents/skills/review-code/SKILL.en.md +22 -36
  313. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +23 -41
  314. package/templates/.agents/skills/review-code/config/verify.en.json +3 -4
  315. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +3 -4
  316. package/templates/.agents/skills/review-code/reference/output-templates.en.md +56 -18
  317. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +56 -18
  318. package/templates/.agents/skills/review-code/reference/report-template.en.md +11 -4
  319. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +11 -4
  320. package/templates/.agents/skills/review-code/reference/review-criteria.en.md +7 -0
  321. package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +7 -0
  322. package/templates/.agents/skills/review-plan/SKILL.en.md +13 -25
  323. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +13 -33
  324. package/templates/.agents/skills/review-plan/config/verify.en.json +3 -4
  325. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +3 -4
  326. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +9 -12
  327. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +9 -12
  328. package/templates/.agents/skills/review-plan/reference/report-template.en.md +9 -2
  329. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +9 -2
  330. package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +7 -0
  331. package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +7 -0
  332. package/templates/.agents/skills/update-agent-infra/SKILL.en.md +1 -2
  333. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +1 -2
  334. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +3 -15
  335. package/templates/.agents/skills/watch-pr/SKILL.en.md +24 -14
  336. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +25 -15
  337. package/templates/.agents/skills/watch-pr/config/verify.json +1 -2
  338. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +2 -2
  339. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +2 -2
  340. package/templates/.agents/templates/task.en.md +6 -1
  341. package/templates/.agents/templates/task.zh-CN.md +6 -1
  342. package/templates/.claude/commands/analyze-task.en.md +1 -1
  343. package/templates/.claude/commands/analyze-task.zh-CN.md +1 -1
  344. package/templates/.claude/commands/block-task.en.md +1 -1
  345. package/templates/.claude/commands/block-task.zh-CN.md +1 -1
  346. package/templates/.claude/commands/cancel-task.en.md +1 -1
  347. package/templates/.claude/commands/cancel-task.zh-CN.md +1 -1
  348. package/templates/.claude/commands/check-task.en.md +1 -1
  349. package/templates/.claude/commands/check-task.zh-CN.md +1 -1
  350. package/templates/.claude/commands/code-task.en.md +1 -1
  351. package/templates/.claude/commands/code-task.zh-CN.md +1 -1
  352. package/templates/.claude/commands/commit.en.md +1 -0
  353. package/templates/.claude/commands/commit.zh-CN.md +1 -0
  354. package/templates/.claude/commands/complete-manual-validation.en.md +1 -1
  355. package/templates/.claude/commands/complete-manual-validation.zh-CN.md +1 -1
  356. package/templates/.claude/commands/complete-task.en.md +1 -1
  357. package/templates/.claude/commands/complete-task.zh-CN.md +1 -1
  358. package/templates/.claude/commands/create-pr.en.md +1 -1
  359. package/templates/.claude/commands/create-pr.zh-CN.md +1 -1
  360. package/templates/.claude/commands/plan-task.en.md +1 -1
  361. package/templates/.claude/commands/plan-task.zh-CN.md +1 -1
  362. package/templates/.claude/commands/review-analysis.en.md +1 -1
  363. package/templates/.claude/commands/review-analysis.zh-CN.md +1 -1
  364. package/templates/.claude/commands/review-code.en.md +1 -1
  365. package/templates/.claude/commands/review-code.zh-CN.md +1 -1
  366. package/templates/.claude/commands/review-plan.en.md +1 -1
  367. package/templates/.claude/commands/review-plan.zh-CN.md +1 -1
  368. package/templates/.claude/commands/watch-pr.en.md +1 -1
  369. package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
  370. package/templates/.gemini/commands/_project_/analyze-task.en.toml +2 -0
  371. package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +2 -0
  372. package/templates/.gemini/commands/_project_/block-task.en.toml +2 -0
  373. package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +2 -0
  374. package/templates/.gemini/commands/_project_/cancel-task.en.toml +2 -0
  375. package/templates/.gemini/commands/_project_/cancel-task.zh-CN.toml +2 -0
  376. package/templates/.gemini/commands/_project_/check-task.en.toml +2 -0
  377. package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +2 -0
  378. package/templates/.gemini/commands/_project_/code-task.en.toml +2 -0
  379. package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +2 -0
  380. package/templates/.gemini/commands/_project_/commit.en.toml +4 -0
  381. package/templates/.gemini/commands/_project_/commit.zh-CN.toml +4 -0
  382. package/templates/.gemini/commands/_project_/complete-manual-validation.en.toml +2 -0
  383. package/templates/.gemini/commands/_project_/complete-manual-validation.zh-CN.toml +2 -0
  384. package/templates/.gemini/commands/_project_/complete-task.en.toml +2 -0
  385. package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +2 -0
  386. package/templates/.gemini/commands/_project_/create-pr.en.toml +2 -0
  387. package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +2 -0
  388. package/templates/.gemini/commands/_project_/plan-task.en.toml +2 -0
  389. package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +2 -0
  390. package/templates/.gemini/commands/_project_/review-analysis.en.toml +2 -0
  391. package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +2 -0
  392. package/templates/.gemini/commands/_project_/review-code.en.toml +2 -0
  393. package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +2 -0
  394. package/templates/.gemini/commands/_project_/review-plan.en.toml +2 -0
  395. package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +2 -0
  396. package/templates/.gemini/commands/_project_/watch-pr.en.toml +2 -0
  397. package/templates/.gemini/commands/_project_/watch-pr.zh-CN.toml +2 -0
  398. package/templates/.git-hooks/check-large-files.cjs +92 -0
  399. package/templates/.git-hooks/check-version-format.sh +5 -1
  400. package/templates/.git-hooks/pre-commit +1 -0
  401. package/templates/.opencode/commands/analyze-task.en.md +1 -1
  402. package/templates/.opencode/commands/analyze-task.zh-CN.md +1 -1
  403. package/templates/.opencode/commands/check-task.en.md +1 -1
  404. package/templates/.opencode/commands/check-task.zh-CN.md +1 -1
  405. package/templates/.opencode/commands/code-task.en.md +1 -1
  406. package/templates/.opencode/commands/code-task.zh-CN.md +1 -1
  407. package/templates/.opencode/commands/commit.en.md +2 -0
  408. package/templates/.opencode/commands/commit.zh-CN.md +2 -0
  409. package/templates/.opencode/commands/complete-task.en.md +1 -1
  410. package/templates/.opencode/commands/complete-task.zh-CN.md +1 -1
  411. package/templates/.opencode/commands/plan-task.en.md +1 -1
  412. package/templates/.opencode/commands/plan-task.zh-CN.md +1 -1
  413. package/templates/.opencode/commands/review-analysis.en.md +1 -1
  414. package/templates/.opencode/commands/review-analysis.zh-CN.md +1 -1
  415. package/templates/.opencode/commands/review-code.en.md +1 -1
  416. package/templates/.opencode/commands/review-code.zh-CN.md +1 -1
  417. package/templates/.opencode/commands/review-plan.en.md +1 -1
  418. package/templates/.opencode/commands/review-plan.zh-CN.md +1 -1
  419. package/templates/.agents/scripts/platform-adapters/platform-sync.github.js +0 -40
  420. package/templates/.agents/scripts/platform-adapters/platform-sync.js +0 -13
  421. package/templates/.agents/scripts/review-diff-fingerprint.js +0 -170
  422. package/templates/.agents/scripts/workflow-warnings.js +0 -290
  423. package/templates/.agents/skills/code-task/scripts/detect-mode.js +0 -257
  424. package/templates/.agents/skills/release/scripts/manage-milestones.github.sh +0 -80
  425. package/templates/.agents/skills/release/scripts/manage-milestones.sh +0 -6
@@ -0,0 +1,906 @@
1
+ // frontmatter, ledger, Git snapshot and platform domains are imported below.
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import process from "node:process";
5
+ import { execFileSync } from "node:child_process";
6
+ import { fileURLToPath } from "node:url";
7
+ import { extractReviewBaseline, extractReviewDiffFingerprint, extractReviewedSnapshotTree, findAuthoritativeReviewCodeArtifact, parseReviewVerdict, resolvePostReviewGlobs } from "./verification-review.js";
8
+ import { check as checkPlatformSync } from "../platform/verification-sync.js";
9
+ import { check as checkRequiredChecks } from "../platform/verification-required.js";
10
+ import { parseTypedTaskFrontmatter } from "./frontmatter.js";
11
+ import { parseLedger } from "./ledger.js";
12
+ import { loadVerificationConfig } from "./verification-config.js";
13
+ import { snapshotReview } from "../git/review-snapshot.js";
14
+ const TASK_ENUMS = {
15
+ type: ["feature", "bugfix", "refactor", "docs", "chore"],
16
+ workflow: ["feature-development", "bug-fix", "refactoring"],
17
+ status: ["active", "blocked", "completed"]
18
+ };
19
+ const DEFAULT_REQUIRED_FIELDS = [
20
+ "id",
21
+ "type",
22
+ "workflow",
23
+ "status",
24
+ "created_at",
25
+ "updated_at",
26
+ "agent_infra_version",
27
+ "current_step",
28
+ "assigned_to"
29
+ ];
30
+ const DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?$/;
31
+ const AGENT_INFRA_VERSION_PATTERN = /^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
32
+ const ACTIVITY_LOG_PATTERN = /^- (\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?) — \*\*(.+?)\*\* by (.+?) — (.+)$/;
33
+ // Start markers (action suffixed with ` [started]`) are excluded from the
34
+ // "latest action" / freshness computation so a step's in-flight marker never
35
+ // satisfies a skill's expected_action_pattern; the matching done entry does.
36
+ const ACTIVITY_LOG_STARTED_RE = /\s*\[started\]\s*$/;
37
+ const BRANCH_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
38
+ // Review disagreement ledger (see .agents/rules/review-handshake.md).
39
+ const LEDGER_SECTION_NAMES = ["审查分歧账本", "Review Disagreement Ledger"];
40
+ const LEDGER_STATUSES = new Set([
41
+ "open",
42
+ "accepted",
43
+ "adjusted",
44
+ "refuted",
45
+ "cannot-judge",
46
+ "confirmed",
47
+ "needs-human-decision",
48
+ "closed",
49
+ "human-decided"
50
+ ]);
51
+ const LEDGER_TERMINAL_OK = new Set(["confirmed", "closed", "human-decided"]);
52
+ const DEFAULT_MAX_HANDSHAKE_ROUNDS = 3;
53
+ const POST_REVIEW_COMMIT_STAGE = "post-review-commit";
54
+ const SHA_PATTERN = /^[0-9a-f]{7,40}$/i;
55
+ const WORKFLOW_WARNING_SECTION_NAMES = ["工作流告警", "Workflow Warnings"];
56
+ const WORKFLOW_WARNING_STATUSES = new Set(["open", "resolved", "ignored"]);
57
+ const WORKFLOW_WARNING_SEVERITIES = new Set(["IMPORTANT", "ACTION_REQUIRED"]);
58
+ const WORKFLOW_WARNING_ID_PATTERN = /^WW-\d+$/;
59
+ const scriptPath = fileURLToPath(import.meta.url);
60
+ let repoRoot = path.resolve(path.dirname(scriptPath), "..", "..");
61
+ const PLATFORM_ADAPTERS = {
62
+ "platform-sync": checkPlatformSync,
63
+ "platform-sync-preflight": (context, shared) => ({ ...checkPlatformSync(context, shared), type: "platform-sync-preflight" }),
64
+ "required-checks": checkRequiredChecks
65
+ };
66
+ const OPTIONAL_PLATFORM_CHECKS = new Set(["platform-sync"]);
67
+ const sharedUtils = {
68
+ loadTask,
69
+ getCheckedRequirements,
70
+ normalizeContent,
71
+ isBlank,
72
+ escapeRegExp,
73
+ passResult,
74
+ failResult,
75
+ blockedResult,
76
+ safeStat,
77
+ parseIssueNumber,
78
+ parsePrNumber
79
+ };
80
+ function runCheck(type, context, shared) {
81
+ switch (type) {
82
+ case "task-meta":
83
+ return checkTaskMeta(context);
84
+ case "artifact":
85
+ return checkArtifact(context);
86
+ case "implementation-input":
87
+ return checkImplementationInput(context);
88
+ case "activity-log":
89
+ return checkActivityLog(context);
90
+ case "completion-checklist":
91
+ return checkCompletionChecklist(context);
92
+ case "review-ledger":
93
+ return checkReviewLedger(context);
94
+ case "review-fact":
95
+ return checkReviewFact(context);
96
+ case "post-review-commit":
97
+ return checkPostReviewCommit(context);
98
+ default: {
99
+ const adapter = PLATFORM_ADAPTERS[type];
100
+ if (!adapter) {
101
+ if (OPTIONAL_PLATFORM_CHECKS.has(type)) {
102
+ return passResult(type, `Skipped: no platform adapter registered for '${type}'`);
103
+ }
104
+ return failResult(type, `Unsupported check type '${type}'.`);
105
+ }
106
+ return adapter(context, shared);
107
+ }
108
+ }
109
+ }
110
+ // === Check Functions ===
111
+ function checkTaskMeta({ taskDir, config }) {
112
+ const task = loadTask(taskDir);
113
+ if (!task.ok) {
114
+ return failResult("task-meta", task.message);
115
+ }
116
+ const metadata = task.metadata;
117
+ const requiredFields = config.required_fields || DEFAULT_REQUIRED_FIELDS;
118
+ const missingFields = requiredFields.filter((field) => isBlank(metadata[field]));
119
+ const blockingMissingFields = missingFields.filter((field) => field !== "agent_infra_version");
120
+ const warnings = [];
121
+ if (missingFields.includes("agent_infra_version")) {
122
+ warnings.push("field 'agent_infra_version' missing — historical task or skipped version stamp");
123
+ }
124
+ if (blockingMissingFields.length > 0) {
125
+ return failResult("task-meta", `Missing required fields: ${blockingMissingFields.join(", ")}`);
126
+ }
127
+ if (!isBlank(metadata.agent_infra_version) &&
128
+ metadata.agent_infra_version !== "unknown" &&
129
+ !AGENT_INFRA_VERSION_PATTERN.test(metadata.agent_infra_version)) {
130
+ return failResult("task-meta", `Invalid agent_infra_version: ${metadata.agent_infra_version}`);
131
+ }
132
+ const invalidDates = ["created_at", "updated_at", "completed_at", "blocked_at", "cancelled_at"]
133
+ .filter((field) => !isBlank(metadata[field]) && !DATE_TIME_PATTERN.test(metadata[field]));
134
+ if (invalidDates.length > 0) {
135
+ return failResult("task-meta", `Invalid date format in: ${invalidDates.join(", ")}`);
136
+ }
137
+ for (const [field, allowedValues] of Object.entries(TASK_ENUMS)) {
138
+ if (!isBlank(metadata[field]) && !allowedValues.includes(metadata[field])) {
139
+ return failResult("task-meta", `Invalid ${field}: ${metadata[field]}`);
140
+ }
141
+ }
142
+ const branchValidationError = validateTaskBranch(metadata);
143
+ if (branchValidationError) {
144
+ return failResult("task-meta", branchValidationError);
145
+ }
146
+ const warningValidationErrors = validateWorkflowWarnings(task.content);
147
+ if (warningValidationErrors.length > 0) {
148
+ return failResult("task-meta", `Invalid Workflow Warnings: ${warningValidationErrors.join("; ")}`);
149
+ }
150
+ const expectedStep = config.expected_step;
151
+ if (expectedStep && metadata.current_step !== expectedStep) {
152
+ return failResult("task-meta", `Expected current_step '${expectedStep}', got '${metadata.current_step || "(empty)"}'`);
153
+ }
154
+ const expectedStatus = config.expected_status;
155
+ if (expectedStatus && metadata.status !== expectedStatus) {
156
+ return failResult("task-meta", `Expected status '${expectedStatus}', got '${metadata.status || "(empty)"}'`);
157
+ }
158
+ if (config.require_issue_number && !parseIssueNumber(metadata.issue_number)) {
159
+ return failResult("task-meta", "Expected a valid issue_number in task metadata");
160
+ }
161
+ if (config.require_completed_at && isBlank(metadata.completed_at)) {
162
+ return failResult("task-meta", "Expected completed_at to be present");
163
+ }
164
+ if (config.require_blocked_at && isBlank(metadata.blocked_at)) {
165
+ return failResult("task-meta", "Expected blocked_at to be present");
166
+ }
167
+ if (config.require_cancelled_at && isBlank(metadata.cancelled_at)) {
168
+ return failResult("task-meta", "Expected cancelled_at to be present");
169
+ }
170
+ if (config.require_start_date && isBlank(metadata.start_date)) {
171
+ return failResult("task-meta", "Expected start_date to be present");
172
+ }
173
+ if (config.require_target_date && isBlank(metadata.target_date)) {
174
+ return failResult("task-meta", "Expected target_date to be present");
175
+ }
176
+ if (config.match_task_dir !== false) {
177
+ const expectedTaskId = path.basename(taskDir);
178
+ if (metadata.id !== expectedTaskId) {
179
+ return failResult("task-meta", `Task id '${metadata.id}' does not match directory '${expectedTaskId}'`);
180
+ }
181
+ }
182
+ const warningSuffix = warnings.length > 0 ? `; warnings: ${warnings.join("; ")}` : "";
183
+ return passResult("task-meta", `Task metadata valid (${requiredFields.length} required fields checked${warningSuffix})`, warnings);
184
+ }
185
+ function validateTaskBranch(metadata) {
186
+ if (isBlank(metadata.branch)) {
187
+ return null;
188
+ }
189
+ const projectName = loadProjectName();
190
+ const expectedPrefix = projectName ? `${projectName}-${metadata.type}-` : "";
191
+ if (expectedPrefix && !String(metadata.branch).startsWith(expectedPrefix)) {
192
+ return `Invalid branch: expected prefix '${expectedPrefix}', got '${metadata.branch}'`;
193
+ }
194
+ const slug = expectedPrefix ? String(metadata.branch).slice(expectedPrefix.length) : String(metadata.branch);
195
+ if (!BRANCH_SLUG_PATTERN.test(slug)) {
196
+ return `Invalid branch: '${metadata.branch}' must use kebab-case suffixes`;
197
+ }
198
+ return null;
199
+ }
200
+ function loadProjectName() {
201
+ const configPath = path.join(repoRoot, ".agents", ".airc.json");
202
+ if (!fs.existsSync(configPath)) {
203
+ return "";
204
+ }
205
+ try {
206
+ const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
207
+ return String(config.project || "").trim();
208
+ }
209
+ catch {
210
+ return "";
211
+ }
212
+ }
213
+ function loadReviewConfig() {
214
+ const configPath = path.join(repoRoot, ".agents", ".airc.json");
215
+ if (!fs.existsSync(configPath)) {
216
+ return {};
217
+ }
218
+ try {
219
+ const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
220
+ return config.review && typeof config.review === "object" ? config.review : {};
221
+ }
222
+ catch {
223
+ return {};
224
+ }
225
+ }
226
+ function checkArtifact({ taskDir, config, artifactFile }) {
227
+ const resolvedArtifact = resolveArtifactPath(taskDir, config.file_pattern, artifactFile);
228
+ if (!resolvedArtifact.ok) {
229
+ return failResult("artifact", resolvedArtifact.message);
230
+ }
231
+ const artifactPath = resolvedArtifact.path;
232
+ const stat = safeStat(artifactPath);
233
+ if (!stat) {
234
+ return failResult("artifact", `Artifact not found: ${path.basename(artifactPath)}`);
235
+ }
236
+ if (stat.size === 0) {
237
+ return failResult("artifact", `Artifact is empty: ${path.basename(artifactPath)}`);
238
+ }
239
+ const content = fs.readFileSync(artifactPath, "utf8");
240
+ const requiredSections = config.required_sections || [];
241
+ const missingSections = requiredSections.filter((section) => !new RegExp(`^##\\s+${escapeRegExp(section)}\\s*$`, "m").test(content));
242
+ if (missingSections.length > 0) {
243
+ return failResult("artifact", `${path.basename(artifactPath)} is missing sections: ${missingSections.join(", ")}`);
244
+ }
245
+ const requiredPatterns = config.required_patterns || [];
246
+ for (const pattern of requiredPatterns) {
247
+ if (!new RegExp(pattern, "m").test(content)) {
248
+ return failResult("artifact", `${path.basename(artifactPath)} is missing required pattern: ${pattern}`);
249
+ }
250
+ }
251
+ return passResult("artifact", `${path.basename(artifactPath)} passed (${requiredSections.length} sections)`);
252
+ }
253
+ function checkImplementationInput({ taskDir, artifactFile }) {
254
+ const task = loadTask(taskDir);
255
+ if (!task.ok)
256
+ return failResult("implementation-input", task.message);
257
+ if (!artifactFile)
258
+ return failResult("implementation-input", "Artifact file is required");
259
+ const artifactPath = path.join(taskDir, artifactFile);
260
+ if (!safeStat(artifactPath)?.isFile())
261
+ return failResult("implementation-input", `Artifact not found: ${artifactFile}`);
262
+ const inputSection = getSectionContent(task.content, ["实现输入", "Implementation Inputs"]);
263
+ const rows = [];
264
+ if (inputSection) {
265
+ const table = inputSection.split(/\r?\n/).filter((line) => line.trim().startsWith("|"));
266
+ const cells = (line) => line.split("|").slice(1, -1).map((cell) => cell.trim());
267
+ const expected = ["id", "ledger_id", "decision_evidence", "stage", "needs_implementation", "decided_at", "status", "consumed_by"];
268
+ if (table.length < 2 || JSON.stringify(cells(table[0])) !== JSON.stringify(expected)) {
269
+ return failResult("implementation-input", "Implementation Inputs table schema is invalid");
270
+ }
271
+ const seen = new Set();
272
+ for (const line of table.slice(2)) {
273
+ const row = cells(line);
274
+ if (row.length !== 8 || !/^II-[1-9]\d*$/.test(row[0]) || seen.has(row[0])) {
275
+ return failResult("implementation-input", "Implementation Inputs table contains an invalid or duplicate id");
276
+ }
277
+ seen.add(row[0]);
278
+ rows.push({ id: row[0], ledgerId: row[1], evidence: row[2], stage: row[3], needs: row[4], status: row[6], consumedBy: row[7] });
279
+ }
280
+ }
281
+ const logSection = getSectionContent(task.content, ["活动日志", "Activity Log"]);
282
+ const doneActions = logSection.split(/\r?\n/).flatMap((line) => {
283
+ const match = line.trim().match(ACTIVITY_LOG_PATTERN);
284
+ return match && !ACTIVITY_LOG_STARTED_RE.test(match[2]) ? [match[2]] : [];
285
+ });
286
+ const latestAction = doneActions.at(-1) || "";
287
+ const actionDecision = /(?:Code Task|Code) \(Round \d+, decision (II-[1-9]\d*)\)/.exec(latestAction)?.[1] || null;
288
+ const report = fs.readFileSync(artifactPath, "utf8");
289
+ const reportSection = getSectionContent(report, ["实现输入", "Implementation Input"]);
290
+ if (!reportSection)
291
+ return failResult("implementation-input", "Implementation Input report section not found");
292
+ const field = (zh, en) => {
293
+ const pattern = "^- \\*\\*(?:" + escapeRegExp(zh) + "|" + escapeRegExp(en) + ")\\*\\*[::]\\s*`?([^`\\n]+)`?\\s*$";
294
+ const match = new RegExp(pattern, "m").exec(reportSection);
295
+ return match?.[1]?.trim() || "";
296
+ };
297
+ const reportInput = field("裁决输入", "Decision Input");
298
+ const reportLedger = field("账本 ID", "Ledger ID");
299
+ const reportEvidence = field("裁决证据", "Decision Evidence");
300
+ if (!actionDecision) {
301
+ if (reportInput && reportInput !== "N/A") {
302
+ return failResult("implementation-input", "Non-decision code action must report Decision Input as N/A");
303
+ }
304
+ return passResult("implementation-input", "Non-decision implementation input identity is consistent");
305
+ }
306
+ if (reportInput !== actionDecision) {
307
+ return failResult("implementation-input", `Report decision input '${reportInput}' does not match Activity Log ${actionDecision}`);
308
+ }
309
+ const matches = rows.filter((row) => row.id === actionDecision);
310
+ if (matches.length !== 1)
311
+ return failResult("implementation-input", `${actionDecision} is missing or duplicated in task table`);
312
+ const row = matches[0];
313
+ if (row.stage !== "code" || row.needs !== "true" || row.status !== "consumed" || row.consumedBy !== artifactFile || !row.evidence) {
314
+ return failResult("implementation-input", `${actionDecision} is not a consumed input for ${artifactFile}`);
315
+ }
316
+ if (reportLedger !== row.ledgerId || reportEvidence !== row.evidence) {
317
+ return failResult("implementation-input", `${actionDecision} report identity does not match task table evidence`);
318
+ }
319
+ return passResult("implementation-input", `${actionDecision} matches Activity Log, report, and task table`);
320
+ }
321
+ function checkActivityLog({ taskDir, config }) {
322
+ const task = loadTask(taskDir);
323
+ if (!task.ok) {
324
+ return failResult("activity-log", task.message);
325
+ }
326
+ const logSection = getSectionContent(task.content, ["活动日志", "Activity Log"]);
327
+ if (!logSection) {
328
+ return failResult("activity-log", "Activity Log section not found");
329
+ }
330
+ const entries = logSection
331
+ .split(/\r?\n/)
332
+ .map((line) => line.trim())
333
+ .filter((line) => line.startsWith("- "));
334
+ if (entries.length === 0) {
335
+ return failResult("activity-log", "Activity Log has no entries");
336
+ }
337
+ let previousTimestamp = "";
338
+ let latestAction = "";
339
+ let latestTimestamp = "";
340
+ for (const entry of entries) {
341
+ const match = entry.match(ACTIVITY_LOG_PATTERN);
342
+ if (!match) {
343
+ return failResult("activity-log", `Invalid Activity Log entry format: ${entry}`);
344
+ }
345
+ const [, timestamp, action] = match;
346
+ if (previousTimestamp && timestamp < previousTimestamp) {
347
+ return failResult("activity-log", "Activity Log timestamps are not in ascending order");
348
+ }
349
+ previousTimestamp = timestamp;
350
+ // Ascending order is checked over every entry, but a `[started]` marker is
351
+ // not a terminal action: keep latestAction/latestTimestamp on the most
352
+ // recent done entry so expected_action_pattern sees it.
353
+ if (!ACTIVITY_LOG_STARTED_RE.test(action)) {
354
+ latestTimestamp = timestamp;
355
+ latestAction = action;
356
+ }
357
+ }
358
+ if (config.expected_action_pattern && !new RegExp(config.expected_action_pattern).test(latestAction)) {
359
+ return failResult("activity-log", `Latest action '${latestAction}' does not match '${config.expected_action_pattern}'`);
360
+ }
361
+ return passResult("activity-log", `Latest entry '${latestAction}' at ${latestTimestamp}`);
362
+ }
363
+ function checkCompletionChecklist({ taskDir, config }) {
364
+ const task = loadTask(taskDir);
365
+ if (!task.ok) {
366
+ return failResult("completion-checklist", task.message);
367
+ }
368
+ const checklist = getSectionContent(task.content, ["完成检查清单", "Completion Checklist"]);
369
+ if (!checklist) {
370
+ return failResult("completion-checklist", "Completion Checklist section not found");
371
+ }
372
+ const items = checklist
373
+ .split(/\r?\n/)
374
+ .map((line) => line.trim())
375
+ .filter((line) => /^- \[(?: |x|X)\] .+$/.test(line));
376
+ if (items.length === 0) {
377
+ return failResult("completion-checklist", "Completion Checklist has no checkbox items");
378
+ }
379
+ if (config.require_all_checked) {
380
+ const unchecked = items
381
+ .map((line) => line.match(/^- \[ \] (.+)$/))
382
+ .filter(Boolean)
383
+ .map((match) => match[1].trim());
384
+ if (unchecked.length > 0) {
385
+ return failResult("completion-checklist", `Completion Checklist has unchecked items: ${unchecked.join(", ")}`);
386
+ }
387
+ }
388
+ return passResult("completion-checklist", `Completion Checklist valid (${items.length} items checked)`);
389
+ }
390
+ function splitMarkdownTableRow(line) {
391
+ let value = String(line || "").trim();
392
+ if (!value.startsWith("|")) {
393
+ return [];
394
+ }
395
+ value = value.replace(/^\|/, "").replace(/\|$/, "");
396
+ const cells = [];
397
+ let cell = "";
398
+ for (let index = 0; index < value.length; index += 1) {
399
+ const char = value[index];
400
+ if (char === "|" && !isEscapedAt(value, index)) {
401
+ cells.push(unescapeMarkdownTableCell(cell.trim()));
402
+ cell = "";
403
+ continue;
404
+ }
405
+ cell += char;
406
+ }
407
+ cells.push(unescapeMarkdownTableCell(cell.trim()));
408
+ return cells;
409
+ }
410
+ function unescapeMarkdownTableCell(value) {
411
+ let output = "";
412
+ for (let index = 0; index < value.length; index += 1) {
413
+ const char = value[index];
414
+ const next = value[index + 1];
415
+ if (char === "\\" && (next === "\\" || next === "|")) {
416
+ output += next;
417
+ index += 1;
418
+ continue;
419
+ }
420
+ output += char;
421
+ }
422
+ return output;
423
+ }
424
+ function isEscapedAt(value, index) {
425
+ let backslashes = 0;
426
+ for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
427
+ backslashes += 1;
428
+ }
429
+ return backslashes % 2 === 1;
430
+ }
431
+ function parseWorkflowWarningRows(section) {
432
+ const rows = [];
433
+ for (const rawLine of String(section || "").split(/\r?\n/)) {
434
+ const cells = splitMarkdownTableRow(rawLine);
435
+ if (cells.length === 0) {
436
+ continue;
437
+ }
438
+ if ((cells[0] || "").toLowerCase() === "id") {
439
+ continue;
440
+ }
441
+ if (cells.every((cell) => /^:?-{3,}:?$/.test(cell))) {
442
+ continue;
443
+ }
444
+ rows.push(cells);
445
+ }
446
+ return rows;
447
+ }
448
+ function validateWorkflowWarnings(content) {
449
+ const section = getSectionContent(content, WORKFLOW_WARNING_SECTION_NAMES);
450
+ if (!section.trim()) {
451
+ return [];
452
+ }
453
+ const rows = parseWorkflowWarningRows(section);
454
+ const errors = [];
455
+ for (const cells of rows) {
456
+ if (cells.length < 11) {
457
+ errors.push(`malformed row (expected 11 columns): ${cells.join(" | ")}`);
458
+ continue;
459
+ }
460
+ const [id, time, step, severity, code, status, target, message, action, resolvedAt, resolution] = cells;
461
+ if (!WORKFLOW_WARNING_ID_PATTERN.test(id)) {
462
+ errors.push(`${id || "(empty id)"}: invalid id`);
463
+ }
464
+ if (!DATE_TIME_PATTERN.test(time)) {
465
+ errors.push(`${id}: invalid time '${time}'`);
466
+ }
467
+ if (isBlank(step)) {
468
+ errors.push(`${id}: step is required`);
469
+ }
470
+ if (!WORKFLOW_WARNING_SEVERITIES.has(severity)) {
471
+ errors.push(`${id}: illegal severity '${severity}'`);
472
+ }
473
+ if (isBlank(code)) {
474
+ errors.push(`${id}: code is required`);
475
+ }
476
+ if (!WORKFLOW_WARNING_STATUSES.has(status)) {
477
+ errors.push(`${id}: illegal status '${status}'`);
478
+ }
479
+ if (isBlank(target)) {
480
+ errors.push(`${id}: target is required`);
481
+ }
482
+ if (isBlank(message)) {
483
+ errors.push(`${id}: message is required`);
484
+ }
485
+ if (status === "open" && isBlank(action)) {
486
+ errors.push(`${id}: open warning requires action`);
487
+ }
488
+ if ((status === "resolved" || status === "ignored") && (isBlank(resolvedAt) || isBlank(resolution))) {
489
+ errors.push(`${id}: ${status} warning requires resolved_at and resolution`);
490
+ }
491
+ }
492
+ return errors;
493
+ }
494
+ function resolveReviewSetting(config, key, fallback) {
495
+ if (config && config[key] !== undefined && config[key] !== null) {
496
+ return config[key];
497
+ }
498
+ const reviewConfig = loadReviewConfig();
499
+ if (reviewConfig[key] !== undefined && reviewConfig[key] !== null) {
500
+ return reviewConfig[key];
501
+ }
502
+ return fallback;
503
+ }
504
+ function checkReviewLedger({ taskDir, config }) {
505
+ const task = loadTask(taskDir);
506
+ if (!task.ok) {
507
+ return failResult("review-ledger", task.message);
508
+ }
509
+ const section = getSectionContent(task.content, LEDGER_SECTION_NAMES);
510
+ if (!section.trim()) {
511
+ return passResult("review-ledger", "No disagreement ledger section; treated as no open disagreements");
512
+ }
513
+ let rows;
514
+ try {
515
+ rows = parseLedger(task.content).map((row) => [
516
+ row.id, row.stage, row.round, row.severity, row.status, row.evidence
517
+ ]);
518
+ }
519
+ catch (error) {
520
+ return failResult("review-ledger", `Invalid disagreement ledger: ${error instanceof Error ? error.message : String(error)}`);
521
+ }
522
+ if (rows.length === 0) {
523
+ return passResult("review-ledger", "Disagreement ledger has no entries");
524
+ }
525
+ const stageScope = Array.isArray(config.stage_scope) ? config.stage_scope : null;
526
+ const maxRounds = Number(resolveReviewSetting(config, "max_handshake_rounds", DEFAULT_MAX_HANDSHAKE_ROUNDS));
527
+ const problems = [];
528
+ let inScopeCount = 0;
529
+ for (const cells of rows) {
530
+ if (cells.length < 6) {
531
+ problems.push(`malformed row (expected 6 columns): ${cells.join(" | ")}`);
532
+ continue;
533
+ }
534
+ const [id, stage, roundRaw, , status, evidence] = cells;
535
+ const stageScoped = stageScope ? stageScope.includes(stage) : true;
536
+ // post-review-commit exemption rows are consumed by the post-review-commit
537
+ // check, not enforced here.
538
+ if (stage === POST_REVIEW_COMMIT_STAGE) {
539
+ continue;
540
+ }
541
+ if (!stageScoped) {
542
+ continue;
543
+ }
544
+ inScopeCount += 1;
545
+ if (!LEDGER_STATUSES.has(status)) {
546
+ problems.push(`${id}: illegal status '${status}'`);
547
+ continue;
548
+ }
549
+ if (status !== "open" && evidence === "") {
550
+ problems.push(`${id}: status '${status}' requires evidence`);
551
+ }
552
+ const round = Number.parseInt(roundRaw, 10);
553
+ if (Number.isFinite(round) &&
554
+ round >= maxRounds &&
555
+ !LEDGER_TERMINAL_OK.has(status) &&
556
+ status !== "needs-human-decision") {
557
+ problems.push(`${id}: round ${round} reached limit ${maxRounds} without convergence; escalate to needs-human-decision`);
558
+ }
559
+ if (!LEDGER_TERMINAL_OK.has(status)) {
560
+ problems.push(`${id}: unresolved (status '${status}')`);
561
+ }
562
+ }
563
+ if (problems.length > 0) {
564
+ return failResult("review-ledger", `Unclosed/invalid disagreements: ${problems.join("; ")}`);
565
+ }
566
+ const scopeLabel = stageScope ? ` for stages [${stageScope.join(", ")}]` : "";
567
+ return passResult("review-ledger", `Disagreement ledger clean (${inScopeCount} in-scope entries terminal${scopeLabel})`);
568
+ }
569
+ function checkPostReviewCommit({ taskDir, config }) {
570
+ const reviewArtifact = findAuthoritativeReviewCodeArtifact(taskDir);
571
+ if (!reviewArtifact.ok) {
572
+ return passResult("post-review-commit", "No review-code artifact; check inactive");
573
+ }
574
+ let gitRoot;
575
+ try {
576
+ gitRoot = execFileSync("git", ["-C", taskDir, "rev-parse", "--show-toplevel"], { encoding: "utf8" }).trim();
577
+ }
578
+ catch {
579
+ return blockedResult("post-review-commit", "git unavailable or task directory is not inside a git repository");
580
+ }
581
+ const task = loadTask(taskDir);
582
+ const content = fs.readFileSync(reviewArtifact.path, "utf8");
583
+ const lastReviewedCommit = task.ok ? (task.metadata.last_reviewed_commit || "").trim() : "";
584
+ const baselineSource = resolvePostReviewBaseline({
585
+ gitRoot,
586
+ lastReviewedCommit,
587
+ reviewArtifact: reviewArtifact.fileName
588
+ });
589
+ if (!baselineSource.ok) {
590
+ return baselineSource.result;
591
+ }
592
+ const sha = baselineSource.sha;
593
+ const globs = resolvePostReviewGlobs(config, loadReviewConfig());
594
+ let commits;
595
+ try {
596
+ const out = execFileSync("git", ["-C", gitRoot, "rev-list", `${sha}..HEAD`, "--", ...globs], { encoding: "utf8" });
597
+ commits = out.split(/\r?\n/).filter((line) => line.trim() !== "");
598
+ }
599
+ catch {
600
+ return blockedResult("post-review-commit", `git rev-list failed for baseline ${sha}; manual inspection required`);
601
+ }
602
+ if (commits.length === 0) {
603
+ return passResult("post-review-commit", `No post-review commits to code/rule paths since ${sha.slice(0, 8)}`);
604
+ }
605
+ let exempt = false;
606
+ try {
607
+ exempt = task.ok && parseLedger(task.content).some((row) => row.stage === POST_REVIEW_COMMIT_STAGE && row.status === "human-decided");
608
+ }
609
+ catch {
610
+ return failResult("post-review-commit", "Invalid disagreement ledger");
611
+ }
612
+ if (exempt) {
613
+ return passResult("post-review-commit", `${commits.length} post-review commit(s) covered by a human-decided exemption`);
614
+ }
615
+ return failResult("post-review-commit", `${commits.length} commit(s) to code/rule paths after reviewed commit ${sha.slice(0, 8)}; re-run review-code or record a human-decided exemption`);
616
+ }
617
+ function checkReviewFact({ taskDir, artifactFile }) {
618
+ const resolvedArtifact = resolveArtifactPath(taskDir, "review-code.md|review-code-r{N}.md", artifactFile);
619
+ if (!resolvedArtifact.ok) {
620
+ return failResult("review-fact", resolvedArtifact.message);
621
+ }
622
+ const task = loadTask(taskDir);
623
+ if (!task.ok) {
624
+ return failResult("review-fact", task.message);
625
+ }
626
+ const content = fs.readFileSync(resolvedArtifact.path, "utf8");
627
+ const verdict = parseReviewVerdict(content);
628
+ const reviewBaseline = extractReviewBaseline(content);
629
+ const reviewedFingerprint = extractReviewDiffFingerprint(content);
630
+ const reviewedTree = extractReviewedSnapshotTree(content);
631
+ if (!["通过", "需要修改", "拒绝", "Approved", "Changes Requested", "Rejected"].includes(verdict)) {
632
+ return failResult("review-fact", `Unsupported review verdict '${verdict}'`);
633
+ }
634
+ let gitRoot;
635
+ let head;
636
+ let baseline;
637
+ try {
638
+ gitRoot = execFileSync("git", ["-C", taskDir, "rev-parse", "--show-toplevel"], { encoding: "utf8" }).trim();
639
+ head = execFileSync("git", ["-C", gitRoot, "rev-parse", "HEAD"], { encoding: "utf8" }).trim();
640
+ baseline = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewBaseline}^{commit}`], { encoding: "utf8" }).trim();
641
+ }
642
+ catch {
643
+ return blockedResult("review-fact", `Unable to resolve review baseline '${reviewBaseline}' in the task repository; re-run review-code`);
644
+ }
645
+ if (baseline !== head) {
646
+ return failResult("review-fact", `Review baseline ${baseline.slice(0, 8)} does not match current HEAD ${head.slice(0, 8)}; re-run review-code`);
647
+ }
648
+ let actualSnapshot;
649
+ try {
650
+ actualSnapshot = snapshotReview({ cwd: gitRoot, mode: "worktree", baseline, globs: resolvePostReviewGlobs({}, loadReviewConfig()) });
651
+ }
652
+ catch {
653
+ return blockedResult("review-fact", `Unable to recompute reviewed diff fingerprint from baseline ${baseline.slice(0, 8)}; re-run review-code`);
654
+ }
655
+ if (actualSnapshot.fingerprint !== reviewedFingerprint) {
656
+ return failResult("review-fact", `Reviewed diff fingerprint does not match the current worktree for baseline ${baseline.slice(0, 8)}; re-run review-code`);
657
+ }
658
+ if (!reviewedTree || actualSnapshot.tree !== reviewedTree) {
659
+ return failResult("review-fact", `Reviewed snapshot tree does not match the current worktree for baseline ${baseline.slice(0, 8)}; re-run review-code`);
660
+ }
661
+ if (["通过", "Approved"].includes(verdict)) {
662
+ const lastReviewedCommit = String(task.metadata.last_reviewed_commit || "").trim();
663
+ const cleanSnapshot = actualSnapshot.tree === execFileSync("git", ["-C", gitRoot, "rev-parse", `${baseline}^{tree}`], { encoding: "utf8" }).trim();
664
+ if (cleanSnapshot && lastReviewedCommit !== baseline) {
665
+ return failResult("review-fact", `Approved clean review must set task last_reviewed_commit to baseline ${baseline.slice(0, 8)}`);
666
+ }
667
+ if (!cleanSnapshot && lastReviewedCommit) {
668
+ return failResult("review-fact", "Approved review with uncommitted changes must remain unanchored until commit");
669
+ }
670
+ }
671
+ return passResult("review-fact", `Review fact valid for ${path.basename(resolvedArtifact.path)} at ${baseline.slice(0, 8)}`);
672
+ }
673
+ function resolvePostReviewBaseline({ gitRoot, lastReviewedCommit, reviewArtifact }) {
674
+ if (SHA_PATTERN.test(lastReviewedCommit) && gitCommitExists(gitRoot, lastReviewedCommit)) {
675
+ return { ok: true, sha: lastReviewedCommit };
676
+ }
677
+ return {
678
+ ok: false,
679
+ result: blockedResult("post-review-commit", `${reviewArtifact}: reviewed snapshot was not anchored to a valid commit; re-run commit or review-code`)
680
+ };
681
+ }
682
+ function gitCommitExists(gitRoot, sha) {
683
+ try {
684
+ execFileSync("git", ["-C", gitRoot, "cat-file", "-e", `${sha}^{commit}`], { encoding: "utf8" });
685
+ return true;
686
+ }
687
+ catch {
688
+ return false;
689
+ }
690
+ }
691
+ // === File & Config Loaders ===
692
+ function loadTask(taskDir) {
693
+ const taskPath = path.join(taskDir, "task.md");
694
+ if (!fs.existsSync(taskPath)) {
695
+ return { ok: false, message: `Task file not found: ${taskPath}` };
696
+ }
697
+ const content = fs.readFileSync(taskPath, "utf8");
698
+ let metadata;
699
+ try {
700
+ metadata = Object.fromEntries(Object.entries(parseTypedTaskFrontmatter(content)).map(([key, value]) => [key, value === null ? "" : String(value)]));
701
+ }
702
+ catch {
703
+ return { ok: false, message: "task.md frontmatter not found or invalid" };
704
+ }
705
+ return { ok: true, content, metadata };
706
+ }
707
+ function resolveArtifactPath(taskDir, filePattern, artifactFile) {
708
+ if (artifactFile) {
709
+ return { ok: true, path: path.join(taskDir, artifactFile) };
710
+ }
711
+ if (!filePattern) {
712
+ return { ok: false, message: "Artifact file is required for this check" };
713
+ }
714
+ const entries = fs.existsSync(taskDir) ? fs.readdirSync(taskDir) : [];
715
+ const matches = [];
716
+ for (const pattern of filePattern.split("|").map((value) => value.trim()).filter(Boolean)) {
717
+ const regex = new RegExp(`^${escapePattern(pattern)}$`);
718
+ for (const entry of entries) {
719
+ const match = entry.match(regex);
720
+ if (!match) {
721
+ continue;
722
+ }
723
+ matches.push({
724
+ fileName: entry,
725
+ round: match[1] ? Number(match[1]) : 0
726
+ });
727
+ }
728
+ }
729
+ if (matches.length === 0) {
730
+ return { ok: false, message: `No artifact matched pattern '${filePattern}'` };
731
+ }
732
+ matches.sort((left, right) => right.round - left.round || left.fileName.localeCompare(right.fileName));
733
+ return { ok: true, path: path.join(taskDir, matches[0].fileName) };
734
+ }
735
+ function getSectionContent(content, names) {
736
+ const lines = content.split(/\r?\n/);
737
+ function visibleHeadings() {
738
+ const headings = [];
739
+ let fence = null;
740
+ for (let index = 0; index < lines.length; index += 1) {
741
+ const line = lines[index];
742
+ if (fence) {
743
+ const closer = line.match(/^ {0,3}(`+|~+)\s*$/);
744
+ if (closer && closer[1][0] === fence.character && closer[1].length >= fence.length) {
745
+ fence = null;
746
+ }
747
+ continue;
748
+ }
749
+ const opener = line.match(/^ {0,3}(`{3,}|~{3,})(?:[^`~].*)?$/);
750
+ if (opener) {
751
+ fence = { character: opener[1][0], length: opener[1].length };
752
+ continue;
753
+ }
754
+ if (line.startsWith("## ")) {
755
+ headings.push({ index, text: line.trim() });
756
+ }
757
+ }
758
+ return headings;
759
+ }
760
+ const headings = visibleHeadings();
761
+ for (const name of names) {
762
+ const heading = `## ${name}`;
763
+ const position = headings.findIndex((item) => item.text === heading);
764
+ if (position === -1) {
765
+ continue;
766
+ }
767
+ const startIndex = headings[position].index;
768
+ const endIndex = headings[position + 1]?.index ?? lines.length;
769
+ return lines.slice(startIndex + 1, endIndex).join("\n").trim();
770
+ }
771
+ return "";
772
+ }
773
+ function getCheckedRequirements(content) {
774
+ const section = getSectionContent(content, ["需求", "Requirements"]);
775
+ if (!section) {
776
+ return [];
777
+ }
778
+ return section
779
+ .split(/\r?\n/)
780
+ .map((line) => line.trim())
781
+ .map((line) => line.match(/^- \[x\] (.+)$/i))
782
+ .filter(Boolean)
783
+ .map((match) => match[1].trim());
784
+ }
785
+ function parseIssueNumber(value) {
786
+ if (isBlank(value) || value === "N/A") {
787
+ return null;
788
+ }
789
+ const match = String(value).match(/\d+/);
790
+ return match ? Number(match[0]) : null;
791
+ }
792
+ function parsePrNumber(value) {
793
+ return parseIssueNumber(value);
794
+ }
795
+ // === Utilities ===
796
+ function normalizeContent(text) {
797
+ return String(text || "")
798
+ .replace(/\r\n/g, "\n")
799
+ .replace(/\n{3,}/g, "\n\n")
800
+ .trim();
801
+ }
802
+ function interpolate(template, taskDir, artifactFile) {
803
+ const artifactStem = artifactFile ? path.basename(artifactFile, path.extname(artifactFile)) : "";
804
+ return template
805
+ .replace(/\{task-id\}/g, path.basename(taskDir))
806
+ .replace(/\{artifact-stem\}/g, artifactStem);
807
+ }
808
+ function summarizeGate(checks) {
809
+ if (checks.some((check) => check.status === "blocked")) {
810
+ return "blocked";
811
+ }
812
+ if (checks.some((check) => check.status === "fail")) {
813
+ return "fail";
814
+ }
815
+ return "pass";
816
+ }
817
+ function summarizeChecks(checks) {
818
+ const counts = {
819
+ pass: checks.filter((check) => check.status === "pass").length,
820
+ fail: checks.filter((check) => check.status === "fail").length,
821
+ blocked: checks.filter((check) => check.status === "blocked").length
822
+ };
823
+ if (counts.blocked > 0) {
824
+ return `${counts.pass} passed, ${counts.fail} failed, ${counts.blocked} blocked`;
825
+ }
826
+ return `${counts.pass} passed, ${counts.fail} failed`;
827
+ }
828
+ function buildAction(gate, checks) {
829
+ if (gate === "pass") {
830
+ return "All declared checks passed";
831
+ }
832
+ const firstFailure = checks.find((check) => check.status !== "pass");
833
+ if (!firstFailure) {
834
+ return "Review validation output";
835
+ }
836
+ if (gate === "blocked") {
837
+ return `Resolve blocked ${firstFailure.type} check and re-run gate`;
838
+ }
839
+ return `Fix ${firstFailure.type} issues and re-run gate`;
840
+ }
841
+ function passResult(type, message, warnings = []) {
842
+ const result = { type, status: "pass", message };
843
+ if (warnings.length > 0) {
844
+ result.warnings = warnings;
845
+ }
846
+ return result;
847
+ }
848
+ function failResult(type, message, failType = "check_failed") {
849
+ return { type, status: "fail", fail_type: failType, message };
850
+ }
851
+ function blockedResult(type, message, failType = "network_error") {
852
+ return { type, status: "blocked", fail_type: failType, message };
853
+ }
854
+ function safeStat(filePath) {
855
+ try {
856
+ return fs.statSync(filePath);
857
+ }
858
+ catch {
859
+ return null;
860
+ }
861
+ }
862
+ function escapePattern(pattern) {
863
+ return escapeRegExp(pattern)
864
+ .replace(/\\\{N\\\}/g, "(\\d+)");
865
+ }
866
+ function escapeRegExp(value) {
867
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
868
+ }
869
+ function isBlank(value) {
870
+ return value === undefined || value === null || String(value).trim() === "";
871
+ }
872
+ function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: requestedChecks, repositoryRoot }) {
873
+ if (repositoryRoot)
874
+ repoRoot = path.resolve(repositoryRoot);
875
+ else {
876
+ let cursor = path.resolve(taskDir);
877
+ while (path.dirname(cursor) !== cursor && !fs.existsSync(path.join(cursor, ".agents")))
878
+ cursor = path.dirname(cursor);
879
+ if (fs.existsSync(path.join(cursor, ".agents")))
880
+ repoRoot = cursor;
881
+ }
882
+ const verifyConfig = loadVerificationConfig(repoRoot, skillName);
883
+ const shared = { ...sharedUtils, repoRoot };
884
+ if (mode === "gate") {
885
+ const checks = [];
886
+ for (const [type, checkConfig] of Object.entries(verifyConfig.checks || {})) {
887
+ if (checkConfig === null)
888
+ continue;
889
+ const result = runCheck(type, { skillName, taskDir: path.resolve(taskDir), artifactFile, config: checkConfig }, shared);
890
+ checks.push(result);
891
+ if (result.status === "blocked")
892
+ break;
893
+ }
894
+ const gate = summarizeGate(checks);
895
+ return { gate, skill: skillName, checks, summary: summarizeChecks(checks), action: buildAction(gate, checks) };
896
+ }
897
+ const type = requestedChecks[0];
898
+ const config = (verifyConfig.checks || {})[type];
899
+ if (config === undefined)
900
+ return { skill: skillName, ...failResult(type, `Unknown check type '${type}' for skill '${skillName}'.`) };
901
+ if (config === null)
902
+ return { skill: skillName, ...passResult(type, `Check '${type}' is disabled for skill '${skillName}'.`) };
903
+ return { skill: skillName, ...runCheck(type, { skillName, taskDir: path.resolve(taskDir), artifactFile, config }, shared) };
904
+ }
905
+ export { verifyInProcess };
906
+ //# sourceMappingURL=verification-engine.js.map