@fitlab-ai/agent-infra 0.9.13 → 0.9.15

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 (428) hide show
  1. package/README.md +10 -0
  2. package/README.zh-CN.md +10 -0
  3. package/bin/cli.ts +26 -9
  4. package/bin/internal-cli.sh +45 -0
  5. package/dist/bin/cli.js +173 -157
  6. package/dist/bin/internal-cli.js +126 -42
  7. package/dist/lib/agent-client.js +5 -0
  8. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +165 -27
  9. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +3 -2
  10. package/dist/lib/defaults.json +103 -103
  11. package/dist/lib/fs/durable-write.js +37 -0
  12. package/dist/lib/fs/file-lock.js +111 -0
  13. package/dist/lib/host-control/audit.js +19 -0
  14. package/dist/lib/host-control/client.js +142 -0
  15. package/dist/lib/host-control/command.js +49 -0
  16. package/dist/lib/host-control/path.js +160 -0
  17. package/dist/lib/host-control/secure-fs.js +140 -0
  18. package/dist/lib/host-control/server.js +159 -0
  19. package/dist/lib/host-control/service.js +112 -0
  20. package/dist/lib/init.js +11 -2
  21. package/dist/lib/internal/agent-client.js +5 -2
  22. package/dist/lib/internal/cli-route-inventory.js +154 -0
  23. package/dist/lib/internal/codex-lifecycle.js +15 -12
  24. package/dist/lib/internal/codex-sandbox-controller.js +8 -2
  25. package/dist/lib/internal/demo-promotion.js +322 -0
  26. package/dist/lib/internal/demo-transcript.js +454 -0
  27. package/dist/lib/internal/git-workflow.js +10 -6
  28. package/dist/lib/internal/host-control.js +28 -0
  29. package/dist/lib/internal/manual-validation.js +322 -0
  30. package/dist/lib/internal/platform-checks.js +16 -4
  31. package/dist/lib/internal/platform-comment.js +16 -4
  32. package/dist/lib/internal/platform-context.js +4 -1
  33. package/dist/lib/internal/platform-issue.js +12 -4
  34. package/dist/lib/internal/platform-metadata.js +88 -0
  35. package/dist/lib/internal/platform-pr-review.js +16 -3
  36. package/dist/lib/internal/platform-pr.js +42 -14
  37. package/dist/lib/internal/platform-release-notes.js +6 -3
  38. package/dist/lib/internal/platform-security.js +93 -0
  39. package/dist/lib/internal/pr-review-grade.js +14 -3
  40. package/dist/lib/internal/release-workflow.js +82 -89
  41. package/dist/lib/internal/sandbox-control.js +171 -7
  42. package/dist/lib/internal/task-activity.js +13 -4
  43. package/dist/lib/internal/task-artifact.js +19 -107
  44. package/dist/lib/internal/task-context.js +4 -1
  45. package/dist/lib/internal/task-create.js +48 -14
  46. package/dist/lib/internal/task-delivery.js +4 -1
  47. package/dist/lib/internal/task-event.js +38 -35
  48. package/dist/lib/internal/task-finalization.js +4 -1
  49. package/dist/lib/internal/task-invalidation.js +4 -1
  50. package/dist/lib/internal/task-ledger.js +12 -1
  51. package/dist/lib/internal/task-lifecycle.js +4 -1
  52. package/dist/lib/internal/task-operation-registry.js +519 -0
  53. package/dist/lib/internal/task-orchestration.js +12 -0
  54. package/dist/lib/internal/task-override.js +10 -3
  55. package/dist/lib/internal/task-qualification.js +90 -0
  56. package/dist/lib/internal/task-review.js +10 -52
  57. package/dist/lib/internal/task-short-id.js +11 -1
  58. package/dist/lib/internal/task-snapshot.js +4 -1
  59. package/dist/lib/internal/task-validate.js +37 -12
  60. package/dist/lib/internal/task-verify.js +5 -1
  61. package/dist/lib/internal/task-warning.js +8 -1
  62. package/dist/lib/owned-path.js +33 -0
  63. package/dist/lib/platform/check-status.js +11 -0
  64. package/dist/lib/platform/comment-safety.js +229 -0
  65. package/dist/lib/platform/completion-backfill.js +1 -1
  66. package/dist/lib/platform/github-data.js +241 -0
  67. package/dist/lib/platform/github-provider.js +248 -26
  68. package/dist/lib/platform/issue-comments.js +146 -34
  69. package/dist/lib/platform/issues.js +1 -179
  70. package/dist/lib/platform/pr-change-report.js +6 -12
  71. package/dist/lib/platform/pr-checks.js +12 -65
  72. package/dist/lib/platform/pr-summary.js +83 -10
  73. package/dist/lib/platform/provider-contract.d.ts +67 -1
  74. package/dist/lib/platform/provider-contract.js +6 -2
  75. package/dist/lib/platform/provider-validation.js +76 -3
  76. package/dist/lib/platform/pull-requests.js +117 -275
  77. package/dist/lib/platform/repository-metadata.js +377 -0
  78. package/dist/lib/platform/security-alerts.js +155 -0
  79. package/dist/lib/platform/snapshots.js +2 -0
  80. package/dist/lib/platform/verification-sync.js +154 -162
  81. package/dist/lib/process-data/index.js +7 -0
  82. package/dist/lib/release/workflow.js +1 -1
  83. package/dist/lib/run/index.js +5 -0
  84. package/dist/lib/sandbox/commands/control-status.js +22 -0
  85. package/dist/lib/sandbox/commands/create.js +39 -8
  86. package/dist/lib/sandbox/commands/ls.js +5 -0
  87. package/dist/lib/sandbox/commands/rm.js +3 -807
  88. package/dist/lib/sandbox/commands/show.js +16 -0
  89. package/dist/lib/sandbox/control/audit.js +203 -0
  90. package/dist/lib/sandbox/control/client.js +125 -12
  91. package/dist/lib/sandbox/control/completed-reentry.js +85 -0
  92. package/dist/lib/sandbox/control/container-identity.js +28 -31
  93. package/dist/lib/sandbox/control/executor.js +233 -34
  94. package/dist/lib/sandbox/control/finalization-response.js +27 -0
  95. package/dist/lib/sandbox/control/identity-sentinel.js +107 -0
  96. package/dist/lib/sandbox/control/lifecycle.js +656 -128
  97. package/dist/lib/sandbox/control/native-file-lock.js +85 -0
  98. package/dist/lib/sandbox/control/protocol.js +55 -4
  99. package/dist/lib/sandbox/control/server.js +720 -79
  100. package/dist/lib/sandbox/control/state.js +63 -3
  101. package/dist/lib/sandbox/control/task-view.js +183 -0
  102. package/dist/lib/sandbox/control/task-workflow.js +74 -0
  103. package/dist/lib/sandbox/control/workflow-executor.js +99 -0
  104. package/dist/lib/sandbox/engines/authority.js +289 -0
  105. package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
  106. package/dist/lib/sandbox/index.js +7 -2
  107. package/dist/lib/sandbox/recovery.js +49 -5
  108. package/dist/lib/sandbox/removal.js +1717 -0
  109. package/dist/lib/sandbox/task-cleanup.js +217 -0
  110. package/dist/lib/sandbox/workspace-view.js +15 -15
  111. package/dist/lib/sandbox/worktree-safety.js +4 -1
  112. package/dist/lib/server/index.js +8 -0
  113. package/dist/lib/task/activity-intent.js +2 -1
  114. package/dist/lib/task/activity-log.js +30 -24
  115. package/dist/lib/task/artifact-command.js +101 -0
  116. package/dist/lib/task/artifact-lifecycle.js +71 -40
  117. package/dist/lib/task/artifact-name.js +36 -0
  118. package/dist/lib/task/artifact-operations.js +474 -0
  119. package/dist/lib/task/artifact-receipts.js +3 -15
  120. package/dist/lib/task/artifact-repair-intent.js +130 -0
  121. package/dist/lib/task/artifact-schema.js +127 -0
  122. package/dist/lib/task/capabilities.js +83 -19
  123. package/dist/lib/task/codex-orchestration.js +71 -25
  124. package/dist/lib/task/commit-identity.js +28 -0
  125. package/dist/lib/task/commit-operation.js +2 -16
  126. package/dist/lib/task/control-authority.js +375 -5
  127. package/dist/lib/task/control-recovery.js +128 -0
  128. package/dist/lib/task/create-service.js +103 -4
  129. package/dist/lib/task/create.js +80 -2
  130. package/dist/lib/task/decision-details.js +2 -46
  131. package/dist/lib/task/events.js +306 -76
  132. package/dist/lib/task/finalization-state.js +9 -0
  133. package/dist/lib/task/human-override.js +3 -6
  134. package/dist/lib/task/implementation-inputs.js +3 -3
  135. package/dist/lib/task/index.js +11 -3
  136. package/dist/lib/task/intermediate-cleanup.js +383 -0
  137. package/dist/lib/task/invalidation.js +18 -65
  138. package/dist/lib/task/ledger-intents.js +7 -22
  139. package/dist/lib/task/ledger.js +1 -3
  140. package/dist/lib/task/lifecycle.js +19 -1
  141. package/dist/lib/task/local-artifact-finalization.js +190 -290
  142. package/dist/lib/task/manual-validation-completion.js +26 -0
  143. package/dist/lib/task/manual-validation-evidence.js +130 -0
  144. package/dist/lib/task/manual-validation-receipt.js +101 -0
  145. package/dist/lib/task/manual-validation-shared.js +40 -0
  146. package/dist/lib/task/manual-validation-transaction.js +243 -0
  147. package/dist/lib/task/markdown.js +47 -0
  148. package/dist/lib/task/orchestration.js +206 -69
  149. package/dist/lib/task/qualification-audit.js +476 -0
  150. package/dist/lib/task/qualification-confirmation.js +109 -0
  151. package/dist/lib/task/qualification-intents.js +148 -0
  152. package/dist/lib/task/review-artifacts.js +23 -40
  153. package/dist/lib/task/review-command.js +25 -0
  154. package/dist/lib/task/review-finalization.js +146 -97
  155. package/dist/lib/task/review-fingerprint.js +2 -2
  156. package/dist/lib/task/sections.js +34 -54
  157. package/dist/lib/task/verification-config.js +11 -0
  158. package/dist/lib/task/verification-engine.js +170 -327
  159. package/dist/lib/task/verification.js +1 -1
  160. package/dist/lib/task/workflow-command.js +17 -0
  161. package/dist/lib/task/workflow-warning-intents.js +0 -16
  162. package/dist/lib/task/workflow-warnings.js +28 -2
  163. package/dist/lib/update.js +2 -0
  164. package/dist/lifecycle-build-manifest.json +3 -3
  165. package/lib/agent-client.ts +9 -0
  166. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +223 -33
  167. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +3 -2
  168. package/lib/fs/durable-write.ts +29 -0
  169. package/lib/fs/file-lock.ts +113 -0
  170. package/lib/host-control/audit.ts +22 -0
  171. package/lib/host-control/client.ts +172 -0
  172. package/lib/host-control/command.ts +60 -0
  173. package/lib/host-control/path.ts +167 -0
  174. package/lib/host-control/secure-fs.ts +135 -0
  175. package/lib/host-control/server.ts +180 -0
  176. package/lib/host-control/service.ts +133 -0
  177. package/lib/init.ts +15 -2
  178. package/lib/internal/agent-client.ts +4 -2
  179. package/lib/internal/cli-route-inventory.ts +142 -0
  180. package/lib/internal/codex-lifecycle.ts +14 -12
  181. package/lib/internal/codex-sandbox-controller.ts +7 -2
  182. package/lib/internal/demo-promotion.ts +354 -0
  183. package/lib/internal/demo-transcript.ts +419 -0
  184. package/lib/internal/git-workflow.ts +9 -6
  185. package/lib/internal/host-control.ts +28 -0
  186. package/lib/internal/manual-validation.ts +306 -0
  187. package/lib/internal/platform-checks.ts +12 -4
  188. package/lib/internal/platform-comment.ts +12 -4
  189. package/lib/internal/platform-context.ts +3 -1
  190. package/lib/internal/platform-issue.ts +11 -4
  191. package/lib/internal/platform-metadata.ts +70 -0
  192. package/lib/internal/platform-pr-review.ts +14 -3
  193. package/lib/internal/platform-pr.ts +38 -14
  194. package/lib/internal/platform-release-notes.ts +5 -3
  195. package/lib/internal/platform-security.ts +83 -0
  196. package/lib/internal/pr-review-grade.ts +10 -3
  197. package/lib/internal/release-workflow.ts +91 -87
  198. package/lib/internal/sandbox-control.ts +181 -6
  199. package/lib/internal/task-activity.ts +12 -4
  200. package/lib/internal/task-artifact.ts +15 -79
  201. package/lib/internal/task-context.ts +3 -1
  202. package/lib/internal/task-create.ts +76 -15
  203. package/lib/internal/task-delivery.ts +3 -1
  204. package/lib/internal/task-event.ts +21 -10
  205. package/lib/internal/task-finalization.ts +3 -1
  206. package/lib/internal/task-invalidation.ts +3 -1
  207. package/lib/internal/task-ledger.ts +11 -1
  208. package/lib/internal/task-lifecycle.ts +3 -1
  209. package/lib/internal/task-operation-registry.ts +590 -0
  210. package/lib/internal/task-orchestration.ts +12 -0
  211. package/lib/internal/task-override.ts +9 -3
  212. package/lib/internal/task-qualification.ts +61 -0
  213. package/lib/internal/task-review.ts +7 -50
  214. package/lib/internal/task-short-id.ts +10 -1
  215. package/lib/internal/task-snapshot.ts +3 -1
  216. package/lib/internal/task-validate.ts +32 -12
  217. package/lib/internal/task-verify.ts +4 -1
  218. package/lib/internal/task-warning.ts +7 -1
  219. package/lib/owned-path.ts +26 -0
  220. package/lib/platform/check-status.ts +9 -0
  221. package/lib/platform/comment-safety.ts +255 -0
  222. package/lib/platform/completion-backfill.ts +1 -1
  223. package/lib/platform/github-data.ts +322 -0
  224. package/lib/platform/github-provider.ts +244 -27
  225. package/lib/platform/issue-comments.ts +159 -35
  226. package/lib/platform/issues.ts +4 -245
  227. package/lib/platform/pr-change-report.ts +6 -12
  228. package/lib/platform/pr-checks.ts +13 -77
  229. package/lib/platform/pr-summary.ts +88 -11
  230. package/lib/platform/provider-contract.ts +78 -3
  231. package/lib/platform/provider-validation.ts +85 -3
  232. package/lib/platform/pull-requests.ts +129 -348
  233. package/lib/platform/repository-metadata.ts +453 -0
  234. package/lib/platform/security-alerts.ts +191 -0
  235. package/lib/platform/snapshots.ts +53 -0
  236. package/lib/platform/verification-sync.ts +171 -177
  237. package/lib/process-data/index.ts +7 -0
  238. package/lib/release/workflow.ts +3 -3
  239. package/lib/run/index.ts +5 -0
  240. package/lib/sandbox/commands/control-status.ts +26 -0
  241. package/lib/sandbox/commands/create.ts +53 -12
  242. package/lib/sandbox/commands/ls.ts +7 -0
  243. package/lib/sandbox/commands/rm.ts +3 -996
  244. package/lib/sandbox/commands/show.ts +16 -0
  245. package/lib/sandbox/control/audit.ts +253 -0
  246. package/lib/sandbox/control/client.ts +150 -13
  247. package/lib/sandbox/control/completed-reentry.ts +98 -0
  248. package/lib/sandbox/control/container-identity.ts +27 -43
  249. package/lib/sandbox/control/executor.ts +262 -37
  250. package/lib/sandbox/control/finalization-response.ts +29 -0
  251. package/lib/sandbox/control/identity-sentinel.ts +137 -0
  252. package/lib/sandbox/control/lifecycle.ts +672 -18
  253. package/lib/sandbox/control/native-file-lock.ts +108 -0
  254. package/lib/sandbox/control/protocol.ts +80 -8
  255. package/lib/sandbox/control/server.ts +779 -82
  256. package/lib/sandbox/control/state.ts +84 -3
  257. package/lib/sandbox/control/task-view.ts +240 -0
  258. package/lib/sandbox/control/task-workflow.ts +95 -0
  259. package/lib/sandbox/control/workflow-executor.ts +102 -0
  260. package/lib/sandbox/engines/authority.ts +365 -0
  261. package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
  262. package/lib/sandbox/index.ts +9 -2
  263. package/lib/sandbox/recovery.ts +49 -6
  264. package/lib/sandbox/removal.ts +2144 -0
  265. package/lib/sandbox/task-cleanup.ts +209 -0
  266. package/lib/sandbox/workspace-view.ts +26 -18
  267. package/lib/sandbox/worktree-safety.ts +4 -1
  268. package/lib/server/index.ts +10 -0
  269. package/lib/task/activity-intent.ts +2 -2
  270. package/lib/task/activity-log.ts +27 -19
  271. package/lib/task/artifact-command.ts +104 -0
  272. package/lib/task/artifact-lifecycle.ts +66 -39
  273. package/lib/task/artifact-name.ts +55 -0
  274. package/lib/task/artifact-operations.ts +580 -0
  275. package/lib/task/artifact-receipts.ts +3 -14
  276. package/lib/task/artifact-repair-intent.ts +152 -0
  277. package/lib/task/artifact-schema.ts +163 -0
  278. package/lib/task/capabilities.ts +82 -22
  279. package/lib/task/codex-orchestration.ts +85 -24
  280. package/lib/task/commit-identity.ts +31 -0
  281. package/lib/task/commit-operation.ts +2 -16
  282. package/lib/task/control-authority.ts +513 -6
  283. package/lib/task/control-recovery.ts +174 -0
  284. package/lib/task/create-service.ts +131 -6
  285. package/lib/task/create.ts +83 -1
  286. package/lib/task/decision-details.ts +3 -71
  287. package/lib/task/events.ts +292 -75
  288. package/lib/task/finalization-state.ts +11 -0
  289. package/lib/task/human-override.ts +3 -8
  290. package/lib/task/implementation-inputs.ts +3 -3
  291. package/lib/task/index.ts +16 -3
  292. package/lib/task/intermediate-cleanup.ts +455 -0
  293. package/lib/task/invalidation.ts +18 -62
  294. package/lib/task/ledger-intents.ts +7 -24
  295. package/lib/task/ledger.ts +1 -3
  296. package/lib/task/lifecycle.ts +17 -1
  297. package/lib/task/local-artifact-finalization.ts +223 -388
  298. package/lib/task/manual-validation-completion.ts +40 -0
  299. package/lib/task/manual-validation-evidence.ts +209 -0
  300. package/lib/task/manual-validation-receipt.ts +152 -0
  301. package/lib/task/manual-validation-shared.ts +50 -0
  302. package/lib/task/manual-validation-transaction.ts +304 -0
  303. package/lib/task/markdown.ts +70 -0
  304. package/lib/task/orchestration.ts +191 -68
  305. package/lib/task/qualification-audit.ts +588 -0
  306. package/lib/task/qualification-confirmation.ts +117 -0
  307. package/lib/task/qualification-intents.ts +150 -0
  308. package/lib/task/review-artifacts.ts +21 -41
  309. package/lib/task/review-command.ts +23 -0
  310. package/lib/task/review-finalization.ts +154 -153
  311. package/lib/task/review-fingerprint.ts +2 -2
  312. package/lib/task/sections.ts +33 -52
  313. package/lib/task/verification-config.ts +12 -0
  314. package/lib/task/verification-engine.ts +165 -370
  315. package/lib/task/verification-types.ts +17 -0
  316. package/lib/task/verification.ts +1 -1
  317. package/lib/task/workflow-command.ts +18 -0
  318. package/lib/task/workflow-warning-intents.ts +0 -13
  319. package/lib/task/workflow-warnings.ts +21 -2
  320. package/lib/update.ts +6 -0
  321. package/package.json +7 -2
  322. package/templates/.agents/hooks/lifecycle-delegation.js +6 -6
  323. package/templates/.agents/rules/README.en.md +2 -0
  324. package/templates/.agents/rules/README.zh-CN.md +2 -0
  325. package/templates/.agents/rules/decision-qualification.en.md +22 -0
  326. package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
  327. package/templates/.agents/rules/evidence-reporting.en.md +28 -0
  328. package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
  329. package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
  330. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
  331. package/templates/.agents/rules/local-artifact-repair.en.md +5 -1
  332. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +5 -1
  333. package/templates/.agents/rules/security-alerts.en.md +8 -8
  334. package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
  335. package/templates/.agents/rules/testing-discipline.en.md +2 -0
  336. package/templates/.agents/rules/testing-discipline.zh-CN.md +2 -0
  337. package/templates/.agents/scripts/package.json +3 -0
  338. package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -2
  339. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +19 -2
  340. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
  341. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
  342. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  343. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  344. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  345. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  346. package/templates/.agents/skills/code-task/SKILL.en.md +14 -1
  347. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +14 -1
  348. package/templates/.agents/skills/code-task/config/verify.en.json +5 -14
  349. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +5 -14
  350. package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
  351. package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
  352. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
  353. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
  354. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +3 -1
  355. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
  356. package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
  357. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
  358. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +37 -21
  359. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +37 -21
  360. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  361. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  362. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +4 -0
  363. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +4 -0
  364. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +16 -7
  365. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +16 -7
  366. package/templates/.agents/skills/complete-task/SKILL.en.md +10 -23
  367. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +10 -23
  368. package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
  369. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
  370. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  371. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  372. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  373. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  374. package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
  375. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
  376. package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
  377. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
  378. package/templates/.agents/skills/plan-task/SKILL.en.md +14 -1
  379. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +16 -1
  380. package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
  381. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
  382. package/templates/.agents/skills/release/SKILL.en.md +7 -3
  383. package/templates/.agents/skills/release/SKILL.zh-CN.md +7 -3
  384. package/templates/.agents/skills/review-analysis/SKILL.en.md +14 -1
  385. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -1
  386. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
  387. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
  388. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
  389. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
  390. package/templates/.agents/skills/review-code/SKILL.en.md +14 -1
  391. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +14 -1
  392. package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
  393. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
  394. package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
  395. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
  396. package/templates/.agents/skills/review-plan/SKILL.en.md +14 -1
  397. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -1
  398. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
  399. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
  400. package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
  401. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
  402. package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
  403. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
  404. package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
  405. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
  406. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +25 -4
  407. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +25 -4
  408. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +4 -1
  409. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +4 -1
  410. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +5 -1
  411. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +5 -1
  412. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  413. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  414. package/templates/.agents/skills/test/SKILL.en.md +29 -7
  415. package/templates/.agents/skills/test/SKILL.zh-CN.md +29 -7
  416. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
  417. package/templates/.agents/templates/task.en.md +6 -0
  418. package/templates/.agents/templates/task.zh-CN.md +6 -0
  419. package/templates/.claude/commands/run-manual-validation.en.md +1 -1
  420. package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
  421. package/dist/lib/platform/adapters.js +0 -56
  422. package/lib/platform/adapters.ts +0 -197
  423. package/templates/.agents/scripts/security-alerts.github.sh +0 -151
  424. package/templates/.agents/scripts/security-alerts.sh +0 -31
  425. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
  426. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
  427. package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
  428. package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
@@ -24,17 +24,30 @@ import { resolveMaterializedReviewedHeadRelation } from "../platform/change-requ
24
24
  import { resolveReviewedHeadRelation } from "../platform/merged-pr-equivalence.ts";
25
25
  import { resolveLocalReviewedCommitRelation } from "../git/reviewed-commit-equivalence.ts";
26
26
  import { parseTypedTaskFrontmatter } from "./frontmatter.ts";
27
- import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from "./ledger.ts";
27
+ import { LEDGER_TERMINAL, LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from "./ledger.ts";
28
28
  import type { LedgerRow } from "./ledger.ts";
29
29
  import { isValidAgentInfraVersion } from "../version.ts";
30
30
  import { equalCounts, parseReviewSummary } from "./review-artifacts.ts";
31
31
  import { inspectDecisionDetailDuplicates } from "./decision-details.ts";
32
+ import { parseImplementationInputs, type ImplementationInput } from "./implementation-inputs.ts";
33
+ import { scanVisibleMarkdown } from "./markdown.ts";
32
34
  import { loadVerificationConfig } from "./verification-config.ts";
33
35
  import { snapshotReview } from "../git/review-snapshot.ts";
36
+ import { inspectActivityLog } from "./activity-log.ts";
37
+ import { parseWorkflowWarnings } from "./workflow-warnings.ts";
34
38
  import { OrchestrationStateError, readRun } from "./orchestration.ts";
39
+ import type { OrchestrationRun } from "./orchestration.ts";
35
40
  import { resolveDeliveryTarget } from "./delivery-target.ts";
36
41
  import { readPrDeliveryFact } from "./pr-delivery-fact.ts";
37
42
  import { validateLocalArtifact } from "./local-artifact-finalization.ts";
43
+ import { validateQualificationAudit } from "./qualification-audit.ts";
44
+ import { getArtifactSchema } from "./artifact-schema.ts";
45
+ import { inspectArtifactContract } from "./artifact-operations.ts";
46
+ import type { VerificationShared } from "./verification-types.ts";
47
+ import { manualValidationFinalSummaryProjectionMatches } from "./manual-validation-receipt.ts";
48
+ import { readManualValidationCompletion } from "./manual-validation-completion.ts";
49
+ import { sha256File } from "./artifact-receipts.ts";
50
+ import { summaryCommentState } from "../platform/pr-summary.ts";
38
51
 
39
52
  const TASK_ENUMS = {
40
53
  type: ["feature", "bugfix", "refactor", "docs", "chore"],
@@ -55,7 +68,6 @@ const DEFAULT_REQUIRED_FIELDS = [
55
68
  ];
56
69
 
57
70
  const DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?$/;
58
- const ACTIVITY_LOG_PATTERN = /^- (\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?) — \*\*(.+?)\*\* by (.+?) — (.+)$/;
59
71
  // Start markers (action suffixed with ` [started]`) are excluded from the
60
72
  // "latest action" / freshness computation so a step's in-flight marker never
61
73
  // satisfies a skill's expected_action_pattern; the matching done entry does.
@@ -64,28 +76,12 @@ const BRANCH_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
64
76
 
65
77
  // Review disagreement ledger (see .agents/rules/review-handshake.md).
66
78
  const LEDGER_SECTION_NAMES = ["审查分歧账本", "Review Disagreement Ledger"];
67
- const LEDGER_STATUSES = new Set([
68
- "open",
69
- "accepted",
70
- "adjusted",
71
- "refuted",
72
- "cannot-judge",
73
- "confirmed",
74
- "needs-human-decision",
75
- "closed",
76
- "human-decided"
77
- ]);
78
- const LEDGER_TERMINAL_OK = new Set(["confirmed", "closed", "human-decided"]);
79
79
  const DEFAULT_MAX_HANDSHAKE_ROUNDS = 3;
80
80
  const POST_REVIEW_COMMIT_STAGE = "post-review-commit";
81
81
  const SHA_PATTERN = /^[0-9a-f]{7,40}$/i;
82
- const WORKFLOW_WARNING_SECTION_NAMES = ["工作流告警", "Workflow Warnings"];
83
- const WORKFLOW_WARNING_STATUSES = new Set(["open", "resolved", "ignored"]);
84
- const WORKFLOW_WARNING_SEVERITIES = new Set(["IMPORTANT", "ACTION_REQUIRED"]);
85
- const WORKFLOW_WARNING_ID_PATTERN = /^WW-\d+$/;
86
82
 
87
83
  const scriptPath = fileURLToPath(import.meta.url);
88
- let repoRoot = path.resolve(path.dirname(scriptPath), "..", "..");
84
+ const defaultRepoRoot = path.resolve(path.dirname(scriptPath), "..", "..");
89
85
 
90
86
  const PLATFORM_ADAPTERS: Record<string, (context: any, shared: any) => any> = {
91
87
  "platform-sync": checkPlatformSync,
@@ -157,7 +153,7 @@ function checkOrchestrationState({ taskDir }: any): any {
157
153
  const file = path.join(taskDir, 'orchestration.json');
158
154
  const stat = safeStat(file);
159
155
  if (!stat?.isFile()) return failResult('orchestration-state', 'orchestration.json is missing');
160
- let run: any;
156
+ let run: OrchestrationRun | null;
161
157
  try {
162
158
  run = readRun(taskDir);
163
159
  } catch (error) {
@@ -189,18 +185,16 @@ function exactText(value: unknown): value is string {
189
185
  return typeof value === 'string' && value.length > 0 && value.trim() === value;
190
186
  }
191
187
 
192
- function validateCleanCompletionEvidence(run: any): string | null {
188
+ function validateCleanCompletionEvidence(run: OrchestrationRun): string | null {
193
189
  const evidence = run.completionEvidence;
194
190
  const shaPattern = /^[0-9a-f]{40}$/i;
195
191
  if (
196
- evidence?.kind !== 'reviewed-head-clean'
197
- || !exactText(evidence.observedAt)
192
+ !evidence
198
193
  || Number.isNaN(Date.parse(evidence.observedAt))
199
194
  || !shaPattern.test(evidence.head)
200
195
  || !shaPattern.test(evidence.headTree)
201
196
  || !shaPattern.test(evidence.worktreeTree)
202
197
  || !shaPattern.test(evidence.lastReviewedCommit)
203
- || !(evidence.prNumber === null || (Number.isInteger(evidence.prNumber) && evidence.prNumber > 0))
204
198
  || !(evidence.prHead === null || shaPattern.test(evidence.prHead))
205
199
  ) {
206
200
  return 'Clean completion evidence has an invalid structure';
@@ -217,8 +211,7 @@ function validateCleanCompletionEvidence(run: any): string | null {
217
211
  || run.pendingDelegation !== null
218
212
  || run.commitAuthorization?.issuedAt !== null
219
213
  || run.commitAuthorization?.consumedAt !== null
220
- || !Array.isArray(run.receipts)
221
- || run.receipts.some((receipt: any) => receipt.stage === 'commit')
214
+ || run.receipts.some((receipt) => receipt.stage === 'commit')
222
215
  ) {
223
216
  return 'Clean completion evidence conflicts with commit delegation state';
224
217
  }
@@ -229,54 +222,16 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
229
222
  const file = path.join(taskDir, 'orchestration.json');
230
223
  const stat = safeStat(file);
231
224
  if (!stat?.isFile()) return failResult('orchestration-evidence', 'orchestration.json is missing');
232
- let run: any;
225
+ let run: OrchestrationRun | null;
233
226
  try {
234
227
  run = readRun(taskDir);
235
228
  } catch (error) {
236
229
  const message = error instanceof OrchestrationStateError ? error.message : String(error);
237
230
  return failResult('orchestration-evidence', `Invalid orchestration.json: ${message}`);
238
231
  }
232
+ if (!run) return failResult('orchestration-evidence', 'orchestration.json is missing');
233
+ // readRun validates the persisted schema, receipt identities and client provenance.
239
234
  const policy = run.modelPolicy;
240
- if (
241
- !policy
242
- || !exactText(policy.executor?.model)
243
- || !exactText(policy.executor?.reasoningEffort)
244
- || !exactText(policy.reviewer?.model)
245
- || !exactText(policy.reviewer?.reasoningEffort)
246
- ) {
247
- return failResult('orchestration-evidence', 'Run model policy requires exact executor and reviewer model and effort');
248
- }
249
- if (
250
- !run.modelPolicySource
251
- || !['explicit', 'project-config'].includes(run.modelPolicySource.kind)
252
- || !exactText(run.modelPolicySource.client)
253
- || !exactText(run.modelPolicySource.resolvedAt)
254
- || !Array.isArray(run.recoveryHistory)
255
- ) {
256
- return failResult('orchestration-evidence', 'Run model policy source or recovery history is invalid');
257
- }
258
- for (const recovery of run.recoveryHistory) {
259
- const guards = recovery.guards;
260
- const validClaudeCodeRecovery = recovery.code === 'CLIENT_CAPABILITY_ENABLED'
261
- && recovery.previousStatus === 'paused'
262
- && recovery.previousPause?.code === 'ORCHESTRATION_CLIENT_UNSUPPORTED'
263
- && recovery.client === 'claude-code'
264
- && recovery.resultingStatus === 'running'
265
- && exactText(recovery.recoveredAt)
266
- && guards?.stepCount === 0
267
- && guards?.nextStage === null
268
- && guards?.baselineEmpty === true
269
- && guards?.receiptCount === 0
270
- && guards?.pendingDelegation === false
271
- && guards?.commitAuthorizationUnused === true
272
- && guards?.completionEvidenceAbsent === true;
273
- if (!validClaudeCodeRecovery) {
274
- return failResult('orchestration-evidence', 'Run recovery history contains invalid provenance');
275
- }
276
- }
277
- if (!Array.isArray(run.receipts)) {
278
- return failResult('orchestration-evidence', 'Run receipts must be an array');
279
- }
280
235
  if (run.completionEvidence != null) {
281
236
  const evidenceError = validateCleanCompletionEvidence(run);
282
237
  if (evidenceError) return failResult('orchestration-evidence', evidenceError);
@@ -306,10 +261,6 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
306
261
  return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has no host-observed actual reasoning effort`);
307
262
  }
308
263
  }
309
- // parentId/childId 校验对所有 client 保持统一(不新增分支);spawnMode 检查按 client 判断
310
- if (!exactText(receipt.parentId) || !exactText(receipt.childId) || receipt.parentId === receipt.childId) {
311
- return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid delegation identity`);
312
- }
313
264
  if (!isClaudeCode && receipt.spawnMode !== 'fresh') {
314
265
  return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid fresh delegation identity`);
315
266
  }
@@ -335,50 +286,9 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
335
286
  ) {
336
287
  return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has an unrelated reasoning-effort fallback reason`);
337
288
  }
338
- if (receipt.client === 'codex') {
339
- const activatedCodex = ['activated', 'stage-completed', 'sealed', 'consumed'].includes(receipt.status);
340
- const host = receipt.hostEvidence;
341
- const provenance = receipt.lifecycleProvenance;
342
- if (
343
- !provenance
344
- || (activatedCodex && (
345
- host?.kind !== 'codex-lifecycle-v2'
346
- || host.protocolVersion !== provenance.protocolVersion
347
- || host.hookDefinitionHash !== provenance.hookDefinitionHash
348
- || host.hookSource !== provenance.hookSource
349
- || host.hookSourcePathDigest !== provenance.hookSourcePathDigest
350
- || host.hookSourceHash !== provenance.hookSourceHash
351
- || host.capabilitySessionId !== provenance.capabilitySessionId
352
- || receipt.parentId !== provenance.capabilitySessionId
353
- || host.capabilityTurnId !== provenance.capabilityTurnId
354
- || host.controllerInstanceDigest !== provenance.controllerInstanceDigest
355
- || host.controlGeneration !== provenance.controlGeneration
356
- || host.spawnToolUseId === provenance.capabilityToolUseId
357
- || !exactText(host.spawnToolUseId)
358
- || !Number.isFinite(Date.parse(host.spawnObservedAt ?? ''))
359
- || !Number.isFinite(Date.parse(receipt.spawnDispatchedAt ?? ''))
360
- || !Number.isFinite(Date.parse(receipt.activationDeadlineAt ?? ''))
361
- || Date.parse(host.spawnObservedAt ?? '') < Date.parse(receipt.spawnDispatchedAt ?? '')
362
- || Date.parse(host.spawnObservedAt ?? '') > Date.parse(receipt.activationDeadlineAt ?? '')
363
- || !exactText(host.hookDefinitionHash)
364
- || !Number.isSafeInteger(host.startRevision)
365
- || host.startRevision < 1
366
- ))
367
- ) {
368
- return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid Codex start evidence`);
369
- }
370
- if (['sealed', 'consumed'].includes(receipt.status) && (
371
- !Number.isSafeInteger(host.stopRevision)
372
- || host.stopRevision <= host.startRevision
373
- || host.consumer !== receipt.id
374
- || !exactText(host.consumedAt)
375
- )) {
376
- return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid Codex consumed stop evidence`);
377
- }
378
- }
379
289
  }
380
290
  }
381
- if (run.receipts.some((receipt: any) => receipt.status !== 'consumed')) {
291
+ if (run.receipts.some((receipt) => receipt.status !== 'consumed')) {
382
292
  return failResult('orchestration-evidence', 'Historical receipts must be consumed');
383
293
  }
384
294
  return passResult('orchestration-evidence', 'Persisted orchestration model and delegation evidence is internally consistent');
@@ -386,7 +296,7 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
386
296
 
387
297
  // === Check Functions ===
388
298
 
389
- function checkTaskMeta({ taskDir, config }: any): any {
299
+ function checkTaskMeta({ taskDir, config, repositoryRoot }: any): any {
390
300
  const task = loadTask(taskDir);
391
301
  if (!task.ok) {
392
302
  return failResult("task-meta", task.message);
@@ -424,14 +334,15 @@ function checkTaskMeta({ taskDir, config }: any): any {
424
334
  }
425
335
  }
426
336
 
427
- const branchValidationError = validateTaskBranch(metadata);
337
+ const branchValidationError = validateTaskBranch(metadata, repositoryRoot);
428
338
  if (branchValidationError) {
429
339
  return failResult("task-meta", branchValidationError);
430
340
  }
431
341
 
432
- const warningValidationErrors = validateWorkflowWarnings(task.content);
433
- if (warningValidationErrors.length > 0) {
434
- return failResult("task-meta", `Invalid Workflow Warnings: ${warningValidationErrors.join("; ")}`);
342
+ try {
343
+ parseWorkflowWarnings(task.content);
344
+ } catch (error) {
345
+ return failResult("task-meta", `Invalid Workflow Warnings: ${error instanceof Error ? error.message : String(error)}`);
435
346
  }
436
347
 
437
348
  const expectedStep = config.expected_step;
@@ -549,12 +460,12 @@ async function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }: any):
549
460
  return passResult('required-pr-delivery', `Pull request delivery policy satisfied (${status})`);
550
461
  }
551
462
 
552
- function validateTaskBranch(metadata: any): any {
463
+ function validateTaskBranch(metadata: any, repoRoot: string): any {
553
464
  if (isBlank(metadata.branch)) {
554
465
  return null;
555
466
  }
556
467
 
557
- const projectName = loadProjectName();
468
+ const projectName = loadProjectName(repoRoot);
558
469
  const expectedPrefix = projectName ? `${projectName}-${metadata.type}-` : "";
559
470
 
560
471
  if (expectedPrefix && !String(metadata.branch).startsWith(expectedPrefix)) {
@@ -569,7 +480,7 @@ function validateTaskBranch(metadata: any): any {
569
480
  return null;
570
481
  }
571
482
 
572
- function loadProjectName(): any {
483
+ function loadProjectName(repoRoot: string): any {
573
484
  const configPath = path.join(repoRoot, ".agents", ".airc.json");
574
485
  if (!fs.existsSync(configPath)) {
575
486
  return "";
@@ -600,15 +511,45 @@ function checkArtifact({ taskDir, config, artifactFile, skillName }: any): any {
600
511
  }
601
512
 
602
513
  const content = fs.readFileSync(artifactPath, "utf8");
603
- const requiredSections = config.required_sections || [];
514
+ let taskContent = "";
515
+ const taskPath = path.join(taskDir, "task.md");
516
+ if (fs.existsSync(taskPath)) {
517
+ try {
518
+ taskContent = fs.readFileSync(taskPath, "utf8");
519
+ } catch (error) {
520
+ return failResult("artifact", `Cannot read task qualification contract: ${error instanceof Error ? error.message : String(error)}`);
521
+ }
522
+ }
523
+ if (taskContent && /^review-(?:analysis|plan|code)$/.test(skillName)) {
524
+ const qualification = validateQualificationAudit(taskContent, content, { artifact: path.basename(artifactPath) });
525
+ if (!qualification.ok) return failResult("artifact", `${path.basename(artifactPath)} has qualification audit errors: ${qualification.code}: ${qualification.message}`);
526
+ }
527
+ const schemaFamily = skillName === "analyze-task"
528
+ ? "analysis"
529
+ : skillName === "review-analysis"
530
+ ? "review-analysis"
531
+ : skillName === "plan-task"
532
+ ? "plan"
533
+ : skillName === "review-plan"
534
+ ? "review-plan"
535
+ : skillName === "code-task"
536
+ ? "code"
537
+ : skillName === "review-code" ? "review-code" : null;
538
+ const schema = schemaFamily ? getArtifactSchema(schemaFamily) : null;
604
539
  const localFamily = skillName === "analyze-task"
605
540
  ? "analysis"
606
541
  : skillName === "plan-task" ? "plan" : skillName === "code-task" ? "code" : null;
542
+ if (schema) {
543
+ const structure = inspectArtifactContract(content, schema);
544
+ if (!structure.ok && !localFamily) {
545
+ return failResult("artifact", `${path.basename(artifactPath)} has shared structural errors: ${structure.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ')}`);
546
+ }
547
+ }
607
548
  if (localFamily) {
608
549
  const local = validateLocalArtifact(content, {
609
550
  family: localFamily,
610
- requiredSections: requiredSections.filter((section: unknown): section is string => typeof section === "string"),
611
- requiredPatterns: (config.required_patterns || []).filter((pattern: unknown): pattern is string => typeof pattern === "string")
551
+ ...(taskContent ? { taskContent } : {}),
552
+ artifact: path.basename(artifactPath)
612
553
  });
613
554
  if (!local.ok) {
614
555
  return failResult(
@@ -618,9 +559,16 @@ function checkArtifact({ taskDir, config, artifactFile, skillName }: any): any {
618
559
  }
619
560
  return passResult(
620
561
  "artifact",
621
- `${path.basename(artifactPath)} passed (${requiredSections.length} sections)`
562
+ `${path.basename(artifactPath)} passed (${schema?.sections.length ?? 0} sections)`
622
563
  );
623
564
  }
565
+ if (schema) {
566
+ return passResult(
567
+ "artifact",
568
+ `${path.basename(artifactPath)} passed (${schema.sections.length} sections)`
569
+ );
570
+ }
571
+ const requiredSections = config.required_sections || [];
624
572
  const missingSections = requiredSections.filter(
625
573
  (section: any) => !new RegExp(`^##\\s+${escapeRegExp(section)}\\s*$`, "m").test(content)
626
574
  );
@@ -703,31 +651,17 @@ function checkImplementationInput({ taskDir, artifactFile }: any): any {
703
651
  const artifactPath = path.join(taskDir, artifactFile);
704
652
  if (!safeStat(artifactPath)?.isFile()) return failResult("implementation-input", `Artifact not found: ${artifactFile}`);
705
653
 
706
- const inputSection = getSectionContent(task.content, ["实现输入", "Implementation Inputs"]);
707
- const rows = [];
708
- if (inputSection) {
709
- const table = inputSection.split(/\r?\n/).filter((line: any) => line.trim().startsWith("|"));
710
- const cells = (line: any) => line.split("|").slice(1, -1).map((cell: any) => cell.trim());
711
- const expected = ["id", "ledger_id", "decision_evidence", "stage", "needs_implementation", "decided_at", "status", "consumed_by"];
712
- if (table.length < 2 || JSON.stringify(cells(table[0])) !== JSON.stringify(expected)) {
713
- return failResult("implementation-input", "Implementation Inputs table schema is invalid");
714
- }
715
- const seen = new Set();
716
- for (const line of table.slice(2)) {
717
- const row = cells(line);
718
- if (row.length !== 8 || !/^II-[1-9]\d*$/.test(row[0]) || seen.has(row[0])) {
719
- return failResult("implementation-input", "Implementation Inputs table contains an invalid or duplicate id");
720
- }
721
- seen.add(row[0]);
722
- rows.push({ id: row[0], ledgerId: row[1], evidence: row[2], stage: row[3], needs: row[4], status: row[6], consumedBy: row[7] });
723
- }
654
+ let rows: ImplementationInput[];
655
+ try {
656
+ rows = parseImplementationInputs(task.content).rows;
657
+ } catch (error) {
658
+ return failResult("implementation-input", `Invalid Implementation Inputs: ${error instanceof Error ? error.message : String(error)}`);
724
659
  }
725
660
 
726
- const logSection = getSectionContent(task.content, ["活动日志", "Activity Log"]);
727
- const doneActions = logSection.split(/\r?\n/).flatMap((line: any) => {
728
- const match = line.trim().match(ACTIVITY_LOG_PATTERN);
729
- return match && !ACTIVITY_LOG_STARTED_RE.test(match[2]) ? [match[2]] : [];
730
- });
661
+ const doneActions = (inspectActivityLog(task.content).section?.entries ?? [])
662
+ .filter((entry) => !ACTIVITY_LOG_STARTED_RE.test(entry.step))
663
+ .map((entry) => entry.step)
664
+ .filter((step) => /^(?:Code Task|Code) \(Round \d+/.test(step));
731
665
  const latestAction = doneActions.at(-1) || "";
732
666
  const actionDecision = /(?:Code Task|Code) \(Round \d+, decision (II-[1-9]\d*)\)/.exec(latestAction)?.[1] || null;
733
667
  const report = fs.readFileSync(artifactPath, "utf8");
@@ -754,10 +688,10 @@ function checkImplementationInput({ taskDir, artifactFile }: any): any {
754
688
  const matches = rows.filter((row) => row.id === actionDecision);
755
689
  if (matches.length !== 1) return failResult("implementation-input", `${actionDecision} is missing or duplicated in task table`);
756
690
  const row = matches[0]!;
757
- if (row.stage !== "code" || row.needs !== "true" || row.status !== "consumed" || row.consumedBy !== artifactFile || !row.evidence) {
691
+ if (row.stage !== "code" || !row.needsImplementation || row.status !== "consumed" || row.consumedBy !== artifactFile || !row.decisionEvidence) {
758
692
  return failResult("implementation-input", `${actionDecision} is not a consumed input for ${artifactFile}`);
759
693
  }
760
- if (reportLedger !== row.ledgerId || reportEvidence !== row.evidence) {
694
+ if (reportLedger !== row.ledgerId || reportEvidence !== row.decisionEvidence) {
761
695
  return failResult("implementation-input", `${actionDecision} report identity does not match task table evidence`);
762
696
  }
763
697
  return passResult("implementation-input", `${actionDecision} matches Activity Log, report, and task table`);
@@ -769,31 +703,20 @@ function checkActivityLog({ taskDir, config }: any): any {
769
703
  return failResult("activity-log", task.message);
770
704
  }
771
705
 
772
- const logSection = getSectionContent(task.content, ["活动日志", "Activity Log"]);
773
- if (!logSection) {
774
- return failResult("activity-log", "Activity Log section not found");
775
- }
776
-
777
- const entries = logSection
778
- .split(/\r?\n/)
779
- .map((line: any) => line.trim())
780
- .filter((line: any) => line.startsWith("- "));
781
-
782
- if (entries.length === 0) {
783
- return failResult("activity-log", "Activity Log has no entries");
784
- }
706
+ const { section, invalidEntries } = inspectActivityLog(task.content);
707
+ if (!section) return failResult("activity-log", "Activity Log section not found or ambiguous");
708
+ if (invalidEntries.length) return failResult("activity-log", `Invalid Activity Log entry format: ${invalidEntries[0]}`);
709
+ const entries = section.entries;
710
+ if (entries.length === 0) return failResult("activity-log", "Activity Log has no entries");
785
711
 
786
712
  let previousTimestamp = "";
787
713
  let latestAction = "";
788
714
  let latestTimestamp = "";
715
+ const doneActions: string[] = [];
789
716
 
790
717
  for (const entry of entries) {
791
- const match = entry.match(ACTIVITY_LOG_PATTERN);
792
- if (!match) {
793
- return failResult("activity-log", `Invalid Activity Log entry format: ${entry}`);
794
- }
795
-
796
- const [, timestamp, action] = match;
718
+ if (!entry.note.trim()) return failResult("activity-log", "Activity Log entry note is required");
719
+ const { time: timestamp, step: action } = entry;
797
720
  if (previousTimestamp && timestamp < previousTimestamp) {
798
721
  return failResult("activity-log", "Activity Log timestamps are not in ascending order");
799
722
  }
@@ -805,6 +728,16 @@ function checkActivityLog({ taskDir, config }: any): any {
805
728
  if (!ACTIVITY_LOG_STARTED_RE.test(action)) {
806
729
  latestTimestamp = timestamp;
807
730
  latestAction = action;
731
+ doneActions.push(action);
732
+ }
733
+ }
734
+
735
+ if (config.expected_action_pattern && !new RegExp(config.expected_action_pattern).test(latestAction)) {
736
+ const expected = new RegExp(config.expected_action_pattern);
737
+ let index = doneActions.length - 1;
738
+ while (index >= 0 && doneActions[index] === 'Commit' && !expected.test(doneActions[index]!)) index -= 1;
739
+ if (index >= 0 && expected.test(doneActions[index]!)) {
740
+ latestAction = doneActions[index]!;
808
741
  }
809
742
  }
810
743
 
@@ -855,118 +788,7 @@ function checkCompletionChecklist({ taskDir, config }: any): any {
855
788
  return passResult("completion-checklist", `Completion Checklist valid (${items.length} items checked)`);
856
789
  }
857
790
 
858
- function splitMarkdownTableRow(line: any): any {
859
- let value = String(line || "").trim();
860
- if (!value.startsWith("|")) {
861
- return [];
862
- }
863
- value = value.replace(/^\|/, "").replace(/\|$/, "");
864
-
865
- const cells = [];
866
- let cell = "";
867
- for (let index = 0; index < value.length; index += 1) {
868
- const char = value[index];
869
- if (char === "|" && !isEscapedAt(value, index)) {
870
- cells.push(unescapeMarkdownTableCell(cell.trim()));
871
- cell = "";
872
- continue;
873
- }
874
- cell += char;
875
- }
876
- cells.push(unescapeMarkdownTableCell(cell.trim()));
877
- return cells;
878
- }
879
-
880
- function unescapeMarkdownTableCell(value: any): any {
881
- let output = "";
882
- for (let index = 0; index < value.length; index += 1) {
883
- const char = value[index];
884
- const next = value[index + 1];
885
- if (char === "\\" && (next === "\\" || next === "|")) {
886
- output += next;
887
- index += 1;
888
- continue;
889
- }
890
- output += char;
891
- }
892
- return output;
893
- }
894
-
895
- function isEscapedAt(value: any, index: any): any {
896
- let backslashes = 0;
897
- for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
898
- backslashes += 1;
899
- }
900
- return backslashes % 2 === 1;
901
- }
902
-
903
- function parseWorkflowWarningRows(section: any): any {
904
- const rows = [];
905
- for (const rawLine of String(section || "").split(/\r?\n/)) {
906
- const cells = splitMarkdownTableRow(rawLine);
907
- if (cells.length === 0) {
908
- continue;
909
- }
910
- if ((cells[0] || "").toLowerCase() === "id") {
911
- continue;
912
- }
913
- if (cells.every((cell: any) => /^:?-{3,}:?$/.test(cell))) {
914
- continue;
915
- }
916
- rows.push(cells);
917
- }
918
- return rows;
919
- }
920
-
921
- function validateWorkflowWarnings(content: any): any {
922
- const section = getSectionContent(content, WORKFLOW_WARNING_SECTION_NAMES);
923
- if (!section.trim()) {
924
- return [];
925
- }
926
-
927
- const rows = parseWorkflowWarningRows(section);
928
- const errors = [];
929
- for (const cells of rows) {
930
- if (cells.length < 11) {
931
- errors.push(`malformed row (expected 11 columns): ${cells.join(" | ")}`);
932
- continue;
933
- }
934
- const [id, time, step, severity, code, status, target, message, action, resolvedAt, resolution] = cells;
935
- if (!WORKFLOW_WARNING_ID_PATTERN.test(id)) {
936
- errors.push(`${id || "(empty id)"}: invalid id`);
937
- }
938
- if (!DATE_TIME_PATTERN.test(time)) {
939
- errors.push(`${id}: invalid time '${time}'`);
940
- }
941
- if (isBlank(step)) {
942
- errors.push(`${id}: step is required`);
943
- }
944
- if (!WORKFLOW_WARNING_SEVERITIES.has(severity)) {
945
- errors.push(`${id}: illegal severity '${severity}'`);
946
- }
947
- if (isBlank(code)) {
948
- errors.push(`${id}: code is required`);
949
- }
950
- if (!WORKFLOW_WARNING_STATUSES.has(status)) {
951
- errors.push(`${id}: illegal status '${status}'`);
952
- }
953
- if (isBlank(target)) {
954
- errors.push(`${id}: target is required`);
955
- }
956
- if (isBlank(message)) {
957
- errors.push(`${id}: message is required`);
958
- }
959
- if (status === "open" && isBlank(action)) {
960
- errors.push(`${id}: open warning requires action`);
961
- }
962
- if ((status === "resolved" || status === "ignored") && (isBlank(resolvedAt) || isBlank(resolution))) {
963
- errors.push(`${id}: ${status} warning requires resolved_at and resolution`);
964
- }
965
- }
966
- return errors;
967
- }
968
-
969
- function resolveReviewSetting(config: any, key: any, fallback: any): any {
791
+ function resolveReviewSetting(config: any, key: any, fallback: any, repoRoot: string): any {
970
792
  if (config && config[key] !== undefined && config[key] !== null) {
971
793
  return config[key];
972
794
  }
@@ -977,7 +799,7 @@ function resolveReviewSetting(config: any, key: any, fallback: any): any {
977
799
  return fallback;
978
800
  }
979
801
 
980
- function checkReviewLedger({ taskDir, config }: any): any {
802
+ function checkReviewLedger({ taskDir, config, repositoryRoot }: any): any {
981
803
  const task = loadTask(taskDir);
982
804
  if (!task.ok) {
983
805
  return failResult("review-ledger", task.message);
@@ -987,9 +809,7 @@ function checkReviewLedger({ taskDir, config }: any): any {
987
809
  try {
988
810
  const ledger = parseLedgerDocument(task.content);
989
811
  if (!ledger.present) return failResult("review-ledger", `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}`);
990
- rows = ledger.rows.map((row) => [
991
- row.id, row.stage, row.round, row.severity, row.status, row.evidence
992
- ]);
812
+ rows = ledger.rows;
993
813
  } catch (error) {
994
814
  return failResult("review-ledger", `Invalid disagreement ledger: ${error instanceof Error ? error.message : String(error)}`);
995
815
  }
@@ -998,17 +818,12 @@ function checkReviewLedger({ taskDir, config }: any): any {
998
818
  }
999
819
 
1000
820
  const stageScope = Array.isArray(config.stage_scope) ? config.stage_scope : null;
1001
- const maxRounds = Number(resolveReviewSetting(config, "maxHandshakeRounds", DEFAULT_MAX_HANDSHAKE_ROUNDS));
821
+ const maxRounds = Number(resolveReviewSetting(config, "maxHandshakeRounds", DEFAULT_MAX_HANDSHAKE_ROUNDS, repositoryRoot));
1002
822
  const problems = [];
1003
823
  let inScopeCount = 0;
1004
824
 
1005
- for (const cells of rows) {
1006
- if (cells.length < 6) {
1007
- problems.push(`malformed row (expected 6 columns): ${cells.join(" | ")}`);
1008
- continue;
1009
- }
1010
-
1011
- const [id, stage, roundRaw, , status, evidence] = cells;
825
+ for (const row of rows) {
826
+ const { id, stage, round: roundRaw, status, evidence } = row;
1012
827
  const stageScoped = stageScope ? stageScope.includes(stage) : true;
1013
828
  // post-review-commit exemption rows are consumed by the post-review-commit
1014
829
  // check, not enforced here.
@@ -1020,8 +835,9 @@ function checkReviewLedger({ taskDir, config }: any): any {
1020
835
  }
1021
836
  inScopeCount += 1;
1022
837
 
1023
- if (!LEDGER_STATUSES.has(status!)) {
1024
- problems.push(`${id}: illegal status '${status}'`);
838
+ const invalid = validateLedgerRows([row]);
839
+ if (invalid) {
840
+ problems.push(`${invalid.code}: ${invalid.message}`);
1025
841
  continue;
1026
842
  }
1027
843
  if (status !== "open" && evidence === "") {
@@ -1031,12 +847,12 @@ function checkReviewLedger({ taskDir, config }: any): any {
1031
847
  if (
1032
848
  Number.isFinite(round) &&
1033
849
  round >= maxRounds &&
1034
- !LEDGER_TERMINAL_OK.has(status!) &&
850
+ !LEDGER_TERMINAL.has(status!) &&
1035
851
  status !== "needs-human-decision"
1036
852
  ) {
1037
853
  problems.push(`${id}: round ${round} reached limit ${maxRounds} without convergence; escalate to needs-human-decision`);
1038
854
  }
1039
- if (!LEDGER_TERMINAL_OK.has(status!)) {
855
+ if (!LEDGER_TERMINAL.has(status!)) {
1040
856
  problems.push(`${id}: unresolved (status '${status}')`);
1041
857
  }
1042
858
  }
@@ -1049,7 +865,7 @@ function checkReviewLedger({ taskDir, config }: any): any {
1049
865
  return passResult("review-ledger", `Disagreement ledger clean (${inScopeCount} in-scope entries terminal${scopeLabel})`);
1050
866
  }
1051
867
 
1052
- function checkManualValidation({ taskDir }: any): any {
868
+ async function checkManualValidation({ taskDir, repositoryRoot }: any): Promise<any> {
1053
869
  // 1. Latest review-code artifact; none -> pass (no review, check not applicable).
1054
870
  const review = findAuthoritativeReviewCodeArtifact(taskDir);
1055
871
  if (!review.ok) {
@@ -1081,15 +897,23 @@ function checkManualValidation({ taskDir }: any): any {
1081
897
  const artifactName = path.basename(resolved.path);
1082
898
  const task = loadTask(taskDir);
1083
899
  if (!task.ok) return failResult("manual-validation", task.message);
1084
- const log = getSectionContent(task.content, ["活动日志", "Activity Log"]);
1085
- const completed = new RegExp(
1086
- `\\*\\*Complete Manual Validation\\*\\*[\\s\\S]*?Manual validation passed → ${escapeRegExp(artifactName)};`
1087
- );
1088
- if (!completed.test(log)) {
1089
- return failResult(
1090
- "manual-validation",
1091
- `Manual validation artifact exists but completion is not recorded for ${artifactName}: re-run /complete-manual-validation`
1092
- );
900
+ const completion = readManualValidationCompletion(taskDir, {
901
+ taskId: task.metadata.id,
902
+ artifact: artifactName
903
+ });
904
+ if (!completion.ok) {
905
+ const source = completion.error.code.startsWith('MANUAL_VALIDATION_RECEIPT_') ? 'receipt' : 'transaction';
906
+ return failResult("manual-validation", `Manual validation ${source} is unavailable: ${completion.error.message}`);
907
+ }
908
+ const { receipt, transaction } = completion.value;
909
+ if (transaction.phase !== "committed" || !transaction.eventAppended || !transaction.postWriteVerified) {
910
+ return failResult("manual-validation", "Manual validation transaction has not reached the committed post-write-verified state");
911
+ }
912
+ if (transaction.pendingSummaryDigest !== receipt.pendingSummaryDigest || transaction.finalSummaryDigest !== receipt.finalSummaryDigest) {
913
+ return failResult("manual-validation", "Manual validation summary digests do not match the committed receipt");
914
+ }
915
+ if (sha256File(resolved.path) !== receipt.artifactSha256) {
916
+ return failResult("manual-validation", `Manual validation artifact digest does not match the receipt for ${artifactName}`);
1093
917
  }
1094
918
  // 6. Timing correlation (PL-3 fix, PL-4 corrected): the completion entry must
1095
919
  // sit AFTER the latest review-code round's completion entry in the
@@ -1098,28 +922,32 @@ function checkManualValidation({ taskDir }: any): any {
1098
922
  // which indexOf never matches). Not reusing completed.exec().index: exec
1099
923
  // anchors to the first '**Complete Manual Validation**' heading, which can
1100
924
  // belong to an earlier round's entry and misorder the standard path.
1101
- const reviewDoneIndex = log.indexOf(`**Review Code (Round ${review.round})** by `);
1102
- const completedIndex = log.indexOf(`Manual validation passed → ${artifactName};`);
1103
- if (reviewDoneIndex === -1) {
1104
- // The latest review-code round's completion entry is missing entirely (abnormal
1105
- // state, e.g. a restored/historical task without a review-code.completed record).
1106
- // Re-running complete-manual-validation cannot restore it, so the remediation
1107
- // targets the review record itself. Fail closed either way.
1108
- return failResult(
1109
- "manual-validation",
1110
- `Latest review-code (round ${review.round}) completion entry is missing from the Activity Log (abnormal state): re-run review-code or restore the completion record`
1111
- );
1112
- }
1113
- if (completedIndex < reviewDoneIndex) {
1114
- return failResult(
1115
- "manual-validation",
1116
- `Latest review-code (round ${review.round}) came after the manual validation completion recorded for ${artifactName}: re-run /complete-manual-validation to cover new pending items`
1117
- );
925
+ const inspectedLog = inspectActivityLog(task.content);
926
+ if (!inspectedLog.section) return failResult("manual-validation", "Activity Log is missing or invalid");
927
+ const reviewDoneIndex = inspectedLog.section.entries.findIndex((entry) => entry.step === `Review Code (Round ${review.round})`);
928
+ const completedIndex = inspectedLog.section.entries.findIndex((entry) => entry.step === "Complete Manual Validation"
929
+ && entry.note.includes(`Manual validation passed → ${artifactName};`)
930
+ && entry.note.includes(`transaction=${receipt.transactionId};`)
931
+ && entry.note.includes(`receipt=${receipt.receiptDigest};`)
932
+ && entry.note.includes(`head=${receipt.prHeadSha}`));
933
+ if (reviewDoneIndex === -1) return failResult("manual-validation", `Latest review-code (round ${review.round}) completion entry is missing from the Activity Log`);
934
+ if (completedIndex === -1) return failResult("manual-validation", `Committed manual validation completion is not recorded for ${artifactName}`);
935
+ if (completedIndex < reviewDoneIndex) return failResult("manual-validation", `Latest review-code (round ${review.round}) came after the manual validation completion recorded for ${artifactName}`);
936
+
937
+ const fact = readPrDeliveryFact(task.metadata);
938
+ if (fact.status === "invalid") return failResult("manual-validation", fact.error.message);
939
+ if (fact.status === "valid" && fact.fact.state === "bound") {
940
+ const inspected = await inspectPlatformPullRequest(task.metadata.id, { cwd: repositoryRoot });
941
+ if (!inspected.pullRequest) return failResult("manual-validation", inspected.error?.message ?? "canonical pull-request head is unavailable");
942
+ if (inspected.pullRequest.head.sha !== receipt.prHeadSha) return failResult("manual-validation", "manual validation receipt is stale for the current pull-request head");
943
+ const summary = await summaryCommentState(task.metadata.id, { cwd: repositoryRoot });
944
+ if (!summary.comment) return failResult("manual-validation", "canonical pull-request summary comment is unavailable");
945
+ if (!manualValidationFinalSummaryProjectionMatches(summary.comment.body, receipt)) return failResult("manual-validation", "canonical pull-request summary does not match the committed manual validation projection");
1118
946
  }
1119
- return passResult("manual-validation", `Manual validation completed → ${artifactName}`);
947
+ return passResult("manual-validation", `Manual validation completed → ${artifactName} (committed receipt and post-write verification)`);
1120
948
  }
1121
949
 
1122
- async function checkPostReviewCommit({ taskDir, config }: any): Promise<any> {
950
+ async function checkPostReviewCommit({ taskDir, config, repositoryRoot }: any): Promise<any> {
1123
951
  const reviewArtifact = findAuthoritativeReviewCodeArtifact(taskDir);
1124
952
  if (!reviewArtifact.ok) {
1125
953
  if (reviewArtifact.error) return failResult("post-review-commit", `Review-code artifact is unavailable: ${reviewArtifact.error}`);
@@ -1139,7 +967,7 @@ async function checkPostReviewCommit({ taskDir, config }: any): Promise<any> {
1139
967
  if (factRead.status === 'invalid') return failResult("post-review-commit", factRead.error.message);
1140
968
  const fact = factRead.status === 'valid' ? factRead.fact : null;
1141
969
  const lastReviewedCommit = task.ok ? (task.metadata.last_reviewed_commit || "").trim() : "";
1142
- const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(repoRoot));
970
+ const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(repositoryRoot));
1143
971
  const hasPullRequest = fact?.state === 'bound';
1144
972
  let inspected: Awaited<ReturnType<typeof inspectPlatformPullRequest>> | null = null;
1145
973
  if (hasPullRequest) {
@@ -1313,7 +1141,7 @@ function resolvePostReviewExemption(content: string):
1313
1141
  }
1314
1142
  }
1315
1143
 
1316
- function checkReviewFact({ taskDir, artifactFile }: any): any {
1144
+ function checkReviewFact({ taskDir, artifactFile, repositoryRoot }: any): any {
1317
1145
  const resolvedArtifact = resolveArtifactPath(
1318
1146
  taskDir,
1319
1147
  "review-code.md|review-code-r{N}.md",
@@ -1397,7 +1225,7 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
1397
1225
  mode: "worktree",
1398
1226
  baseline,
1399
1227
  diffBase,
1400
- globs: resolvePostReviewGlobs({}, loadPostReviewConfig(repoRoot))
1228
+ globs: resolvePostReviewGlobs({}, loadPostReviewConfig(repositoryRoot))
1401
1229
  });
1402
1230
  } catch {
1403
1231
  return blockedResult(
@@ -1524,46 +1352,13 @@ function resolveArtifactPath(taskDir: any, filePattern: any, artifactFile: any):
1524
1352
  return { ok: true, path: path.join(taskDir, matches[0]!.fileName) };
1525
1353
  }
1526
1354
 
1527
- function getSectionContent(content: any, names: any): any {
1528
- const lines = content.split(/\r?\n/);
1529
-
1530
- function visibleHeadings(): any {
1531
- const headings = [];
1532
- let fence = null;
1533
- for (let index = 0; index < lines.length; index += 1) {
1534
- const line = lines[index];
1535
- if (fence) {
1536
- const closer = line.match(/^ {0,3}(`+|~+)\s*$/);
1537
- if (closer && closer[1][0] === fence.character && closer[1].length >= fence.length) {
1538
- fence = null;
1539
- }
1540
- continue;
1541
- }
1542
- const opener = line.match(/^ {0,3}(`{3,}|~{3,})(?:[^`~].*)?$/);
1543
- if (opener) {
1544
- fence = { character: opener[1][0], length: opener[1].length };
1545
- continue;
1546
- }
1547
- if (line.startsWith("## ")) {
1548
- headings.push({ index, text: line.trim() });
1549
- }
1550
- }
1551
- return headings;
1552
- }
1553
-
1554
- const headings = visibleHeadings();
1555
-
1355
+ function getSectionContent(content: string, names: readonly string[]): string {
1356
+ const headings = scanVisibleMarkdown(content).headings.filter((heading) => heading.level === 2);
1556
1357
  for (const name of names) {
1557
- const heading = `## ${name}`;
1558
- const position = headings.findIndex((item: any) => item.text === heading);
1559
- if (position === -1) {
1560
- continue;
1561
- }
1562
- const startIndex = headings[position]!.index;
1563
- const endIndex = headings[position + 1]?.index ?? lines.length;
1564
- return lines.slice(startIndex + 1, endIndex).join("\n").trim();
1358
+ const position = headings.findIndex((heading) => heading.text === name);
1359
+ if (position === -1) continue;
1360
+ return content.slice(headings[position]!.end + 1, headings[position + 1]?.start ?? content.length).replace(/\r\n/g, "\n").trim();
1565
1361
  }
1566
-
1567
1362
  return "";
1568
1363
  }
1569
1364
 
@@ -1691,14 +1486,14 @@ function isBlank(value: any): any {
1691
1486
  }
1692
1487
 
1693
1488
  async function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: requestedChecks, repositoryRoot }: any): Promise<any> {
1694
- if (repositoryRoot) repoRoot = path.resolve(repositoryRoot);
1695
- else {
1489
+ let repoRoot = repositoryRoot ? path.resolve(repositoryRoot) : defaultRepoRoot;
1490
+ if (!repositoryRoot) {
1696
1491
  let cursor = path.resolve(taskDir);
1697
1492
  while (path.dirname(cursor) !== cursor && !fs.existsSync(path.join(cursor, ".agents"))) cursor = path.dirname(cursor);
1698
1493
  if (fs.existsSync(path.join(cursor, ".agents"))) repoRoot = cursor;
1699
1494
  }
1700
1495
  const verifyConfig = loadVerificationConfig(repoRoot, skillName);
1701
- const shared = { ...sharedUtils, repoRoot };
1496
+ const shared: VerificationShared = { ...sharedUtils, repoRoot };
1702
1497
  if (mode === "gate") {
1703
1498
  const checks = [];
1704
1499
  for (const [type, checkConfig] of Object.entries(verifyConfig.checks || {})) {