@fitlab-ai/agent-infra 0.9.10 → 0.9.12

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 (375) hide show
  1. package/README.md +19 -9
  2. package/README.zh-CN.md +19 -9
  3. package/bin/cli.ts +17 -4
  4. package/dist/bin/cli.js +19 -4
  5. package/dist/bin/internal-cli.js +55 -4
  6. package/dist/lib/agent-client.js +0 -1
  7. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +71 -10
  8. package/dist/lib/agent-clients/adapters/opencode-sandbox.js +0 -4
  9. package/dist/lib/agent-clients/adapters/traecli.js +7 -8
  10. package/dist/lib/agent-clients/config.js +14 -99
  11. package/dist/lib/agent-clients/reconcile.js +1 -11
  12. package/dist/lib/agent-clients/schema.js +5 -4
  13. package/dist/lib/agent-clients/tokens.js +5 -15
  14. package/dist/lib/decide.js +14 -30
  15. package/dist/lib/defaults.json +8 -0
  16. package/dist/lib/git/workflow.js +43 -1
  17. package/dist/lib/init.js +3 -2
  18. package/dist/lib/internal/git-workflow.js +8 -1
  19. package/dist/lib/internal/platform-pr.js +8 -2
  20. package/dist/lib/internal/release-workflow.js +0 -1
  21. package/dist/lib/internal/task-delivery.js +59 -0
  22. package/dist/lib/internal/task-finalization.js +19 -9
  23. package/dist/lib/internal/task-ledger.js +8 -2
  24. package/dist/lib/internal/task-lifecycle.js +17 -93
  25. package/dist/lib/internal/task-orchestration.js +30 -216
  26. package/dist/lib/internal/task-validate.js +2 -1
  27. package/dist/lib/merge.js +205 -103
  28. package/dist/lib/platform/github-client.js +7 -1
  29. package/dist/lib/platform/pr-checks.js +8 -5
  30. package/dist/lib/platform/pr-summary.js +12 -8
  31. package/dist/lib/platform/pull-requests.js +393 -91
  32. package/dist/lib/platform/verification-required.js +13 -2
  33. package/dist/lib/platform/verification-sync.js +9 -4
  34. package/dist/lib/pr-review/evidence-grading.js +12 -4
  35. package/dist/lib/process-data/normalize.js +2 -9
  36. package/dist/lib/run/host.js +46 -16
  37. package/dist/lib/sandbox/agent-client-reconciler.js +4 -12
  38. package/dist/lib/sandbox/commands/create.js +3 -3
  39. package/dist/lib/sandbox/commands/enter.js +18 -4
  40. package/dist/lib/sandbox/config.js +8 -12
  41. package/dist/lib/sandbox/control/executor.js +131 -39
  42. package/dist/lib/sandbox/control/lifecycle.js +55 -24
  43. package/dist/lib/sandbox/control/server.js +18 -16
  44. package/dist/lib/sandbox/mounts.js +3 -2
  45. package/dist/lib/sandbox/recovery.js +123 -22
  46. package/dist/lib/sandbox/workspace-identity.js +14 -0
  47. package/dist/lib/sandbox/workspace-view.js +8 -9
  48. package/dist/lib/self-update.js +278 -0
  49. package/dist/lib/server/process-state.js +2 -2
  50. package/dist/lib/server/protocol.js +5 -5
  51. package/dist/lib/task/activity-log.js +4 -1
  52. package/dist/lib/task/artifact-lifecycle.js +6 -4
  53. package/dist/lib/task/codex-orchestration.js +1 -1
  54. package/dist/lib/task/command-options.js +1 -3
  55. package/dist/lib/task/commands/cat.js +0 -5
  56. package/dist/lib/task/commands/decisions.js +76 -92
  57. package/dist/lib/task/commands/files.js +6 -6
  58. package/dist/lib/task/commands/grep.js +25 -61
  59. package/dist/lib/task/commands/issue-body.js +6 -6
  60. package/dist/lib/task/commands/log.js +25 -10
  61. package/dist/lib/task/commands/show.js +5 -6
  62. package/dist/lib/task/commands/status.js +8 -8
  63. package/dist/lib/task/commit-intent.js +100 -0
  64. package/dist/lib/task/commit-operation.js +181 -91
  65. package/dist/lib/task/commit-policy.js +1 -1
  66. package/dist/lib/task/control-authority.js +431 -0
  67. package/dist/lib/task/create.js +39 -8
  68. package/dist/lib/task/current-contract.js +35 -0
  69. package/dist/lib/task/decision-details.js +218 -0
  70. package/dist/lib/task/decision-intents.js +5 -2
  71. package/dist/lib/task/delivery-target.js +97 -0
  72. package/dist/lib/task/delivery.js +153 -0
  73. package/dist/lib/task/events.js +11 -5
  74. package/dist/lib/task/human-override.js +5 -2
  75. package/dist/lib/task/index.js +19 -20
  76. package/dist/lib/task/ledger-intents.js +8 -9
  77. package/dist/lib/task/ledger.js +13 -6
  78. package/dist/lib/task/lifecycle.js +122 -9
  79. package/dist/lib/task/orchestration.js +105 -75
  80. package/dist/lib/task/pr-delivery-fact.js +182 -0
  81. package/dist/lib/task/review-artifacts.js +31 -12
  82. package/dist/lib/task/review-finalization.js +13 -4
  83. package/dist/lib/task/review-fingerprint.js +8 -0
  84. package/dist/lib/task/verification-engine.js +86 -39
  85. package/dist/lib/task/verification-review.js +2 -2
  86. package/dist/lib/task/workspace-snapshot.js +5 -11
  87. package/dist/lib/task/write.js +11 -1
  88. package/dist/lib/update.js +13 -35
  89. package/dist/lib/version.js +5 -1
  90. package/dist/lifecycle-build-manifest.json +3 -3
  91. package/lib/agent-client.ts +0 -1
  92. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +105 -10
  93. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +12 -1
  94. package/lib/agent-clients/adapters/opencode-sandbox.ts +0 -5
  95. package/lib/agent-clients/adapters/traecli.ts +7 -8
  96. package/lib/agent-clients/config.ts +14 -144
  97. package/lib/agent-clients/reconcile.ts +1 -12
  98. package/lib/agent-clients/schema.ts +5 -4
  99. package/lib/agent-clients/tokens.ts +5 -18
  100. package/lib/decide.ts +12 -22
  101. package/lib/defaults.json +8 -0
  102. package/lib/git/workflow.ts +38 -1
  103. package/lib/init.ts +5 -2
  104. package/lib/internal/git-workflow.ts +7 -1
  105. package/lib/internal/platform-pr.ts +8 -1
  106. package/lib/internal/release-workflow.ts +0 -1
  107. package/lib/internal/task-delivery.ts +53 -0
  108. package/lib/internal/task-finalization.ts +27 -13
  109. package/lib/internal/task-ledger.ts +8 -2
  110. package/lib/internal/task-lifecycle.ts +33 -76
  111. package/lib/internal/task-orchestration.ts +33 -190
  112. package/lib/internal/task-validate.ts +3 -2
  113. package/lib/merge.ts +236 -120
  114. package/lib/platform/github-client.ts +8 -1
  115. package/lib/platform/pr-checks.ts +7 -5
  116. package/lib/platform/pr-summary.ts +10 -7
  117. package/lib/platform/pull-requests.ts +425 -87
  118. package/lib/platform/verification-required.ts +12 -2
  119. package/lib/platform/verification-sync.ts +9 -4
  120. package/lib/pr-review/evidence-grading.ts +7 -4
  121. package/lib/process-data/normalize.ts +2 -8
  122. package/lib/run/host.ts +63 -14
  123. package/lib/sandbox/agent-client-reconciler.ts +5 -15
  124. package/lib/sandbox/commands/create.ts +4 -4
  125. package/lib/sandbox/commands/enter.ts +24 -4
  126. package/lib/sandbox/config.ts +9 -14
  127. package/lib/sandbox/control/container-identity.ts +2 -2
  128. package/lib/sandbox/control/executor.ts +148 -51
  129. package/lib/sandbox/control/lifecycle.ts +59 -31
  130. package/lib/sandbox/control/protocol.ts +1 -3
  131. package/lib/sandbox/control/server.ts +15 -12
  132. package/lib/sandbox/control/state.ts +7 -7
  133. package/lib/sandbox/mounts.ts +4 -3
  134. package/lib/sandbox/recovery.ts +162 -34
  135. package/lib/sandbox/tools.ts +1 -1
  136. package/lib/sandbox/workspace-identity.ts +28 -0
  137. package/lib/sandbox/workspace-view.ts +14 -10
  138. package/lib/self-update.ts +341 -0
  139. package/lib/server/process-state.ts +2 -2
  140. package/lib/server/protocol.ts +5 -5
  141. package/lib/task/activity-log.ts +6 -1
  142. package/lib/task/artifact-lifecycle.ts +7 -5
  143. package/lib/task/codex-orchestration.ts +2 -1
  144. package/lib/task/command-options.ts +1 -2
  145. package/lib/task/commands/cat.ts +0 -4
  146. package/lib/task/commands/decisions.ts +80 -75
  147. package/lib/task/commands/files.ts +6 -6
  148. package/lib/task/commands/grep.ts +23 -51
  149. package/lib/task/commands/issue-body.ts +6 -6
  150. package/lib/task/commands/log.ts +22 -10
  151. package/lib/task/commands/show.ts +5 -6
  152. package/lib/task/commands/status.ts +8 -8
  153. package/lib/task/commit-intent.ts +137 -0
  154. package/lib/task/commit-operation.ts +161 -79
  155. package/lib/task/commit-policy.ts +1 -2
  156. package/lib/task/control-authority.ts +563 -0
  157. package/lib/task/create.ts +40 -10
  158. package/lib/task/current-contract.ts +49 -0
  159. package/lib/task/decision-details.ts +280 -0
  160. package/lib/task/decision-intents.ts +7 -2
  161. package/lib/task/delivery-target.ts +130 -0
  162. package/lib/task/delivery.ts +160 -0
  163. package/lib/task/events.ts +10 -5
  164. package/lib/task/human-override.ts +5 -2
  165. package/lib/task/index.ts +19 -20
  166. package/lib/task/ledger-intents.ts +6 -8
  167. package/lib/task/ledger.ts +17 -7
  168. package/lib/task/lifecycle.ts +113 -4
  169. package/lib/task/orchestration.ts +102 -80
  170. package/lib/task/pr-delivery-fact.ts +254 -0
  171. package/lib/task/review-artifacts.ts +53 -15
  172. package/lib/task/review-finalization.ts +21 -5
  173. package/lib/task/review-fingerprint.ts +10 -0
  174. package/lib/task/verification-engine.ts +78 -46
  175. package/lib/task/verification-review.ts +3 -1
  176. package/lib/task/workspace-snapshot.ts +4 -13
  177. package/lib/task/write.ts +20 -1
  178. package/lib/update.ts +14 -38
  179. package/lib/version.ts +6 -1
  180. package/package.json +1 -1
  181. package/templates/.agents/README.en.md +5 -3
  182. package/templates/.agents/README.zh-CN.md +5 -3
  183. package/templates/.agents/rules/README.en.md +4 -2
  184. package/templates/.agents/rules/README.zh-CN.md +4 -2
  185. package/templates/.agents/rules/compatibility-policy.en.md +5 -4
  186. package/templates/.agents/rules/compatibility-policy.zh-CN.md +5 -4
  187. package/templates/.agents/rules/create-issue.en.md +11 -2
  188. package/templates/.agents/rules/create-issue.zh-CN.md +24 -2
  189. package/templates/.agents/rules/human-decision-context.en.md +9 -7
  190. package/templates/.agents/rules/human-decision-context.zh-CN.md +9 -7
  191. package/templates/.agents/rules/{issue-fields.github.en.md → issue-fields.en.md} +1 -1
  192. package/templates/.agents/rules/{issue-fields.github.zh-CN.md → issue-fields.zh-CN.md} +1 -1
  193. package/templates/.agents/rules/issue-pr-commands.en.md +5 -18
  194. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
  195. package/templates/.agents/rules/issue-sync.en.md +26 -5
  196. package/templates/.agents/rules/issue-sync.zh-CN.md +62 -5
  197. package/templates/.agents/rules/label-milestone-setup.en.md +15 -2
  198. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +15 -2
  199. package/templates/.agents/rules/local-artifact-repair.en.md +46 -0
  200. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +46 -0
  201. package/templates/.agents/rules/milestone-inference.en.md +12 -2
  202. package/templates/.agents/rules/milestone-inference.zh-CN.md +25 -3
  203. package/templates/.agents/rules/next-step-output.en.md +3 -3
  204. package/templates/.agents/rules/next-step-output.zh-CN.md +3 -3
  205. package/templates/.agents/rules/no-mid-flow-questions.en.md +1 -1
  206. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +1 -1
  207. package/templates/.agents/rules/pr-sync.en.md +23 -14
  208. package/templates/.agents/rules/pr-sync.zh-CN.md +23 -2
  209. package/templates/.agents/rules/release-commands.en.md +42 -3
  210. package/templates/.agents/rules/release-commands.zh-CN.md +42 -3
  211. package/templates/.agents/rules/review-handshake.en.md +1 -1
  212. package/templates/.agents/rules/review-handshake.zh-CN.md +1 -1
  213. package/templates/.agents/rules/security-alerts.en.md +17 -2
  214. package/templates/.agents/rules/security-alerts.zh-CN.md +17 -2
  215. package/templates/.agents/rules/sync-content-generation.en.md +8 -0
  216. package/templates/.agents/rules/sync-content-generation.zh-CN.md +8 -0
  217. package/templates/.agents/rules/task-management.en.md +2 -3
  218. package/templates/.agents/rules/task-management.zh-CN.md +2 -3
  219. package/templates/.agents/scripts/security-alerts.github.sh +151 -0
  220. package/templates/.agents/scripts/security-alerts.sh +31 -0
  221. package/templates/.agents/skills/analyze-task/SKILL.en.md +4 -3
  222. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +4 -3
  223. package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
  224. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
  225. package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
  226. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
  227. package/templates/.agents/skills/check-task/SKILL.en.md +2 -2
  228. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +2 -2
  229. package/templates/.agents/skills/close-codescan/SKILL.en.md +3 -3
  230. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +3 -3
  231. package/templates/.agents/skills/close-dependabot/SKILL.en.md +3 -3
  232. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +3 -3
  233. package/templates/.agents/skills/code-task/SKILL.en.md +8 -5
  234. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +9 -6
  235. package/templates/.agents/skills/commit/SKILL.en.md +30 -10
  236. package/templates/.agents/skills/commit/SKILL.zh-CN.md +6 -7
  237. package/templates/.agents/skills/commit/config/verify.json +1 -1
  238. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +3 -3
  239. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +3 -3
  240. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  241. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  242. package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -2
  243. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -2
  244. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +7 -6
  245. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +7 -6
  246. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  247. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  248. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +1 -1
  249. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
  250. package/templates/.agents/skills/complete-task/SKILL.en.md +13 -13
  251. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +13 -13
  252. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +2 -2
  253. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +2 -2
  254. package/templates/.agents/skills/create-pr/SKILL.en.md +9 -11
  255. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +9 -11
  256. package/templates/.agents/skills/create-pr/reference/change-report.en.md +9 -4
  257. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +9 -4
  258. package/templates/.agents/skills/create-pr/scripts/change-report.mjs +203 -0
  259. package/templates/.agents/skills/create-release-note/SKILL.en.md +5 -6
  260. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +5 -6
  261. package/templates/.agents/skills/create-task/SKILL.en.md +2 -1
  262. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +2 -1
  263. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  264. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  265. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  266. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  267. package/templates/.agents/skills/import-issue/SKILL.en.md +1 -1
  268. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +1 -1
  269. package/templates/.agents/skills/init-labels/SKILL.en.md +9 -10
  270. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +9 -10
  271. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +57 -1
  272. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +27 -1
  273. package/templates/.agents/skills/init-milestones/SKILL.en.md +3 -5
  274. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +3 -5
  275. package/templates/.agents/skills/plan-task/SKILL.en.md +4 -3
  276. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +4 -3
  277. package/templates/.agents/skills/restore-task/SKILL.en.md +1 -1
  278. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +1 -1
  279. package/templates/.agents/skills/review-analysis/SKILL.en.md +8 -5
  280. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +8 -5
  281. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -0
  282. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -0
  283. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +18 -0
  284. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +18 -0
  285. package/templates/.agents/skills/review-code/SKILL.en.md +11 -8
  286. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +11 -8
  287. package/templates/.agents/skills/review-code/config/verify.en.json +1 -0
  288. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -0
  289. package/templates/.agents/skills/review-code/reference/migration-risks.en.md +2 -1
  290. package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +2 -1
  291. package/templates/.agents/skills/review-code/reference/output-templates.en.md +19 -1
  292. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +19 -1
  293. package/templates/.agents/skills/review-code/reference/report-template.en.md +4 -2
  294. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +4 -2
  295. package/templates/.agents/skills/review-plan/SKILL.en.md +8 -5
  296. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +8 -5
  297. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -0
  298. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -0
  299. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +18 -0
  300. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +18 -0
  301. package/templates/.agents/skills/review-pr/SKILL.en.md +1 -0
  302. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +1 -0
  303. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +2 -2
  304. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +2 -2
  305. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -0
  306. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -0
  307. package/templates/.agents/skills/run-task/SKILL.en.md +5 -1
  308. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +5 -1
  309. package/templates/.agents/skills/update-agent-infra/SKILL.en.md +2 -2
  310. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +2 -2
  311. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +144 -109
  312. package/templates/.agents/skills/watch-pr/SKILL.en.md +5 -5
  313. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +5 -5
  314. package/templates/.agents/templates/task.en.md +6 -2
  315. package/templates/.agents/templates/task.zh-CN.md +6 -2
  316. package/templates/.agents/workflows/bug-fix.en.yaml +9 -8
  317. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +9 -8
  318. package/templates/.agents/workflows/feature-development.en.yaml +9 -8
  319. package/templates/.agents/workflows/feature-development.zh-CN.yaml +9 -8
  320. package/templates/.agents/workflows/refactoring.en.yaml +9 -8
  321. package/templates/.agents/workflows/refactoring.zh-CN.yaml +9 -8
  322. package/templates/.claude/commands/analyze-task.en.md +1 -1
  323. package/templates/.claude/commands/analyze-task.zh-CN.md +1 -1
  324. package/templates/.claude/commands/block-task.en.md +1 -1
  325. package/templates/.claude/commands/block-task.zh-CN.md +1 -1
  326. package/templates/.claude/commands/cancel-task.en.md +1 -1
  327. package/templates/.claude/commands/cancel-task.zh-CN.md +1 -1
  328. package/templates/.claude/commands/check-task.en.md +1 -1
  329. package/templates/.claude/commands/check-task.zh-CN.md +1 -1
  330. package/templates/.claude/commands/code-task.en.md +1 -1
  331. package/templates/.claude/commands/code-task.zh-CN.md +1 -1
  332. package/templates/.claude/commands/commit.en.md +1 -1
  333. package/templates/.claude/commands/commit.zh-CN.md +1 -1
  334. package/templates/.claude/commands/complete-manual-validation.en.md +1 -1
  335. package/templates/.claude/commands/complete-manual-validation.zh-CN.md +1 -1
  336. package/templates/.claude/commands/complete-task.en.md +1 -1
  337. package/templates/.claude/commands/complete-task.zh-CN.md +1 -1
  338. package/templates/.claude/commands/create-pr.en.md +1 -1
  339. package/templates/.claude/commands/create-pr.zh-CN.md +1 -1
  340. package/templates/.claude/commands/plan-task.en.md +1 -1
  341. package/templates/.claude/commands/plan-task.zh-CN.md +1 -1
  342. package/templates/.claude/commands/review-analysis.en.md +1 -1
  343. package/templates/.claude/commands/review-analysis.zh-CN.md +1 -1
  344. package/templates/.claude/commands/review-code.en.md +1 -1
  345. package/templates/.claude/commands/review-code.zh-CN.md +1 -1
  346. package/templates/.claude/commands/review-plan.en.md +1 -1
  347. package/templates/.claude/commands/review-plan.zh-CN.md +1 -1
  348. package/templates/.claude/commands/run-manual-validation.en.md +1 -1
  349. package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
  350. package/templates/.claude/commands/run-task.en.md +1 -1
  351. package/templates/.claude/commands/run-task.zh-CN.md +1 -1
  352. package/templates/.claude/commands/watch-pr.en.md +1 -1
  353. package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
  354. package/templates/{.trae/skills → .traecli/commands}/update-agent-infra.en.md +0 -1
  355. package/templates/{.trae/skills → .traecli/commands}/update-agent-infra.zh-CN.md +0 -1
  356. package/dist/lib/builtin-tuis.js +0 -40
  357. package/lib/builtin-tuis.ts +0 -56
  358. package/templates/.agents/rules/create-issue.github.en.md +0 -14
  359. package/templates/.agents/rules/create-issue.github.zh-CN.md +0 -27
  360. package/templates/.agents/rules/issue-pr-commands.github.en.md +0 -34
  361. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +0 -49
  362. package/templates/.agents/rules/issue-sync.github.en.md +0 -40
  363. package/templates/.agents/rules/issue-sync.github.zh-CN.md +0 -76
  364. package/templates/.agents/rules/label-milestone-setup.github.en.md +0 -60
  365. package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +0 -60
  366. package/templates/.agents/rules/milestone-inference.github.en.md +0 -15
  367. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +0 -27
  368. package/templates/.agents/rules/pr-checks-commands.github.en.md +0 -18
  369. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +0 -34
  370. package/templates/.agents/rules/pr-sync.github.en.md +0 -43
  371. package/templates/.agents/rules/pr-sync.github.zh-CN.md +0 -69
  372. package/templates/.agents/rules/release-commands.github.en.md +0 -38
  373. package/templates/.agents/rules/release-commands.github.zh-CN.md +0 -38
  374. package/templates/.agents/rules/security-alerts.github.en.md +0 -43
  375. package/templates/.agents/rules/security-alerts.github.zh-CN.md +0 -43
@@ -15,14 +15,15 @@ const AGENT_CLIENTS_SCHEMA = {
15
15
  maxItems: AGENT_CLIENT_IDS.length,
16
16
  uniqueItems: true,
17
17
  description: 'Canonical Agent Client configuration. Object ID completeness and uniqueness are enforced by the runtime normalizer.',
18
- items: {
18
+ additionalItems: false,
19
+ items: AGENT_CLIENT_IDS.map((id) => ({
19
20
  type: 'object',
20
21
  additionalProperties: false,
21
22
  required: ['id', 'enabled', 'installInSandbox'],
22
23
  properties: {
23
24
  id: {
24
- type: 'string',
25
- enum: [...AGENT_CLIENT_IDS]
25
+ const: id,
26
+ type: 'string'
26
27
  },
27
28
  enabled: {
28
29
  type: 'boolean'
@@ -40,7 +41,7 @@ const AGENT_CLIENTS_SCHEMA = {
40
41
  }
41
42
  }
42
43
  }
43
- }
44
+ }))
44
45
  },
45
46
  customTUIs: {
46
47
  type: 'array',
@@ -1,13 +1,11 @@
1
1
  // Active AI collaborator short tokens — the write-side whitelist for the
2
2
  // activity log. Migrated from lib/task/commands/log.ts so that the write-side
3
- // internal commands and the rendering side share one definition. Historical
4
- // Gemini tokens remain read-only and are handled by classifyAgent below.
3
+ // internal commands and the rendering side share one definition.
5
4
  export const KNOWN_AI_AGENTS: ReadonlySet<string> =
6
5
  new Set(['claude', 'codex', 'antigravity', 'opencode', 'cursor', 'traecli']);
7
6
 
8
- // Long name -> short name mapping (HD-4, decision A): `claude-code` reuses the
9
- // existing orchestration precedent, and `antigravity-cli` is the active
10
- // client. `gemini-cli` is intentionally not writable.
7
+ // Long name -> short name mapping: `claude-code` reuses the existing
8
+ // orchestration precedent, and `antigravity-cli` is the active client.
11
9
  export const AGENT_LONG_NAMES: Readonly<Record<string, string>> = {
12
10
  'claude-code': 'claude',
13
11
  'antigravity-cli': 'antigravity'
@@ -17,17 +15,6 @@ export const AGENT_USAGE_HINT =
17
15
  "agent must be a short token (claude/codex/antigravity/opencode/cursor/traecli), " +
18
16
  "a long name (claude-code -> claude, antigravity-cli -> antigravity), or 'human'";
19
17
 
20
- // Read-side historical compatibility for activity-log rendering: `gemini` and
21
- // `gemini-cli` stay recognizable when displaying old logs, but are never
22
- // accepted by normalizeAgentToken (write side).
23
- const READ_KNOWN_AI_AGENTS: ReadonlySet<string> =
24
- new Set([...KNOWN_AI_AGENTS, 'gemini']);
25
-
26
- const READ_AGENT_LONG_NAMES: Readonly<Record<string, string>> = {
27
- ...AGENT_LONG_NAMES,
28
- 'gemini-cli': 'gemini'
29
- };
30
-
31
18
  // Strict write-side validation: the value must be exactly a short token, a
32
19
  // long name, or 'human'; returns the normalized short token, or null when
33
20
  // the value is not a recognized agent.
@@ -47,7 +34,7 @@ export function classifyAgent(raw: string):
47
34
  const token = raw.trim().split(/\s+/)[0]?.replace(/\(.*$/, '') ?? '';
48
35
  if (token === '') return { status: 'unknown', display: 'human' };
49
36
  if (token === 'human') return { status: 'human', display: 'human' };
50
- if (READ_KNOWN_AI_AGENTS.has(token)) return { status: 'ai', display: token };
51
- const short = READ_AGENT_LONG_NAMES[token];
37
+ if (KNOWN_AI_AGENTS.has(token)) return { status: 'ai', display: token };
38
+ const short = AGENT_LONG_NAMES[token];
52
39
  return short ? { status: 'ai', display: short } : { status: 'unknown', display: 'human' };
53
40
  }
package/lib/decide.ts CHANGED
@@ -3,7 +3,7 @@ import { parseTaskScope } from './task/command-options.ts';
3
3
  import { applyHumanDecision } from './task/decision-intents.ts';
4
4
  import { canonicalTimestamp } from './task/write.ts';
5
5
  import { consumeHumanOverride, failureId } from './task/human-override.ts';
6
- import { resolveTaskRef } from './task/resolve-ref.ts';
6
+ import { resolveTaskContext } from './task/resolve-ref.ts';
7
7
  import { TaskExecutionLockError, withTaskExecutionLock } from './task/task-execution-lock.ts';
8
8
 
9
9
  type DecideOptions = {
@@ -55,44 +55,36 @@ export async function decide(args: string[], options: DecideOptions = {}): Promi
55
55
  item = scope.positionals[++index];
56
56
  if (!item) { process.stderr.write(`Error: ${arg} requires a value\n`); return 1; }
57
57
  } else if (arg.startsWith('--item=')) {
58
- if (item !== undefined) { process.stderr.write("Error: duplicate option '--item'\n"); return 1; }
59
- item = arg.slice('--item='.length);
60
- if (item === '') { process.stderr.write('Error: --item requires a value\n'); return 1; }
58
+ process.stderr.write('Error: --item=... is not supported; use --item <selector> or -i <selector>\n'); return 1;
61
59
  } else operands.push(arg);
62
60
  }
63
- let taskRef = scope.taskRef;
64
- let selector = item;
65
- let decisionParts: string[];
66
- if (item !== undefined) {
67
- decisionParts = operands;
68
- } else if (!scope.explicit) {
69
- [taskRef, selector, ...decisionParts] = operands;
70
- } else {
71
- decisionParts = [];
72
- }
61
+ const taskRef = scope.taskRef;
62
+ const selector = item;
63
+ const decisionParts = operands;
73
64
  if (!selector || decisionParts.length === 0) {
74
- process.stderr.write('Usage: ai decide [--task <ref>] --item <ordinal|ledger-id> [--needs-implementation true|false] <decision>\n ai decide <task-ref> <ordinal|ledger-id> [--needs-implementation true|false] <decision>\n');
65
+ process.stderr.write('Usage: ai decide [--task <ref> | -t <ref>] (--item <ordinal|ledger-id> | -i <ordinal|ledger-id>) [--needs-implementation true|false] <decision>\n');
75
66
  return 1;
76
67
  }
77
68
  try {
78
69
  const parsedDecision = parseDecisionParts(decisionParts);
79
70
  const now = (options.now ?? canonicalTimestamp)();
71
+ const resolved = resolveTaskContext(taskRef, { repoRoot: options.repoRoot });
72
+ if (!resolved.ok) throw new Error(resolved.message);
80
73
  const request = {
81
- taskRef, selector, decision: parsedDecision.decision,
74
+ taskRef: resolved.taskId, selector, decision: parsedDecision.decision,
82
75
  needsImplementation: parsedDecision.needsImplementation
83
76
  };
84
77
  const writeOptions = {
85
- repoRoot: options.repoRoot,
78
+ repoRoot: resolved.repoRoot,
86
79
  metadataProvider: () => ({ timestamp: now, agentInfraVersion: options.version ?? VERSION })
87
80
  };
88
- const resolved = taskRef ? resolveTaskRef(taskRef, { repoRoot: options.repoRoot }) : null;
89
81
  let result;
90
82
  const execute = () => {
91
83
  let current = applyHumanDecision(request, writeOptions);
92
84
  if (current.status !== 'failed' || !parsedDecision.overrideTicket) return current;
93
85
  if (!parsedDecision.overrideTarget || !parsedDecision.overrideScope) throw new Error('override ticket requires --override-target and --override-scope');
94
86
  const consumed = consumeHumanOverride({
95
- taskRef: resolved?.ok ? resolved.taskId : String(taskRef ?? ''),
87
+ taskRef: resolved.taskId,
96
88
  ticketId: parsedDecision.overrideTicket,
97
89
  failureId: failureId('decision-intent', current.error?.code ?? 'TASK_STATE_MISMATCH'),
98
90
  target: parsedDecision.overrideTarget,
@@ -110,9 +102,7 @@ export async function decide(args: string[], options: DecideOptions = {}): Promi
110
102
  if (consumed.status === 'failed') throw new Error(consumed.error.message);
111
103
  return current;
112
104
  };
113
- result = resolved?.ok
114
- ? withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-decision', execute)
115
- : execute();
105
+ result = withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-decision', execute);
116
106
  if (result.error) throw new Error(result.error.message);
117
107
  return 0;
118
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
  },
@@ -90,6 +94,10 @@
90
94
  ],
91
95
  "ejected": [],
92
96
  "retiredManaged": [
97
+ {
98
+ "path": ".trae/skills/",
99
+ "templateHashes": []
100
+ },
93
101
  {
94
102
  "path": ".agents/workspace/README.md",
95
103
  "templateHashes": [
@@ -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
 
@@ -43,6 +44,7 @@ type AgentConfig = {
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>;
@@ -117,7 +119,7 @@ async function cmdInit(): Promise<void> {
117
119
  // check existing config
118
120
  if (fs.existsSync(configPath)) {
119
121
  err('This project already has agent-infra configuration.');
120
- err('Use /update-agent-infra in your AI TUI to update.');
122
+ err('Use /update-agent-infra in your AI TUI to sync project files.');
121
123
  process.exitCode = 1;
122
124
  return;
123
125
  }
@@ -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)
@@ -294,7 +297,7 @@ async function cmdInit(): Promise<void> {
294
297
  console.log('');
295
298
  ok('Project initialized successfully!');
296
299
  console.log('');
297
- console.log(' If this init used npx, install agent-infra persistently before update or validation:');
300
+ console.log(' If this init used npx, install agent-infra persistently before ai update or validation:');
298
301
  console.log(' npm install -g @fitlab-ai/agent-infra');
299
302
  console.log('');
300
303
  if (workflowPlan.nextSteps.length === 0) {
@@ -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;
@@ -7,6 +7,7 @@ import {
7
7
  createPlatformPullRequest,
8
8
  inspectPlatformPullRequest,
9
9
  resolveExternalPullRequest,
10
+ skipPlatformPullRequestFact,
10
11
  syncPlatformPullRequest
11
12
  } from '../platform/pull-requests.ts';
12
13
  import type { PullRequestResult } from '../platform/pull-requests.ts';
@@ -17,6 +18,7 @@ const USAGE = `Usage: agent-infra-internal platform-pr inspect <task-ref> [--cwd
17
18
  agent-infra-internal platform-pr resolve-external <task-ref> --agent <agent> [--pr <N>] [--dry-run] [--cwd <path>]
18
19
  agent-infra-internal platform-pr create <task-ref> --agent <agent> --base <branch> --head <branch> --title-file <path|-> --body-file <path|-> [--draft] [--dry-run] [--cwd <path>]
19
20
  agent-infra-internal platform-pr bind <task-ref> --pr <N> --agent <agent> [--dry-run] [--cwd <path>]
21
+ agent-infra-internal platform-pr skip <task-ref> --agent <agent> [--dry-run] [--cwd <path>]
20
22
  agent-infra-internal platform-pr sync <task-ref> --agent <agent> [--metadata] [--closing-issue] --result <pr_created|pr_reused|no_op> [--dry-run] [--cwd <path>]
21
23
  agent-infra-internal platform-pr summary-context <task-ref> [--cwd <path>]
22
24
  agent-infra-internal platform-pr summary-sync <task-ref> --agent <agent> --body-file <path|-> --result <pr_created|pr_reused|no_op> [--dry-run] [--cwd <path>]
@@ -64,7 +66,7 @@ function readFile(value: string, cwd: string): string {
64
66
  function platformPr(args: string[] = []): void {
65
67
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
66
68
  const operation = args[0];
67
- if (!operation || !['inspect', 'resolve-external', 'create', 'bind', 'sync', 'summary-context', 'summary-sync'].includes(operation)) { fail('a valid operation is required'); return; }
69
+ if (!operation || !['inspect', 'resolve-external', 'create', 'bind', 'skip', 'sync', 'summary-context', 'summary-sync'].includes(operation)) { fail('a valid operation is required'); return; }
68
70
  const taskRef = args[1];
69
71
  if (!taskRef || taskRef.startsWith('--')) { fail(`${operation} requires a task ref`); return; }
70
72
  const parsed = parse(args, 2);
@@ -76,6 +78,7 @@ function platformPr(args: string[] = []): void {
76
78
  'resolve-external': ['cwd', 'agent', 'pr', 'dryRun'],
77
79
  create: ['cwd', 'agent', 'base', 'head', 'titleFile', 'bodyFile', 'draft', 'dryRun'],
78
80
  bind: ['cwd', 'agent', 'pr', 'dryRun'],
81
+ skip: ['cwd', 'agent', 'dryRun'],
79
82
  sync: ['cwd', 'agent', 'metadata', 'closingIssue', 'result', 'dryRun'],
80
83
  'summary-context': ['cwd'],
81
84
  'summary-sync': ['cwd', 'agent', 'bodyFile', 'result', 'dryRun']
@@ -88,6 +91,10 @@ function platformPr(args: string[] = []): void {
88
91
  const agent = normalizeAgentToken(values.agent);
89
92
  if (!agent) { fail(`invalid --agent '${values.agent}': ${AGENT_USAGE_HINT}`); return; }
90
93
  values.agent = agent;
94
+ if (operation === 'skip') {
95
+ finish(skipPlatformPullRequestFact(taskRef, { cwd, agent, dryRun: values.dryRun === true }));
96
+ return;
97
+ }
91
98
  const primaryResult = values.result === undefined ? undefined : values.result;
92
99
  if (primaryResult !== undefined && !['pr_created', 'pr_reused', 'no_op'].includes(primaryResult as string)) {
93
100
  fail('--result must be pr_created, pr_reused, or no_op');
@@ -36,7 +36,6 @@ const DEMO_INPUT_PATHS = [
36
36
  'lib/prompt.ts',
37
37
  'lib/paths.ts',
38
38
  'lib/render.ts',
39
- 'lib/builtin-tuis.ts',
40
39
  'lib/sandbox/engines/'
41
40
  ] as const;
42
41
  const DEMO_DIGEST_PATH = 'assets/demo-init.inputs.sha256';
@@ -0,0 +1,53 @@
1
+ import path from 'node:path';
2
+
3
+ import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.ts';
4
+ import { deliverTaskBranch } from '../task/delivery.ts';
5
+
6
+ const USAGE = `Usage: agent-infra-internal task-delivery <task-ref> deliver --agent <agent> [--remote <name>] [--base <branch>] [--dry-run] [--cwd <path>]\n`;
7
+
8
+ function taskDelivery(args: string[] = []): void {
9
+ const taskRef = args[0];
10
+ const operation = args[1];
11
+ if (!taskRef || operation !== 'deliver') {
12
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'DELIVERY_PAYLOAD_INVALID', message: 'task ref and deliver operation are required' } })}\n`);
13
+ process.stderr.write(USAGE);
14
+ process.exitCode = 1;
15
+ return;
16
+ }
17
+ let agent = '';
18
+ let remote: string | undefined;
19
+ let baseRef: string | undefined;
20
+ let cwd = process.cwd();
21
+ let dryRun = false;
22
+ for (let index = 2; index < args.length; index += 1) {
23
+ const flag = args[index];
24
+ if (flag === '--dry-run') { dryRun = true; continue; }
25
+ const value = args[++index];
26
+ if (value === undefined || value.startsWith('--')) {
27
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'DELIVERY_PAYLOAD_INVALID', message: `${flag} requires a value` } })}\n`);
28
+ process.exitCode = 1;
29
+ return;
30
+ }
31
+ if (flag === '--agent') agent = value;
32
+ else if (flag === '--remote') remote = value;
33
+ else if (flag === '--base') baseRef = value;
34
+ else if (flag === '--cwd') cwd = path.resolve(value);
35
+ else {
36
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'DELIVERY_PAYLOAD_INVALID', message: `unknown option '${flag}'` } })}\n`);
37
+ process.exitCode = 1;
38
+ return;
39
+ }
40
+ }
41
+ const normalized = normalizeAgentToken(agent);
42
+ if (!normalized) {
43
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'DELIVERY_PAYLOAD_INVALID', message: `invalid --agent '${agent}': ${AGENT_USAGE_HINT}` } })}\n`);
44
+ process.exitCode = 1;
45
+ return;
46
+ }
47
+ const result = deliverTaskBranch(taskRef, { repoRoot: cwd, agent: normalized, remote, baseRef, dryRun });
48
+ process.stdout.write(`${JSON.stringify(result)}\n`);
49
+ if (result.status === 'failed') process.exitCode = 1;
50
+ if (result.status === 'blocked') process.exitCode = 2;
51
+ }
52
+
53
+ export { taskDelivery };
@@ -1,7 +1,10 @@
1
- import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.ts';
1
+ import {
2
+ createDirectHostExecutionContext,
3
+ dispatchTaskControlOperation,
4
+ parseTaskControlOperation
5
+ } from '../task/control-authority.ts';
2
6
  import { applyTaskFinalization } from '../task/finalization.ts';
3
7
  import { detectRepoRoot, resolveTaskRef } from '../task/resolve-ref.ts';
4
- import { verifyTaskEvent } from '../task/verification.ts';
5
8
 
6
9
  const USAGE = 'Usage: agent-infra-internal task-finalization <N | TASK-id> complete --agent <agent>\n';
7
10
 
@@ -28,17 +31,26 @@ function fail(message: string): void {
28
31
  process.exitCode = 1;
29
32
  }
30
33
 
34
+ function parseFailure(error: unknown): string {
35
+ const message = error instanceof Error ? error.message : String(error);
36
+ return message.replace(/^TASK_CONTROL_OPERATION_INVALID: /u, '');
37
+ }
38
+
31
39
  function taskFinalization(args: string[] = []): void {
32
40
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
33
- if (args.length !== 4 || !args[0] || args[1] !== 'complete' || args[2] !== '--agent' || !args[3]) {
34
- fail('task ref, complete intent, and --agent are required');
41
+
42
+ let operation;
43
+ try {
44
+ operation = parseTaskControlOperation('task-finalization', args);
45
+ } catch (error) {
46
+ fail(parseFailure(error));
35
47
  return;
36
48
  }
37
- const agent = normalizeAgentToken(args[3]);
38
- if (!agent) {
39
- fail(`invalid --agent: ${AGENT_USAGE_HINT}`);
49
+ if (operation.family !== 'task-finalization') {
50
+ fail('finalization operation is invalid');
40
51
  return;
41
52
  }
53
+
42
54
  let repoRoot: string;
43
55
  try {
44
56
  repoRoot = detectRepoRoot();
@@ -48,18 +60,20 @@ function taskFinalization(args: string[] = []): void {
48
60
  process.exitCode = 1;
49
61
  return;
50
62
  }
51
- const resolved = resolveTaskRef(args[0], { repoRoot });
63
+ const resolved = resolveTaskRef(operation.request.taskRef, { repoRoot });
52
64
  if (!resolved.ok) {
53
65
  const detail = { code: resolved.code, message: resolved.message, retryable: false };
54
66
  process.stdout.write(envelope('failed', false, true, null, detail));
55
67
  process.exitCode = 1;
56
68
  return;
57
69
  }
58
- const result = applyTaskFinalization(
59
- { taskRef: resolved.taskId, intent: 'complete', agent },
60
- { repoRoot, preflight: (request, options) => verifyTaskEvent(
61
- { ...request, event: 'complete-task.hard-preflight' }, options
62
- ) }
70
+ const boundOperation = {
71
+ ...operation,
72
+ request: { ...operation.request, taskRef: resolved.taskId }
73
+ };
74
+ const result = dispatchTaskControlOperation(
75
+ createDirectHostExecutionContext({ repoRoot }),
76
+ boundOperation
63
77
  );
64
78
  process.stdout.write(envelope(result.status, result.changed, true, result, result.error));
65
79
  process.exitCode = exitCode(result.status);
@@ -3,7 +3,7 @@ import fs from 'node:fs';
3
3
  import { applyLedgerIntent } from '../task/ledger-intents.ts';
4
4
  import type { LedgerIntent } from '../task/ledger-intents.ts';
5
5
  import { consumeHumanOverride, failureId, overrideDryRunConflict } from '../task/human-override.ts';
6
- import { isReviewStage, parseLedger, summarizeLedgerStage, validateLedgerRows } from '../task/ledger.ts';
6
+ import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, isReviewStage, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from '../task/ledger.ts';
7
7
  import { resolveTaskRef } from '../task/resolve-ref.ts';
8
8
  import { TaskExecutionLockError, withTaskExecutionLock } from '../task/task-execution-lock.ts';
9
9
 
@@ -81,7 +81,13 @@ function taskLedger(args: string[] = []): void {
81
81
  return;
82
82
  }
83
83
  try {
84
- const rows = parseLedger(fs.readFileSync(resolved.taskMdPath, 'utf8'));
84
+ const ledger = parseLedgerDocument(fs.readFileSync(resolved.taskMdPath, 'utf8'));
85
+ if (!ledger.present) {
86
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, taskId: resolved.taskId, error: { code: LEDGER_SECTION_MISSING_CODE, message: LEDGER_SECTION_MISSING_MESSAGE } })}\n`);
87
+ process.exitCode = 1;
88
+ return;
89
+ }
90
+ const rows = ledger.rows;
85
91
  const invalid = validateLedgerRows(rows);
86
92
  if (invalid) {
87
93
  process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, taskId: resolved.taskId, error: invalid })}\n`);
@@ -1,17 +1,14 @@
1
- import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.ts';
2
- import { consumeHumanOverride, failureId, overrideDryRunConflict } from '../task/human-override.ts';
3
- import { applyTaskLifecycle, lifecycleIntentCatalog } from '../task/lifecycle.ts';
4
- import type { TaskLifecycleRequest } from '../task/lifecycle.ts';
1
+ import {
2
+ createDirectHostExecutionContext,
3
+ dispatchTaskControlOperation,
4
+ parseTaskControlOperation,
5
+ type TaskLifecycleControlRequest
6
+ } from '../task/control-authority.ts';
7
+ import { lifecycleIntentCatalog } from '../task/lifecycle.ts';
5
8
  import { detectRepoRoot, resolveTaskRef } from '../task/resolve-ref.ts';
6
- import { TaskExecutionLockError, withTaskExecutionLock } from '../task/task-execution-lock.ts';
9
+ import type { TaskLifecycleResult } from '../task/lifecycle.ts';
7
10
 
8
11
  const USAGE = `Usage: agent-infra-internal task-lifecycle <N | TASK-id> <intent> --agent <agent> [intent flags] [--dry-run]\n\nIntents: ${lifecycleIntentCatalog.join(', ')}\nOverride: --override-ticket <ticket> --override-target <target> --override-scope <scope>\n`;
9
- const FLAGS: Record<string, string> = {
10
- '--agent': 'agent', '--reason': 'reason', '--unblock-condition': 'unblockCondition',
11
- '--note': 'note', '--alert-number': 'alertNumber', '--staging-dir': 'stagingDir',
12
- '--issue-number': 'issueNumber', '--override-ticket': 'overrideTicket',
13
- '--override-target': 'overrideTarget', '--override-scope': 'overrideScope'
14
- };
15
12
 
16
13
  function usageFailure(message: string): void {
17
14
  process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'LIFECYCLE_PAYLOAD_INVALID', message } })}\n`);
@@ -19,36 +16,29 @@ function usageFailure(message: string): void {
19
16
  process.exitCode = 1;
20
17
  }
21
18
 
19
+ function parseFailure(error: unknown): string {
20
+ const message = error instanceof Error ? error.message : String(error);
21
+ return message.replace(/^TASK_CONTROL_OPERATION_INVALID: /u, '');
22
+ }
23
+
22
24
  function taskLifecycle(args: string[] = []): void {
23
25
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
24
- if (args.length < 2) { usageFailure('task ref and intent are required'); return; }
25
- const values: Record<string, unknown> = { taskRef: args[0], intent: args[1], agent: '' };
26
- const seen = new Set<string>();
27
- for (let index = 2; index < args.length; index += 1) {
28
- const flag = args[index]!;
29
- if (flag === '--dry-run') {
30
- if (seen.has(flag)) { usageFailure(`duplicate option '${flag}'`); return; }
31
- seen.add(flag); values.dryRun = true; continue;
32
- }
33
- const key = FLAGS[flag];
34
- if (!key) { usageFailure(`unknown option '${flag}'`); return; }
35
- if (seen.has(flag)) { usageFailure(`duplicate option '${flag}'`); return; }
36
- const value = args[++index];
37
- if (value === undefined || value.startsWith('--')) { usageFailure(`option '${flag}' requires a value`); return; }
38
- seen.add(flag);
39
- values[key] = key === 'alertNumber' || key === 'issueNumber' ? Number(value) : value;
26
+
27
+ let operation;
28
+ try {
29
+ operation = parseTaskControlOperation('task-lifecycle', args);
30
+ } catch (error) {
31
+ usageFailure(parseFailure(error));
32
+ return;
40
33
  }
41
- const agent = normalizeAgentToken(String(values.agent ?? ''));
42
- if (!agent) { usageFailure(`invalid --agent '${values.agent}': ${AGENT_USAGE_HINT}`); return; }
43
- values.agent = agent;
44
- const dryRunConflict = overrideDryRunConflict(values);
45
- if (dryRunConflict) { usageFailure(dryRunConflict.message); return; }
34
+ if (operation.family !== 'task-lifecycle') {
35
+ usageFailure('lifecycle operation is invalid');
36
+ return;
37
+ }
38
+
39
+ const request = operation.request as TaskLifecycleControlRequest;
46
40
  let repoRoot: string;
47
- let taskId: string;
48
- if (values.intent === 'restore') {
49
- // restore's precondition is that the task does NOT exist locally yet (it only lives
50
- // in a staging dir), so resolveTaskRef's existence check is inapplicable here; identity
51
- // is guaranteed by applyTaskLifecycle's own full-TASK-id check plus staging validation.
41
+ if (request.intent === 'restore') {
52
42
  try {
53
43
  repoRoot = detectRepoRoot();
54
44
  } catch (error) {
@@ -56,53 +46,20 @@ function taskLifecycle(args: string[] = []): void {
56
46
  process.exitCode = 1;
57
47
  return;
58
48
  }
59
- taskId = String(values.taskRef);
60
49
  } else {
61
- const resolved = resolveTaskRef(String(values.taskRef));
50
+ const resolved = resolveTaskRef(request.taskRef);
62
51
  if (!resolved.ok) {
63
52
  process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: resolved.code, message: resolved.message } })}\n`);
64
53
  process.exitCode = 1;
65
54
  return;
66
55
  }
67
56
  repoRoot = resolved.repoRoot;
68
- taskId = resolved.taskId;
69
- }
70
- let result: ReturnType<typeof applyTaskLifecycle> & { humanOverride?: unknown };
71
- try {
72
- result = withTaskExecutionLock(
73
- repoRoot,
74
- taskId,
75
- `task-lifecycle.${String(values.intent)}`,
76
- () => {
77
- const lifecycleResult = applyTaskLifecycle(values as TaskLifecycleRequest);
78
- if (lifecycleResult.status !== 'failed' || !values.overrideTicket) return lifecycleResult;
79
- if (!values.overrideTarget || !values.overrideScope) {
80
- return {
81
- ...lifecycleResult,
82
- error: { code: 'OVERRIDE_PAYLOAD_INVALID', message: 'override ticket requires --override-target and --override-scope' }
83
- };
84
- }
85
- const override = consumeHumanOverride({
86
- taskRef: String(values.taskRef),
87
- ticketId: String(values.overrideTicket),
88
- failureId: failureId('lifecycle.apply', lifecycleResult.error?.code ?? 'LIFECYCLE_FAILED'),
89
- target: String(values.overrideTarget),
90
- scope: String(values.overrideScope),
91
- intent: String(values.intent) as TaskLifecycleRequest['intent'],
92
- ...(values.alertNumber ? { alertNumber: Number(values.alertNumber) } : {}),
93
- ...(values.issueNumber ? { issueNumber: Number(values.issueNumber) } : {}),
94
- ...(values.stagingDir ? { stagingDir: String(values.stagingDir) } : {})
95
- });
96
- if (override.status === 'failed') return { ...lifecycleResult, humanOverride: override };
97
- return { ...lifecycleResult, ...override, humanOverride: override, error: null };
98
- }
99
- );
100
- } catch (error) {
101
- if (!(error instanceof TaskExecutionLockError)) throw error;
102
- process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: error.code, message: error.message } })}\n`);
103
- process.exitCode = 1;
104
- return;
105
57
  }
58
+
59
+ const result = dispatchTaskControlOperation(
60
+ createDirectHostExecutionContext({ repoRoot }),
61
+ operation
62
+ ) as TaskLifecycleResult & { humanOverride?: unknown };
106
63
  process.stdout.write(`${JSON.stringify(result)}\n`);
107
64
  if (result.status === 'failed') process.exitCode = 1;
108
65
  }