@fitlab-ai/agent-infra 0.9.11 → 0.9.13

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 (356) hide show
  1. package/README.md +13 -13
  2. package/README.zh-CN.md +13 -13
  3. package/dist/bin/internal-cli.js +29 -19
  4. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +71 -10
  5. package/dist/lib/agent-clients/next-steps.js +6 -1
  6. package/dist/lib/decide.js +3 -3
  7. package/dist/lib/defaults.json +4 -0
  8. package/dist/lib/git/workflow.js +43 -1
  9. package/dist/lib/init.js +1 -0
  10. package/dist/lib/internal/git-workflow.js +8 -1
  11. package/dist/lib/internal/platform-checks.js +3 -3
  12. package/dist/lib/internal/platform-comment.js +9 -9
  13. package/dist/lib/internal/platform-context.js +2 -2
  14. package/dist/lib/internal/platform-issue.js +8 -9
  15. package/dist/lib/internal/platform-pr-review.js +10 -10
  16. package/dist/lib/internal/platform-pr.js +68 -23
  17. package/dist/lib/internal/platform-release-notes.js +3 -3
  18. package/dist/lib/internal/pr-review-grade.js +11 -9
  19. package/dist/lib/internal/release-workflow.js +4 -4
  20. package/dist/lib/internal/sandbox-control.js +30 -4
  21. package/dist/lib/internal/task-activity.js +3 -3
  22. package/dist/lib/internal/task-artifact.js +76 -24
  23. package/dist/lib/internal/task-create.js +2 -2
  24. package/dist/lib/internal/task-delivery.js +59 -0
  25. package/dist/lib/internal/task-event.js +6 -3
  26. package/dist/lib/internal/task-finalization.js +2 -2
  27. package/dist/lib/internal/task-invalidation.js +60 -0
  28. package/dist/lib/internal/task-ledger.js +9 -6
  29. package/dist/lib/internal/task-lifecycle.js +2 -2
  30. package/dist/lib/internal/task-override.js +4 -4
  31. package/dist/lib/internal/task-review.js +3 -3
  32. package/dist/lib/internal/task-verify.js +6 -6
  33. package/dist/lib/internal/task-warning.js +3 -3
  34. package/dist/lib/platform/adapters.js +1 -3
  35. package/dist/lib/platform/change-request-git-evidence.js +27 -7
  36. package/dist/lib/platform/completion-backfill.js +6 -5
  37. package/dist/lib/platform/context.js +70 -130
  38. package/dist/lib/platform/github-client.js +8 -2
  39. package/dist/lib/platform/github-provider.js +903 -0
  40. package/dist/lib/platform/in-label-sync.js +143 -0
  41. package/dist/lib/platform/issue-comments.js +94 -41
  42. package/dist/lib/platform/issues.js +335 -189
  43. package/dist/lib/platform/metadata-labels.js +6 -2
  44. package/dist/lib/platform/none-provider.js +28 -0
  45. package/dist/lib/platform/pr-change-report.js +551 -0
  46. package/dist/lib/platform/pr-checks.js +124 -106
  47. package/dist/lib/platform/pr-review.js +88 -72
  48. package/dist/lib/platform/pr-summary.js +523 -49
  49. package/dist/lib/platform/provider-bridge.js +45 -0
  50. package/dist/lib/platform/provider-contract.d.ts +487 -0
  51. package/dist/lib/platform/provider-contract.js +95 -0
  52. package/dist/lib/platform/provider-loader.js +251 -0
  53. package/dist/lib/platform/provider-validation.js +504 -0
  54. package/dist/lib/platform/pull-request-metadata.js +8 -6
  55. package/dist/lib/platform/pull-requests.js +1050 -502
  56. package/dist/lib/platform/release-notes.js +78 -55
  57. package/dist/lib/platform/releases.js +79 -50
  58. package/dist/lib/platform/resource-identity.d.ts +26 -0
  59. package/dist/lib/platform/resource-identity.js +92 -0
  60. package/dist/lib/platform/task-identities.js +31 -0
  61. package/dist/lib/platform/verification-required.js +22 -12
  62. package/dist/lib/platform/verification-sync.js +118 -239
  63. package/dist/lib/pr-review/evidence-grading.js +30 -9
  64. package/dist/lib/run/index.js +63 -23
  65. package/dist/lib/sandbox/config.js +5 -0
  66. package/dist/lib/sandbox/control/client.js +96 -15
  67. package/dist/lib/sandbox/control/executor.js +3 -3
  68. package/dist/lib/sandbox/control/lifecycle.js +29 -7
  69. package/dist/lib/sandbox/control/protocol.js +77 -0
  70. package/dist/lib/sandbox/control/server.js +398 -25
  71. package/dist/lib/sandbox/control/state.js +204 -1
  72. package/dist/lib/server/process-state.js +2 -2
  73. package/dist/lib/server/protocol.js +38 -1
  74. package/dist/lib/task/activity-log.js +8 -1
  75. package/dist/lib/task/artifact-lifecycle.js +35 -7
  76. package/dist/lib/task/capabilities.js +239 -0
  77. package/dist/lib/task/commands/status.js +32 -0
  78. package/dist/lib/task/commit-intent.js +100 -0
  79. package/dist/lib/task/commit-operation.js +207 -102
  80. package/dist/lib/task/control-authority.js +8 -5
  81. package/dist/lib/task/create-service.js +8 -8
  82. package/dist/lib/task/create.js +33 -7
  83. package/dist/lib/task/current-contract.js +5 -1
  84. package/dist/lib/task/decision-details.js +3 -48
  85. package/dist/lib/task/delivery-target.js +97 -0
  86. package/dist/lib/task/delivery.js +153 -0
  87. package/dist/lib/task/events.js +297 -17
  88. package/dist/lib/task/finalization.js +37 -13
  89. package/dist/lib/task/human-override.js +61 -36
  90. package/dist/lib/task/invalidation-command.js +86 -0
  91. package/dist/lib/task/invalidation.js +260 -0
  92. package/dist/lib/task/ledger-intents.js +37 -0
  93. package/dist/lib/task/lifecycle.js +106 -9
  94. package/dist/lib/task/local-artifact-finalization.js +374 -0
  95. package/dist/lib/task/orchestration.js +100 -151
  96. package/dist/lib/task/pr-delivery-fact.js +183 -0
  97. package/dist/lib/task/review-finalization.js +4 -8
  98. package/dist/lib/task/review-fingerprint.js +32 -2
  99. package/dist/lib/task/rework-intent.js +138 -0
  100. package/dist/lib/task/skill-scope.js +23 -0
  101. package/dist/lib/task/task-execution-lock.js +27 -17
  102. package/dist/lib/task/verification-engine.js +89 -38
  103. package/dist/lib/task/verification-review.js +1 -1
  104. package/dist/lib/task/verification.js +3 -3
  105. package/dist/lib/task/workflow-warning-intents.js +1 -1
  106. package/dist/lib/task/write.js +11 -0
  107. package/dist/lib/update.js +9 -0
  108. package/dist/lib/version.js +11 -1
  109. package/dist/lifecycle-build-manifest.json +3 -3
  110. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +105 -10
  111. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +12 -1
  112. package/lib/agent-clients/next-steps.ts +6 -1
  113. package/lib/decide.ts +3 -3
  114. package/lib/defaults.json +4 -0
  115. package/lib/git/workflow.ts +38 -1
  116. package/lib/init.ts +4 -1
  117. package/lib/internal/git-workflow.ts +7 -1
  118. package/lib/internal/platform-checks.ts +3 -3
  119. package/lib/internal/platform-comment.ts +8 -8
  120. package/lib/internal/platform-context.ts +2 -2
  121. package/lib/internal/platform-issue.ts +7 -8
  122. package/lib/internal/platform-pr-review.ts +9 -9
  123. package/lib/internal/platform-pr.ts +53 -21
  124. package/lib/internal/platform-release-notes.ts +3 -3
  125. package/lib/internal/pr-review-grade.ts +10 -8
  126. package/lib/internal/release-workflow.ts +4 -4
  127. package/lib/internal/sandbox-control.ts +27 -3
  128. package/lib/internal/task-activity.ts +3 -3
  129. package/lib/internal/task-artifact.ts +65 -22
  130. package/lib/internal/task-create.ts +2 -2
  131. package/lib/internal/task-delivery.ts +53 -0
  132. package/lib/internal/task-event.ts +6 -3
  133. package/lib/internal/task-finalization.ts +3 -3
  134. package/lib/internal/task-invalidation.ts +39 -0
  135. package/lib/internal/task-ledger.ts +11 -8
  136. package/lib/internal/task-lifecycle.ts +2 -2
  137. package/lib/internal/task-override.ts +6 -6
  138. package/lib/internal/task-review.ts +3 -3
  139. package/lib/internal/task-verify.ts +6 -6
  140. package/lib/internal/task-warning.ts +3 -3
  141. package/lib/platform/adapters.ts +3 -2
  142. package/lib/platform/change-request-git-evidence.ts +36 -9
  143. package/lib/platform/completion-backfill.ts +9 -8
  144. package/lib/platform/context.ts +97 -134
  145. package/lib/platform/github-client.ts +10 -3
  146. package/lib/platform/github-provider.ts +910 -0
  147. package/lib/platform/in-label-sync.ts +208 -0
  148. package/lib/platform/issue-comments.ts +97 -47
  149. package/lib/platform/issues.ts +344 -174
  150. package/lib/platform/metadata-labels.ts +5 -2
  151. package/lib/platform/none-provider.ts +35 -0
  152. package/lib/platform/pr-change-report.ts +645 -0
  153. package/lib/platform/pr-checks.ts +129 -107
  154. package/lib/platform/pr-review.ts +88 -85
  155. package/lib/platform/pr-summary.ts +562 -52
  156. package/lib/platform/provider-bridge.ts +82 -0
  157. package/lib/platform/provider-contract.ts +536 -0
  158. package/lib/platform/provider-loader.ts +307 -0
  159. package/lib/platform/provider-validation.ts +529 -0
  160. package/lib/platform/pull-request-metadata.ts +10 -7
  161. package/lib/platform/pull-requests.ts +1126 -505
  162. package/lib/platform/release-notes.ts +76 -59
  163. package/lib/platform/releases.ts +77 -43
  164. package/lib/platform/resource-identity.ts +121 -0
  165. package/lib/platform/task-identities.ts +40 -0
  166. package/lib/platform/types.ts +4 -2
  167. package/lib/platform/verification-required.ts +21 -13
  168. package/lib/platform/verification-sync.ts +118 -293
  169. package/lib/pr-review/evidence-grading.ts +31 -11
  170. package/lib/run/index.ts +57 -22
  171. package/lib/sandbox/config.ts +7 -0
  172. package/lib/sandbox/control/client.ts +105 -15
  173. package/lib/sandbox/control/executor.ts +4 -4
  174. package/lib/sandbox/control/lifecycle.ts +30 -8
  175. package/lib/sandbox/control/protocol.ts +113 -0
  176. package/lib/sandbox/control/server.ts +431 -23
  177. package/lib/sandbox/control/state.ts +251 -1
  178. package/lib/server/process-state.ts +2 -2
  179. package/lib/server/protocol.ts +36 -1
  180. package/lib/task/activity-log.ts +8 -0
  181. package/lib/task/artifact-lifecycle.ts +34 -8
  182. package/lib/task/capabilities.ts +262 -0
  183. package/lib/task/commands/status.ts +38 -0
  184. package/lib/task/commit-intent.ts +137 -0
  185. package/lib/task/commit-operation.ts +186 -88
  186. package/lib/task/control-authority.ts +11 -8
  187. package/lib/task/create-service.ts +8 -8
  188. package/lib/task/create.ts +34 -9
  189. package/lib/task/current-contract.ts +6 -1
  190. package/lib/task/decision-details.ts +8 -64
  191. package/lib/task/delivery-target.ts +130 -0
  192. package/lib/task/delivery.ts +160 -0
  193. package/lib/task/events.ts +296 -16
  194. package/lib/task/finalization.ts +50 -14
  195. package/lib/task/human-override.ts +73 -46
  196. package/lib/task/invalidation-command.ts +86 -0
  197. package/lib/task/invalidation.ts +332 -0
  198. package/lib/task/ledger-intents.ts +35 -1
  199. package/lib/task/lifecycle.ts +93 -4
  200. package/lib/task/local-artifact-finalization.ts +563 -0
  201. package/lib/task/orchestration.ts +110 -146
  202. package/lib/task/pr-delivery-fact.ts +237 -0
  203. package/lib/task/review-finalization.ts +4 -14
  204. package/lib/task/review-fingerprint.ts +33 -2
  205. package/lib/task/rework-intent.ts +165 -0
  206. package/lib/task/skill-scope.ts +24 -0
  207. package/lib/task/task-execution-lock.ts +23 -14
  208. package/lib/task/verification-engine.ts +95 -43
  209. package/lib/task/verification-review.ts +2 -0
  210. package/lib/task/verification.ts +4 -4
  211. package/lib/task/workflow-warning-intents.ts +1 -1
  212. package/lib/task/write.ts +19 -0
  213. package/lib/update.ts +11 -1
  214. package/lib/version.ts +15 -1
  215. package/package.json +7 -1
  216. package/templates/.agents/rules/README.en.md +4 -2
  217. package/templates/.agents/rules/README.zh-CN.md +4 -2
  218. package/templates/.agents/rules/create-issue.en.md +11 -2
  219. package/templates/.agents/rules/create-issue.zh-CN.md +24 -2
  220. package/templates/.agents/rules/issue-pr-commands.en.md +4 -17
  221. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
  222. package/templates/.agents/rules/issue-sync.en.md +28 -5
  223. package/templates/.agents/rules/issue-sync.zh-CN.md +64 -5
  224. package/templates/.agents/rules/label-milestone-setup.en.md +15 -2
  225. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +15 -2
  226. package/templates/.agents/rules/local-artifact-repair.en.md +53 -0
  227. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +53 -0
  228. package/templates/.agents/rules/milestone-inference.en.md +12 -2
  229. package/templates/.agents/rules/milestone-inference.zh-CN.md +25 -3
  230. package/templates/.agents/rules/pr-sync.en.md +28 -13
  231. package/templates/.agents/rules/pr-sync.zh-CN.md +39 -5
  232. package/templates/.agents/rules/release-commands.en.md +42 -3
  233. package/templates/.agents/rules/release-commands.zh-CN.md +42 -3
  234. package/templates/.agents/rules/security-alerts.en.md +17 -2
  235. package/templates/.agents/rules/security-alerts.zh-CN.md +17 -2
  236. package/templates/.agents/rules/sync-content-generation.en.md +8 -0
  237. package/templates/.agents/rules/sync-content-generation.zh-CN.md +8 -0
  238. package/templates/.agents/rules/task-management.en.md +1 -1
  239. package/templates/.agents/rules/task-management.zh-CN.md +1 -1
  240. package/templates/.agents/rules/task-short-id.en.md +1 -4
  241. package/templates/.agents/rules/task-short-id.zh-CN.md +1 -3
  242. package/templates/.agents/scripts/security-alerts.github.sh +151 -0
  243. package/templates/.agents/scripts/security-alerts.sh +31 -0
  244. package/templates/.agents/skills/analyze-task/SKILL.en.md +14 -3
  245. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +11 -3
  246. package/templates/.agents/skills/check-task/SKILL.en.md +16 -37
  247. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -37
  248. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  249. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  250. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  251. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  252. package/templates/.agents/skills/code-task/SKILL.en.md +32 -10
  253. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +35 -13
  254. package/templates/.agents/skills/code-task/config/verify.en.json +1 -0
  255. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -0
  256. package/templates/.agents/skills/commit/SKILL.en.md +3 -3
  257. package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -3
  258. package/templates/.agents/skills/commit/config/verify.json +1 -1
  259. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +3 -3
  260. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +3 -3
  261. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +2 -0
  262. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +2 -0
  263. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +4 -4
  264. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +4 -4
  265. package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -2
  266. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -2
  267. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +7 -4
  268. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +7 -4
  269. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  270. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  271. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +5 -4
  272. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +5 -4
  273. package/templates/.agents/skills/complete-task/SKILL.en.md +31 -13
  274. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +30 -13
  275. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +2 -2
  276. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +2 -2
  277. package/templates/.agents/skills/create-pr/SKILL.en.md +11 -10
  278. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +11 -11
  279. package/templates/.agents/skills/create-pr/config/verify.json +1 -0
  280. package/templates/.agents/skills/create-pr/reference/change-report.en.md +16 -4
  281. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +16 -4
  282. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +5 -3
  283. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +5 -3
  284. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +1 -1
  285. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +1 -1
  286. package/templates/.agents/skills/create-pr/scripts/change-report.mjs +3 -0
  287. package/templates/.agents/skills/create-task/SKILL.en.md +1 -0
  288. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -0
  289. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  290. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  291. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  292. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  293. package/templates/.agents/skills/init-labels/SKILL.en.md +9 -10
  294. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +9 -10
  295. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +57 -1
  296. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +27 -1
  297. package/templates/.agents/skills/init-milestones/SKILL.en.md +3 -5
  298. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +3 -5
  299. package/templates/.agents/skills/plan-task/SKILL.en.md +14 -3
  300. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +11 -3
  301. package/templates/.agents/skills/review-analysis/SKILL.en.md +6 -5
  302. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +6 -5
  303. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +18 -0
  304. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +18 -0
  305. package/templates/.agents/skills/review-code/SKILL.en.md +10 -9
  306. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +10 -9
  307. package/templates/.agents/skills/review-code/reference/output-templates.en.md +19 -1
  308. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +19 -1
  309. package/templates/.agents/skills/review-code/reference/report-template.en.md +4 -2
  310. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +4 -2
  311. package/templates/.agents/skills/review-plan/SKILL.en.md +6 -5
  312. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +6 -5
  313. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +18 -0
  314. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +18 -0
  315. package/templates/.agents/skills/review-pr/SKILL.en.md +1 -0
  316. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +1 -0
  317. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +2 -2
  318. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +2 -2
  319. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -2
  320. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -2
  321. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  322. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  323. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +4 -0
  324. package/templates/.agents/skills/watch-pr/SKILL.en.md +6 -6
  325. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +6 -6
  326. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +6 -0
  327. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +6 -0
  328. package/templates/.agents/templates/task.en.md +23 -2
  329. package/templates/.agents/templates/task.zh-CN.md +23 -2
  330. package/templates/.agents/workflows/bug-fix.en.yaml +9 -8
  331. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +9 -8
  332. package/templates/.agents/workflows/feature-development.en.yaml +9 -8
  333. package/templates/.agents/workflows/feature-development.zh-CN.yaml +9 -8
  334. package/templates/.agents/workflows/refactoring.en.yaml +9 -8
  335. package/templates/.agents/workflows/refactoring.zh-CN.yaml +9 -8
  336. package/templates/.github/workflows/pr-label.yml +7 -26
  337. package/templates/.agents/rules/create-issue.github.en.md +0 -14
  338. package/templates/.agents/rules/create-issue.github.zh-CN.md +0 -27
  339. package/templates/.agents/rules/issue-pr-commands.github.en.md +0 -34
  340. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +0 -49
  341. package/templates/.agents/rules/issue-sync.github.en.md +0 -40
  342. package/templates/.agents/rules/issue-sync.github.zh-CN.md +0 -76
  343. package/templates/.agents/rules/label-milestone-setup.github.en.md +0 -60
  344. package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +0 -60
  345. package/templates/.agents/rules/milestone-inference.github.en.md +0 -15
  346. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +0 -27
  347. package/templates/.agents/rules/pr-checks-commands.github.en.md +0 -18
  348. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +0 -34
  349. package/templates/.agents/rules/pr-sync.github.en.md +0 -43
  350. package/templates/.agents/rules/pr-sync.github.zh-CN.md +0 -69
  351. package/templates/.agents/rules/release-commands.github.en.md +0 -44
  352. package/templates/.agents/rules/release-commands.github.zh-CN.md +0 -44
  353. package/templates/.agents/rules/security-alerts.github.en.md +0 -43
  354. package/templates/.agents/rules/security-alerts.github.zh-CN.md +0 -43
  355. /package/templates/.agents/rules/{issue-fields.github.en.md → issue-fields.en.md} +0 -0
  356. /package/templates/.agents/rules/{issue-fields.github.zh-CN.md → issue-fields.zh-CN.md} +0 -0
@@ -43,6 +43,7 @@ async function cmdSync() {
43
43
  const sandboxAdded = !config.sandbox;
44
44
  const taskAdded = !config.task;
45
45
  const labelsAdded = !config.labels;
46
+ const deliveryAdded = !config.delivery;
46
47
  if (platformAdded)
47
48
  config.platform = structuredClone(defaults.platform);
48
49
  if (sandboxAdded)
@@ -51,6 +52,8 @@ async function cmdSync() {
51
52
  config.task = structuredClone(defaults.task);
52
53
  if (labelsAdded)
53
54
  config.labels = structuredClone(defaults.labels);
55
+ if (deliveryAdded)
56
+ config.delivery = structuredClone(defaults.delivery);
54
57
  const workflowPlan = planAgentClientReconciliation({
55
58
  config: config,
56
59
  mutation: { type: 'replace-state', state: normalizedOriginal.state },
@@ -98,6 +101,9 @@ async function cmdSync() {
98
101
  if (labelsAdded) {
99
102
  info(`Default labels.in config added to ${CONFIG_PATH}.`);
100
103
  }
104
+ if (deliveryAdded) {
105
+ info(`Default delivery target added to ${CONFIG_PATH}.`);
106
+ }
101
107
  }
102
108
  else {
103
109
  info(`File registry changed in ${CONFIG_PATH}.`);
@@ -114,6 +120,9 @@ async function cmdSync() {
114
120
  if (hasNewEntries && platformAdded) {
115
121
  info(`Default platform config added to ${CONFIG_PATH}.`);
116
122
  }
123
+ if (hasNewEntries && deliveryAdded) {
124
+ info(`Default delivery target added to ${CONFIG_PATH}.`);
125
+ }
117
126
  ok(`Updated ${CONFIG_PATH}`);
118
127
  }
119
128
  // done
@@ -1,4 +1,5 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
+ import semver from 'semver';
2
3
  const packageJsonUrl = [
3
4
  new URL('../package.json', import.meta.url),
4
5
  new URL('../../package.json', import.meta.url),
@@ -9,8 +10,17 @@ if (!packageJsonUrl) {
9
10
  const { version } = JSON.parse(readFileSync(packageJsonUrl, 'utf8'));
10
11
  const VERSION = `v${version}`;
11
12
  const AGENT_INFRA_VERSION_PATTERN = /^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
13
+ const LEGACY_COMPATIBILITY_CUTOFF_VERSION = '1.0.0';
12
14
  function isValidAgentInfraVersion(value) {
13
15
  return typeof value === 'string' && AGENT_INFRA_VERSION_PATTERN.test(value);
14
16
  }
15
- export { VERSION, isValidAgentInfraVersion };
17
+ function isLegacyCompatibilityEnabled(runtimeVersion = VERSION) {
18
+ const normalized = runtimeVersion.startsWith('v') ? runtimeVersion.slice(1) : runtimeVersion;
19
+ const parsed = semver.valid(normalized);
20
+ return parsed !== null && semver.lt(parsed, LEGACY_COMPATIBILITY_CUTOFF_VERSION);
21
+ }
22
+ function legacyCompatibilityError(resource, runtimeVersion = VERSION) {
23
+ return Object.assign(new Error(`PLATFORM_IDENTITY_LEGACY_UNSUPPORTED: ${resource} requires migration to the current schema before v${LEGACY_COMPATIBILITY_CUTOFF_VERSION} runtime ${runtimeVersion}`), { code: 'PLATFORM_IDENTITY_LEGACY_UNSUPPORTED' });
24
+ }
25
+ export { LEGACY_COMPATIBILITY_CUTOFF_VERSION, VERSION, isLegacyCompatibilityEnabled, isValidAgentInfraVersion, legacyCompatibilityError };
16
26
  //# sourceMappingURL=version.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "protocolVersion": 3,
3
- "packageVersion": "0.9.11",
4
- "sourceInputHash": "00e07caf1313615df10d46ae620767d7d15c3cc59712c1da581623057b87e0a6",
5
- "internalExecutableBuildHash": "8a481b1d79da5e5f31ef79cd3428f1b51df2b859e70724e50dcc5910f8ee40c6"
3
+ "packageVersion": "0.9.13",
4
+ "sourceInputHash": "5e4d3ad1c1e7e3c909489ef59ff318ea9cffe5f538ae37d83923773946357afe",
5
+ "internalExecutableBuildHash": "c8cabf5c6bc776cdcb9621f712172ebda95ff9b12fb6f67213e18bc0159516fd"
6
6
  }
@@ -22,6 +22,14 @@ type LifecycleBuildIdentityOptions = Readonly<{
22
22
  type LifecycleManifestFiles = Readonly<{
23
23
  executableFiles: readonly string[];
24
24
  contractFiles: readonly string[];
25
+ launcherShebang: LifecycleLauncherShebang;
26
+ }>;
27
+
28
+ type LifecycleLauncherShebang = Readonly<{
29
+ sourceFile: string;
30
+ compiledFile: string;
31
+ canonicalLine: string;
32
+ acceptedLines: readonly string[];
25
33
  }>;
26
34
 
27
35
  type IdentityVerification = Readonly<{
@@ -53,6 +61,56 @@ function normalizeRelativePath(value: string): string {
53
61
  return value.replaceAll('\\', '/');
54
62
  }
55
63
 
64
+ function isSafeLifecyclePath(value: unknown): value is string {
65
+ return exactText(value)
66
+ && value === normalizeRelativePath(value)
67
+ && !path.isAbsolute(value)
68
+ && !/^[A-Za-z]:[\\/]/u.test(value)
69
+ && !value.split('/').includes('..');
70
+ }
71
+
72
+ function isLifecycleLauncherLine(value: unknown): value is string {
73
+ return typeof value === 'string'
74
+ && value.length > 1
75
+ && value.slice(0, -1).trim() === value.slice(0, -1)
76
+ && value.startsWith('#!')
77
+ && value.endsWith('\n')
78
+ && value.indexOf('\n') === value.length - 1
79
+ && !value.includes('\r');
80
+ }
81
+
82
+ function readLifecycleLauncherShebang(
83
+ value: unknown,
84
+ executableFiles: readonly string[]
85
+ ): LifecycleLauncherShebang {
86
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
87
+ throw new Error('Lifecycle manifest launcher shebang policy is invalid');
88
+ }
89
+ const policy = value as Record<string, unknown>;
90
+ if (!isSafeLifecyclePath(policy.sourceFile)
91
+ || !isSafeLifecyclePath(policy.compiledFile)
92
+ || !isLifecycleLauncherLine(policy.canonicalLine)
93
+ || !Array.isArray(policy.acceptedLines)
94
+ || !policy.acceptedLines.every(isLifecycleLauncherLine)
95
+ || new Set(policy.acceptedLines).size !== policy.acceptedLines.length
96
+ || !policy.acceptedLines.includes(policy.canonicalLine)
97
+ || !executableFiles.includes(policy.sourceFile)
98
+ || policy.compiledFile !== normalizeRelativePath(path.join(
99
+ 'dist',
100
+ policy.sourceFile.endsWith('.ts')
101
+ ? policy.sourceFile.replace(/\.ts$/u, '.js')
102
+ : policy.sourceFile
103
+ ))) {
104
+ throw new Error('Lifecycle manifest launcher shebang policy is invalid');
105
+ }
106
+ return Object.freeze({
107
+ sourceFile: policy.sourceFile,
108
+ compiledFile: policy.compiledFile,
109
+ canonicalLine: policy.canonicalLine,
110
+ acceptedLines: Object.freeze([...policy.acceptedLines])
111
+ });
112
+ }
113
+
56
114
  function readLifecycleManifestFiles(packageRoot: string): LifecycleManifestFiles {
57
115
  const file = path.join(
58
116
  packageRoot,
@@ -65,18 +123,21 @@ function readLifecycleManifestFiles(packageRoot: string): LifecycleManifestFiles
65
123
  const value = JSON.parse(fs.readFileSync(file, 'utf8')) as {
66
124
  executableFiles?: unknown;
67
125
  contractFiles?: unknown;
126
+ launcherShebang?: unknown;
68
127
  };
69
128
  if (!Array.isArray(value.executableFiles)
70
129
  || !Array.isArray(value.contractFiles)
71
- || !value.executableFiles.every(exactText)
72
- || !value.contractFiles.every(exactText)
130
+ || !value.executableFiles.every(isSafeLifecyclePath)
131
+ || !value.contractFiles.every(isSafeLifecyclePath)
73
132
  || new Set(value.executableFiles).size !== value.executableFiles.length
74
133
  || new Set(value.contractFiles).size !== value.contractFiles.length) {
75
134
  throw new Error('Lifecycle manifest file list is invalid');
76
135
  }
136
+ const executableFiles = Object.freeze([...value.executableFiles] as string[]);
77
137
  return Object.freeze({
78
- executableFiles: Object.freeze([...value.executableFiles] as string[]),
79
- contractFiles: Object.freeze([...value.contractFiles] as string[])
138
+ executableFiles,
139
+ contractFiles: Object.freeze([...value.contractFiles] as string[]),
140
+ launcherShebang: readLifecycleLauncherShebang(value.launcherShebang, executableFiles)
80
141
  });
81
142
  }
82
143
 
@@ -94,7 +155,28 @@ function executablePackageRoot(): string {
94
155
  }
95
156
  }
96
157
 
97
- function hashFiles(root: string, files: readonly string[]): string {
158
+ function normalizeLifecycleLauncherBytes(
159
+ relative: string,
160
+ content: Buffer,
161
+ policy: LifecycleLauncherShebang
162
+ ): Buffer {
163
+ const normalized = normalizeRelativePath(relative);
164
+ if (normalized !== policy.sourceFile && normalized !== policy.compiledFile) return content;
165
+ const lineEnd = content.indexOf(0x0a);
166
+ if (lineEnd < 0) return content;
167
+ const firstLine = content.subarray(0, lineEnd + 1);
168
+ if (!policy.acceptedLines.some((line) => Buffer.from(line).equals(firstLine))) return content;
169
+ return Buffer.concat([
170
+ Buffer.from(policy.canonicalLine),
171
+ content.subarray(lineEnd + 1)
172
+ ]);
173
+ }
174
+
175
+ function hashFiles(
176
+ root: string,
177
+ files: readonly string[],
178
+ launcherShebang?: LifecycleLauncherShebang
179
+ ): string {
98
180
  const hash = crypto.createHash('sha256');
99
181
  for (const relative of [...new Set(files.map(normalizeRelativePath))].sort()) {
100
182
  if (path.isAbsolute(relative) || relative.split(/[\\/]/u).includes('..')) {
@@ -107,7 +189,10 @@ function hashFiles(root: string, files: readonly string[]): string {
107
189
  }
108
190
  hash.update(relative);
109
191
  hash.update('\0');
110
- hash.update(fs.readFileSync(file));
192
+ const content = fs.readFileSync(file);
193
+ hash.update(launcherShebang
194
+ ? normalizeLifecycleLauncherBytes(relative, content, launcherShebang)
195
+ : content);
111
196
  hash.update('\0');
112
197
  }
113
198
  return hash.digest('hex');
@@ -157,7 +242,7 @@ function computeLifecycleBuildIdentity(
157
242
  if (!exactText(packageJson.version)) throw new Error('Lifecycle package version is invalid');
158
243
  let internalExecutableBuildHash: string;
159
244
  if (options.executableFiles) {
160
- internalExecutableBuildHash = hashFiles(repoRoot, options.executableFiles);
245
+ internalExecutableBuildHash = hashFiles(repoRoot, options.executableFiles, defaults.launcherShebang);
161
246
  } else {
162
247
  const manifestFile = path.join(executableRoot, 'dist', 'lifecycle-build-manifest.json');
163
248
  if (fs.existsSync(manifestFile)) {
@@ -177,16 +262,25 @@ function computeLifecycleBuildIdentity(
177
262
  const compiledFiles = defaults.executableFiles.map((file) =>
178
263
  file.endsWith('.ts') ? path.join('dist', file.replace(/\.ts$/u, '.js')) : file
179
264
  );
180
- if (hashFiles(executableRoot, resolveLifecycleExecutableFiles(executableRoot, compiledFiles)) !== manifest.internalExecutableBuildHash) {
265
+ if (hashFiles(
266
+ executableRoot,
267
+ resolveLifecycleExecutableFiles(executableRoot, compiledFiles),
268
+ defaults.launcherShebang
269
+ ) !== manifest.internalExecutableBuildHash) {
181
270
  throw new Error('Lifecycle compiled executable build does not match its manifest');
182
271
  }
183
- } else if (hashFiles(executableRoot, resolveLifecycleExecutableFiles(executableRoot, defaults.executableFiles)) !== manifest.sourceInputHash) {
272
+ } else if (hashFiles(
273
+ executableRoot,
274
+ resolveLifecycleExecutableFiles(executableRoot, defaults.executableFiles),
275
+ defaults.launcherShebang
276
+ ) !== manifest.sourceInputHash) {
184
277
  throw new Error('Lifecycle executable build manifest is stale or invalid');
185
278
  }
186
279
  internalExecutableBuildHash = manifest.internalExecutableBuildHash;
187
280
  } else internalExecutableBuildHash = hashFiles(
188
281
  executableRoot,
189
- resolveLifecycleExecutableFiles(executableRoot, defaults.executableFiles)
282
+ resolveLifecycleExecutableFiles(executableRoot, defaults.executableFiles),
283
+ defaults.launcherShebang
190
284
  );
191
285
  }
192
286
  return Object.freeze({
@@ -249,6 +343,7 @@ export type {
249
343
  IdentityVerification,
250
344
  LifecycleIdentityWarning,
251
345
  LifecycleBuildIdentity,
346
+ LifecycleLauncherShebang,
252
347
  LifecycleManifestFiles,
253
348
  LifecycleBuildIdentityOptions
254
349
  };
@@ -30,5 +30,16 @@
30
30
  ".agents/hooks/lifecycle-delegation.js",
31
31
  ".agents/skills/run-task/SKILL.md",
32
32
  ".agents/rules/lifecycle-orchestration.md"
33
- ]
33
+ ],
34
+ "launcherShebang": {
35
+ "sourceFile": "bin/internal-cli.ts",
36
+ "compiledFile": "dist/bin/internal-cli.js",
37
+ "canonicalLine": "#!/usr/bin/env node\n",
38
+ "acceptedLines": [
39
+ "#!/usr/bin/env node\n",
40
+ "#!/opt/homebrew/opt/node/bin/node\n",
41
+ "#!/usr/local/opt/node/bin/node\n",
42
+ "#!/home/linuxbrew/.linuxbrew/opt/node/bin/node\n"
43
+ ]
44
+ }
34
45
  }
@@ -1,6 +1,7 @@
1
1
  import { listEnabledAgentClientAdapters } from './registry.ts';
2
2
  import { renderAgentClientInvocation } from './invocation.ts';
3
3
  import semver from 'semver';
4
+ import { isTaskScopeSkill } from '../task/skill-scope.ts';
4
5
  import type { CustomTUI } from './custom-tuis.ts';
5
6
  import type { AgentClientId, AgentClientState } from './types.ts';
6
7
 
@@ -45,7 +46,11 @@ function renderNextStepCommands(
45
46
  }
46
47
 
47
48
  const args = [
48
- ...(input.taskRef === undefined ? [] : [input.taskRef]),
49
+ ...(input.taskRef === undefined
50
+ ? []
51
+ : isTaskScopeSkill(input.skillName)
52
+ ? ['--task', input.taskRef]
53
+ : [input.taskRef]),
49
54
  ...(input.version === undefined ? [] : [input.version])
50
55
  ];
51
56
 
package/lib/decide.ts CHANGED
@@ -79,11 +79,11 @@ export async function decide(args: string[], options: DecideOptions = {}): Promi
79
79
  metadataProvider: () => ({ timestamp: now, agentInfraVersion: options.version ?? VERSION })
80
80
  };
81
81
  let result;
82
- const execute = () => {
82
+ const execute = async () => {
83
83
  let current = applyHumanDecision(request, writeOptions);
84
84
  if (current.status !== 'failed' || !parsedDecision.overrideTicket) return current;
85
85
  if (!parsedDecision.overrideTarget || !parsedDecision.overrideScope) throw new Error('override ticket requires --override-target and --override-scope');
86
- const consumed = consumeHumanOverride({
86
+ const consumed = await consumeHumanOverride({
87
87
  taskRef: resolved.taskId,
88
88
  ticketId: parsedDecision.overrideTicket,
89
89
  failureId: failureId('decision-intent', current.error?.code ?? 'TASK_STATE_MISMATCH'),
@@ -102,7 +102,7 @@ export async function decide(args: string[], options: DecideOptions = {}): Promi
102
102
  if (consumed.status === 'failed') throw new Error(consumed.error.message);
103
103
  return current;
104
104
  };
105
- result = withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-decision', execute);
105
+ result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-decision', execute);
106
106
  if (result.error) throw new Error(result.error.message);
107
107
  return 0;
108
108
  } catch (error) {
package/lib/defaults.json CHANGED
@@ -48,6 +48,10 @@
48
48
  "task": {
49
49
  "shortIdLength": 2
50
50
  },
51
+ "delivery": {
52
+ "remote": "origin",
53
+ "baseRef": "main"
54
+ },
51
55
  "labels": {
52
56
  "in": {}
53
57
  },
@@ -1,5 +1,6 @@
1
1
  import { spawnSync } from 'node:child_process';
2
2
  import fs from 'node:fs';
3
+ import os from 'node:os';
3
4
  import path from 'node:path';
4
5
 
5
6
  type CommandResult = { status: number | null; stdout: string; stderr: string };
@@ -105,6 +106,42 @@ function commitExplicitPaths(input: { cwd: string; paths: readonly string[]; mes
105
106
  return { status: 'applied' as const, changed: true, snapshot: after.snapshot, operations: [{ name: 'stage', status: 'applied' as const }, { name: 'commit', status: 'applied' as const }], error: null };
106
107
  }
107
108
 
109
+ function previewCommitTree(input: { cwd: string; paths: readonly string[]; expectedHead: string }) {
110
+ const invalid = validatePaths(input.paths);
111
+ if (invalid) return { status: 'failed' as const, tree: null, error: { code: 'GIT_COMMIT_INPUT_INVALID', message: invalid } };
112
+ const before = inspectGitWorkflow(input.cwd);
113
+ if (!before.snapshot) return { status: 'failed' as const, tree: null, error: { code: 'GIT_INSPECT_FAILED', message: 'Unable to inspect Git repository' } };
114
+ if (before.snapshot.head !== input.expectedHead) {
115
+ return { status: 'failed' as const, tree: null, error: { code: 'GIT_HEAD_MISMATCH', message: `Expected HEAD ${input.expectedHead}, received ${before.snapshot.head}` } };
116
+ }
117
+ const selected = new Set(input.paths);
118
+ const unrelatedStaged = before.snapshot.staged.filter((candidate) => !selected.has(candidate));
119
+ if (unrelatedStaged.length > 0) {
120
+ return { status: 'failed' as const, tree: null, error: { code: 'GIT_STAGED_SCOPE_MISMATCH', message: `Unrelated staged paths: ${unrelatedStaged.join(', ')}` } };
121
+ }
122
+ const temporaryDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-infra-preview-index-'));
123
+ const indexFile = path.join(temporaryDirectory, 'index');
124
+ const temporaryRunner: GitRunner = (args, cwd) => {
125
+ const result = spawnSync('git', [...args], {
126
+ cwd,
127
+ env: { ...process.env, GIT_INDEX_FILE: indexFile },
128
+ encoding: 'utf8'
129
+ });
130
+ return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };
131
+ };
132
+ try {
133
+ const read = run(temporaryRunner, input.cwd, ['read-tree', input.expectedHead]);
134
+ if (read.status !== 0) return { status: 'failed' as const, tree: null, error: { code: 'GIT_PREVIEW_FAILED', message: read.stderr.trim() || 'Unable to prepare a temporary Git index' } };
135
+ const stage = run(temporaryRunner, input.cwd, ['add', '-A', '--', ...input.paths]);
136
+ if (stage.status !== 0) return { status: 'failed' as const, tree: null, error: { code: 'GIT_PREVIEW_FAILED', message: stage.stderr.trim() || 'Unable to stage the requested paths in a temporary index' } };
137
+ const tree = value(temporaryRunner, input.cwd, ['write-tree']);
138
+ if (!tree) return { status: 'failed' as const, tree: null, error: { code: 'GIT_PREVIEW_FAILED', message: 'Unable to write the temporary Git tree' } };
139
+ return { status: 'planned' as const, tree, error: null };
140
+ } finally {
141
+ fs.rmSync(temporaryDirectory, { recursive: true, force: true });
142
+ }
143
+ }
144
+
108
145
  function pushGitRefs(input: { cwd: string; remote: string; refs: readonly string[]; expectedSha?: string }, runner: GitRunner = defaultRunner) {
109
146
  if (!input.remote || input.refs.length === 0) return { status: 'failed' as const, changed: false, snapshot: inspectGitWorkflow(input.cwd, runner).snapshot, operations: [], error: { code: 'GIT_PUSH_INPUT_INVALID', message: 'Remote and refs are required' } };
110
147
  const operations: GitOperation[] = [];
@@ -192,5 +229,5 @@ function pushRebasedBranch(input: PushRebasedInput, runner: GitRunner = defaultR
192
229
  return { status: 'applied' as const, changed: true, snapshot: inspectGitWorkflow(input.cwd, runner).snapshot, operations: [{ name: 'push-rebased', status: 'applied' as const, ref: input.branch }], error: null };
193
230
  }
194
231
 
195
- export { commitExplicitPaths, inspectGitWorkflow, pushGitRefs, pushRebasedBranch };
232
+ export { commitExplicitPaths, inspectGitWorkflow, previewCommitTree, pushGitRefs, pushRebasedBranch };
196
233
  export type { CommandResult, GitRunner, PushRebasedInput };
package/lib/init.ts CHANGED
@@ -32,6 +32,7 @@ type Defaults = {
32
32
  files: FileRegistry;
33
33
  sandbox: Record<string, unknown>;
34
34
  task: { shortIdLength: number };
35
+ delivery: { remote: string; baseRef: string };
35
36
  labels: Record<string, unknown>;
36
37
  };
37
38
 
@@ -39,10 +40,11 @@ type AgentConfig = {
39
40
  project: string;
40
41
  org: string;
41
42
  language: string;
42
- platform: { type: string };
43
+ platform: { type: string; providers?: Record<string, unknown> };
43
44
  templateVersion: string;
44
45
  sandbox: Record<string, unknown>;
45
46
  task: { shortIdLength: number };
47
+ delivery: { remote: string; baseRef: string };
46
48
  labels: Record<string, unknown>;
47
49
  files: FileRegistry;
48
50
  agentClients: ReturnType<typeof serializeAgentClients>;
@@ -244,6 +246,7 @@ async function cmdInit(): Promise<void> {
244
246
  templateVersion: VERSION,
245
247
  sandbox: structuredClone(defaults.sandbox),
246
248
  task: structuredClone(defaults.task),
249
+ delivery: structuredClone(defaults.delivery),
247
250
  labels: structuredClone(defaults.labels),
248
251
  files: { managed: [], merged: [], ejected: [] },
249
252
  agentClients: serializeAgentClients(defaultState)
@@ -1,5 +1,5 @@
1
1
  import fs from 'node:fs';
2
- import { inspectGitWorkflow, pushRebasedBranch } from '../git/workflow.ts';
2
+ import { inspectGitWorkflow, previewCommitTree, pushRebasedBranch } from '../git/workflow.ts';
3
3
  import { compareReviewTrees, snapshotReview } from '../git/review-snapshot.ts';
4
4
  import { resolvePostReviewGlobs } from '../task/review-fingerprint.ts';
5
5
  import { executeCommitOperation } from '../task/commit-operation.ts';
@@ -26,6 +26,12 @@ function gitWorkflow(args: string[] = []): void {
26
26
  const inputIndex = rest.indexOf('--input');
27
27
  const input = inputIndex >= 0 && rest[inputIndex + 1] ? JSON.parse(fs.readFileSync(rest[inputIndex + 1]!, 'utf8')) : null;
28
28
  result = input ? pushRebasedBranch({ cwd: cwd ?? process.cwd(), ...input }) : { status: 'failed', changed: false, error: { code: 'GIT_INPUT_REQUIRED', message: '--input JSON file is required' } };
29
+ } else if (action === 'preview-tree') {
30
+ const inputIndex = rest.indexOf('--input');
31
+ const input = inputIndex >= 0 && rest[inputIndex + 1] ? JSON.parse(fs.readFileSync(rest[inputIndex + 1]!, 'utf8')) : null;
32
+ result = input
33
+ ? previewCommitTree({ cwd: cwd ?? process.cwd(), paths: input.paths, expectedHead: input.expectedHead })
34
+ : { status: 'failed', changed: false, error: { code: 'GIT_INPUT_REQUIRED', message: '--input JSON file is required' } };
29
35
  } else if (action === 'snapshot' || action === 'compare-trees') {
30
36
  const inputIndex = rest.indexOf('--input');
31
37
  const input = inputIndex >= 0 && rest[inputIndex + 1] ? JSON.parse(fs.readFileSync(rest[inputIndex + 1]!, 'utf8')) : null;
@@ -70,17 +70,17 @@ async function platformChecks(args: string[] = []): Promise<void> {
70
70
  };
71
71
  const unexpected = Object.keys(values).find((name) => !allowed[operation]!.includes(name));
72
72
  if (unexpected) { fail(`${operation} does not accept --${unexpected}`); return; }
73
- if (operation === 'inspect') { finish(inspectPullRequestReadiness(taskRef, { cwd })); return; }
73
+ if (operation === 'inspect') { finish(await inspectPullRequestReadiness(taskRef, { cwd })); return; }
74
74
  if (operation === 'resolve-run') {
75
75
  if (!values.checkName) { fail('resolve-run requires --check-name'); return; }
76
- finish(resolvePlatformCheckRun(taskRef, { cwd, checkName: values.checkName, detailsUrl: values.detailsUrl }));
76
+ finish(await resolvePlatformCheckRun(taskRef, { cwd, checkName: values.checkName, detailsUrl: values.detailsUrl }));
77
77
  return;
78
78
  }
79
79
  if (operation === 'logs') {
80
80
  const run = positive(values.run);
81
81
  const job = values.job === undefined ? undefined : positive(values.job);
82
82
  if (!run || values.job !== undefined && !job) { fail('logs requires a positive --run and optional positive --job'); return; }
83
- finish(fetchPlatformCheckLogs(taskRef, { cwd, run, job: job || undefined }));
83
+ finish(await fetchPlatformCheckLogs(taskRef, { cwd, run, job: job || undefined }));
84
84
  return;
85
85
  }
86
86
  const intervalSeconds = positive(values.intervalSeconds);
@@ -11,7 +11,7 @@ import type { CommentKind } from '../platform/issue-comments.ts';
11
11
  import type { PlatformResult } from '../platform/types.ts';
12
12
  import { backfillCompletionComments } from '../platform/completion-backfill.ts';
13
13
 
14
- const USAGE = `Usage: agent-infra-internal platform-comment list --issue <N> [--cwd <path>]
14
+ const USAGE = `Usage: agent-infra-internal platform-comment list --issue <token> [--cwd <path>]
15
15
  agent-infra-internal platform-comment owner <task-ref> [--cwd <path>]
16
16
  agent-infra-internal platform-comment backfill <task-ref> --agent <agent> [--cwd <path>]
17
17
  agent-infra-internal platform-comment sync <task-ref> --kind <kind> --agent <agent> [--artifact <file>] [--body-file <path|->] [--status-label <label>] [--backfill] [--cwd <path>]
@@ -52,7 +52,7 @@ function readBodyFile(value: string, cwd: string): string {
52
52
  return fs.readFileSync(path.resolve(cwd, value), 'utf8');
53
53
  }
54
54
 
55
- function platformComment(args: string[] = []): void {
55
+ async function platformComment(args: string[] = []): Promise<void> {
56
56
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
57
57
  const operation = args[0];
58
58
  if (!operation || !['list', 'owner', 'backfill', 'sync'].includes(operation)) { fail('a valid operation is required'); return; }
@@ -63,17 +63,17 @@ function platformComment(args: string[] = []): void {
63
63
  if (parsed.error) { fail(parsed.error); return; }
64
64
  const cwd = path.resolve(typeof parsed.values.cwd === 'string' ? parsed.values.cwd : process.cwd());
65
65
  if (operation === 'list') {
66
- const issue = Number(parsed.values.issue);
67
- if (!Number.isInteger(issue) || issue <= 0) { fail('list requires a positive --issue'); return; }
66
+ const issue = parsed.values.issue;
67
+ if (typeof issue !== 'string' || !issue) { fail('list requires --issue <token>'); return; }
68
68
  const unexpected = Object.keys(parsed.values).find((key) => !['issue', 'cwd'].includes(key));
69
69
  if (unexpected) { fail(`list does not accept '--${unexpected}'`); return; }
70
- finish(listPlatformComments(issue, cwd));
70
+ finish(await listPlatformComments(issue, cwd));
71
71
  return;
72
72
  }
73
73
  if (operation === 'owner') {
74
74
  const unexpected = Object.keys(parsed.values).find((key) => key !== 'cwd');
75
75
  if (unexpected) { fail(`owner does not accept '--${unexpected}'`); return; }
76
- finish(checkPlatformCommentOwner(taskRef!, { cwd }));
76
+ finish(await checkPlatformCommentOwner(taskRef!, { cwd }));
77
77
  return;
78
78
  }
79
79
  if (operation === 'backfill') {
@@ -83,7 +83,7 @@ function platformComment(args: string[] = []): void {
83
83
  if (typeof agent !== 'string' || !agent) { fail('backfill requires --agent'); return; }
84
84
  const normalizedAgent = normalizeAgentToken(agent);
85
85
  if (!normalizedAgent) { fail(`invalid --agent '${agent}': ${AGENT_USAGE_HINT}`); return; }
86
- finish(backfillCompletionComments(taskRef!, { cwd, agent: normalizedAgent }));
86
+ finish(await backfillCompletionComments(taskRef!, { cwd, agent: normalizedAgent }));
87
87
  return;
88
88
  }
89
89
  const kind = parsed.values.kind;
@@ -101,7 +101,7 @@ function platformComment(args: string[] = []): void {
101
101
  fail(`unable to read body file: ${error instanceof Error ? error.message : String(error)}`);
102
102
  return;
103
103
  }
104
- finish(syncPlatformComment(taskRef!, {
104
+ finish(await syncPlatformComment(taskRef!, {
105
105
  kind: kind as CommentKind,
106
106
  agent: normalizedAgent,
107
107
  artifact: typeof parsed.values.artifact === 'string' ? parsed.values.artifact : undefined,
@@ -10,7 +10,7 @@ function fail(message: string): void {
10
10
  process.exitCode = 1;
11
11
  }
12
12
 
13
- function platformContext(args: string[] = []): void {
13
+ async function platformContext(args: string[] = []): Promise<void> {
14
14
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
15
15
  if (args[0] !== 'resolve') { fail("operation must be 'resolve'"); return; }
16
16
  let cwd = process.cwd();
@@ -24,7 +24,7 @@ function platformContext(args: string[] = []): void {
24
24
  seen.add(flag);
25
25
  cwd = path.resolve(value);
26
26
  }
27
- const result = resolvePlatformContext({ cwd });
27
+ const result = await resolvePlatformContext({ cwd });
28
28
  process.stdout.write(`${JSON.stringify(result)}\n`);
29
29
  if (result.status === 'failed') process.exitCode = 1;
30
30
  if (result.status === 'blocked') process.exitCode = 2;
@@ -11,7 +11,7 @@ import type { IssueResult } from '../platform/issues.ts';
11
11
 
12
12
  const USAGE = `Usage: agent-infra-internal platform-issue inspect <task-ref> [--cwd <path>]
13
13
  agent-infra-internal platform-issue create <task-ref> --agent <agent> [--dry-run] [--cwd <path>]
14
- agent-infra-internal platform-issue bind <task-ref> --issue <N> --agent <agent> [--dry-run] [--cwd <path>]
14
+ agent-infra-internal platform-issue bind <task-ref> --issue <token> --agent <agent> [--dry-run] [--cwd <path>]
15
15
  agent-infra-internal platform-issue sync <task-ref> --agent <agent> [--status <suffix|none>] [--assignees current|none] [--milestone initial|specific|none] [--issue-type] [--fields] [--requirements] [--in-labels from-diff|none] [--base <branch>] [--state open|closed] [--close-reason completed|not_planned] [--dry-run] [--cwd <path>]
16
16
  `;
17
17
 
@@ -59,7 +59,7 @@ function oneOf(values: Record<string, string | boolean>, name: string, allowed:
59
59
  return value;
60
60
  }
61
61
 
62
- function platformIssue(args: string[] = []): void {
62
+ async function platformIssue(args: string[] = []): Promise<void> {
63
63
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
64
64
  const operation = args[0];
65
65
  if (!operation || !['inspect', 'create', 'bind', 'sync'].includes(operation)) { fail('a valid operation is required'); return; }
@@ -75,18 +75,17 @@ function platformIssue(args: string[] = []): void {
75
75
  };
76
76
  const unexpected = Object.keys(values).find((name) => !allowed[operation]!.includes(name));
77
77
  if (unexpected) { fail(`${operation} does not accept --${unexpected}`); return; }
78
- if (operation === 'inspect') { finish(inspectPlatformIssue(taskRef, { cwd })); return; }
78
+ if (operation === 'inspect') { finish(await inspectPlatformIssue(taskRef, { cwd })); return; }
79
79
  if (typeof values.agent !== 'string' || !values.agent) { fail(`${operation} requires --agent`); return; }
80
80
  const agent = normalizeAgentToken(values.agent);
81
81
  if (!agent) { fail(`invalid --agent '${values.agent}': ${AGENT_USAGE_HINT}`); return; }
82
82
  values.agent = agent;
83
83
  if (operation === 'create') {
84
- finish(createPlatformIssue(taskRef, { cwd, agent: values.agent, dryRun: values.dryRun === true })); return;
84
+ finish(await createPlatformIssue(taskRef, { cwd, agent: values.agent, dryRun: values.dryRun === true })); return;
85
85
  }
86
86
  if (operation === 'bind') {
87
- const issue = Number(values.issue);
88
- if (!Number.isInteger(issue) || issue <= 0) { fail('bind requires a positive --issue'); return; }
89
- finish(bindPlatformIssue(taskRef, { cwd, agent: values.agent, issue, dryRun: values.dryRun === true })); return;
87
+ if (typeof values.issue !== 'string' || !values.issue) { fail('bind requires --issue <token>'); return; }
88
+ finish(await bindPlatformIssue(taskRef, { cwd, agent: values.agent, issue: values.issue, dryRun: values.dryRun === true })); return;
90
89
  }
91
90
  try {
92
91
  const assignees = oneOf(values, 'assignees', ['current', 'none']);
@@ -99,7 +98,7 @@ function platformIssue(args: string[] = []): void {
99
98
  if (closeReason && state !== 'closed') throw new Error('--close-reason requires --state closed');
100
99
  const desiredKeys = ['status', 'assignees', 'milestone', 'issueType', 'fields', 'requirements', 'inLabels', 'state'];
101
100
  if (!desiredKeys.some((name) => values[name] !== undefined)) throw new Error('sync requires at least one desired-state option');
102
- finish(syncPlatformIssue(taskRef, {
101
+ finish(await syncPlatformIssue(taskRef, {
103
102
  cwd, agent: values.agent, dryRun: values.dryRun === true,
104
103
  status: typeof values.status === 'string' ? values.status : undefined,
105
104
  assignees: assignees as 'current' | 'none' | undefined,
@@ -6,9 +6,9 @@ import { listPrReviews, publishPrReview } from '../platform/pr-review.ts';
6
6
  import type { PrReviewEvent } from '../platform/pr-review.ts';
7
7
  import type { PlatformResult } from '../platform/types.ts';
8
8
 
9
- const USAGE = `Usage: agent-infra-internal platform-pr-review inspect --pr <N> [--cwd <path>]
10
- agent-infra-internal platform-pr-review list --pr <N> [--cwd <path>]
11
- agent-infra-internal platform-pr-review publish --pr <N> --scope <taskId|pr{N}> --round <N> --commit <sha> --event <COMMENT|APPROVE|REQUEST_CHANGES> --body-file <path|-> [--dry-run] [--cwd <path>]
9
+ const USAGE = `Usage: agent-infra-internal platform-pr-review inspect --pr <token> [--cwd <path>]
10
+ agent-infra-internal platform-pr-review list --pr <token> [--cwd <path>]
11
+ agent-infra-internal platform-pr-review publish --pr <token> --scope <taskId|pr{N}> --round <N> --commit <sha> --event <COMMENT|APPROVE|REQUEST_CHANGES> --body-file <path|-> [--dry-run] [--cwd <path>]
12
12
  `;
13
13
 
14
14
  const BOOLEAN_FLAGS = new Set(['--dry-run']);
@@ -50,7 +50,7 @@ function readBodyFile(value: string, cwd: string): string {
50
50
  return value === '-' ? fs.readFileSync(0, 'utf8') : fs.readFileSync(path.resolve(cwd, value), 'utf8');
51
51
  }
52
52
 
53
- function platformPrReview(args: string[] = []): void {
53
+ async function platformPrReview(args: string[] = []): Promise<void> {
54
54
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
55
55
  const operation = args[0];
56
56
  if (!operation || !['inspect', 'list', 'publish'].includes(operation)) { fail('a valid operation is required'); return; }
@@ -65,14 +65,14 @@ function platformPrReview(args: string[] = []): void {
65
65
  };
66
66
  const unexpected = Object.keys(values).find((name) => !allowed[operation]!.includes(name));
67
67
  if (unexpected) { fail(`${operation} does not accept --${unexpected}`); return; }
68
- const pr = Number(values.pr);
69
- if (!Number.isInteger(pr) || pr <= 0) { fail(`${operation} requires a positive --pr`); return; }
68
+ const pr = values.pr;
69
+ if (typeof pr !== 'string' || !pr) { fail(`${operation} requires --pr <token>`); return; }
70
70
  if (operation === 'inspect') {
71
- finish(inspectPlatformPullRequestByNumber(pr, { cwd }));
71
+ finish(await inspectPlatformPullRequestByNumber(pr, { cwd }));
72
72
  return;
73
73
  }
74
74
  if (operation === 'list') {
75
- finish(listPrReviews(pr, { cwd }));
75
+ finish(await listPrReviews(pr, { cwd }));
76
76
  return;
77
77
  }
78
78
  const scope = typeof values.scope === 'string' ? values.scope : '';
@@ -91,7 +91,7 @@ function platformPrReview(args: string[] = []): void {
91
91
  fail(`unable to read body file: ${error instanceof Error ? error.message : String(error)}`);
92
92
  return;
93
93
  }
94
- finish(publishPrReview({
94
+ finish(await publishPrReview({
95
95
  cwd,
96
96
  prNumber: pr,
97
97
  identity: { scope, round, commitSha: commit },