@fitlab-ai/agent-infra 0.9.0 → 0.9.2

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 (327) hide show
  1. package/README.md +22 -5
  2. package/README.zh-CN.md +21 -5
  3. package/bin/cli.ts +12 -0
  4. package/dist/bin/cli.js +14 -0
  5. package/dist/bin/internal-cli.js +20 -0
  6. package/dist/lib/agent-client.js +163 -0
  7. package/dist/lib/agent-clients/adapter.js +294 -0
  8. package/dist/lib/agent-clients/adapters/claude-code.js +62 -0
  9. package/dist/lib/agent-clients/adapters/codex-sandbox.js +210 -0
  10. package/dist/lib/agent-clients/adapters/codex.js +54 -0
  11. package/dist/lib/agent-clients/adapters/gemini-cli.js +64 -0
  12. package/dist/lib/agent-clients/adapters/index.js +20 -0
  13. package/dist/lib/agent-clients/adapters/opencode.js +64 -0
  14. package/dist/lib/agent-clients/config.js +177 -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 +38 -0
  18. package/dist/lib/agent-clients/project-assets.js +45 -0
  19. package/dist/lib/agent-clients/reconcile.js +235 -0
  20. package/dist/lib/agent-clients/registry.js +72 -0
  21. package/dist/lib/agent-clients/schema.js +57 -0
  22. package/dist/lib/agent-clients/types.js +29 -0
  23. package/dist/lib/builtin-tuis.js +9 -14
  24. package/dist/lib/defaults.json +85 -73
  25. package/dist/lib/git/review-snapshot.js +25 -10
  26. package/dist/lib/git/reviewed-commit-equivalence.js +110 -0
  27. package/dist/lib/init.js +47 -91
  28. package/dist/lib/internal/agent-client.js +117 -0
  29. package/dist/lib/internal/git-workflow.js +1 -1
  30. package/dist/lib/internal/platform-release-notes.js +53 -0
  31. package/dist/lib/internal/release-workflow.js +175 -17
  32. package/dist/lib/internal/task-orchestration.js +151 -0
  33. package/dist/lib/internal/task-review.js +65 -0
  34. package/dist/lib/merge.js +2 -1
  35. package/dist/lib/platform/adapters.js +38 -1
  36. package/dist/lib/platform/change-request-git-evidence.js +113 -0
  37. package/dist/lib/platform/github-release-notes.js +96 -0
  38. package/dist/lib/platform/issues.js +4 -2
  39. package/dist/lib/platform/merged-pr-equivalence.js +84 -0
  40. package/dist/lib/platform/pr-checks.js +43 -15
  41. package/dist/lib/platform/pull-requests.js +113 -7
  42. package/dist/lib/platform/release-notes.js +143 -0
  43. package/dist/lib/platform/releases.js +1 -1
  44. package/dist/lib/platform/verification-required.js +31 -9
  45. package/dist/lib/prompt.js +15 -3
  46. package/dist/lib/release/channels.js +4 -1
  47. package/dist/lib/release/workflow.js +4 -2
  48. package/dist/lib/remove-dir.js +25 -0
  49. package/dist/lib/run/tui.js +8 -2
  50. package/dist/lib/sandbox/agent-client-reconciler.js +234 -0
  51. package/dist/lib/sandbox/build-proxy.js +63 -0
  52. package/dist/lib/sandbox/clipboard/linux.js +2 -1
  53. package/dist/lib/sandbox/commands/create.js +133 -189
  54. package/dist/lib/sandbox/commands/enter.js +17 -1
  55. package/dist/lib/sandbox/commands/prune.js +2 -2
  56. package/dist/lib/sandbox/commands/rebuild.js +24 -7
  57. package/dist/lib/sandbox/commands/rm.js +3 -2
  58. package/dist/lib/sandbox/config.js +21 -4
  59. package/dist/lib/sandbox/constants.js +3 -0
  60. package/dist/lib/sandbox/dockerfile.js +2 -1
  61. package/dist/lib/sandbox/image-build.js +2 -1
  62. package/dist/lib/sandbox/managed-fs.js +10 -5
  63. package/dist/lib/sandbox/recovery.js +52 -36
  64. package/dist/lib/sandbox/runtimes/ai-tools.dockerfile +24 -3
  65. package/dist/lib/sandbox/runtimes/base.dockerfile +8 -1
  66. package/dist/lib/sandbox/runtimes/java17.dockerfile +8 -1
  67. package/dist/lib/sandbox/runtimes/java21.dockerfile +8 -1
  68. package/dist/lib/sandbox/runtimes/node20.dockerfile +8 -1
  69. package/dist/lib/sandbox/runtimes/node22.dockerfile +8 -1
  70. package/dist/lib/sandbox/runtimes/python3.dockerfile +8 -1
  71. package/dist/lib/sandbox/shell.js +3 -2
  72. package/dist/lib/sandbox/tool-types.js +8 -0
  73. package/dist/lib/sandbox/tools.js +2 -126
  74. package/dist/lib/task/artifact-lifecycle.js +1 -49
  75. package/dist/lib/task/commands/decisions.js +50 -20
  76. package/dist/lib/task/commands/issue-body.js +10 -5
  77. package/dist/lib/task/delegation-receipts.js +107 -0
  78. package/dist/lib/task/events.js +101 -2
  79. package/dist/lib/task/issue-form.js +2 -0
  80. package/dist/lib/task/orchestration.js +420 -0
  81. package/dist/lib/task/review-artifacts.js +143 -59
  82. package/dist/lib/task/review-finalization.js +166 -0
  83. package/dist/lib/task/review-fingerprint.js +13 -0
  84. package/dist/lib/task/verification-checks.js +2 -1
  85. package/dist/lib/task/verification-engine.js +168 -23
  86. package/dist/lib/task/verification-review.js +1 -1
  87. package/dist/lib/task/verification.js +4 -2
  88. package/dist/lib/task/workspace-snapshot.js +34 -0
  89. package/dist/lib/update.js +42 -161
  90. package/lib/agent-client.ts +214 -0
  91. package/lib/agent-clients/adapter.ts +461 -0
  92. package/lib/agent-clients/adapters/claude-code.ts +70 -0
  93. package/lib/agent-clients/adapters/codex-sandbox.ts +245 -0
  94. package/lib/agent-clients/adapters/codex.ts +58 -0
  95. package/lib/agent-clients/adapters/gemini-cli.ts +65 -0
  96. package/lib/agent-clients/adapters/index.ts +27 -0
  97. package/lib/agent-clients/adapters/opencode.ts +66 -0
  98. package/lib/agent-clients/config.ts +278 -0
  99. package/lib/agent-clients/custom-tuis.ts +149 -0
  100. package/lib/agent-clients/invocation.ts +19 -0
  101. package/lib/agent-clients/next-steps.ts +72 -0
  102. package/lib/agent-clients/project-assets.ts +96 -0
  103. package/lib/agent-clients/reconcile.ts +324 -0
  104. package/lib/agent-clients/registry.ts +144 -0
  105. package/lib/agent-clients/schema.ts +62 -0
  106. package/lib/agent-clients/types.ts +78 -0
  107. package/lib/benchmark/schemas/v1.0.0/case-manifest.schema.json +120 -0
  108. package/lib/benchmark/schemas/v1.0.0/common.schema.json +109 -0
  109. package/lib/benchmark/schemas/v1.0.0/grader-result.schema.json +160 -0
  110. package/lib/benchmark/schemas/v1.0.0/run-manifest.schema.json +122 -0
  111. package/lib/benchmark/schemas/v1.0.0/subject.schema.json +227 -0
  112. package/lib/builtin-tuis.ts +16 -15
  113. package/lib/defaults.json +24 -12
  114. package/lib/git/review-snapshot.ts +39 -9
  115. package/lib/git/reviewed-commit-equivalence.ts +135 -0
  116. package/lib/init.ts +53 -121
  117. package/lib/internal/agent-client.ts +131 -0
  118. package/lib/internal/git-workflow.ts +1 -1
  119. package/lib/internal/platform-release-notes.ts +55 -0
  120. package/lib/internal/release-workflow.ts +172 -18
  121. package/lib/internal/task-orchestration.ts +132 -0
  122. package/lib/internal/task-review.ts +65 -0
  123. package/lib/merge.ts +2 -1
  124. package/lib/platform/adapters.ts +142 -3
  125. package/lib/platform/change-request-git-evidence.ts +159 -0
  126. package/lib/platform/github-release-notes.ts +132 -0
  127. package/lib/platform/issues.ts +6 -4
  128. package/lib/platform/merged-pr-equivalence.ts +107 -0
  129. package/lib/platform/pr-checks.ts +57 -28
  130. package/lib/platform/pull-requests.ts +140 -25
  131. package/lib/platform/release-notes.ts +167 -0
  132. package/lib/platform/releases.ts +1 -1
  133. package/lib/platform/verification-required.ts +37 -9
  134. package/lib/prompt.ts +16 -3
  135. package/lib/release/channels.ts +4 -1
  136. package/lib/release/workflow.ts +4 -3
  137. package/lib/remove-dir.ts +28 -0
  138. package/lib/run/tui.ts +9 -1
  139. package/lib/sandbox/agent-client-reconciler.ts +378 -0
  140. package/lib/sandbox/build-proxy.ts +94 -0
  141. package/lib/sandbox/clipboard/linux.ts +2 -1
  142. package/lib/sandbox/commands/create.ts +188 -203
  143. package/lib/sandbox/commands/enter.ts +23 -1
  144. package/lib/sandbox/commands/prune.ts +2 -2
  145. package/lib/sandbox/commands/rebuild.ts +29 -7
  146. package/lib/sandbox/commands/rm.ts +3 -2
  147. package/lib/sandbox/config.ts +31 -4
  148. package/lib/sandbox/constants.ts +6 -0
  149. package/lib/sandbox/dockerfile.ts +2 -1
  150. package/lib/sandbox/image-build.ts +4 -1
  151. package/lib/sandbox/managed-fs.ts +18 -5
  152. package/lib/sandbox/recovery.ts +98 -67
  153. package/lib/sandbox/runtimes/ai-tools.dockerfile +24 -3
  154. package/lib/sandbox/runtimes/base.dockerfile +8 -1
  155. package/lib/sandbox/runtimes/java17.dockerfile +8 -1
  156. package/lib/sandbox/runtimes/java21.dockerfile +8 -1
  157. package/lib/sandbox/runtimes/node20.dockerfile +8 -1
  158. package/lib/sandbox/runtimes/node22.dockerfile +8 -1
  159. package/lib/sandbox/runtimes/python3.dockerfile +8 -1
  160. package/lib/sandbox/shell.ts +4 -2
  161. package/lib/sandbox/tool-types.ts +143 -0
  162. package/lib/sandbox/tools.ts +5 -157
  163. package/lib/task/artifact-lifecycle.ts +1 -38
  164. package/lib/task/commands/decisions.ts +53 -20
  165. package/lib/task/commands/issue-body.ts +10 -5
  166. package/lib/task/delegation-receipts.ts +170 -0
  167. package/lib/task/events.ts +111 -3
  168. package/lib/task/issue-form.ts +4 -0
  169. package/lib/task/orchestration.ts +543 -0
  170. package/lib/task/review-artifacts.ts +201 -69
  171. package/lib/task/review-finalization.ts +275 -0
  172. package/lib/task/review-fingerprint.ts +15 -1
  173. package/lib/task/verification-checks.ts +2 -1
  174. package/lib/task/verification-engine.ts +190 -25
  175. package/lib/task/verification-review.ts +2 -0
  176. package/lib/task/verification.ts +6 -3
  177. package/lib/task/workspace-snapshot.ts +36 -0
  178. package/lib/update.ts +48 -184
  179. package/package.json +2 -2
  180. package/templates/.agents/README.en.md +21 -20
  181. package/templates/.agents/README.zh-CN.md +21 -20
  182. package/templates/.agents/hooks/lifecycle-delegation.js +64 -0
  183. package/templates/.agents/rules/README.en.md +2 -0
  184. package/templates/.agents/rules/README.zh-CN.md +2 -0
  185. package/templates/.agents/rules/commit-and-pr.en.md +1 -0
  186. package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -0
  187. package/templates/.agents/rules/human-decision-context.en.md +14 -12
  188. package/templates/.agents/rules/human-decision-context.zh-CN.md +14 -12
  189. package/templates/.agents/rules/lifecycle-orchestration.en.md +21 -0
  190. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +21 -0
  191. package/templates/.agents/rules/next-step-output.en.md +16 -0
  192. package/templates/.agents/rules/next-step-output.zh-CN.md +16 -0
  193. package/templates/.agents/rules/no-mid-flow-questions.en.md +2 -0
  194. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +2 -0
  195. package/templates/.agents/rules/release-commands.en.md +2 -2
  196. package/templates/.agents/rules/release-commands.github.en.md +15 -39
  197. package/templates/.agents/rules/release-commands.github.zh-CN.md +14 -38
  198. package/templates/.agents/rules/release-commands.zh-CN.md +2 -2
  199. package/templates/.agents/rules/review-handshake.en.md +4 -3
  200. package/templates/.agents/rules/review-handshake.zh-CN.md +4 -3
  201. package/templates/.agents/rules/review-method.en.md +113 -0
  202. package/templates/.agents/rules/review-method.zh-CN.md +98 -0
  203. package/templates/.agents/rules/testing-discipline.en.md +20 -2
  204. package/templates/.agents/rules/testing-discipline.zh-CN.md +20 -2
  205. package/templates/.agents/skills/analyze-task/SKILL.en.md +9 -6
  206. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +9 -6
  207. package/templates/.agents/skills/block-task/SKILL.en.md +4 -4
  208. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +4 -4
  209. package/templates/.agents/skills/cancel-task/SKILL.en.md +4 -4
  210. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +5 -5
  211. package/templates/.agents/skills/check-task/SKILL.en.md +16 -16
  212. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -16
  213. package/templates/.agents/skills/close-codescan/SKILL.en.md +4 -4
  214. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +4 -4
  215. package/templates/.agents/skills/close-dependabot/SKILL.en.md +4 -4
  216. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +4 -4
  217. package/templates/.agents/skills/code-task/SKILL.en.md +1 -1
  218. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +2 -2
  219. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +14 -16
  220. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +14 -16
  221. package/templates/.agents/skills/code-task/reference/output-template.en.md +3 -3
  222. package/templates/.agents/skills/code-task/reference/output-template.zh-CN.md +3 -3
  223. package/templates/.agents/skills/commit/SKILL.en.md +11 -1
  224. package/templates/.agents/skills/commit/SKILL.zh-CN.md +11 -1
  225. package/templates/.agents/skills/commit/reference/task-status-update.en.md +24 -28
  226. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +24 -28
  227. package/templates/.agents/skills/complete-task/SKILL.en.md +3 -3
  228. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
  229. package/templates/.agents/skills/complete-task/config/verify.en.json +0 -1
  230. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +0 -1
  231. package/templates/.agents/skills/create-pr/SKILL.en.md +10 -10
  232. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +10 -10
  233. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +3 -3
  234. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +3 -3
  235. package/templates/.agents/skills/create-release-note/SKILL.en.md +17 -38
  236. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +16 -37
  237. package/templates/.agents/skills/create-task/SKILL.en.md +15 -11
  238. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +15 -11
  239. package/templates/.agents/skills/create-task/reference/context-capture.en.md +29 -0
  240. package/templates/.agents/skills/create-task/reference/context-capture.zh-CN.md +29 -0
  241. package/templates/.agents/skills/import-codescan/SKILL.en.md +5 -5
  242. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +5 -5
  243. package/templates/.agents/skills/import-dependabot/SKILL.en.md +5 -5
  244. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +5 -5
  245. package/templates/.agents/skills/import-issue/SKILL.en.md +5 -5
  246. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +5 -5
  247. package/templates/.agents/skills/init-labels/SKILL.en.md +4 -4
  248. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +4 -4
  249. package/templates/.agents/skills/init-milestones/SKILL.en.md +4 -4
  250. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +4 -4
  251. package/templates/.agents/skills/plan-task/SKILL.en.md +5 -5
  252. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +5 -5
  253. package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
  254. package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
  255. package/templates/.agents/skills/release/SKILL.en.md +1 -1
  256. package/templates/.agents/skills/review-analysis/SKILL.en.md +13 -2
  257. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -3
  258. package/templates/.agents/skills/review-analysis/config/verify.en.json +6 -0
  259. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +6 -0
  260. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +13 -15
  261. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +13 -15
  262. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +51 -5
  263. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +52 -6
  264. package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +25 -22
  265. package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +25 -22
  266. package/templates/.agents/skills/review-code/SKILL.en.md +28 -8
  267. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +28 -8
  268. package/templates/.agents/skills/review-code/config/verify.en.json +7 -0
  269. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +7 -0
  270. package/templates/.agents/skills/review-code/reference/concurrency-risks.en.md +25 -0
  271. package/templates/.agents/skills/review-code/reference/concurrency-risks.zh-CN.md +25 -0
  272. package/templates/.agents/skills/review-code/reference/cross-platform-risks.en.md +27 -0
  273. package/templates/.agents/skills/review-code/reference/cross-platform-risks.zh-CN.md +27 -0
  274. package/templates/.agents/skills/review-code/reference/documentation-antipatterns.en.md +13 -0
  275. package/templates/.agents/skills/review-code/reference/documentation-antipatterns.zh-CN.md +13 -0
  276. package/templates/.agents/skills/review-code/reference/migration-risks.en.md +25 -0
  277. package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +25 -0
  278. package/templates/.agents/skills/review-code/reference/output-templates.en.md +22 -24
  279. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +22 -24
  280. package/templates/.agents/skills/review-code/reference/report-template.en.md +54 -7
  281. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +54 -7
  282. package/templates/.agents/skills/review-code/reference/review-criteria.en.md +29 -24
  283. package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +29 -24
  284. package/templates/.agents/skills/review-code/reference/security-risks.en.md +25 -0
  285. package/templates/.agents/skills/review-code/reference/security-risks.zh-CN.md +25 -0
  286. package/templates/.agents/skills/review-plan/SKILL.en.md +13 -2
  287. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -3
  288. package/templates/.agents/skills/review-plan/config/verify.en.json +6 -0
  289. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +6 -0
  290. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +13 -15
  291. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +13 -15
  292. package/templates/.agents/skills/review-plan/reference/report-template.en.md +61 -5
  293. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +61 -5
  294. package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +21 -24
  295. package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +21 -24
  296. package/templates/.agents/skills/run-task/SKILL.en.md +22 -0
  297. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +22 -0
  298. package/templates/.agents/skills/run-task/config/verify.en.json +9 -0
  299. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +9 -0
  300. package/templates/.agents/skills/test/SKILL.en.md +4 -4
  301. package/templates/.agents/skills/test/SKILL.zh-CN.md +4 -4
  302. package/templates/.agents/skills/test-integration/SKILL.en.md +4 -4
  303. package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +4 -4
  304. package/templates/.agents/skills/update-agent-infra/SKILL.en.md +5 -5
  305. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +5 -5
  306. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +647 -203
  307. package/templates/.agents/skills/upgrade-dependency/SKILL.en.md +4 -4
  308. package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +4 -4
  309. package/templates/.agents/skills/watch-pr/SKILL.en.md +8 -8
  310. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +8 -8
  311. package/templates/.agents/templates/task.en.md +18 -0
  312. package/templates/.agents/templates/task.zh-CN.md +18 -0
  313. package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +6 -0
  314. package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +6 -0
  315. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +6 -0
  316. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +6 -0
  317. package/templates/.claude/commands/run-task.en.md +8 -0
  318. package/templates/.claude/commands/run-task.zh-CN.md +8 -0
  319. package/templates/.claude/settings.json +24 -0
  320. package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +3 -0
  321. package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +3 -0
  322. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +3 -0
  323. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +3 -0
  324. package/templates/.gemini/commands/_project_/run-task.en.toml +8 -0
  325. package/templates/.gemini/commands/_project_/run-task.zh-CN.toml +8 -0
  326. package/templates/.opencode/commands/run-task.en.md +11 -0
  327. package/templates/.opencode/commands/run-task.zh-CN.md +11 -0
@@ -7,16 +7,23 @@ import { fileURLToPath } from "node:url";
7
7
 
8
8
  import {
9
9
  extractReviewBaseline,
10
+ extractReviewDiffBase,
10
11
  extractReviewDiffFingerprint,
11
12
  extractReviewedSnapshotTree,
12
13
  findAuthoritativeReviewCodeArtifact,
14
+ loadPostReviewConfig,
13
15
  parseReviewVerdict,
14
16
  resolvePostReviewGlobs
15
17
  } from "./verification-review.ts";
16
18
  import { check as checkPlatformSync } from "../platform/verification-sync.ts";
17
19
  import { check as checkRequiredChecks } from "../platform/verification-required.ts";
20
+ import { inspectPlatformPullRequest } from "../platform/pull-requests.ts";
21
+ import { resolveMaterializedReviewedHeadRelation } from "../platform/change-request-git-evidence.ts";
22
+ import { resolveReviewedHeadRelation } from "../platform/merged-pr-equivalence.ts";
23
+ import { resolveLocalReviewedCommitRelation } from "../git/reviewed-commit-equivalence.ts";
18
24
  import { parseTypedTaskFrontmatter } from "./frontmatter.ts";
19
- import { parseLedger } from "./ledger.ts";
25
+ import { parseLedger, summarizeLedgerStage, validateLedgerRows } from "./ledger.ts";
26
+ import { equalCounts, parseReviewSummary } from "./review-artifacts.ts";
20
27
  import { loadVerificationConfig } from "./verification-config.ts";
21
28
  import { snapshotReview } from "../git/review-snapshot.ts";
22
29
 
@@ -107,10 +114,14 @@ function runCheck(type: any, context: any, shared: any): any {
107
114
  return checkCompletionChecklist(context);
108
115
  case "review-ledger":
109
116
  return checkReviewLedger(context);
117
+ case "review-summary":
118
+ return checkReviewSummary(context);
110
119
  case "review-fact":
111
120
  return checkReviewFact(context);
112
121
  case "post-review-commit":
113
122
  return checkPostReviewCommit(context);
123
+ case "orchestration-state":
124
+ return checkOrchestrationState(context);
114
125
  default: {
115
126
  const adapter = PLATFORM_ADAPTERS[type];
116
127
  if (!adapter) {
@@ -126,6 +137,32 @@ function runCheck(type: any, context: any, shared: any): any {
126
137
  }
127
138
  }
128
139
 
140
+ function checkOrchestrationState({ taskDir }: any): any {
141
+ const file = path.join(taskDir, 'orchestration.json');
142
+ const stat = safeStat(file);
143
+ if (!stat?.isFile()) return failResult('orchestration-state', 'orchestration.json is missing');
144
+ let run: any;
145
+ try {
146
+ run = JSON.parse(fs.readFileSync(file, 'utf8'));
147
+ } catch (error) {
148
+ return failResult('orchestration-state', `Invalid orchestration.json: ${String(error)}`);
149
+ }
150
+ if (run.schemaVersion !== 1 || !['paused', 'completed'].includes(run.status)) {
151
+ return failResult('orchestration-state', `Expected paused or completed run, received '${run.status}'`);
152
+ }
153
+ if (run.status === 'paused' && (!run.pause?.code || !run.pause?.message)) {
154
+ return failResult('orchestration-state', 'Paused run requires a stable pause code and message');
155
+ }
156
+ if (run.status === 'completed') {
157
+ if (run.pendingDelegation !== null || !run.commitAuthorization?.consumedAt) {
158
+ return failResult('orchestration-state', 'Completed run must consume commit authorization and clear pending delegation');
159
+ }
160
+ } else if (run.pendingDelegation?.status === 'sealed') {
161
+ return failResult('orchestration-state', 'Paused run has a sealed delegation that could still advance');
162
+ }
163
+ return passResult('orchestration-state', `Orchestration run is safely ${run.status}`);
164
+ }
165
+
129
166
  // === Check Functions ===
130
167
 
131
168
  function checkTaskMeta({ taskDir, config }: any): any {
@@ -268,20 +305,6 @@ function loadProjectName(): any {
268
305
  }
269
306
  }
270
307
 
271
- function loadReviewConfig(): any {
272
- const configPath = path.join(repoRoot, ".agents", ".airc.json");
273
- if (!fs.existsSync(configPath)) {
274
- return {};
275
- }
276
-
277
- try {
278
- const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
279
- return config.review && typeof config.review === "object" ? config.review : {};
280
- } catch {
281
- return {};
282
- }
283
- }
284
-
285
308
  function checkArtifact({ taskDir, config, artifactFile }: any): any {
286
309
  const resolvedArtifact = resolveArtifactPath(taskDir, config.file_pattern, artifactFile);
287
310
  if (!resolvedArtifact.ok) {
@@ -324,6 +347,43 @@ function checkArtifact({ taskDir, config, artifactFile }: any): any {
324
347
  );
325
348
  }
326
349
 
350
+ function checkReviewSummary({ taskDir, config, artifactFile }: any): any {
351
+ const stage = String(config.stage || "");
352
+ if (!["analysis", "plan", "code"].includes(stage)) {
353
+ return failResult("review-summary", `Invalid review stage '${stage}'`);
354
+ }
355
+ const resolvedArtifact = resolveArtifactPath(taskDir, "", artifactFile);
356
+ if (!resolvedArtifact.ok || !safeStat(resolvedArtifact.path)?.isFile()) {
357
+ return failResult("review-summary", resolvedArtifact.message || "Review artifact is missing");
358
+ }
359
+ const parsed = parseReviewSummary(fs.readFileSync(resolvedArtifact.path, "utf8"));
360
+ if (!parsed.ok) return failResult("review-summary", `${parsed.code}: ${parsed.message}`);
361
+ if (!parsed.summary.counts) {
362
+ return failResult("review-summary", "Review summary finding counts are not finalized");
363
+ }
364
+ const task = loadTask(taskDir);
365
+ if (!task.ok) return failResult("review-summary", task.message);
366
+ let rows;
367
+ try {
368
+ rows = parseLedger(task.content);
369
+ } catch (error) {
370
+ return failResult("review-summary", `Invalid disagreement ledger: ${String(error)}`);
371
+ }
372
+ const invalid = validateLedgerRows(rows);
373
+ if (invalid) return failResult("review-summary", `${invalid.code}: ${invalid.message}`);
374
+ const expected = summarizeLedgerStage(rows, stage as "analysis" | "plan" | "code").unresolvedFindingCounts;
375
+ if (!equalCounts(parsed.summary.counts, expected)) {
376
+ return failResult(
377
+ "review-summary",
378
+ `Review summary counts ${JSON.stringify(parsed.summary.counts)} do not match ledger ${JSON.stringify(expected)}`
379
+ );
380
+ }
381
+ return passResult(
382
+ "review-summary",
383
+ `${path.basename(resolvedArtifact.path)} finding counts match the ${stage} ledger`
384
+ );
385
+ }
386
+
327
387
  function checkImplementationInput({ taskDir, artifactFile }: any): any {
328
388
  const task = loadTask(taskDir);
329
389
  if (!task.ok) return failResult("implementation-input", task.message);
@@ -598,7 +658,7 @@ function resolveReviewSetting(config: any, key: any, fallback: any): any {
598
658
  if (config && config[key] !== undefined && config[key] !== null) {
599
659
  return config[key];
600
660
  }
601
- const reviewConfig = loadReviewConfig();
661
+ const reviewConfig = loadPostReviewConfig(repoRoot);
602
662
  if (reviewConfig[key] !== undefined && reviewConfig[key] !== null) {
603
663
  return reviewConfig[key];
604
664
  }
@@ -694,8 +754,51 @@ function checkPostReviewCommit({ taskDir, config }: any): any {
694
754
  }
695
755
 
696
756
  const task = loadTask(taskDir);
697
- const content = fs.readFileSync(reviewArtifact.path!, "utf8");
757
+ if (!task.ok) return failResult("post-review-commit", task.message);
698
758
  const lastReviewedCommit = task.ok ? (task.metadata.last_reviewed_commit || "").trim() : "";
759
+ const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(repoRoot));
760
+ const hasPullRequest = Number(task.metadata.pr_number) > 0;
761
+ let inspected: ReturnType<typeof inspectPlatformPullRequest> | null = null;
762
+ if (hasPullRequest) {
763
+ inspected = inspectPlatformPullRequest(task.metadata.id, { cwd: gitRoot });
764
+ if (!inspected.pullRequest) {
765
+ const message = inspected.error?.message || "PR merge snapshot is unavailable";
766
+ const code = inspected.error?.code || "PR_INSPECTION_INVALID";
767
+ return inspected.status === "blocked"
768
+ ? blockedResult("post-review-commit", message, code)
769
+ : failResult("post-review-commit", message, code);
770
+ }
771
+ if (
772
+ inspected.pullRequest.state === "closed" &&
773
+ inspected.pullRequest.mergedAt &&
774
+ inspected.pullRequest.mergeCommitSha
775
+ ) {
776
+ const relation = resolveMaterializedReviewedHeadRelation({
777
+ cwd: gitRoot,
778
+ platformType: inspected.platform.type,
779
+ lastReviewedCommit,
780
+ pullRequest: inspected.pullRequest
781
+ });
782
+ if (relation.status === "merged-equivalent") {
783
+ return passResult(
784
+ "post-review-commit",
785
+ `Reviewed PR head is content-equivalent to squash merge ${relation.mergeCommit.slice(0, 8)} on target ${relation.comparisonHead.slice(0, 8)}`
786
+ );
787
+ }
788
+ if (relation.status === "blocked") {
789
+ return blockedResult("post-review-commit", relation.message, relation.code);
790
+ }
791
+ if (relation.status === "strict") {
792
+ return failResult(
793
+ "post-review-commit",
794
+ "Merged PR evidence did not establish squash merge equivalence",
795
+ "PR_MERGE_IDENTITY_INVALID"
796
+ );
797
+ }
798
+ return failResult("post-review-commit", relation.message, relation.code);
799
+ }
800
+ }
801
+
699
802
  const baselineSource = resolvePostReviewBaseline({
700
803
  gitRoot,
701
804
  lastReviewedCommit,
@@ -706,7 +809,6 @@ function checkPostReviewCommit({ taskDir, config }: any): any {
706
809
  }
707
810
 
708
811
  const sha = baselineSource.sha;
709
- const globs = resolvePostReviewGlobs(config, loadReviewConfig());
710
812
  let commits;
711
813
  try {
712
814
  const out = execFileSync("git", ["-C", gitRoot, "rev-list", `${sha}..HEAD`, "--", ...globs], { encoding: "utf8" });
@@ -719,15 +821,50 @@ function checkPostReviewCommit({ taskDir, config }: any): any {
719
821
  return passResult("post-review-commit", `No post-review commits to code/rule paths since ${sha.slice(0, 8)}`);
720
822
  }
721
823
 
722
- let exempt = false;
824
+ let localHead = "";
723
825
  try {
724
- exempt = task.ok && parseLedger(task.content).some(
725
- (row) => row.stage === POST_REVIEW_COMMIT_STAGE && row.status === "human-decided"
726
- );
826
+ localHead = execFileSync("git", ["-C", gitRoot, "rev-parse", "HEAD"], { encoding: "utf8" }).trim();
727
827
  } catch {
728
- return failResult("post-review-commit", "Invalid disagreement ledger");
828
+ return blockedResult("post-review-commit", "Unable to resolve the local HEAD");
729
829
  }
730
- if (exempt) {
830
+
831
+ if (hasPullRequest) {
832
+ if (inspected?.pullRequest) {
833
+ const relation = resolveReviewedHeadRelation({
834
+ gitRoot,
835
+ comparisonHead: localHead,
836
+ lastReviewedCommit: sha,
837
+ pullRequest: inspected.pullRequest
838
+ });
839
+ if (relation.status === "merged-equivalent") {
840
+ return passResult("post-review-commit", `Reviewed PR head is content-equivalent to squash merge ${relation.mergeCommit.slice(0, 8)}`);
841
+ }
842
+ if (relation.status === "blocked") {
843
+ return blockedResult("post-review-commit", relation.message, relation.code);
844
+ }
845
+ }
846
+ } else if (commits.length === 1) {
847
+ const relation = resolveLocalReviewedCommitRelation({
848
+ gitRoot,
849
+ localHead,
850
+ lastReviewedCommit: sha,
851
+ rewrittenCommit: commits[0]!,
852
+ pathspecs: globs
853
+ });
854
+ if (relation.status === "local-equivalent") {
855
+ return passResult(
856
+ "post-review-commit",
857
+ `Reviewed commit is content-equivalent to local rewrite ${relation.rewrittenCommit.slice(0, 8)}`
858
+ );
859
+ }
860
+ if (relation.status === "blocked") {
861
+ return blockedResult("post-review-commit", relation.message);
862
+ }
863
+ }
864
+
865
+ const exemption = resolvePostReviewExemption(task.content);
866
+ if (!exemption.ok) return failResult("post-review-commit", exemption.message);
867
+ if (exemption.exempt) {
731
868
  return passResult(
732
869
  "post-review-commit",
733
870
  `${commits.length} post-review commit(s) covered by a human-decided exemption`
@@ -740,6 +877,21 @@ function checkPostReviewCommit({ taskDir, config }: any): any {
740
877
  );
741
878
  }
742
879
 
880
+ function resolvePostReviewExemption(content: string):
881
+ | { ok: true; exempt: boolean }
882
+ | { ok: false; message: string } {
883
+ try {
884
+ return {
885
+ ok: true,
886
+ exempt: parseLedger(content).some(
887
+ (row) => row.stage === POST_REVIEW_COMMIT_STAGE && row.status === "human-decided"
888
+ )
889
+ };
890
+ } catch {
891
+ return { ok: false, message: "Invalid disagreement ledger" };
892
+ }
893
+ }
894
+
743
895
  function checkReviewFact({ taskDir, artifactFile }: any): any {
744
896
  const resolvedArtifact = resolveArtifactPath(
745
897
  taskDir,
@@ -758,6 +910,7 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
758
910
  const content = fs.readFileSync(resolvedArtifact.path, "utf8");
759
911
  const verdict = parseReviewVerdict(content);
760
912
  const reviewBaseline = extractReviewBaseline(content);
913
+ const reviewDiffBase = extractReviewDiffBase(content);
761
914
  const reviewedFingerprint = extractReviewDiffFingerprint(content);
762
915
  const reviewedTree = extractReviewedSnapshotTree(content);
763
916
 
@@ -768,10 +921,16 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
768
921
  let gitRoot;
769
922
  let head;
770
923
  let baseline;
924
+ let diffBase;
771
925
  try {
772
926
  gitRoot = execFileSync("git", ["-C", taskDir, "rev-parse", "--show-toplevel"], { encoding: "utf8" }).trim();
773
927
  head = execFileSync("git", ["-C", gitRoot, "rev-parse", "HEAD"], { encoding: "utf8" }).trim();
774
928
  baseline = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewBaseline}^{commit}`], { encoding: "utf8" }).trim();
929
+ diffBase = execFileSync(
930
+ "git",
931
+ ["-C", gitRoot, "rev-parse", `${reviewDiffBase || reviewBaseline}^{commit}`],
932
+ { encoding: "utf8" }
933
+ ).trim();
775
934
  } catch {
776
935
  return blockedResult(
777
936
  "review-fact",
@@ -788,7 +947,13 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
788
947
 
789
948
  let actualSnapshot;
790
949
  try {
791
- actualSnapshot = snapshotReview({ cwd: gitRoot, mode: "worktree", baseline, globs: resolvePostReviewGlobs({}, loadReviewConfig()) });
950
+ actualSnapshot = snapshotReview({
951
+ cwd: gitRoot,
952
+ mode: "worktree",
953
+ baseline,
954
+ diffBase,
955
+ globs: resolvePostReviewGlobs({}, loadPostReviewConfig(repoRoot))
956
+ });
792
957
  } catch {
793
958
  return blockedResult(
794
959
  "review-fact",
@@ -1,8 +1,10 @@
1
1
  export {
2
2
  extractReviewBaseline,
3
+ extractReviewDiffBase,
3
4
  extractReviewDiffFingerprint,
4
5
  extractReviewedSnapshotTree,
5
6
  findAuthoritativeReviewCodeArtifact,
7
+ loadPostReviewConfig,
6
8
  parseReviewVerdict,
7
9
  resolvePostReviewGlobs
8
10
  } from './review-fingerprint.ts';
@@ -16,7 +16,8 @@ type VerificationEvent =
16
16
  | 'complete-task.preflight' | 'complete-task.completed'
17
17
  | 'create-pr.completed' | 'create-task.completed'
18
18
  | 'import-codescan.completed' | 'import-dependabot.completed'
19
- | 'import-issue.completed' | 'watch-pr.completed';
19
+ | 'import-issue.completed' | 'watch-pr.completed'
20
+ | 'run-task.paused' | 'run-task.completed';
20
21
  type VerificationSpec = {
21
22
  skill: string;
22
23
  expectedState: 'active' | 'blocked' | 'completed';
@@ -63,14 +64,16 @@ const VERIFICATION_CATALOG: Readonly<Record<VerificationEvent, VerificationSpec>
63
64
  'block-task.completed': gate('block-task', 'blocked'),
64
65
  'cancel-task.completed': gate('cancel-task', 'completed'),
65
66
  'commit.completed': gate('commit', 'active'),
66
- 'complete-task.preflight': { skill: 'complete-task', expectedState: 'active', mode: 'checks', checks: ['review-ledger', 'post-review-commit', 'required-checks', 'platform-sync-preflight'] },
67
+ 'complete-task.preflight': { skill: 'complete-task', expectedState: 'active', mode: 'checks', checks: ['review-ledger', 'post-review-commit', 'platform-sync-preflight'] },
67
68
  'complete-task.completed': gate('complete-task', 'completed'),
68
69
  'create-pr.completed': gate('create-pr', 'active'),
69
70
  'create-task.completed': gate('create-task', 'active'),
70
71
  'import-codescan.completed': gate('import-codescan', 'active'),
71
72
  'import-dependabot.completed': gate('import-dependabot', 'active'),
72
73
  'import-issue.completed': gate('import-issue', 'active'),
73
- 'watch-pr.completed': gate('watch-pr', 'active')
74
+ 'watch-pr.completed': gate('watch-pr', 'active'),
75
+ 'run-task.paused': { skill: 'run-task', expectedState: 'active', mode: 'checks', checks: ['orchestration-state'] },
76
+ 'run-task.completed': { skill: 'run-task', expectedState: 'active', mode: 'checks', checks: ['orchestration-state'] }
74
77
  };
75
78
 
76
79
  function failure(request: { taskRef: string; event: string; artifact?: string }, code: string, message: string, extra: Partial<TaskVerificationResult> = {}): TaskVerificationResult {
@@ -0,0 +1,36 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { spawnSync } from 'node:child_process';
5
+
6
+ function git(repoRoot: string, indexFile: string | null, args: string[]): string {
7
+ const env = indexFile ? { ...process.env, GIT_INDEX_FILE: indexFile } : process.env;
8
+ const result = spawnSync('git', args, { cwd: repoRoot, env, encoding: 'utf8' });
9
+ if (result.status !== 0) {
10
+ throw new Error(String(result.stderr || result.stdout || `git ${args[0]} failed`).trim());
11
+ }
12
+ return result.stdout;
13
+ }
14
+
15
+ function captureWorkspaceSnapshot(repoRoot: string): string {
16
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-infra-orchestration-index-'));
17
+ const indexFile = path.join(tempDir, 'index');
18
+ try {
19
+ git(repoRoot, indexFile, ['read-tree', 'HEAD']);
20
+ git(repoRoot, indexFile, ['add', '-A', '--', ':/']);
21
+ const workspace = path.join(repoRoot, '.agents', 'workspace', 'active');
22
+ if (fs.existsSync(workspace)) {
23
+ git(repoRoot, indexFile, ['add', '-f', '--', '.agents/workspace/active']);
24
+ }
25
+ return git(repoRoot, indexFile, ['write-tree']).trim();
26
+ } finally {
27
+ fs.rmSync(tempDir, { recursive: true, force: true });
28
+ }
29
+ }
30
+
31
+ function diffWorkspaceSnapshots(repoRoot: string, before: string, after: string): string[] {
32
+ const output = git(repoRoot, null, ['diff', '--name-only', '-z', before, after]);
33
+ return output.split('\0').filter(Boolean);
34
+ }
35
+
36
+ export { captureWorkspaceSnapshot, diffWorkspaceSnapshots };