@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
@@ -1,3 +1,4 @@
1
+ // frontmatter, ledger, Git snapshot and platform domains are imported below.
1
2
  import fs from "node:fs";
2
3
  import path from "node:path";
3
4
  import process from "node:process";
@@ -11,13 +12,13 @@ import {
11
12
  findAuthoritativeReviewCodeArtifact,
12
13
  parseReviewVerdict,
13
14
  resolvePostReviewGlobs
14
- } from "./lib/post-review-commit.js";
15
-
16
- const EXIT_CODE = {
17
- pass: 0,
18
- fail: 1,
19
- blocked: 2
20
- };
15
+ } from "./verification-review.ts";
16
+ import { check as checkPlatformSync } from "../platform/verification-sync.ts";
17
+ import { check as checkRequiredChecks } from "../platform/verification-required.ts";
18
+ import { parseTypedTaskFrontmatter } from "./frontmatter.ts";
19
+ import { parseLedger } from "./ledger.ts";
20
+ import { loadVerificationConfig } from "./verification-config.ts";
21
+ import { snapshotReview } from "../git/review-snapshot.ts";
21
22
 
22
23
  const TASK_ENUMS = {
23
24
  type: ["feature", "bugfix", "refactor", "docs", "chore"],
@@ -37,7 +38,6 @@ const DEFAULT_REQUIRED_FIELDS = [
37
38
  "assigned_to"
38
39
  ];
39
40
 
40
- const DEFAULT_FRESHNESS_MINUTES = 30;
41
41
  const DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?$/;
42
42
  const AGENT_INFRA_VERSION_PATTERN = /^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
43
43
  const ACTIVITY_LOG_PATTERN = /^- (\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?) — \*\*(.+?)\*\* by (.+?) — (.+)$/;
@@ -70,25 +70,14 @@ const WORKFLOW_WARNING_SEVERITIES = new Set(["IMPORTANT", "ACTION_REQUIRED"]);
70
70
  const WORKFLOW_WARNING_ID_PATTERN = /^WW-\d+$/;
71
71
 
72
72
  const scriptPath = fileURLToPath(import.meta.url);
73
- const repoRoot = path.resolve(path.dirname(scriptPath), "..", "..");
73
+ let repoRoot = path.resolve(path.dirname(scriptPath), "..", "..");
74
74
 
75
- const PLATFORM_ADAPTERS = {};
75
+ const PLATFORM_ADAPTERS: Record<string, (context: any, shared: any) => any> = {
76
+ "platform-sync": checkPlatformSync,
77
+ "platform-sync-preflight": (context: any, shared: any) => ({ ...checkPlatformSync(context, shared), type: "platform-sync-preflight" }),
78
+ "required-checks": checkRequiredChecks
79
+ };
76
80
  const OPTIONAL_PLATFORM_CHECKS = new Set(["platform-sync"]);
77
- const adaptersDir = path.join(path.dirname(scriptPath), "platform-adapters");
78
-
79
- if (fs.existsSync(adaptersDir)) {
80
- for (const file of fs.readdirSync(adaptersDir)) {
81
- if (!file.endsWith(".js")) {
82
- continue;
83
- }
84
-
85
- const adapterName = path.basename(file, ".js");
86
- const mod = await import(new URL(`./platform-adapters/${file}`, import.meta.url));
87
- if (typeof mod.check === "function") {
88
- PLATFORM_ADAPTERS[adapterName] = mod.check;
89
- }
90
- }
91
- }
92
81
 
93
82
  const sharedUtils = {
94
83
  loadTask,
@@ -101,125 +90,17 @@ const sharedUtils = {
101
90
  blockedResult,
102
91
  safeStat,
103
92
  parseIssueNumber,
104
- parsePrNumber,
105
- repoRoot
93
+ parsePrNumber
106
94
  };
107
95
 
108
- // === CLI Entry ===
109
-
110
- function main(argv) {
111
- const [mode, ...rest] = argv;
112
-
113
- if (mode === "gate") {
114
- runGate(rest);
115
- return;
116
- }
117
-
118
- if (mode === "check") {
119
- runSingleCheck(rest);
120
- return;
121
- }
122
-
123
- printUsageAndExit();
124
- }
125
-
126
- function runGate(args) {
127
- const { value: formatValue, rest: positional } = extractOption(args, "--format");
128
- const format = normalizeFormat(formatValue);
129
- const [skillName, taskDirArg, artifactFile] = positional;
130
-
131
- if (!skillName || !taskDirArg) {
132
- printUsageAndExit();
133
- }
134
-
135
- const taskDir = path.resolve(taskDirArg);
136
- const verifyConfig = loadVerifyConfig(skillName);
137
- const checks = [];
138
-
139
- for (const [type, checkConfig] of Object.entries(verifyConfig.checks || {})) {
140
- if (checkConfig === null) {
141
- continue;
142
- }
143
-
144
- const result = runCheck(type, {
145
- skillName,
146
- taskDir,
147
- artifactFile,
148
- config: checkConfig
149
- });
150
-
151
- checks.push(result);
152
-
153
- if (result.status === "blocked") {
154
- break;
155
- }
156
- }
157
-
158
- const gate = summarizeGate(checks);
159
- const output = {
160
- gate,
161
- skill: skillName,
162
- checks,
163
- summary: summarizeChecks(checks),
164
- action: buildAction(gate, checks)
165
- };
166
-
167
- writeOutput(output, format);
168
- process.exit(EXIT_CODE[gate]);
169
- }
170
-
171
- function runSingleCheck(args) {
172
- const { value: formatValue, rest: formatArgs } = extractOption(args, "--format");
173
- const format = normalizeFormat(formatValue);
174
- const { value: skillName, rest: positional } = extractOption(formatArgs, "--skill");
175
-
176
- if (!skillName) {
177
- printUsageAndExit();
178
- }
179
-
180
- const [type, taskDirArg, artifactFile] = positional;
181
-
182
- if (!type || !taskDirArg) {
183
- printUsageAndExit();
184
- }
185
-
186
- const verifyConfig = loadVerifyConfig(skillName);
187
- const config = (verifyConfig.checks || {})[type];
188
-
189
- if (config === undefined) {
190
- failUsage(`Unknown check type '${type}' for skill '${skillName}'.`);
191
- }
192
-
193
- if (config === null) {
194
- writeOutput({
195
- type,
196
- skill: skillName,
197
- status: "pass",
198
- message: `Check '${type}' is disabled for skill '${skillName}'.`
199
- }, format);
200
- process.exit(0);
201
- }
202
-
203
- const result = runCheck(type, {
204
- skillName,
205
- taskDir: path.resolve(taskDirArg),
206
- artifactFile,
207
- config
208
- });
209
-
210
- writeOutput({
211
- skill: skillName,
212
- ...result
213
- }, format);
214
- process.exit(EXIT_CODE[result.status] ?? 1);
215
- }
216
-
217
- function runCheck(type, context) {
96
+ function runCheck(type: any, context: any, shared: any): any {
218
97
  switch (type) {
219
98
  case "task-meta":
220
99
  return checkTaskMeta(context);
221
100
  case "artifact":
222
101
  return checkArtifact(context);
102
+ case "implementation-input":
103
+ return checkImplementationInput(context);
223
104
  case "activity-log":
224
105
  return checkActivityLog(context);
225
106
  case "completion-checklist":
@@ -240,14 +121,14 @@ function runCheck(type, context) {
240
121
  return failResult(type, `Unsupported check type '${type}'.`);
241
122
  }
242
123
 
243
- return adapter(context, sharedUtils);
124
+ return adapter(context, shared);
244
125
  }
245
126
  }
246
127
  }
247
128
 
248
129
  // === Check Functions ===
249
130
 
250
- function checkTaskMeta({ taskDir, config }) {
131
+ function checkTaskMeta({ taskDir, config }: any): any {
251
132
  const task = loadTask(taskDir);
252
133
  if (!task.ok) {
253
134
  return failResult("task-meta", task.message);
@@ -255,8 +136,8 @@ function checkTaskMeta({ taskDir, config }) {
255
136
 
256
137
  const metadata = task.metadata;
257
138
  const requiredFields = config.required_fields || DEFAULT_REQUIRED_FIELDS;
258
- const missingFields = requiredFields.filter((field) => isBlank(metadata[field]));
259
- const blockingMissingFields = missingFields.filter((field) => field !== "agent_infra_version");
139
+ const missingFields = requiredFields.filter((field: any) => isBlank(metadata[field]));
140
+ const blockingMissingFields = missingFields.filter((field: any) => field !== "agent_infra_version");
260
141
  const warnings = [];
261
142
  if (missingFields.includes("agent_infra_version")) {
262
143
  warnings.push("field 'agent_infra_version' missing — historical task or skipped version stamp");
@@ -349,11 +230,11 @@ function checkTaskMeta({ taskDir, config }) {
349
230
  return passResult(
350
231
  "task-meta",
351
232
  `Task metadata valid (${requiredFields.length} required fields checked${warningSuffix})`,
352
- warnings
233
+ warnings as string[]
353
234
  );
354
235
  }
355
236
 
356
- function validateTaskBranch(metadata) {
237
+ function validateTaskBranch(metadata: any): any {
357
238
  if (isBlank(metadata.branch)) {
358
239
  return null;
359
240
  }
@@ -373,7 +254,7 @@ function validateTaskBranch(metadata) {
373
254
  return null;
374
255
  }
375
256
 
376
- function loadProjectName() {
257
+ function loadProjectName(): any {
377
258
  const configPath = path.join(repoRoot, ".agents", ".airc.json");
378
259
  if (!fs.existsSync(configPath)) {
379
260
  return "";
@@ -387,7 +268,7 @@ function loadProjectName() {
387
268
  }
388
269
  }
389
270
 
390
- function loadReviewConfig() {
271
+ function loadReviewConfig(): any {
391
272
  const configPath = path.join(repoRoot, ".agents", ".airc.json");
392
273
  if (!fs.existsSync(configPath)) {
393
274
  return {};
@@ -401,7 +282,7 @@ function loadReviewConfig() {
401
282
  }
402
283
  }
403
284
 
404
- function checkArtifact({ taskDir, config, artifactFile }) {
285
+ function checkArtifact({ taskDir, config, artifactFile }: any): any {
405
286
  const resolvedArtifact = resolveArtifactPath(taskDir, config.file_pattern, artifactFile);
406
287
  if (!resolvedArtifact.ok) {
407
288
  return failResult("artifact", resolvedArtifact.message);
@@ -420,7 +301,7 @@ function checkArtifact({ taskDir, config, artifactFile }) {
420
301
  const content = fs.readFileSync(artifactPath, "utf8");
421
302
  const requiredSections = config.required_sections || [];
422
303
  const missingSections = requiredSections.filter(
423
- (section) => !new RegExp(`^##\\s+${escapeRegExp(section)}\\s*$`, "m").test(content)
304
+ (section: any) => !new RegExp(`^##\\s+${escapeRegExp(section)}\\s*$`, "m").test(content)
424
305
  );
425
306
 
426
307
  if (missingSections.length > 0) {
@@ -437,22 +318,80 @@ function checkArtifact({ taskDir, config, artifactFile }) {
437
318
  }
438
319
  }
439
320
 
440
- const freshnessMinutes = Number(config.freshness_minutes ?? DEFAULT_FRESHNESS_MINUTES);
441
- const ageMinutes = (Date.now() - stat.mtimeMs) / 60000;
442
- if (Number.isFinite(freshnessMinutes) && ageMinutes > freshnessMinutes) {
443
- return failResult(
444
- "artifact",
445
- `${path.basename(artifactPath)} is stale (${ageMinutes.toFixed(1)}m old, limit ${freshnessMinutes}m)`
446
- );
447
- }
448
-
449
321
  return passResult(
450
322
  "artifact",
451
- `${path.basename(artifactPath)} passed (${requiredSections.length} sections, ${Math.max(0, freshnessMinutes)}m freshness window)`
323
+ `${path.basename(artifactPath)} passed (${requiredSections.length} sections)`
452
324
  );
453
325
  }
454
326
 
455
- function checkActivityLog({ taskDir, config }) {
327
+ function checkImplementationInput({ taskDir, artifactFile }: any): any {
328
+ const task = loadTask(taskDir);
329
+ if (!task.ok) return failResult("implementation-input", task.message);
330
+ if (!artifactFile) return failResult("implementation-input", "Artifact file is required");
331
+ const artifactPath = path.join(taskDir, artifactFile);
332
+ if (!safeStat(artifactPath)?.isFile()) return failResult("implementation-input", `Artifact not found: ${artifactFile}`);
333
+
334
+ const inputSection = getSectionContent(task.content, ["实现输入", "Implementation Inputs"]);
335
+ const rows = [];
336
+ if (inputSection) {
337
+ const table = inputSection.split(/\r?\n/).filter((line: any) => line.trim().startsWith("|"));
338
+ const cells = (line: any) => line.split("|").slice(1, -1).map((cell: any) => cell.trim());
339
+ const expected = ["id", "ledger_id", "decision_evidence", "stage", "needs_implementation", "decided_at", "status", "consumed_by"];
340
+ if (table.length < 2 || JSON.stringify(cells(table[0])) !== JSON.stringify(expected)) {
341
+ return failResult("implementation-input", "Implementation Inputs table schema is invalid");
342
+ }
343
+ const seen = new Set();
344
+ for (const line of table.slice(2)) {
345
+ const row = cells(line);
346
+ if (row.length !== 8 || !/^II-[1-9]\d*$/.test(row[0]) || seen.has(row[0])) {
347
+ return failResult("implementation-input", "Implementation Inputs table contains an invalid or duplicate id");
348
+ }
349
+ seen.add(row[0]);
350
+ rows.push({ id: row[0], ledgerId: row[1], evidence: row[2], stage: row[3], needs: row[4], status: row[6], consumedBy: row[7] });
351
+ }
352
+ }
353
+
354
+ const logSection = getSectionContent(task.content, ["活动日志", "Activity Log"]);
355
+ const doneActions = logSection.split(/\r?\n/).flatMap((line: any) => {
356
+ const match = line.trim().match(ACTIVITY_LOG_PATTERN);
357
+ return match && !ACTIVITY_LOG_STARTED_RE.test(match[2]) ? [match[2]] : [];
358
+ });
359
+ const latestAction = doneActions.at(-1) || "";
360
+ const actionDecision = /(?:Code Task|Code) \(Round \d+, decision (II-[1-9]\d*)\)/.exec(latestAction)?.[1] || null;
361
+ const report = fs.readFileSync(artifactPath, "utf8");
362
+ const reportSection = getSectionContent(report, ["实现输入", "Implementation Input"]);
363
+ if (!reportSection) return failResult("implementation-input", "Implementation Input report section not found");
364
+ const field = (zh: any, en: any) => {
365
+ const pattern = "^- \\*\\*(?:" + escapeRegExp(zh) + "|" + escapeRegExp(en) + ")\\*\\*[::]\\s*`?([^`\\n]+)`?\\s*$";
366
+ const match = new RegExp(pattern, "m").exec(reportSection);
367
+ return match?.[1]?.trim() || "";
368
+ };
369
+ const reportInput = field("裁决输入", "Decision Input");
370
+ const reportLedger = field("账本 ID", "Ledger ID");
371
+ const reportEvidence = field("裁决证据", "Decision Evidence");
372
+
373
+ if (!actionDecision) {
374
+ if (reportInput && reportInput !== "N/A") {
375
+ return failResult("implementation-input", "Non-decision code action must report Decision Input as N/A");
376
+ }
377
+ return passResult("implementation-input", "Non-decision implementation input identity is consistent");
378
+ }
379
+ if (reportInput !== actionDecision) {
380
+ return failResult("implementation-input", `Report decision input '${reportInput}' does not match Activity Log ${actionDecision}`);
381
+ }
382
+ const matches = rows.filter((row) => row.id === actionDecision);
383
+ if (matches.length !== 1) return failResult("implementation-input", `${actionDecision} is missing or duplicated in task table`);
384
+ const row = matches[0]!;
385
+ if (row.stage !== "code" || row.needs !== "true" || row.status !== "consumed" || row.consumedBy !== artifactFile || !row.evidence) {
386
+ return failResult("implementation-input", `${actionDecision} is not a consumed input for ${artifactFile}`);
387
+ }
388
+ if (reportLedger !== row.ledgerId || reportEvidence !== row.evidence) {
389
+ return failResult("implementation-input", `${actionDecision} report identity does not match task table evidence`);
390
+ }
391
+ return passResult("implementation-input", `${actionDecision} matches Activity Log, report, and task table`);
392
+ }
393
+
394
+ function checkActivityLog({ taskDir, config }: any): any {
456
395
  const task = loadTask(taskDir);
457
396
  if (!task.ok) {
458
397
  return failResult("activity-log", task.message);
@@ -465,8 +404,8 @@ function checkActivityLog({ taskDir, config }) {
465
404
 
466
405
  const entries = logSection
467
406
  .split(/\r?\n/)
468
- .map((line) => line.trim())
469
- .filter((line) => line.startsWith("- "));
407
+ .map((line: any) => line.trim())
408
+ .filter((line: any) => line.startsWith("- "));
470
409
 
471
410
  if (entries.length === 0) {
472
411
  return failResult("activity-log", "Activity Log has no entries");
@@ -490,7 +429,7 @@ function checkActivityLog({ taskDir, config }) {
490
429
  previousTimestamp = timestamp;
491
430
  // Ascending order is checked over every entry, but a `[started]` marker is
492
431
  // not a terminal action: keep latestAction/latestTimestamp on the most
493
- // recent done entry so expected_action_pattern and freshness see it.
432
+ // recent done entry so expected_action_pattern sees it.
494
433
  if (!ACTIVITY_LOG_STARTED_RE.test(action)) {
495
434
  latestTimestamp = timestamp;
496
435
  latestAction = action;
@@ -504,21 +443,10 @@ function checkActivityLog({ taskDir, config }) {
504
443
  );
505
444
  }
506
445
 
507
- const freshnessMinutes = Number(config.freshness_minutes ?? DEFAULT_FRESHNESS_MINUTES);
508
- if (Number.isFinite(freshnessMinutes)) {
509
- const ageMinutes = minutesSinceTimestamp(latestTimestamp);
510
- if (ageMinutes > freshnessMinutes) {
511
- return failResult(
512
- "activity-log",
513
- `Latest Activity Log entry is stale (${ageMinutes.toFixed(1)}m old, limit ${freshnessMinutes}m)`
514
- );
515
- }
516
- }
517
-
518
446
  return passResult("activity-log", `Latest entry '${latestAction}' at ${latestTimestamp}`);
519
447
  }
520
448
 
521
- function checkCompletionChecklist({ taskDir, config }) {
449
+ function checkCompletionChecklist({ taskDir, config }: any): any {
522
450
  const task = loadTask(taskDir);
523
451
  if (!task.ok) {
524
452
  return failResult("completion-checklist", task.message);
@@ -531,8 +459,8 @@ function checkCompletionChecklist({ taskDir, config }) {
531
459
 
532
460
  const items = checklist
533
461
  .split(/\r?\n/)
534
- .map((line) => line.trim())
535
- .filter((line) => /^- \[(?: |x|X)\] .+$/.test(line));
462
+ .map((line: any) => line.trim())
463
+ .filter((line: any) => /^- \[(?: |x|X)\] .+$/.test(line));
536
464
 
537
465
  if (items.length === 0) {
538
466
  return failResult("completion-checklist", "Completion Checklist has no checkbox items");
@@ -540,9 +468,9 @@ function checkCompletionChecklist({ taskDir, config }) {
540
468
 
541
469
  if (config.require_all_checked) {
542
470
  const unchecked = items
543
- .map((line) => line.match(/^- \[ \] (.+)$/))
471
+ .map((line: any) => line.match(/^- \[ \] (.+)$/))
544
472
  .filter(Boolean)
545
- .map((match) => match[1].trim());
473
+ .map((match: any) => match[1].trim());
546
474
 
547
475
  if (unchecked.length > 0) {
548
476
  return failResult(
@@ -555,27 +483,7 @@ function checkCompletionChecklist({ taskDir, config }) {
555
483
  return passResult("completion-checklist", `Completion Checklist valid (${items.length} items checked)`);
556
484
  }
557
485
 
558
- function parseLedgerRows(section) {
559
- const rows = [];
560
- for (const rawLine of String(section || "").split(/\r?\n/)) {
561
- const line = rawLine.trim();
562
- if (!line.startsWith("|")) {
563
- continue;
564
- }
565
- if (/^\|[\s:|-]+\|?$/.test(line)) {
566
- continue; // separator row
567
- }
568
- const inner = line.replace(/^\|/, "").replace(/\|$/, "");
569
- const cells = inner.split("|").map((cell) => cell.trim());
570
- if ((cells[0] || "").toLowerCase() === "id") {
571
- continue; // header row
572
- }
573
- rows.push(cells);
574
- }
575
- return rows;
576
- }
577
-
578
- function splitMarkdownTableRow(line) {
486
+ function splitMarkdownTableRow(line: any): any {
579
487
  let value = String(line || "").trim();
580
488
  if (!value.startsWith("|")) {
581
489
  return [];
@@ -597,7 +505,7 @@ function splitMarkdownTableRow(line) {
597
505
  return cells;
598
506
  }
599
507
 
600
- function unescapeMarkdownTableCell(value) {
508
+ function unescapeMarkdownTableCell(value: any): any {
601
509
  let output = "";
602
510
  for (let index = 0; index < value.length; index += 1) {
603
511
  const char = value[index];
@@ -612,7 +520,7 @@ function unescapeMarkdownTableCell(value) {
612
520
  return output;
613
521
  }
614
522
 
615
- function isEscapedAt(value, index) {
523
+ function isEscapedAt(value: any, index: any): any {
616
524
  let backslashes = 0;
617
525
  for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
618
526
  backslashes += 1;
@@ -620,7 +528,7 @@ function isEscapedAt(value, index) {
620
528
  return backslashes % 2 === 1;
621
529
  }
622
530
 
623
- function parseWorkflowWarningRows(section) {
531
+ function parseWorkflowWarningRows(section: any): any {
624
532
  const rows = [];
625
533
  for (const rawLine of String(section || "").split(/\r?\n/)) {
626
534
  const cells = splitMarkdownTableRow(rawLine);
@@ -630,7 +538,7 @@ function parseWorkflowWarningRows(section) {
630
538
  if ((cells[0] || "").toLowerCase() === "id") {
631
539
  continue;
632
540
  }
633
- if (cells.every((cell) => /^:?-{3,}:?$/.test(cell))) {
541
+ if (cells.every((cell: any) => /^:?-{3,}:?$/.test(cell))) {
634
542
  continue;
635
543
  }
636
544
  rows.push(cells);
@@ -638,7 +546,7 @@ function parseWorkflowWarningRows(section) {
638
546
  return rows;
639
547
  }
640
548
 
641
- function validateWorkflowWarnings(content) {
549
+ function validateWorkflowWarnings(content: any): any {
642
550
  const section = getSectionContent(content, WORKFLOW_WARNING_SECTION_NAMES);
643
551
  if (!section.trim()) {
644
552
  return [];
@@ -686,7 +594,7 @@ function validateWorkflowWarnings(content) {
686
594
  return errors;
687
595
  }
688
596
 
689
- function resolveReviewSetting(config, key, fallback) {
597
+ function resolveReviewSetting(config: any, key: any, fallback: any): any {
690
598
  if (config && config[key] !== undefined && config[key] !== null) {
691
599
  return config[key];
692
600
  }
@@ -697,7 +605,7 @@ function resolveReviewSetting(config, key, fallback) {
697
605
  return fallback;
698
606
  }
699
607
 
700
- function checkReviewLedger({ taskDir, config }) {
608
+ function checkReviewLedger({ taskDir, config }: any): any {
701
609
  const task = loadTask(taskDir);
702
610
  if (!task.ok) {
703
611
  return failResult("review-ledger", task.message);
@@ -708,7 +616,14 @@ function checkReviewLedger({ taskDir, config }) {
708
616
  return passResult("review-ledger", "No disagreement ledger section; treated as no open disagreements");
709
617
  }
710
618
 
711
- const rows = parseLedgerRows(section);
619
+ let rows;
620
+ try {
621
+ rows = parseLedger(task.content).map((row) => [
622
+ row.id, row.stage, row.round, row.severity, row.status, row.evidence
623
+ ]);
624
+ } catch (error) {
625
+ return failResult("review-ledger", `Invalid disagreement ledger: ${error instanceof Error ? error.message : String(error)}`);
626
+ }
712
627
  if (rows.length === 0) {
713
628
  return passResult("review-ledger", "Disagreement ledger has no entries");
714
629
  }
@@ -736,23 +651,23 @@ function checkReviewLedger({ taskDir, config }) {
736
651
  }
737
652
  inScopeCount += 1;
738
653
 
739
- if (!LEDGER_STATUSES.has(status)) {
654
+ if (!LEDGER_STATUSES.has(status!)) {
740
655
  problems.push(`${id}: illegal status '${status}'`);
741
656
  continue;
742
657
  }
743
658
  if (status !== "open" && evidence === "") {
744
659
  problems.push(`${id}: status '${status}' requires evidence`);
745
660
  }
746
- const round = Number.parseInt(roundRaw, 10);
661
+ const round = Number.parseInt(roundRaw!, 10);
747
662
  if (
748
663
  Number.isFinite(round) &&
749
664
  round >= maxRounds &&
750
- !LEDGER_TERMINAL_OK.has(status) &&
665
+ !LEDGER_TERMINAL_OK.has(status!) &&
751
666
  status !== "needs-human-decision"
752
667
  ) {
753
668
  problems.push(`${id}: round ${round} reached limit ${maxRounds} without convergence; escalate to needs-human-decision`);
754
669
  }
755
- if (!LEDGER_TERMINAL_OK.has(status)) {
670
+ if (!LEDGER_TERMINAL_OK.has(status!)) {
756
671
  problems.push(`${id}: unresolved (status '${status}')`);
757
672
  }
758
673
  }
@@ -765,7 +680,7 @@ function checkReviewLedger({ taskDir, config }) {
765
680
  return passResult("review-ledger", `Disagreement ledger clean (${inScopeCount} in-scope entries terminal${scopeLabel})`);
766
681
  }
767
682
 
768
- function checkPostReviewCommit({ taskDir, config }) {
683
+ function checkPostReviewCommit({ taskDir, config }: any): any {
769
684
  const reviewArtifact = findAuthoritativeReviewCodeArtifact(taskDir);
770
685
  if (!reviewArtifact.ok) {
771
686
  return passResult("post-review-commit", "No review-code artifact; check inactive");
@@ -779,7 +694,7 @@ function checkPostReviewCommit({ taskDir, config }) {
779
694
  }
780
695
 
781
696
  const task = loadTask(taskDir);
782
- const content = fs.readFileSync(reviewArtifact.path, "utf8");
697
+ const content = fs.readFileSync(reviewArtifact.path!, "utf8");
783
698
  const lastReviewedCommit = task.ok ? (task.metadata.last_reviewed_commit || "").trim() : "";
784
699
  const baselineSource = resolvePostReviewBaseline({
785
700
  gitRoot,
@@ -804,10 +719,14 @@ function checkPostReviewCommit({ taskDir, config }) {
804
719
  return passResult("post-review-commit", `No post-review commits to code/rule paths since ${sha.slice(0, 8)}`);
805
720
  }
806
721
 
807
- const ledgerSection = task.ok ? getSectionContent(task.content, LEDGER_SECTION_NAMES) : "";
808
- const exempt = parseLedgerRows(ledgerSection).some(
809
- (cells) => cells[1] === POST_REVIEW_COMMIT_STAGE && cells[4] === "human-decided"
810
- );
722
+ let exempt = false;
723
+ try {
724
+ exempt = task.ok && parseLedger(task.content).some(
725
+ (row) => row.stage === POST_REVIEW_COMMIT_STAGE && row.status === "human-decided"
726
+ );
727
+ } catch {
728
+ return failResult("post-review-commit", "Invalid disagreement ledger");
729
+ }
811
730
  if (exempt) {
812
731
  return passResult(
813
732
  "post-review-commit",
@@ -821,7 +740,7 @@ function checkPostReviewCommit({ taskDir, config }) {
821
740
  );
822
741
  }
823
742
 
824
- function checkReviewFact({ taskDir, artifactFile }) {
743
+ function checkReviewFact({ taskDir, artifactFile }: any): any {
825
744
  const resolvedArtifact = resolveArtifactPath(
826
745
  taskDir,
827
746
  "review-code.md|review-code-r{N}.md",
@@ -869,11 +788,7 @@ function checkReviewFact({ taskDir, artifactFile }) {
869
788
 
870
789
  let actualSnapshot;
871
790
  try {
872
- actualSnapshot = JSON.parse(execFileSync(
873
- process.execPath,
874
- [path.join(repoRoot, ".agents", "scripts", "review-diff-fingerprint.js"), "worktree", baseline, "--format", "json"],
875
- { cwd: gitRoot, encoding: "utf8" }
876
- ));
791
+ actualSnapshot = snapshotReview({ cwd: gitRoot, mode: "worktree", baseline, globs: resolvePostReviewGlobs({}, loadReviewConfig()) });
877
792
  } catch {
878
793
  return blockedResult(
879
794
  "review-fact",
@@ -922,7 +837,7 @@ function checkReviewFact({ taskDir, artifactFile }) {
922
837
  );
923
838
  }
924
839
 
925
- function resolvePostReviewBaseline({ gitRoot, lastReviewedCommit, reviewArtifact }) {
840
+ function resolvePostReviewBaseline({ gitRoot, lastReviewedCommit, reviewArtifact }: any): any {
926
841
  if (SHA_PATTERN.test(lastReviewedCommit) && gitCommitExists(gitRoot, lastReviewedCommit)) {
927
842
  return { ok: true, sha: lastReviewedCommit };
928
843
  }
@@ -936,7 +851,7 @@ function resolvePostReviewBaseline({ gitRoot, lastReviewedCommit, reviewArtifact
936
851
  };
937
852
  }
938
853
 
939
- function gitCommitExists(gitRoot, sha) {
854
+ function gitCommitExists(gitRoot: any, sha: any): any {
940
855
  try {
941
856
  execFileSync("git", ["-C", gitRoot, "cat-file", "-e", `${sha}^{commit}`], { encoding: "utf8" });
942
857
  return true;
@@ -947,31 +862,24 @@ function gitCommitExists(gitRoot, sha) {
947
862
 
948
863
  // === File & Config Loaders ===
949
864
 
950
- function loadVerifyConfig(skillName) {
951
- const verifyPath = path.join(repoRoot, ".agents", "skills", skillName, "config", "verify.json");
952
- if (!fs.existsSync(verifyPath)) {
953
- failUsage(`config/verify.json not found for skill '${skillName}'`);
954
- }
955
-
956
- return JSON.parse(fs.readFileSync(verifyPath, "utf8"));
957
- }
958
-
959
- function loadTask(taskDir) {
865
+ function loadTask(taskDir: any): any {
960
866
  const taskPath = path.join(taskDir, "task.md");
961
867
  if (!fs.existsSync(taskPath)) {
962
868
  return { ok: false, message: `Task file not found: ${taskPath}` };
963
869
  }
964
870
 
965
871
  const content = fs.readFileSync(taskPath, "utf8");
966
- const metadata = parseFrontmatter(content);
967
- if (!metadata) {
872
+ let metadata;
873
+ try {
874
+ metadata = Object.fromEntries(Object.entries(parseTypedTaskFrontmatter(content)).map(([key, value]) => [key, value === null ? "" : String(value)]));
875
+ } catch {
968
876
  return { ok: false, message: "task.md frontmatter not found or invalid" };
969
877
  }
970
878
 
971
879
  return { ok: true, content, metadata };
972
880
  }
973
881
 
974
- function resolveArtifactPath(taskDir, filePattern, artifactFile) {
882
+ function resolveArtifactPath(taskDir: any, filePattern: any, artifactFile: any): any {
975
883
  if (artifactFile) {
976
884
  return { ok: true, path: path.join(taskDir, artifactFile) };
977
885
  }
@@ -983,7 +891,7 @@ function resolveArtifactPath(taskDir, filePattern, artifactFile) {
983
891
  const entries = fs.existsSync(taskDir) ? fs.readdirSync(taskDir) : [];
984
892
  const matches = [];
985
893
 
986
- for (const pattern of filePattern.split("|").map((value) => value.trim()).filter(Boolean)) {
894
+ for (const pattern of filePattern.split("|").map((value: any) => value.trim()).filter(Boolean)) {
987
895
  const regex = new RegExp(`^${escapePattern(pattern)}$`);
988
896
  for (const entry of entries) {
989
897
  const match = entry.match(regex);
@@ -1003,33 +911,13 @@ function resolveArtifactPath(taskDir, filePattern, artifactFile) {
1003
911
  }
1004
912
 
1005
913
  matches.sort((left, right) => right.round - left.round || left.fileName.localeCompare(right.fileName));
1006
- return { ok: true, path: path.join(taskDir, matches[0].fileName) };
1007
- }
1008
-
1009
- function parseFrontmatter(content) {
1010
- const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
1011
- if (!match) {
1012
- return null;
1013
- }
1014
-
1015
- const metadata = {};
1016
- for (const line of match[1].split(/\r?\n/)) {
1017
- const parsed = line.match(/^([A-Za-z0-9_]+):\s*(.*)$/);
1018
- if (!parsed) {
1019
- continue;
1020
- }
1021
-
1022
- const [, key, rawValue] = parsed;
1023
- metadata[key] = rawValue.trim().replace(/^['"]|['"]$/g, "");
1024
- }
1025
-
1026
- return metadata;
914
+ return { ok: true, path: path.join(taskDir, matches[0]!.fileName) };
1027
915
  }
1028
916
 
1029
- function getSectionContent(content, names) {
917
+ function getSectionContent(content: any, names: any): any {
1030
918
  const lines = content.split(/\r?\n/);
1031
919
 
1032
- function visibleHeadings() {
920
+ function visibleHeadings(): any {
1033
921
  const headings = [];
1034
922
  let fence = null;
1035
923
  for (let index = 0; index < lines.length; index += 1) {
@@ -1057,11 +945,11 @@ function getSectionContent(content, names) {
1057
945
 
1058
946
  for (const name of names) {
1059
947
  const heading = `## ${name}`;
1060
- const position = headings.findIndex((item) => item.text === heading);
948
+ const position = headings.findIndex((item: any) => item.text === heading);
1061
949
  if (position === -1) {
1062
950
  continue;
1063
951
  }
1064
- const startIndex = headings[position].index;
952
+ const startIndex = headings[position]!.index;
1065
953
  const endIndex = headings[position + 1]?.index ?? lines.length;
1066
954
  return lines.slice(startIndex + 1, endIndex).join("\n").trim();
1067
955
  }
@@ -1069,7 +957,7 @@ function getSectionContent(content, names) {
1069
957
  return "";
1070
958
  }
1071
959
 
1072
- function getCheckedRequirements(content) {
960
+ function getCheckedRequirements(content: any): any {
1073
961
  const section = getSectionContent(content, ["需求", "Requirements"]);
1074
962
  if (!section) {
1075
963
  return [];
@@ -1077,13 +965,13 @@ function getCheckedRequirements(content) {
1077
965
 
1078
966
  return section
1079
967
  .split(/\r?\n/)
1080
- .map((line) => line.trim())
1081
- .map((line) => line.match(/^- \[x\] (.+)$/i))
968
+ .map((line: any) => line.trim())
969
+ .map((line: any) => line.match(/^- \[x\] (.+)$/i))
1082
970
  .filter(Boolean)
1083
- .map((match) => match[1].trim());
971
+ .map((match: any) => match[1].trim());
1084
972
  }
1085
973
 
1086
- function parseIssueNumber(value) {
974
+ function parseIssueNumber(value: any): any {
1087
975
  if (isBlank(value) || value === "N/A") {
1088
976
  return null;
1089
977
  }
@@ -1092,53 +980,43 @@ function parseIssueNumber(value) {
1092
980
  return match ? Number(match[0]) : null;
1093
981
  }
1094
982
 
1095
- function parsePrNumber(value) {
983
+ function parsePrNumber(value: any): any {
1096
984
  return parseIssueNumber(value);
1097
985
  }
1098
986
 
1099
987
  // === Utilities ===
1100
988
 
1101
- function normalizeContent(text) {
989
+ function normalizeContent(text: any): any {
1102
990
  return String(text || "")
1103
991
  .replace(/\r\n/g, "\n")
1104
992
  .replace(/\n{3,}/g, "\n\n")
1105
993
  .trim();
1106
994
  }
1107
995
 
1108
- function minutesSinceTimestamp(timestamp) {
1109
- const normalized = timestamp.includes("T") ? timestamp : timestamp.replace(" ", "T");
1110
- const parsed = Date.parse(normalized);
1111
- if (Number.isNaN(parsed)) {
1112
- return Number.POSITIVE_INFINITY;
1113
- }
1114
-
1115
- return (Date.now() - parsed) / 60000;
1116
- }
1117
-
1118
- function interpolate(template, taskDir, artifactFile) {
996
+ function interpolate(template: any, taskDir: any, artifactFile: any): any {
1119
997
  const artifactStem = artifactFile ? path.basename(artifactFile, path.extname(artifactFile)) : "";
1120
998
  return template
1121
999
  .replace(/\{task-id\}/g, path.basename(taskDir))
1122
1000
  .replace(/\{artifact-stem\}/g, artifactStem);
1123
1001
  }
1124
1002
 
1125
- function summarizeGate(checks) {
1126
- if (checks.some((check) => check.status === "blocked")) {
1003
+ function summarizeGate(checks: any): any {
1004
+ if (checks.some((check: any) => check.status === "blocked")) {
1127
1005
  return "blocked";
1128
1006
  }
1129
1007
 
1130
- if (checks.some((check) => check.status === "fail")) {
1008
+ if (checks.some((check: any) => check.status === "fail")) {
1131
1009
  return "fail";
1132
1010
  }
1133
1011
 
1134
1012
  return "pass";
1135
1013
  }
1136
1014
 
1137
- function summarizeChecks(checks) {
1015
+ function summarizeChecks(checks: any): any {
1138
1016
  const counts = {
1139
- pass: checks.filter((check) => check.status === "pass").length,
1140
- fail: checks.filter((check) => check.status === "fail").length,
1141
- blocked: checks.filter((check) => check.status === "blocked").length
1017
+ pass: checks.filter((check: any) => check.status === "pass").length,
1018
+ fail: checks.filter((check: any) => check.status === "fail").length,
1019
+ blocked: checks.filter((check: any) => check.status === "blocked").length
1142
1020
  };
1143
1021
 
1144
1022
  if (counts.blocked > 0) {
@@ -1148,12 +1026,12 @@ function summarizeChecks(checks) {
1148
1026
  return `${counts.pass} passed, ${counts.fail} failed`;
1149
1027
  }
1150
1028
 
1151
- function buildAction(gate, checks) {
1029
+ function buildAction(gate: any, checks: any): any {
1152
1030
  if (gate === "pass") {
1153
1031
  return "All declared checks passed";
1154
1032
  }
1155
1033
 
1156
- const firstFailure = checks.find((check) => check.status !== "pass");
1034
+ const firstFailure = checks.find((check: any) => check.status !== "pass");
1157
1035
  if (!firstFailure) {
1158
1036
  return "Review validation output";
1159
1037
  }
@@ -1165,47 +1043,23 @@ function buildAction(gate, checks) {
1165
1043
  return `Fix ${firstFailure.type} issues and re-run gate`;
1166
1044
  }
1167
1045
 
1168
- function buildCheckAction(result) {
1169
- if (result.status === "pass") {
1170
- return "Requested check passed";
1171
- }
1172
-
1173
- if (result.status === "blocked") {
1174
- return `Resolve blocked ${result.type} check and re-run check`;
1175
- }
1176
-
1177
- return `Fix ${result.type} issues and re-run check`;
1178
- }
1179
-
1180
- function buildSingleCheckSummary(status) {
1181
- if (status === "pass") {
1182
- return "1 passed, 0 failed";
1183
- }
1184
-
1185
- if (status === "blocked") {
1186
- return "0 passed, 0 failed, 1 blocked";
1187
- }
1188
-
1189
- return "0 passed, 1 failed";
1190
- }
1191
-
1192
- function passResult(type, message, warnings = []) {
1193
- const result = { type, status: "pass", message };
1046
+ function passResult(type: any, message: any, warnings: string[] = []): any {
1047
+ const result: { type: any; status: string; message: any; warnings?: string[] } = { type, status: "pass", message };
1194
1048
  if (warnings.length > 0) {
1195
1049
  result.warnings = warnings;
1196
1050
  }
1197
1051
  return result;
1198
1052
  }
1199
1053
 
1200
- function failResult(type, message, failType = "check_failed") {
1054
+ function failResult(type: any, message: any, failType = "check_failed"): any {
1201
1055
  return { type, status: "fail", fail_type: failType, message };
1202
1056
  }
1203
1057
 
1204
- function blockedResult(type, message, failType = "network_error") {
1058
+ function blockedResult(type: any, message: any, failType = "network_error"): any {
1205
1059
  return { type, status: "blocked", fail_type: failType, message };
1206
1060
  }
1207
1061
 
1208
- function safeStat(filePath) {
1062
+ function safeStat(filePath: any): any {
1209
1063
  try {
1210
1064
  return fs.statSync(filePath);
1211
1065
  } catch {
@@ -1213,105 +1067,44 @@ function safeStat(filePath) {
1213
1067
  }
1214
1068
  }
1215
1069
 
1216
- function escapePattern(pattern) {
1070
+ function escapePattern(pattern: any): any {
1217
1071
  return escapeRegExp(pattern)
1218
1072
  .replace(/\\\{N\\\}/g, "(\\d+)");
1219
1073
  }
1220
1074
 
1221
- function escapeRegExp(value) {
1075
+ function escapeRegExp(value: any): any {
1222
1076
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1223
1077
  }
1224
1078
 
1225
- function isBlank(value) {
1079
+ function isBlank(value: any): any {
1226
1080
  return value === undefined || value === null || String(value).trim() === "";
1227
1081
  }
1228
1082
 
1229
- function extractOption(args, name) {
1230
- const rest = [];
1231
- let value;
1232
-
1233
- for (let index = 0; index < args.length; index += 1) {
1234
- const arg = args[index];
1235
- if (arg === name) {
1236
- value = args[index + 1];
1237
- index += 1;
1238
- continue;
1239
- }
1240
-
1241
- const inlinePrefix = `${name}=`;
1242
- if (arg.startsWith(inlinePrefix)) {
1243
- value = arg.slice(inlinePrefix.length);
1244
- continue;
1245
- }
1246
-
1247
- rest.push(arg);
1248
- }
1249
-
1250
- return { value, rest };
1251
- }
1252
-
1253
- function normalizeFormat(value) {
1254
- return value === "text" ? "text" : "json";
1255
- }
1256
-
1257
- function formatStatusLabel(status) {
1258
- if (status === "fail") {
1259
- return "FAIL";
1083
+ function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: requestedChecks, repositoryRoot }: any): any {
1084
+ if (repositoryRoot) repoRoot = path.resolve(repositoryRoot);
1085
+ else {
1086
+ let cursor = path.resolve(taskDir);
1087
+ while (path.dirname(cursor) !== cursor && !fs.existsSync(path.join(cursor, ".agents"))) cursor = path.dirname(cursor);
1088
+ if (fs.existsSync(path.join(cursor, ".agents"))) repoRoot = cursor;
1260
1089
  }
1261
-
1262
- if (status === "blocked") {
1263
- return "BLOCKED";
1264
- }
1265
-
1266
- return "pass";
1267
- }
1268
-
1269
- function writeOutput(value, format) {
1270
- if (format === "text") {
1271
- writeText(value);
1272
- return;
1273
- }
1274
-
1275
- writeJson(value);
1276
- }
1277
-
1278
- function writeText(value) {
1279
- const lines = [];
1280
-
1281
- if (Array.isArray(value.checks)) {
1282
- lines.push(`Verification: ${value.gate} | Skill: ${value.skill}`);
1283
- lines.push("");
1284
- for (const check of value.checks) {
1285
- lines.push(` [${formatStatusLabel(check.status)}] ${check.type} - ${check.message}`);
1090
+ const verifyConfig = loadVerificationConfig(repoRoot, skillName);
1091
+ const shared = { ...sharedUtils, repoRoot };
1092
+ if (mode === "gate") {
1093
+ const checks = [];
1094
+ for (const [type, checkConfig] of Object.entries(verifyConfig.checks || {})) {
1095
+ if (checkConfig === null) continue;
1096
+ const result = runCheck(type, { skillName, taskDir: path.resolve(taskDir), artifactFile, config: checkConfig }, shared);
1097
+ checks.push(result);
1098
+ if (result.status === "blocked") break;
1286
1099
  }
1287
- lines.push("");
1288
- lines.push(`Result: ${value.summary} - ${value.action}`);
1289
- } else {
1290
- lines.push(`Check: ${value.status} | Skill: ${value.skill} | Type: ${value.type}`);
1291
- lines.push("");
1292
- lines.push(` [${formatStatusLabel(value.status)}] ${value.type} - ${value.message}`);
1293
- lines.push("");
1294
- lines.push(`Result: ${buildSingleCheckSummary(value.status)} - ${buildCheckAction(value)}`);
1100
+ const gate = summarizeGate(checks);
1101
+ return { gate, skill: skillName, checks, summary: summarizeChecks(checks), action: buildAction(gate, checks) };
1295
1102
  }
1296
-
1297
- process.stdout.write(`${lines.join("\n")}\n`);
1298
- }
1299
-
1300
- function writeJson(value) {
1301
- process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
1302
- }
1303
-
1304
- function printUsageAndExit() {
1305
- failUsage(
1306
- "Usage:\n" +
1307
- " node .agents/scripts/validate-artifact.js gate <skill-name> <task-dir> [artifact-file] [--format json|text]\n" +
1308
- " node .agents/scripts/validate-artifact.js check <type> <task-dir> [artifact-file] --skill <skill-name> [--format json|text]"
1309
- );
1310
- }
1311
-
1312
- function failUsage(message) {
1313
- process.stderr.write(`${message}\n`);
1314
- process.exit(1);
1103
+ const type = requestedChecks[0];
1104
+ const config = (verifyConfig.checks || {})[type];
1105
+ if (config === undefined) return { skill: skillName, ...failResult(type, `Unknown check type '${type}' for skill '${skillName}'.`) };
1106
+ if (config === null) return { skill: skillName, ...passResult(type, `Check '${type}' is disabled for skill '${skillName}'.`) };
1107
+ return { skill: skillName, ...runCheck(type, { skillName, taskDir: path.resolve(taskDir), artifactFile, config }, shared) };
1315
1108
  }
1316
1109
 
1317
- main(process.argv.slice(2));
1110
+ export { verifyInProcess };