@fitlab-ai/agent-infra 0.9.1 → 0.9.3

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 (476) hide show
  1. package/README.md +24 -11
  2. package/README.zh-CN.md +24 -11
  3. package/bin/cli.ts +12 -0
  4. package/dist/bin/cli.js +14 -0
  5. package/dist/bin/internal-cli.js +30 -0
  6. package/dist/lib/agent-client.js +163 -0
  7. package/dist/lib/agent-clients/adapter.js +337 -0
  8. package/dist/lib/agent-clients/adapters/antigravity-cli.js +64 -0
  9. package/dist/lib/agent-clients/adapters/claude-code.js +71 -0
  10. package/dist/lib/agent-clients/adapters/codex-sandbox.js +210 -0
  11. package/dist/lib/agent-clients/adapters/codex.js +63 -0
  12. package/dist/lib/agent-clients/adapters/index.js +20 -0
  13. package/dist/lib/agent-clients/adapters/opencode.js +73 -0
  14. package/dist/lib/agent-clients/config.js +215 -0
  15. package/dist/lib/agent-clients/custom-tuis.js +99 -0
  16. package/dist/lib/agent-clients/invocation.js +9 -0
  17. package/dist/lib/agent-clients/next-steps.js +47 -0
  18. package/dist/lib/agent-clients/project-assets.js +45 -0
  19. package/dist/lib/agent-clients/reconcile.js +236 -0
  20. package/dist/lib/agent-clients/registry.js +78 -0
  21. package/dist/lib/agent-clients/schema.js +75 -0
  22. package/dist/lib/agent-clients/tokens.js +49 -0
  23. package/dist/lib/agent-clients/types.js +29 -0
  24. package/dist/lib/builtin-tuis.js +9 -14
  25. package/dist/lib/defaults.json +85 -73
  26. package/dist/lib/git/review-snapshot.js +25 -10
  27. package/dist/lib/git/reviewed-commit-equivalence.js +110 -0
  28. package/dist/lib/git/workflow.js +54 -1
  29. package/dist/lib/init.js +47 -91
  30. package/dist/lib/internal/agent-client.js +174 -0
  31. package/dist/lib/internal/git-workflow.js +7 -2
  32. package/dist/lib/internal/platform-checks.js +3 -3
  33. package/dist/lib/internal/platform-comment.js +29 -2
  34. package/dist/lib/internal/platform-issue.js +7 -0
  35. package/dist/lib/internal/platform-pr-review.js +132 -0
  36. package/dist/lib/internal/platform-pr.js +20 -2
  37. package/dist/lib/internal/platform-release-notes.js +52 -16
  38. package/dist/lib/internal/pr-review-grade.js +140 -0
  39. package/dist/lib/internal/release-workflow.js +82 -20
  40. package/dist/lib/internal/task-activity.js +73 -0
  41. package/dist/lib/internal/task-event.js +17 -1
  42. package/dist/lib/internal/task-lifecycle.js +7 -0
  43. package/dist/lib/internal/task-orchestration.js +196 -0
  44. package/dist/lib/internal/task-review.js +70 -0
  45. package/dist/lib/merge.js +2 -1
  46. package/dist/lib/platform/adapters.js +45 -1
  47. package/dist/lib/platform/change-request-git-evidence.js +113 -0
  48. package/dist/lib/platform/completion-backfill.js +122 -0
  49. package/dist/lib/platform/issue-comments.js +3 -2
  50. package/dist/lib/platform/merged-pr-equivalence.js +156 -16
  51. package/dist/lib/platform/pr-checks.js +101 -50
  52. package/dist/lib/platform/pr-review.js +166 -0
  53. package/dist/lib/platform/pull-requests.js +432 -7
  54. package/dist/lib/platform/release-notes.js +85 -3
  55. package/dist/lib/platform/releases.js +1 -1
  56. package/dist/lib/platform/verification-required.js +8 -10
  57. package/dist/lib/pr-review/evidence-grading.js +229 -0
  58. package/dist/lib/prompt.js +15 -3
  59. package/dist/lib/release/channels.js +4 -1
  60. package/dist/lib/release/workflow.js +4 -2
  61. package/dist/lib/remove-dir.js +25 -0
  62. package/dist/lib/run/tui.js +11 -7
  63. package/dist/lib/sandbox/agent-client-reconciler.js +234 -0
  64. package/dist/lib/sandbox/clipboard/linux.js +2 -1
  65. package/dist/lib/sandbox/commands/create.js +76 -200
  66. package/dist/lib/sandbox/commands/enter.js +17 -1
  67. package/dist/lib/sandbox/commands/prune.js +2 -2
  68. package/dist/lib/sandbox/commands/rm.js +3 -2
  69. package/dist/lib/sandbox/commands/show.js +1 -1
  70. package/dist/lib/sandbox/config.js +21 -4
  71. package/dist/lib/sandbox/constants.js +3 -0
  72. package/dist/lib/sandbox/dockerfile.js +2 -1
  73. package/dist/lib/sandbox/managed-fs.js +10 -5
  74. package/dist/lib/sandbox/recovery.js +52 -36
  75. package/dist/lib/sandbox/shell.js +1 -1
  76. package/dist/lib/sandbox/tool-types.js +8 -0
  77. package/dist/lib/sandbox/tools.js +2 -126
  78. package/dist/lib/task/activity-intent.js +101 -0
  79. package/dist/lib/task/artifact-lifecycle.js +3 -50
  80. package/dist/lib/task/commands/decisions.js +50 -20
  81. package/dist/lib/task/commands/log.js +15 -14
  82. package/dist/lib/task/delegation-receipts.js +128 -0
  83. package/dist/lib/task/events.js +146 -8
  84. package/dist/lib/task/finalization-artifacts.js +35 -0
  85. package/dist/lib/task/lifecycle-execution.js +46 -0
  86. package/dist/lib/task/orchestration.js +784 -0
  87. package/dist/lib/task/review-artifacts.js +143 -59
  88. package/dist/lib/task/review-finalization.js +186 -0
  89. package/dist/lib/task/review-fingerprint.js +4 -0
  90. package/dist/lib/task/task-execution-lock.js +231 -0
  91. package/dist/lib/task/verification-checks.js +2 -1
  92. package/dist/lib/task/verification-engine.js +372 -28
  93. package/dist/lib/task/verification-review.js +1 -1
  94. package/dist/lib/task/verification.js +5 -2
  95. package/dist/lib/task/workspace-snapshot.js +46 -0
  96. package/dist/lib/update.js +42 -161
  97. package/lib/agent-client.ts +214 -0
  98. package/lib/agent-clients/adapter.ts +534 -0
  99. package/lib/agent-clients/adapters/antigravity-cli.ts +65 -0
  100. package/lib/agent-clients/adapters/claude-code.ts +79 -0
  101. package/lib/agent-clients/adapters/codex-sandbox.ts +245 -0
  102. package/lib/agent-clients/adapters/codex.ts +67 -0
  103. package/lib/agent-clients/adapters/index.ts +27 -0
  104. package/lib/agent-clients/adapters/opencode.ts +75 -0
  105. package/lib/agent-clients/config.ts +323 -0
  106. package/lib/agent-clients/custom-tuis.ts +149 -0
  107. package/lib/agent-clients/invocation.ts +19 -0
  108. package/lib/agent-clients/next-steps.ts +85 -0
  109. package/lib/agent-clients/project-assets.ts +96 -0
  110. package/lib/agent-clients/reconcile.ts +325 -0
  111. package/lib/agent-clients/registry.ts +154 -0
  112. package/lib/agent-clients/schema.ts +80 -0
  113. package/lib/agent-clients/tokens.ts +53 -0
  114. package/lib/agent-clients/types.ts +92 -0
  115. package/lib/benchmark/schemas/v1.0.0/case-manifest.schema.json +120 -0
  116. package/lib/benchmark/schemas/v1.0.0/common.schema.json +109 -0
  117. package/lib/benchmark/schemas/v1.0.0/grader-result.schema.json +160 -0
  118. package/lib/benchmark/schemas/v1.0.0/run-manifest.schema.json +122 -0
  119. package/lib/benchmark/schemas/v1.0.0/subject.schema.json +227 -0
  120. package/lib/builtin-tuis.ts +16 -15
  121. package/lib/defaults.json +24 -12
  122. package/lib/git/review-snapshot.ts +39 -9
  123. package/lib/git/reviewed-commit-equivalence.ts +135 -0
  124. package/lib/git/workflow.ts +66 -2
  125. package/lib/init.ts +53 -121
  126. package/lib/internal/agent-client.ts +186 -0
  127. package/lib/internal/git-workflow.ts +6 -2
  128. package/lib/internal/platform-checks.ts +4 -4
  129. package/lib/internal/platform-comment.ts +17 -2
  130. package/lib/internal/platform-issue.ts +4 -0
  131. package/lib/internal/platform-pr-review.ts +104 -0
  132. package/lib/internal/platform-pr.ts +14 -1
  133. package/lib/internal/platform-release-notes.ts +59 -16
  134. package/lib/internal/pr-review-grade.ts +130 -0
  135. package/lib/internal/release-workflow.ts +79 -20
  136. package/lib/internal/task-activity.ts +55 -0
  137. package/lib/internal/task-event.ts +9 -1
  138. package/lib/internal/task-lifecycle.ts +4 -0
  139. package/lib/internal/task-orchestration.ts +171 -0
  140. package/lib/internal/task-review.ts +70 -0
  141. package/lib/merge.ts +2 -1
  142. package/lib/platform/adapters.ts +169 -3
  143. package/lib/platform/change-request-git-evidence.ts +159 -0
  144. package/lib/platform/completion-backfill.ts +134 -0
  145. package/lib/platform/issue-comments.ts +3 -2
  146. package/lib/platform/merged-pr-equivalence.ts +178 -19
  147. package/lib/platform/pr-checks.ts +121 -66
  148. package/lib/platform/pr-review.ts +201 -0
  149. package/lib/platform/pull-requests.ts +529 -27
  150. package/lib/platform/release-notes.ts +100 -4
  151. package/lib/platform/releases.ts +1 -1
  152. package/lib/platform/verification-required.ts +12 -10
  153. package/lib/pr-review/evidence-grading.ts +318 -0
  154. package/lib/prompt.ts +16 -3
  155. package/lib/release/channels.ts +4 -1
  156. package/lib/release/workflow.ts +4 -3
  157. package/lib/remove-dir.ts +28 -0
  158. package/lib/run/tui.ts +12 -5
  159. package/lib/sandbox/agent-client-reconciler.ts +378 -0
  160. package/lib/sandbox/clipboard/linux.ts +2 -1
  161. package/lib/sandbox/commands/create.ts +111 -212
  162. package/lib/sandbox/commands/enter.ts +23 -1
  163. package/lib/sandbox/commands/prune.ts +2 -2
  164. package/lib/sandbox/commands/rm.ts +3 -2
  165. package/lib/sandbox/commands/show.ts +1 -1
  166. package/lib/sandbox/config.ts +31 -4
  167. package/lib/sandbox/constants.ts +6 -0
  168. package/lib/sandbox/dockerfile.ts +2 -1
  169. package/lib/sandbox/managed-fs.ts +18 -5
  170. package/lib/sandbox/recovery.ts +98 -67
  171. package/lib/sandbox/shell.ts +1 -1
  172. package/lib/sandbox/tool-types.ts +143 -0
  173. package/lib/sandbox/tools.ts +5 -157
  174. package/lib/server/server.schema.json +2 -2
  175. package/lib/task/activity-intent.ts +128 -0
  176. package/lib/task/artifact-lifecycle.ts +3 -39
  177. package/lib/task/commands/decisions.ts +53 -20
  178. package/lib/task/commands/log.ts +15 -14
  179. package/lib/task/delegation-receipts.ts +199 -0
  180. package/lib/task/events.ts +164 -11
  181. package/lib/task/finalization-artifacts.ts +58 -0
  182. package/lib/task/lifecycle-execution.ts +106 -0
  183. package/lib/task/orchestration.ts +1022 -0
  184. package/lib/task/review-artifacts.ts +201 -69
  185. package/lib/task/review-finalization.ts +306 -0
  186. package/lib/task/review-fingerprint.ts +5 -0
  187. package/lib/task/task-execution-lock.ts +296 -0
  188. package/lib/task/verification-checks.ts +2 -1
  189. package/lib/task/verification-engine.ts +424 -28
  190. package/lib/task/verification-review.ts +1 -0
  191. package/lib/task/verification.ts +8 -3
  192. package/lib/task/workspace-snapshot.ts +57 -0
  193. package/lib/update.ts +48 -184
  194. package/package.json +4 -4
  195. package/templates/.agents/QUICKSTART.en.md +25 -8
  196. package/templates/.agents/QUICKSTART.zh-CN.md +25 -8
  197. package/templates/.agents/README.en.md +29 -25
  198. package/templates/.agents/README.zh-CN.md +29 -25
  199. package/templates/.agents/hooks/lifecycle-delegation.js +75 -0
  200. package/templates/.agents/rules/README.en.md +2 -0
  201. package/templates/.agents/rules/README.zh-CN.md +2 -0
  202. package/templates/.agents/rules/commit-and-pr.en.md +1 -0
  203. package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -0
  204. package/templates/.agents/rules/create-issue.github.en.md +4 -2
  205. package/templates/.agents/rules/create-issue.github.zh-CN.md +4 -2
  206. package/templates/.agents/rules/human-decision-context.en.md +14 -12
  207. package/templates/.agents/rules/human-decision-context.zh-CN.md +14 -12
  208. package/templates/.agents/rules/issue-fields.github.en.md +3 -1
  209. package/templates/.agents/rules/issue-fields.github.zh-CN.md +3 -1
  210. package/templates/.agents/rules/issue-pr-commands.en.md +5 -3
  211. package/templates/.agents/rules/issue-pr-commands.github.en.md +5 -3
  212. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +5 -3
  213. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +5 -3
  214. package/templates/.agents/rules/issue-sync.github.en.md +7 -3
  215. package/templates/.agents/rules/issue-sync.github.zh-CN.md +8 -4
  216. package/templates/.agents/rules/lifecycle-orchestration.en.md +24 -0
  217. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +24 -0
  218. package/templates/.agents/rules/milestone-inference.github.en.md +4 -2
  219. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +4 -2
  220. package/templates/.agents/rules/next-step-output.en.md +18 -0
  221. package/templates/.agents/rules/next-step-output.zh-CN.md +18 -0
  222. package/templates/.agents/rules/no-mid-flow-questions.en.md +19 -0
  223. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +19 -0
  224. package/templates/.agents/rules/pr-checks-commands.en.md +3 -3
  225. package/templates/.agents/rules/pr-checks-commands.github.en.md +2 -2
  226. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +2 -2
  227. package/templates/.agents/rules/pr-checks-commands.zh-CN.md +3 -3
  228. package/templates/.agents/rules/pr-sync.en.md +3 -1
  229. package/templates/.agents/rules/pr-sync.github.en.md +11 -1
  230. package/templates/.agents/rules/pr-sync.github.zh-CN.md +11 -1
  231. package/templates/.agents/rules/pr-sync.zh-CN.md +3 -1
  232. package/templates/.agents/rules/release-commands.en.md +1 -1
  233. package/templates/.agents/rules/release-commands.github.en.md +21 -5
  234. package/templates/.agents/rules/release-commands.github.zh-CN.md +21 -5
  235. package/templates/.agents/rules/release-commands.zh-CN.md +1 -1
  236. package/templates/.agents/rules/review-handshake.en.md +4 -4
  237. package/templates/.agents/rules/review-handshake.zh-CN.md +4 -4
  238. package/templates/.agents/rules/review-method.en.md +113 -0
  239. package/templates/.agents/rules/review-method.zh-CN.md +98 -0
  240. package/templates/.agents/rules/task-management.en.md +11 -0
  241. package/templates/.agents/rules/task-management.zh-CN.md +11 -0
  242. package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -12
  243. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +15 -12
  244. package/templates/.agents/skills/block-task/SKILL.en.md +11 -9
  245. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +11 -9
  246. package/templates/.agents/skills/cancel-task/SKILL.en.md +10 -8
  247. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +11 -9
  248. package/templates/.agents/skills/check-task/SKILL.en.md +16 -16
  249. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -16
  250. package/templates/.agents/skills/close-codescan/SKILL.en.md +7 -5
  251. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +7 -5
  252. package/templates/.agents/skills/close-dependabot/SKILL.en.md +7 -5
  253. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +7 -5
  254. package/templates/.agents/skills/code-task/SKILL.en.md +10 -7
  255. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +13 -10
  256. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +14 -16
  257. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +14 -16
  258. package/templates/.agents/skills/code-task/reference/output-template.en.md +3 -3
  259. package/templates/.agents/skills/code-task/reference/output-template.zh-CN.md +3 -3
  260. package/templates/.agents/skills/commit/SKILL.en.md +13 -1
  261. package/templates/.agents/skills/commit/SKILL.zh-CN.md +13 -1
  262. package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -1
  263. package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -1
  264. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
  265. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
  266. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  267. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  268. package/templates/.agents/skills/commit/reference/task-status-update.en.md +24 -28
  269. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +24 -28
  270. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +6 -4
  271. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +6 -4
  272. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +1 -1
  273. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
  274. package/templates/.agents/skills/complete-task/SKILL.en.md +23 -8
  275. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +23 -8
  276. package/templates/.agents/skills/complete-task/config/verify.en.json +1 -0
  277. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +1 -0
  278. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +17 -0
  279. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +17 -0
  280. package/templates/.agents/skills/create-pr/SKILL.en.md +13 -11
  281. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +13 -11
  282. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +1 -1
  283. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +1 -1
  284. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +3 -3
  285. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +3 -3
  286. package/templates/.agents/skills/create-release-note/SKILL.en.md +17 -16
  287. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +17 -16
  288. package/templates/.agents/skills/create-task/SKILL.en.md +16 -14
  289. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +16 -14
  290. package/templates/.agents/skills/import-codescan/SKILL.en.md +5 -5
  291. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +5 -5
  292. package/templates/.agents/skills/import-dependabot/SKILL.en.md +5 -5
  293. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +5 -5
  294. package/templates/.agents/skills/import-issue/SKILL.en.md +10 -8
  295. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +10 -8
  296. package/templates/.agents/skills/init-labels/SKILL.en.md +4 -4
  297. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +4 -4
  298. package/templates/.agents/skills/init-milestones/SKILL.en.md +4 -4
  299. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +4 -4
  300. package/templates/.agents/skills/plan-task/SKILL.en.md +13 -10
  301. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +13 -10
  302. package/templates/.agents/skills/post-release/SKILL.en.md +2 -0
  303. package/templates/.agents/skills/post-release/SKILL.zh-CN.md +2 -0
  304. package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
  305. package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
  306. package/templates/.agents/skills/release/SKILL.en.md +16 -10
  307. package/templates/.agents/skills/release/SKILL.zh-CN.md +16 -10
  308. package/templates/.agents/skills/restore-task/SKILL.en.md +4 -1
  309. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +4 -1
  310. package/templates/.agents/skills/review-analysis/SKILL.en.md +18 -4
  311. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +19 -5
  312. package/templates/.agents/skills/review-analysis/config/verify.en.json +6 -0
  313. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +6 -0
  314. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +13 -15
  315. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +13 -15
  316. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +51 -5
  317. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +52 -6
  318. package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +25 -22
  319. package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +25 -22
  320. package/templates/.agents/skills/review-code/SKILL.en.md +35 -12
  321. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +35 -12
  322. package/templates/.agents/skills/review-code/config/verify.en.json +7 -0
  323. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +7 -0
  324. package/templates/.agents/skills/review-code/reference/concurrency-risks.en.md +25 -0
  325. package/templates/.agents/skills/review-code/reference/concurrency-risks.zh-CN.md +25 -0
  326. package/templates/.agents/skills/review-code/reference/cross-platform-risks.en.md +27 -0
  327. package/templates/.agents/skills/review-code/reference/cross-platform-risks.zh-CN.md +27 -0
  328. package/templates/.agents/skills/review-code/reference/documentation-antipatterns.en.md +13 -0
  329. package/templates/.agents/skills/review-code/reference/documentation-antipatterns.zh-CN.md +13 -0
  330. package/templates/.agents/skills/review-code/reference/migration-risks.en.md +25 -0
  331. package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +25 -0
  332. package/templates/.agents/skills/review-code/reference/output-templates.en.md +22 -24
  333. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +22 -24
  334. package/templates/.agents/skills/review-code/reference/report-template.en.md +54 -7
  335. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +54 -7
  336. package/templates/.agents/skills/review-code/reference/review-criteria.en.md +29 -24
  337. package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +29 -24
  338. package/templates/.agents/skills/review-code/reference/security-risks.en.md +25 -0
  339. package/templates/.agents/skills/review-code/reference/security-risks.zh-CN.md +25 -0
  340. package/templates/.agents/skills/review-plan/SKILL.en.md +18 -4
  341. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +19 -5
  342. package/templates/.agents/skills/review-plan/config/verify.en.json +6 -0
  343. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +6 -0
  344. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +13 -15
  345. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +13 -15
  346. package/templates/.agents/skills/review-plan/reference/report-template.en.md +61 -5
  347. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +61 -5
  348. package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +21 -24
  349. package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +21 -24
  350. package/templates/.agents/skills/review-pr/SKILL.en.md +158 -0
  351. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +158 -0
  352. package/templates/.agents/skills/review-pr/config/verify.en.json +37 -0
  353. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +37 -0
  354. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +65 -0
  355. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +65 -0
  356. package/templates/.agents/skills/review-pr/reference/output-guidance.en.md +18 -0
  357. package/templates/.agents/skills/review-pr/reference/output-guidance.zh-CN.md +18 -0
  358. package/templates/.agents/skills/review-pr/reference/report-template.en.md +85 -0
  359. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +85 -0
  360. package/templates/.agents/skills/run-task/SKILL.en.md +22 -0
  361. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +22 -0
  362. package/templates/.agents/skills/run-task/config/verify.en.json +10 -0
  363. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +10 -0
  364. package/templates/.agents/skills/run-task/reference/host-validation.en.md +20 -0
  365. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +20 -0
  366. package/templates/.agents/skills/test/SKILL.en.md +4 -4
  367. package/templates/.agents/skills/test/SKILL.zh-CN.md +4 -4
  368. package/templates/.agents/skills/test-integration/SKILL.en.md +4 -4
  369. package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +4 -4
  370. package/templates/.agents/skills/update-agent-infra/SKILL.en.md +5 -5
  371. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +5 -5
  372. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +664 -246
  373. package/templates/.agents/skills/upgrade-dependency/SKILL.en.md +4 -4
  374. package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +4 -4
  375. package/templates/.agents/skills/watch-pr/SKILL.en.md +21 -21
  376. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +21 -21
  377. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +27 -6
  378. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +26 -5
  379. package/templates/.agents/templates/task.en.md +1 -1
  380. package/templates/.agents/templates/task.zh-CN.md +1 -1
  381. package/templates/.agents/workflows/bug-fix.en.yaml +3 -3
  382. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +3 -3
  383. package/templates/.agents/workflows/code-review.en.yaml +1 -1
  384. package/templates/.agents/workflows/code-review.zh-CN.yaml +1 -1
  385. package/templates/.agents/workflows/feature-development.en.yaml +4 -4
  386. package/templates/.agents/workflows/feature-development.zh-CN.yaml +4 -4
  387. package/templates/.agents/workflows/refactoring.en.yaml +3 -3
  388. package/templates/.agents/workflows/refactoring.zh-CN.yaml +3 -3
  389. package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +6 -0
  390. package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +6 -0
  391. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +6 -0
  392. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +6 -0
  393. package/templates/.claude/commands/post-release.en.md +1 -0
  394. package/templates/.claude/commands/post-release.zh-CN.md +1 -0
  395. package/templates/.claude/commands/review-pr.en.md +8 -0
  396. package/templates/.claude/commands/review-pr.zh-CN.md +8 -0
  397. package/templates/.claude/commands/run-task.en.md +8 -0
  398. package/templates/.claude/commands/run-task.zh-CN.md +8 -0
  399. package/templates/.claude/settings.json +24 -0
  400. package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +3 -0
  401. package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +3 -0
  402. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +3 -0
  403. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +3 -0
  404. package/templates/.gemini/commands/_project_/review-pr.en.toml +10 -0
  405. package/templates/.gemini/commands/_project_/review-pr.zh-CN.toml +10 -0
  406. package/templates/.opencode/commands/post-release.en.md +2 -0
  407. package/templates/.opencode/commands/post-release.zh-CN.md +2 -0
  408. package/templates/.opencode/commands/review-pr.en.md +11 -0
  409. package/templates/.opencode/commands/review-pr.zh-CN.md +11 -0
  410. package/templates/.opencode/commands/run-task.en.md +11 -0
  411. package/templates/.opencode/commands/run-task.zh-CN.md +11 -0
  412. package/templates/.gemini/commands/_project_/analyze-task.en.toml +0 -10
  413. package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +0 -10
  414. package/templates/.gemini/commands/_project_/archive-tasks.en.toml +0 -10
  415. package/templates/.gemini/commands/_project_/archive-tasks.zh-CN.toml +0 -10
  416. package/templates/.gemini/commands/_project_/block-task.en.toml +0 -10
  417. package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +0 -10
  418. package/templates/.gemini/commands/_project_/cancel-task.en.toml +0 -10
  419. package/templates/.gemini/commands/_project_/cancel-task.zh-CN.toml +0 -10
  420. package/templates/.gemini/commands/_project_/check-task.en.toml +0 -10
  421. package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +0 -10
  422. package/templates/.gemini/commands/_project_/close-codescan.en.toml +0 -8
  423. package/templates/.gemini/commands/_project_/close-codescan.zh-CN.toml +0 -8
  424. package/templates/.gemini/commands/_project_/close-dependabot.en.toml +0 -8
  425. package/templates/.gemini/commands/_project_/close-dependabot.zh-CN.toml +0 -8
  426. package/templates/.gemini/commands/_project_/code-task.en.toml +0 -10
  427. package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +0 -10
  428. package/templates/.gemini/commands/_project_/commit.en.toml +0 -10
  429. package/templates/.gemini/commands/_project_/commit.zh-CN.toml +0 -10
  430. package/templates/.gemini/commands/_project_/complete-manual-validation.en.toml +0 -10
  431. package/templates/.gemini/commands/_project_/complete-manual-validation.zh-CN.toml +0 -10
  432. package/templates/.gemini/commands/_project_/complete-task.en.toml +0 -10
  433. package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +0 -10
  434. package/templates/.gemini/commands/_project_/create-pr.en.toml +0 -10
  435. package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +0 -10
  436. package/templates/.gemini/commands/_project_/create-release-note.en.toml +0 -8
  437. package/templates/.gemini/commands/_project_/create-release-note.zh-CN.toml +0 -8
  438. package/templates/.gemini/commands/_project_/create-task.en.toml +0 -8
  439. package/templates/.gemini/commands/_project_/create-task.zh-CN.toml +0 -8
  440. package/templates/.gemini/commands/_project_/import-codescan.en.toml +0 -8
  441. package/templates/.gemini/commands/_project_/import-codescan.zh-CN.toml +0 -8
  442. package/templates/.gemini/commands/_project_/import-dependabot.en.toml +0 -8
  443. package/templates/.gemini/commands/_project_/import-dependabot.zh-CN.toml +0 -8
  444. package/templates/.gemini/commands/_project_/import-issue.en.toml +0 -8
  445. package/templates/.gemini/commands/_project_/import-issue.zh-CN.toml +0 -8
  446. package/templates/.gemini/commands/_project_/init-labels.en.toml +0 -8
  447. package/templates/.gemini/commands/_project_/init-labels.zh-CN.toml +0 -8
  448. package/templates/.gemini/commands/_project_/init-milestones.en.toml +0 -10
  449. package/templates/.gemini/commands/_project_/init-milestones.zh-CN.toml +0 -10
  450. package/templates/.gemini/commands/_project_/plan-task.en.toml +0 -10
  451. package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +0 -10
  452. package/templates/.gemini/commands/_project_/post-release.en.toml +0 -6
  453. package/templates/.gemini/commands/_project_/post-release.zh-CN.toml +0 -6
  454. package/templates/.gemini/commands/_project_/refine-title.en.toml +0 -8
  455. package/templates/.gemini/commands/_project_/refine-title.zh-CN.toml +0 -8
  456. package/templates/.gemini/commands/_project_/release.en.toml +0 -8
  457. package/templates/.gemini/commands/_project_/release.zh-CN.toml +0 -8
  458. package/templates/.gemini/commands/_project_/restore-task.en.toml +0 -8
  459. package/templates/.gemini/commands/_project_/restore-task.zh-CN.toml +0 -8
  460. package/templates/.gemini/commands/_project_/review-analysis.en.toml +0 -10
  461. package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +0 -10
  462. package/templates/.gemini/commands/_project_/review-code.en.toml +0 -10
  463. package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +0 -10
  464. package/templates/.gemini/commands/_project_/review-plan.en.toml +0 -10
  465. package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +0 -10
  466. package/templates/.gemini/commands/_project_/test-integration.en.toml +0 -6
  467. package/templates/.gemini/commands/_project_/test-integration.zh-CN.toml +0 -6
  468. package/templates/.gemini/commands/_project_/test.en.toml +0 -6
  469. package/templates/.gemini/commands/_project_/test.zh-CN.toml +0 -6
  470. package/templates/.gemini/commands/_project_/update-agent-infra.en.toml +0 -6
  471. package/templates/.gemini/commands/_project_/update-agent-infra.zh-CN.toml +0 -6
  472. package/templates/.gemini/commands/_project_/upgrade-dependency.en.toml +0 -8
  473. package/templates/.gemini/commands/_project_/upgrade-dependency.zh-CN.toml +0 -8
  474. package/templates/.gemini/commands/_project_/watch-pr.en.toml +0 -10
  475. package/templates/.gemini/commands/_project_/watch-pr.zh-CN.toml +0 -10
  476. package/templates/.gemini/settings.json +0 -3
@@ -1,13 +1,15 @@
1
- // Shared helpers for review-artifact parsing.
2
- // Imported by typed artifact lifecycle and verification so the round/verdict vocabulary stays
3
- // in a single source of truth (prevents the cross-file drift this lifecycle
4
- // is designed to eliminate).
5
- import fs from "node:fs";
6
- import path from "node:path";
7
- export function escapeRegExp(value) {
8
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ const SUMMARY_HEADINGS = new Set(['审查摘要', 'Review Summary']);
4
+ const PLACEHOLDERS = [
5
+ '{unresolved-blockers}',
6
+ '{unresolved-major}',
7
+ '{unresolved-minor}'
8
+ ];
9
+ function escapeRegExp(value) {
10
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
9
11
  }
10
- export function maxRound(entries, stem) {
12
+ function maxRound(entries, stem) {
11
13
  let max = 0;
12
14
  for (const entry of entries) {
13
15
  if (entry === `${stem}.md`) {
@@ -15,87 +17,169 @@ export function maxRound(entries, stem) {
15
17
  continue;
16
18
  }
17
19
  const match = entry.match(new RegExp(`^${escapeRegExp(stem)}-r(\\d+)\\.md$`));
18
- if (match) {
20
+ if (match)
19
21
  max = Math.max(max, Number(match[1]));
20
- }
21
22
  }
22
23
  return max;
23
24
  }
24
- export function artifactName(stem, round) {
25
+ function artifactName(stem, round) {
25
26
  return round === 1 ? `${stem}.md` : `${stem}-r${round}.md`;
26
27
  }
27
- export function normalizeVerdict(raw) {
28
+ function normalizeVerdict(raw) {
28
29
  const value = String(raw).trim().toLowerCase();
29
- if (value === "通过" || value === "approved") {
30
- return "Approved";
31
- }
32
- if (value === "需要修改" || value === "changes requested") {
33
- return "Changes Requested";
34
- }
35
- if (value === "拒绝" || value === "rejected") {
36
- return "Rejected";
37
- }
38
- return "";
30
+ if (value === '通过' || value === 'approved')
31
+ return 'Approved';
32
+ if (value === '需要修改' || value === 'changes requested')
33
+ return 'Changes Requested';
34
+ if (value === '拒绝' || value === 'rejected')
35
+ return 'Rejected';
36
+ return '';
39
37
  }
40
- export function extractSection(content, names) {
38
+ function extractSection(content, names) {
41
39
  const lines = content.split(/\r?\n/);
42
40
  const nameSet = new Set(names);
43
41
  const start = lines.findIndex((line) => {
44
42
  const match = line.trim().match(/^##\s+(.+?)\s*$/);
45
43
  return match ? nameSet.has(match[1]) : false;
46
44
  });
47
- if (start === -1) {
48
- return "";
49
- }
45
+ if (start === -1)
46
+ return '';
50
47
  const sectionLines = [];
51
48
  for (let index = start + 1; index < lines.length; index += 1) {
52
- if (/^##\s+/.test(lines[index])) {
49
+ if (/^##\s+/.test(lines[index]))
53
50
  break;
54
- }
55
51
  sectionLines.push(lines[index]);
56
52
  }
57
- return sectionLines.join("\n");
53
+ return sectionLines.join('\n');
58
54
  }
59
- // Parse the canonical verdict out of a review-* artifact.
60
- // Returns { ok, verdict, message }. Verdict collapses Approved into
61
- // "Approved-with-issues" when the findings counts are non-zero.
62
- export function parseVerdict(reviewPath) {
63
- if (!fs.existsSync(reviewPath)) {
64
- return { ok: false, verdict: null, message: `Review artifact not found: ${path.basename(reviewPath)}` };
55
+ function summaryBounds(content) {
56
+ const headings = [...content.matchAll(/^##\s+(.+?)\s*$/gm)]
57
+ .map((match) => ({ index: match.index, end: match.index + match[0].length, name: match[1] }));
58
+ const summaries = headings.filter((heading) => SUMMARY_HEADINGS.has(heading.name));
59
+ if (summaries.length !== 1)
60
+ return null;
61
+ const summary = summaries[0];
62
+ const next = headings.find((heading) => heading.index > summary.index);
63
+ return { start: summary.end, end: next?.index ?? content.length };
64
+ }
65
+ function uniqueLine(content, bounds, pattern) {
66
+ const section = content.slice(bounds.start, bounds.end);
67
+ const matches = [...section.matchAll(pattern)];
68
+ if (matches.length !== 1)
69
+ return null;
70
+ const match = matches[0];
71
+ return {
72
+ value: match[1],
73
+ start: bounds.start + match.index,
74
+ end: bounds.start + match.index + match[0].length
75
+ };
76
+ }
77
+ function parseCounts(value) {
78
+ const zh = /^(\d+)\s*阻塞项,\s*(\d+)\s*主要,\s*(\d+)\s*次要(?:\s*\/.*)?$/.exec(value);
79
+ const en = /^(\d+)\s*blockers?,\s*(\d+)\s*majors?,\s*(\d+)\s*minors?(?:\s*\/.*)?$/i.exec(value);
80
+ const match = zh ?? en;
81
+ if (!match)
82
+ return null;
83
+ const [blocker, major, minor] = match.slice(1, 4).map(Number);
84
+ if (![blocker, major, minor].every(Number.isSafeInteger))
85
+ return null;
86
+ return { blocker: blocker, major: major, minor: minor };
87
+ }
88
+ function parseManualValidation(value) {
89
+ const match = /\*\*(?:人工校验|Manual[- ]validation)\*\*[::]\s*(\d+)/i.exec(value);
90
+ if (!match)
91
+ return null;
92
+ const count = Number(match[1]);
93
+ return Number.isSafeInteger(count) ? count : null;
94
+ }
95
+ function hasCanonicalPlaceholders(value) {
96
+ const zh = /^\{unresolved-blockers\}\s*阻塞项,\s*\{unresolved-major\}\s*主要,\s*\{unresolved-minor\}\s*次要(?:\s*\/.*)?$/.test(value);
97
+ const en = /^\{unresolved-blockers\}\s*blockers?,\s*\{unresolved-major\}\s*majors?,\s*\{unresolved-minor\}\s*minors?(?:\s*\/.*)?$/i.test(value);
98
+ return zh || en;
99
+ }
100
+ function parseReviewSummary(content) {
101
+ const bounds = summaryBounds(content);
102
+ if (!bounds) {
103
+ return { ok: false, code: 'REVIEW_SUMMARY_NOT_FOUND', message: 'review artifact must contain one review summary section' };
65
104
  }
66
- const content = fs.readFileSync(reviewPath, "utf8");
67
- const summary = extractSection(content, ["审查摘要", "Review Summary"]);
68
- const fileName = path.basename(reviewPath);
69
- if (!summary) {
70
- return { ok: false, verdict: null, message: `cannot locate review summary section in ${fileName}` };
105
+ const verdictLine = uniqueLine(content, bounds, /^[-*]?\s*\*\*(?:总体结论|Overall Verdict)\*\*[::]\s*(.+?)\s*$/gim);
106
+ const findingsLine = uniqueLine(content, bounds, /^[-*]?\s*\*\*(?:发现(AI 可处理)|Findings \(AI-actionable\))\*\*[::]\s*(.+?)\s*$/gim);
107
+ const verdict = verdictLine ? normalizeVerdict(verdictLine.value) : '';
108
+ if (!verdict || !findingsLine) {
109
+ return { ok: false, code: 'REVIEW_SUMMARY_NOT_FOUND', message: 'review summary verdict or finding count line is missing or repeated' };
71
110
  }
72
- const verdictMatch = summary.match(/^[-*]?\s*\*\*(?:总体结论|Overall Verdict)\*\*[::]\s*(.+?)\s*$/im);
73
- if (!verdictMatch) {
74
- return { ok: false, verdict: null, message: `cannot parse verdict in ${fileName}` };
111
+ const counts = parseCounts(findingsLine.value);
112
+ if (counts) {
113
+ return {
114
+ ok: true,
115
+ summary: { verdict, counts, manualValidation: parseManualValidation(findingsLine.value), countState: 'numeric' },
116
+ findingsStart: findingsLine.start,
117
+ findingsEnd: findingsLine.end
118
+ };
75
119
  }
76
- const verdict = normalizeVerdict(verdictMatch[1]);
77
- if (!verdict) {
120
+ const placeholderOccurrences = PLACEHOLDERS.map((token) => ([...findingsLine.value.matchAll(new RegExp(escapeRegExp(token), 'g'))].length));
121
+ if (hasCanonicalPlaceholders(findingsLine.value) && placeholderOccurrences.every((count) => count === 1)) {
78
122
  return {
79
- ok: false,
80
- verdict: null,
81
- message: `unrecognized verdict '${verdictMatch[1].trim()}' in ${fileName}`
123
+ ok: true,
124
+ summary: { verdict, counts: null, manualValidation: parseManualValidation(findingsLine.value), countState: 'placeholders' },
125
+ findingsStart: findingsLine.start,
126
+ findingsEnd: findingsLine.end
82
127
  };
83
128
  }
84
- if (verdict !== "Approved") {
85
- return { ok: true, verdict };
129
+ return {
130
+ ok: false,
131
+ code: 'REVIEW_SUMMARY_PLACEHOLDER_INVALID',
132
+ message: 'review summary finding counts must be three canonical placeholders or non-negative integers'
133
+ };
134
+ }
135
+ function equalCounts(left, right) {
136
+ return left.blocker === right.blocker && left.major === right.major && left.minor === right.minor;
137
+ }
138
+ function finalizeReviewSummaryContent(content, counts) {
139
+ const parsed = parseReviewSummary(content);
140
+ if (!parsed.ok)
141
+ return parsed;
142
+ if (parsed.summary.countState === 'numeric') {
143
+ if (equalCounts(parsed.summary.counts, counts))
144
+ return { ok: true, changed: false, content };
145
+ return {
146
+ ok: false,
147
+ code: 'REVIEW_SUMMARY_COUNT_MISMATCH',
148
+ message: 'review summary finding counts do not match the ledger snapshot'
149
+ };
86
150
  }
87
- const findingsMatch = summary.match(/^[-*]?\s*\*\*(?:发现(AI 可处理)|Findings \(AI-actionable\))\*\*[::]\s*(.+?)\s*$/im);
88
- if (!findingsMatch) {
89
- return { ok: false, verdict, message: `cannot parse findings count in ${fileName}` };
151
+ let line = content.slice(parsed.findingsStart, parsed.findingsEnd);
152
+ line = line
153
+ .replace(PLACEHOLDERS[0], String(counts.blocker))
154
+ .replace(PLACEHOLDERS[1], String(counts.major))
155
+ .replace(PLACEHOLDERS[2], String(counts.minor));
156
+ return {
157
+ ok: true,
158
+ changed: true,
159
+ content: content.slice(0, parsed.findingsStart) + line + content.slice(parsed.findingsEnd)
160
+ };
161
+ }
162
+ function parseVerdict(reviewPath) {
163
+ if (!fs.existsSync(reviewPath)) {
164
+ return { ok: false, verdict: null, message: `Review artifact not found: ${path.basename(reviewPath)}` };
90
165
  }
91
- const counts = findingsMatch[1].match(/(\d+)\s*(?:阻塞项|blockers?).*?(\d+)\s*(?:主要|majors?).*?(\d+)\s*(?:次要|minors?)/i);
92
- if (!counts) {
93
- return { ok: false, verdict, message: `cannot parse findings count in ${fileName}` };
166
+ const parsed = parseReviewSummary(fs.readFileSync(reviewPath, 'utf8'));
167
+ if (!parsed.ok) {
168
+ return {
169
+ ok: false,
170
+ verdict: null,
171
+ message: `cannot parse review summary in ${path.basename(reviewPath)}: ${parsed.message}`
172
+ };
94
173
  }
95
- const [, blockers, majors, minors] = counts.map(Number);
174
+ const { verdict, counts } = parsed.summary;
175
+ if (verdict !== 'Approved')
176
+ return { ok: true, verdict };
96
177
  return {
97
178
  ok: true,
98
- verdict: blockers === 0 && majors === 0 && minors === 0 ? "Approved" : "Approved-with-issues"
179
+ verdict: counts && equalCounts(counts, { blocker: 0, major: 0, minor: 0 })
180
+ ? 'Approved'
181
+ : 'Approved-with-issues'
99
182
  };
100
183
  }
184
+ export { artifactName, equalCounts, escapeRegExp, extractSection, finalizeReviewSummaryContent, maxRound, normalizeVerdict, parseReviewSummary, parseVerdict };
101
185
  //# sourceMappingURL=review-artifacts.js.map
@@ -0,0 +1,186 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { locateActivityLog, pairEntries } from './activity-log.js';
5
+ import { parseArtifactName, validateCompletedArtifact } from './artifact-lifecycle.js';
6
+ import { parseLedger, summarizeLedgerStage, validateLedgerRows } from './ledger.js';
7
+ import { finalizeReviewSummaryContent } from './review-artifacts.js';
8
+ import { resolveTaskRef } from './resolve-ref.js';
9
+ import { validateLifecycleExecution } from './lifecycle-execution.js';
10
+ import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.js';
11
+ const STAGES = {
12
+ analysis: { family: 'review-analysis', action: 'Review Analysis' },
13
+ plan: { family: 'review-plan', action: 'Review Plan' },
14
+ code: { family: 'review-code', action: 'Review Code' }
15
+ };
16
+ const DEFAULT_FILE_SYSTEM = {
17
+ readFileSync: (file) => fs.readFileSync(file, 'utf8'),
18
+ statModeSync: (file) => fs.statSync(file).mode,
19
+ writeFileSync: (file, content, mode) => fs.writeFileSync(file, content, { encoding: 'utf8', flag: 'wx', mode }),
20
+ renameSync: (from, to) => fs.renameSync(from, to),
21
+ unlinkSync: (file) => fs.unlinkSync(file)
22
+ };
23
+ function failed(request, code, message, taskId = null, stageStatus = null) {
24
+ return {
25
+ status: 'failed',
26
+ changed: false,
27
+ intent: 'finalize-summary',
28
+ requestRef: request.taskRef,
29
+ taskId,
30
+ stage: request.stage,
31
+ artifact: request.artifact,
32
+ stageStatus,
33
+ operations: [],
34
+ error: { code, message }
35
+ };
36
+ }
37
+ function openReviewRound(content, action, round) {
38
+ const section = locateActivityLog(content);
39
+ if (!section)
40
+ return false;
41
+ const expected = `${action} (Round ${round})`;
42
+ return pairEntries(section.entries).filter((row) => (row.step === expected && Boolean(row.started) && !row.done)).length === 1;
43
+ }
44
+ function cleanupTemp(fileSystem, tempPath) {
45
+ try {
46
+ fileSystem.unlinkSync(tempPath);
47
+ }
48
+ catch {
49
+ // Best-effort cleanup preserves the primary failure.
50
+ }
51
+ }
52
+ function finalizeReviewSummaryUnlocked(request, options = {}) {
53
+ const stage = request.stage;
54
+ const spec = STAGES[stage];
55
+ if (!spec)
56
+ return failed(request, 'REVIEW_STAGE_INVALID', `unsupported review stage '${request.stage}'`);
57
+ if (!request.taskRef || !request.artifact) {
58
+ return failed(request, 'REVIEW_PAYLOAD_INVALID', 'taskRef, stage, and artifact are required');
59
+ }
60
+ const resolved = resolveTaskRef(request.taskRef, { repoRoot: options.repoRoot });
61
+ if (!resolved.ok)
62
+ return failed(request, resolved.code, resolved.message, resolved.taskId);
63
+ if (resolved.state !== 'active') {
64
+ return failed(request, 'TASK_STATE_MISMATCH', `task ${resolved.taskId} is ${resolved.state}, expected active`, resolved.taskId);
65
+ }
66
+ const parsedArtifact = parseArtifactName(request.artifact);
67
+ if (!parsedArtifact || parsedArtifact.family !== spec.family) {
68
+ return failed(request, 'REVIEW_ARTIFACT_IDENTITY_INVALID', `artifact '${request.artifact}' does not match ${spec.family}`, resolved.taskId);
69
+ }
70
+ const validated = validateCompletedArtifact(resolved.taskDir, spec.family, request.artifact, parsedArtifact.round);
71
+ if (!validated.ok) {
72
+ const code = validated.error.code === 'ARTIFACT_NOT_REGULAR'
73
+ ? 'REVIEW_ARTIFACT_NOT_REGULAR'
74
+ : 'REVIEW_ARTIFACT_IDENTITY_INVALID';
75
+ return failed(request, code, validated.error.message, resolved.taskId);
76
+ }
77
+ const fileSystem = { ...DEFAULT_FILE_SYSTEM, ...options.fileSystem };
78
+ let taskContent;
79
+ let artifactContent;
80
+ try {
81
+ taskContent = fileSystem.readFileSync(resolved.taskMdPath);
82
+ artifactContent = fileSystem.readFileSync(validated.artifact.path);
83
+ }
84
+ catch (error) {
85
+ return failed(request, 'REVIEW_ARTIFACT_NOT_REGULAR', String(error), resolved.taskId);
86
+ }
87
+ if (!openReviewRound(taskContent, spec.action, parsedArtifact.round)) {
88
+ return failed(request, 'REVIEW_ARTIFACT_IDENTITY_INVALID', `${request.artifact} does not have one matching open started review event`, resolved.taskId);
89
+ }
90
+ const execution = validateLifecycleExecution(request.taskRef, {
91
+ mode: request.orchestrated ? 'orchestrated' : 'standalone',
92
+ identity: {
93
+ stage: spec.family,
94
+ round: parsedArtifact.round,
95
+ artifact: request.artifact,
96
+ role: 'reviewer'
97
+ },
98
+ dryRun: request.dryRun
99
+ }, { repoRoot: options.repoRoot });
100
+ if (!execution.ok) {
101
+ return failed(request, 'REVIEW_PROVENANCE_INVALID', `${execution.error?.code ?? 'ORCHESTRATION_PROVENANCE_MISMATCH'}: ${execution.error?.message ?? 'orchestration provenance validation failed'}`, resolved.taskId);
102
+ }
103
+ let rows;
104
+ try {
105
+ rows = parseLedger(taskContent);
106
+ }
107
+ catch (error) {
108
+ return failed(request, 'REVIEW_LEDGER_INVALID', String(error), resolved.taskId);
109
+ }
110
+ const ledgerError = validateLedgerRows(rows);
111
+ if (ledgerError) {
112
+ return failed(request, 'REVIEW_LEDGER_INVALID', `${ledgerError.code}: ${ledgerError.message}`, resolved.taskId);
113
+ }
114
+ const stageStatus = summarizeLedgerStage(rows, stage);
115
+ const transformed = finalizeReviewSummaryContent(artifactContent, stageStatus.unresolvedFindingCounts);
116
+ if (!transformed.ok) {
117
+ return failed(request, transformed.code, transformed.message, resolved.taskId, stageStatus);
118
+ }
119
+ if (!transformed.changed) {
120
+ return {
121
+ ...failed(request, 'REVIEW_ARTIFACT_CONFLICT', '', resolved.taskId, stageStatus),
122
+ status: 'no-op',
123
+ error: null
124
+ };
125
+ }
126
+ const operations = [{ kind: 'artifact', artifact: request.artifact, operation: 'update' }];
127
+ if (request.dryRun) {
128
+ return {
129
+ ...failed(request, 'REVIEW_ARTIFACT_CONFLICT', '', resolved.taskId, stageStatus),
130
+ status: 'planned',
131
+ changed: true,
132
+ operations,
133
+ error: null
134
+ };
135
+ }
136
+ const tempPath = path.join(resolved.taskDir, `.${request.artifact}.tmp-${process.pid}-${(options.randomSuffix ?? randomUUID)()}`);
137
+ let mode;
138
+ try {
139
+ mode = fileSystem.statModeSync(validated.artifact.path);
140
+ fileSystem.writeFileSync(tempPath, transformed.content, mode);
141
+ }
142
+ catch (error) {
143
+ cleanupTemp(fileSystem, tempPath);
144
+ return failed(request, 'REVIEW_TEMP_WRITE_FAILED', String(error), resolved.taskId, stageStatus);
145
+ }
146
+ try {
147
+ if (fileSystem.readFileSync(validated.artifact.path) !== artifactContent) {
148
+ cleanupTemp(fileSystem, tempPath);
149
+ return failed(request, 'REVIEW_ARTIFACT_CONFLICT', `${request.artifact} changed during finalization`, resolved.taskId, stageStatus);
150
+ }
151
+ fileSystem.renameSync(tempPath, validated.artifact.path);
152
+ }
153
+ catch (error) {
154
+ cleanupTemp(fileSystem, tempPath);
155
+ return failed(request, 'REVIEW_RENAME_FAILED', String(error), resolved.taskId, stageStatus);
156
+ }
157
+ return {
158
+ status: 'applied',
159
+ changed: true,
160
+ intent: 'finalize-summary',
161
+ requestRef: request.taskRef,
162
+ taskId: resolved.taskId,
163
+ stage,
164
+ artifact: request.artifact,
165
+ stageStatus,
166
+ operations,
167
+ error: null
168
+ };
169
+ }
170
+ function finalizeReviewSummary(request, options = {}) {
171
+ if (request.dryRun)
172
+ return finalizeReviewSummaryUnlocked(request, options);
173
+ const resolved = resolveTaskRef(request.taskRef, { repoRoot: options.repoRoot });
174
+ if (!resolved.ok)
175
+ return finalizeReviewSummaryUnlocked(request, options);
176
+ try {
177
+ return withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-review.finalize-summary', () => finalizeReviewSummaryUnlocked(request, options));
178
+ }
179
+ catch (error) {
180
+ if (!(error instanceof TaskExecutionLockError))
181
+ throw error;
182
+ return failed(request, 'REVIEW_PROVENANCE_INVALID', `${error.code}: ${error.message}`, resolved.taskId);
183
+ }
184
+ }
185
+ export { finalizeReviewSummary };
186
+ //# sourceMappingURL=review-finalization.js.map
@@ -40,6 +40,10 @@ export function extractReviewBaseline(content) {
40
40
  const match = String(content).match(/^[-*]?\s*\*\*(?:审查基线提交|Review Baseline Commit)\*\*[::]\s*(.*?)\s*$/m);
41
41
  return match ? match[1].trim().replace(/`/g, "") : "";
42
42
  }
43
+ export function extractReviewDiffBase(content) {
44
+ const match = String(content).match(/^[-*]?\s*\*\*(?:审查差异基线|Reviewed Diff Base)\*\*[::]\s*(.*?)\s*$/m);
45
+ return match ? match[1].trim().replace(/`/g, "") : "";
46
+ }
43
47
  export function extractReviewDiffFingerprint(content) {
44
48
  const match = String(content).match(/^[-*]?\s*\*\*(?:审查差异指纹|Reviewed Diff Fingerprint)\*\*[::]\s*(.*?)\s*$/m);
45
49
  return match ? match[1].trim().replace(/`/g, "") : "";
@@ -0,0 +1,231 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { createHash, randomUUID } from 'node:crypto';
5
+ import { getProcessStartTime, processIdentityMatches } from '../server/process-state.js';
6
+ class TaskExecutionLockError extends Error {
7
+ code;
8
+ detail;
9
+ constructor(code, message, detail) {
10
+ super(message);
11
+ this.name = 'TaskExecutionLockError';
12
+ this.code = code;
13
+ this.detail = detail;
14
+ }
15
+ }
16
+ function errno(error) {
17
+ const value = error?.code;
18
+ return typeof value === 'string' ? value : null;
19
+ }
20
+ function mapLinkError(operation, error, key) {
21
+ const code = errno(error);
22
+ if (code === 'EEXIST')
23
+ return 'exists';
24
+ if (operation === 'quarantine' && code === 'ENOENT')
25
+ return 'missing';
26
+ const detail = { operation, errno: code, key };
27
+ if (['EPERM', 'EACCES', 'ENOSYS', 'ENOTSUP', 'EOPNOTSUPP', 'EXDEV'].includes(code ?? '')) {
28
+ return new TaskExecutionLockError('ORCHESTRATION_LOCK_UNSUPPORTED', `lifecycle lock hard-link operation '${operation}' is unsupported`, detail);
29
+ }
30
+ return new TaskExecutionLockError('ORCHESTRATION_LOCK_FAILED', `lifecycle lock hard-link operation '${operation}' failed`, detail);
31
+ }
32
+ function lockKey(repoRoot, taskId) {
33
+ const canonicalRepoRoot = fs.realpathSync.native(repoRoot);
34
+ const key = createHash('sha256').update(`${canonicalRepoRoot}\0${taskId}`).digest('hex');
35
+ return { canonicalRepoRoot, key };
36
+ }
37
+ function parseOwner(raw, key) {
38
+ try {
39
+ const value = JSON.parse(raw);
40
+ if (value !== null
41
+ && value.version === 1
42
+ && Number.isSafeInteger(value.pid)
43
+ && (value.pid ?? 0) > 0
44
+ && typeof value.startTime === 'string'
45
+ && value.startTime.length > 0
46
+ && typeof value.token === 'string'
47
+ && value.token.length > 0
48
+ && typeof value.owner === 'string'
49
+ && typeof value.canonicalRepoRoot === 'string'
50
+ && typeof value.taskId === 'string'
51
+ && typeof value.acquiredAt === 'string') {
52
+ return value;
53
+ }
54
+ }
55
+ catch {
56
+ // Fall through to the stable lock failure below.
57
+ }
58
+ throw new TaskExecutionLockError('ORCHESTRATION_LOCK_FAILED', 'lifecycle lock owner record is invalid', { operation: 'read', errno: null, key });
59
+ }
60
+ function unlinkIfPresent(file) {
61
+ try {
62
+ fs.unlinkSync(file);
63
+ }
64
+ catch (error) {
65
+ if (errno(error) !== 'ENOENT')
66
+ throw error;
67
+ }
68
+ }
69
+ function sameInode(left, right) {
70
+ return left.dev === right.dev && left.ino === right.ino;
71
+ }
72
+ function reclaimStaleLock(fixed, quarantine, snapshot, key, link) {
73
+ let linked = false;
74
+ try {
75
+ link(fixed, quarantine);
76
+ linked = true;
77
+ }
78
+ catch (error) {
79
+ const disposition = mapLinkError('quarantine', error, key);
80
+ if (disposition === 'missing')
81
+ return;
82
+ if (disposition === 'exists') {
83
+ try {
84
+ const quarantineSnapshot = fs.readFileSync(quarantine, 'utf8');
85
+ const fixedStat = fs.statSync(fixed);
86
+ const quarantineStat = fs.statSync(quarantine);
87
+ if (quarantineSnapshot === snapshot && sameInode(fixedStat, quarantineStat)) {
88
+ unlinkIfPresent(quarantine);
89
+ }
90
+ }
91
+ catch (readError) {
92
+ if (errno(readError) !== 'ENOENT')
93
+ throw readError;
94
+ }
95
+ return;
96
+ }
97
+ if (disposition instanceof TaskExecutionLockError)
98
+ throw disposition;
99
+ }
100
+ try {
101
+ const fixedSnapshot = fs.readFileSync(fixed, 'utf8');
102
+ const fixedStat = fs.statSync(fixed);
103
+ const quarantineStat = fs.statSync(quarantine);
104
+ if (fixedSnapshot === snapshot && sameInode(fixedStat, quarantineStat))
105
+ unlinkIfPresent(fixed);
106
+ }
107
+ catch (error) {
108
+ if (errno(error) !== 'ENOENT')
109
+ throw error;
110
+ }
111
+ finally {
112
+ if (linked)
113
+ unlinkIfPresent(quarantine);
114
+ }
115
+ }
116
+ function cleanStaleCandidates(lockRoot, key, identityMatches) {
117
+ const prefix = `${key}.candidate.`;
118
+ for (const name of fs.readdirSync(lockRoot)) {
119
+ if (!name.startsWith(prefix))
120
+ continue;
121
+ const candidate = path.join(lockRoot, name);
122
+ try {
123
+ const owner = parseOwner(fs.readFileSync(candidate, 'utf8'), key);
124
+ if (!identityMatches(owner))
125
+ unlinkIfPresent(candidate);
126
+ }
127
+ catch {
128
+ // A malformed candidate never owns the fixed lock and is left for manual diagnosis.
129
+ }
130
+ }
131
+ }
132
+ function withTaskExecutionLock(repoRoot, taskId, ownerName, callback, options = {}) {
133
+ let identity;
134
+ try {
135
+ identity = lockKey(repoRoot, taskId);
136
+ }
137
+ catch (error) {
138
+ throw new TaskExecutionLockError('ORCHESTRATION_LOCK_FAILED', 'failed to canonicalize the repository for lifecycle locking', { operation: 'canonicalize', errno: errno(error), key: 'unresolved' });
139
+ }
140
+ const { canonicalRepoRoot, key } = identity;
141
+ const lockRoot = options.lockRoot ?? path.join(os.tmpdir(), 'agent-infra-lifecycle-locks');
142
+ const token = (options.token ?? randomUUID)();
143
+ const candidate = path.join(lockRoot, `${key}.candidate.${process.pid}.${token}`);
144
+ const fixed = path.join(lockRoot, `${key}.lock`);
145
+ const link = options.linkSync ?? fs.linkSync;
146
+ const startTime = (options.getStartTime ?? getProcessStartTime)(process.pid);
147
+ if (startTime === null) {
148
+ throw new TaskExecutionLockError('ORCHESTRATION_LOCK_FAILED', 'current process start time is unavailable', { operation: 'identity', errno: null, key });
149
+ }
150
+ const owner = {
151
+ version: 1,
152
+ pid: process.pid,
153
+ startTime,
154
+ token,
155
+ owner: ownerName,
156
+ canonicalRepoRoot,
157
+ taskId,
158
+ acquiredAt: (options.now ?? (() => new Date().toISOString()))()
159
+ };
160
+ const serialized = `${JSON.stringify(owner)}\n`;
161
+ let ownsFixed = false;
162
+ try {
163
+ fs.mkdirSync(lockRoot, { recursive: true });
164
+ cleanStaleCandidates(lockRoot, key, options.identityMatches ?? processIdentityMatches);
165
+ const descriptor = fs.openSync(candidate, 'wx', 0o600);
166
+ try {
167
+ fs.writeFileSync(descriptor, serialized);
168
+ fs.fsyncSync(descriptor);
169
+ }
170
+ finally {
171
+ fs.closeSync(descriptor);
172
+ }
173
+ for (let attempt = 0; attempt < 16; attempt += 1) {
174
+ try {
175
+ link(candidate, fixed);
176
+ ownsFixed = true;
177
+ break;
178
+ }
179
+ catch (error) {
180
+ const disposition = mapLinkError('acquire', error, key);
181
+ if (disposition instanceof TaskExecutionLockError)
182
+ throw disposition;
183
+ let snapshot;
184
+ let current;
185
+ try {
186
+ snapshot = fs.readFileSync(fixed, 'utf8');
187
+ current = parseOwner(snapshot, key);
188
+ }
189
+ catch (readError) {
190
+ if (errno(readError) === 'ENOENT')
191
+ continue;
192
+ throw readError;
193
+ }
194
+ if ((options.identityMatches ?? processIdentityMatches)(current)) {
195
+ throw new TaskExecutionLockError('ORCHESTRATION_LOCK_BUSY', 'another lifecycle operation holds the task lock', { operation: 'acquire', errno: 'EEXIST', key });
196
+ }
197
+ reclaimStaleLock(fixed, `${fixed}.quarantine.${current.token}`, snapshot, key, link);
198
+ }
199
+ }
200
+ if (!ownsFixed) {
201
+ throw new TaskExecutionLockError('ORCHESTRATION_LOCK_BUSY', 'lifecycle task lock could not be acquired after stale recovery', { operation: 'acquire', errno: 'EEXIST', key });
202
+ }
203
+ unlinkIfPresent(candidate);
204
+ return callback();
205
+ }
206
+ catch (error) {
207
+ if (error instanceof TaskExecutionLockError)
208
+ throw error;
209
+ throw new TaskExecutionLockError('ORCHESTRATION_LOCK_FAILED', 'lifecycle task lock operation failed', { operation: ownsFixed ? 'callback' : 'acquire', errno: errno(error), key });
210
+ }
211
+ finally {
212
+ try {
213
+ unlinkIfPresent(candidate);
214
+ }
215
+ catch {
216
+ // Candidate cleanup is best-effort and must not replace the primary result.
217
+ }
218
+ if (ownsFixed) {
219
+ try {
220
+ const current = parseOwner(fs.readFileSync(fixed, 'utf8'), key);
221
+ if (current.token === token)
222
+ unlinkIfPresent(fixed);
223
+ }
224
+ catch {
225
+ // A missing or replaced fixed lock is not owned by this invocation.
226
+ }
227
+ }
228
+ }
229
+ }
230
+ export { TaskExecutionLockError, lockKey, mapLinkError, withTaskExecutionLock };
231
+ //# sourceMappingURL=task-execution-lock.js.map