@fitlab-ai/agent-infra 0.9.14 → 0.10.0

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 (354) hide show
  1. package/README.md +10 -0
  2. package/README.zh-CN.md +10 -0
  3. package/bin/internal-cli.sh +45 -0
  4. package/dist/bin/internal-cli.js +93 -30
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +165 -27
  6. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +9 -4
  7. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +43 -3
  8. package/dist/lib/defaults.json +103 -103
  9. package/dist/lib/fs/durable-write.js +39 -0
  10. package/dist/lib/fs/file-lock.js +111 -0
  11. package/dist/lib/host-control/audit.js +19 -0
  12. package/dist/lib/host-control/client.js +142 -0
  13. package/dist/lib/host-control/command.js +49 -0
  14. package/dist/lib/host-control/path.js +160 -0
  15. package/dist/lib/host-control/secure-fs.js +140 -0
  16. package/dist/lib/host-control/server.js +159 -0
  17. package/dist/lib/host-control/service.js +112 -0
  18. package/dist/lib/init.js +11 -2
  19. package/dist/lib/internal/cli-route-inventory.js +4 -2
  20. package/dist/lib/internal/codex-lifecycle.js +6 -6
  21. package/dist/lib/internal/demo-promotion.js +322 -0
  22. package/dist/lib/internal/demo-transcript.js +454 -0
  23. package/dist/lib/internal/host-control.js +28 -0
  24. package/dist/lib/internal/manual-validation.js +331 -0
  25. package/dist/lib/internal/platform-pr.js +18 -4
  26. package/dist/lib/internal/release-workflow.js +63 -84
  27. package/dist/lib/internal/sandbox-control.js +149 -2
  28. package/dist/lib/internal/task-artifact.js +16 -263
  29. package/dist/lib/internal/task-create.js +6 -5
  30. package/dist/lib/internal/task-event.js +37 -37
  31. package/dist/lib/internal/task-lifecycle.js +2 -2
  32. package/dist/lib/internal/task-operation-registry.js +101 -4
  33. package/dist/lib/internal/task-review.js +11 -56
  34. package/dist/lib/internal/task-validate.js +30 -10
  35. package/dist/lib/owned-path.js +33 -0
  36. package/dist/lib/platform/check-status.js +11 -0
  37. package/dist/lib/platform/comment-safety.js +4 -1
  38. package/dist/lib/platform/completion-backfill.js +1 -1
  39. package/dist/lib/platform/github-data.js +241 -0
  40. package/dist/lib/platform/github-provider.js +15 -20
  41. package/dist/lib/platform/issue-comments.js +18 -12
  42. package/dist/lib/platform/issues.js +2 -180
  43. package/dist/lib/platform/pr-change-report.js +5 -4
  44. package/dist/lib/platform/pr-checks.js +12 -65
  45. package/dist/lib/platform/pr-summary.js +117 -33
  46. package/dist/lib/platform/pull-requests.js +5 -108
  47. package/dist/lib/platform/snapshots.js +2 -0
  48. package/dist/lib/platform/task-identities.js +2 -9
  49. package/dist/lib/platform/verification-sync.js +132 -143
  50. package/dist/lib/pr-review/evidence-grading.js +4 -8
  51. package/dist/lib/release/workflow.js +1 -1
  52. package/dist/lib/sandbox/commands/create.js +7 -2
  53. package/dist/lib/sandbox/commands/rm.js +19 -1511
  54. package/dist/lib/sandbox/control/audit.js +203 -0
  55. package/dist/lib/sandbox/control/client.js +93 -54
  56. package/dist/lib/sandbox/control/executor.js +129 -65
  57. package/dist/lib/sandbox/control/finalization-response.js +27 -0
  58. package/dist/lib/sandbox/control/identity-sentinel.js +107 -0
  59. package/dist/lib/sandbox/control/lifecycle.js +36 -2
  60. package/dist/lib/sandbox/control/native-file-lock.js +6 -98
  61. package/dist/lib/sandbox/control/protocol.js +55 -4
  62. package/dist/lib/sandbox/control/server.js +518 -127
  63. package/dist/lib/sandbox/control/state.js +64 -0
  64. package/dist/lib/sandbox/control/task-workflow.js +74 -0
  65. package/dist/lib/sandbox/control/workflow-executor.js +89 -0
  66. package/dist/lib/sandbox/index.js +1 -2
  67. package/dist/lib/sandbox/recovery.js +28 -4
  68. package/dist/lib/sandbox/removal.js +822 -0
  69. package/dist/lib/sandbox/task-cleanup.js +217 -0
  70. package/dist/lib/sandbox/workspace-identity.js +17 -1
  71. package/dist/lib/sandbox/workspace-view.js +13 -14
  72. package/dist/lib/task/activity-intent.js +2 -1
  73. package/dist/lib/task/activity-log.js +30 -24
  74. package/dist/lib/task/artifact-command.js +79 -0
  75. package/dist/lib/task/artifact-lifecycle.js +30 -28
  76. package/dist/lib/task/artifact-name.js +36 -0
  77. package/dist/lib/task/artifact-operations.js +29 -289
  78. package/dist/lib/task/artifact-receipts.js +3 -15
  79. package/dist/lib/task/artifact-recovery.js +430 -0
  80. package/dist/lib/task/artifact-repair-intent.js +134 -29
  81. package/dist/lib/task/artifact-schema.js +6 -14
  82. package/dist/lib/task/capabilities.js +12 -19
  83. package/dist/lib/task/codex-orchestration.js +71 -25
  84. package/dist/lib/task/commit-identity.js +28 -0
  85. package/dist/lib/task/commit-operation.js +33 -20
  86. package/dist/lib/task/control-authority.js +403 -6
  87. package/dist/lib/task/control-recovery.js +140 -0
  88. package/dist/lib/task/create-service.js +1 -8
  89. package/dist/lib/task/create.js +62 -9
  90. package/dist/lib/task/decision-details.js +2 -46
  91. package/dist/lib/task/delegation-receipts.js +64 -3
  92. package/dist/lib/task/events.js +275 -22
  93. package/dist/lib/task/finalization-state.js +9 -0
  94. package/dist/lib/task/human-override.js +8 -14
  95. package/dist/lib/task/implementation-inputs.js +3 -3
  96. package/dist/lib/task/intermediate-cleanup.js +441 -0
  97. package/dist/lib/task/invalidation.js +18 -65
  98. package/dist/lib/task/ledger-intents.js +7 -22
  99. package/dist/lib/task/ledger.js +1 -3
  100. package/dist/lib/task/lifecycle-recovery.js +549 -0
  101. package/dist/lib/task/lifecycle.js +31 -4
  102. package/dist/lib/task/local-artifact-finalization.js +197 -197
  103. package/dist/lib/task/manual-validation-completion.js +26 -0
  104. package/dist/lib/task/manual-validation-evidence.js +130 -0
  105. package/dist/lib/task/manual-validation-receipt.js +105 -0
  106. package/dist/lib/task/manual-validation-shared.js +40 -0
  107. package/dist/lib/task/manual-validation-transaction.js +243 -0
  108. package/dist/lib/task/markdown.js +47 -0
  109. package/dist/lib/task/orchestration.js +66 -19
  110. package/dist/lib/task/pr-delivery-fact.js +12 -56
  111. package/dist/lib/task/qualification-audit.js +20 -34
  112. package/dist/lib/task/recovery-warning.js +19 -0
  113. package/dist/lib/task/review-artifacts.js +2 -18
  114. package/dist/lib/task/review-command.js +26 -0
  115. package/dist/lib/task/review-finalization.js +175 -216
  116. package/dist/lib/task/review-fingerprint.js +2 -2
  117. package/dist/lib/task/sections.js +34 -56
  118. package/dist/lib/task/short-id.js +15 -7
  119. package/dist/lib/task/task-execution-lock.js +1 -1
  120. package/dist/lib/task/verification-engine.js +119 -337
  121. package/dist/lib/task/verification.js +1 -1
  122. package/dist/lib/task/workflow-command.js +16 -0
  123. package/dist/lib/task/workflow-warning-intents.js +0 -16
  124. package/dist/lib/task/workflow-warnings.js +28 -2
  125. package/dist/lib/update.js +2 -0
  126. package/dist/lib/version.js +1 -11
  127. package/dist/lifecycle-build-manifest.json +3 -3
  128. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +223 -33
  129. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +10 -4
  130. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +55 -3
  131. package/lib/fs/durable-write.ts +30 -0
  132. package/lib/fs/file-lock.ts +113 -0
  133. package/lib/host-control/audit.ts +22 -0
  134. package/lib/host-control/client.ts +172 -0
  135. package/lib/host-control/command.ts +60 -0
  136. package/lib/host-control/path.ts +167 -0
  137. package/lib/host-control/secure-fs.ts +135 -0
  138. package/lib/host-control/server.ts +180 -0
  139. package/lib/host-control/service.ts +133 -0
  140. package/lib/init.ts +15 -2
  141. package/lib/internal/cli-route-inventory.ts +4 -2
  142. package/lib/internal/codex-lifecycle.ts +6 -6
  143. package/lib/internal/demo-promotion.ts +354 -0
  144. package/lib/internal/demo-transcript.ts +419 -0
  145. package/lib/internal/host-control.ts +28 -0
  146. package/lib/internal/manual-validation.ts +315 -0
  147. package/lib/internal/platform-pr.ts +15 -4
  148. package/lib/internal/release-workflow.ts +74 -82
  149. package/lib/internal/sandbox-control.ts +162 -1
  150. package/lib/internal/task-artifact.ts +14 -217
  151. package/lib/internal/task-create.ts +5 -5
  152. package/lib/internal/task-event.ts +20 -11
  153. package/lib/internal/task-lifecycle.ts +4 -3
  154. package/lib/internal/task-operation-registry.ts +111 -4
  155. package/lib/internal/task-review.ts +9 -54
  156. package/lib/internal/task-validate.ts +26 -10
  157. package/lib/owned-path.ts +26 -0
  158. package/lib/platform/check-status.ts +9 -0
  159. package/lib/platform/comment-safety.ts +5 -0
  160. package/lib/platform/completion-backfill.ts +1 -1
  161. package/lib/platform/github-data.ts +322 -0
  162. package/lib/platform/github-provider.ts +15 -20
  163. package/lib/platform/issue-comments.ts +21 -14
  164. package/lib/platform/issues.ts +5 -246
  165. package/lib/platform/pr-change-report.ts +7 -5
  166. package/lib/platform/pr-checks.ts +13 -77
  167. package/lib/platform/pr-summary.ts +123 -35
  168. package/lib/platform/pull-requests.ts +6 -173
  169. package/lib/platform/snapshots.ts +53 -0
  170. package/lib/platform/task-identities.ts +3 -14
  171. package/lib/platform/verification-sync.ts +150 -156
  172. package/lib/pr-review/evidence-grading.ts +4 -9
  173. package/lib/release/workflow.ts +3 -3
  174. package/lib/sandbox/commands/create.ts +7 -6
  175. package/lib/sandbox/commands/rm.ts +21 -1895
  176. package/lib/sandbox/control/audit.ts +253 -0
  177. package/lib/sandbox/control/client.ts +109 -66
  178. package/lib/sandbox/control/executor.ts +134 -74
  179. package/lib/sandbox/control/finalization-response.ts +29 -0
  180. package/lib/sandbox/control/identity-sentinel.ts +137 -0
  181. package/lib/sandbox/control/lifecycle.ts +45 -3
  182. package/lib/sandbox/control/native-file-lock.ts +6 -107
  183. package/lib/sandbox/control/protocol.ts +80 -6
  184. package/lib/sandbox/control/server.ts +567 -132
  185. package/lib/sandbox/control/state.ts +86 -0
  186. package/lib/sandbox/control/task-workflow.ts +95 -0
  187. package/lib/sandbox/control/workflow-executor.ts +92 -0
  188. package/lib/sandbox/index.ts +1 -2
  189. package/lib/sandbox/recovery.ts +28 -5
  190. package/lib/sandbox/removal.ts +1142 -0
  191. package/lib/sandbox/task-cleanup.ts +209 -0
  192. package/lib/sandbox/workspace-identity.ts +19 -3
  193. package/lib/sandbox/workspace-view.ts +17 -15
  194. package/lib/task/activity-intent.ts +2 -2
  195. package/lib/task/activity-log.ts +27 -19
  196. package/lib/task/artifact-command.ts +85 -0
  197. package/lib/task/artifact-lifecycle.ts +31 -26
  198. package/lib/task/artifact-name.ts +55 -0
  199. package/lib/task/artifact-operations.ts +34 -310
  200. package/lib/task/artifact-receipts.ts +3 -14
  201. package/lib/task/artifact-recovery.ts +519 -0
  202. package/lib/task/artifact-repair-intent.ts +162 -33
  203. package/lib/task/artifact-schema.ts +5 -34
  204. package/lib/task/capabilities.ts +13 -22
  205. package/lib/task/codex-orchestration.ts +85 -24
  206. package/lib/task/commit-identity.ts +31 -0
  207. package/lib/task/commit-operation.ts +37 -20
  208. package/lib/task/control-authority.ts +540 -10
  209. package/lib/task/control-recovery.ts +186 -0
  210. package/lib/task/create-service.ts +1 -10
  211. package/lib/task/create.ts +63 -8
  212. package/lib/task/decision-details.ts +3 -71
  213. package/lib/task/delegation-receipts.ts +73 -2
  214. package/lib/task/events.ts +309 -24
  215. package/lib/task/finalization-state.ts +11 -0
  216. package/lib/task/human-override.ts +8 -16
  217. package/lib/task/implementation-inputs.ts +3 -3
  218. package/lib/task/intermediate-cleanup.ts +493 -0
  219. package/lib/task/invalidation.ts +18 -62
  220. package/lib/task/ledger-intents.ts +7 -24
  221. package/lib/task/ledger.ts +1 -3
  222. package/lib/task/lifecycle-recovery.ts +691 -0
  223. package/lib/task/lifecycle.ts +30 -5
  224. package/lib/task/local-artifact-finalization.ts +244 -234
  225. package/lib/task/manual-validation-completion.ts +40 -0
  226. package/lib/task/manual-validation-evidence.ts +209 -0
  227. package/lib/task/manual-validation-receipt.ts +156 -0
  228. package/lib/task/manual-validation-shared.ts +50 -0
  229. package/lib/task/manual-validation-transaction.ts +304 -0
  230. package/lib/task/markdown.ts +70 -0
  231. package/lib/task/orchestration.ts +84 -19
  232. package/lib/task/pr-delivery-fact.ts +15 -62
  233. package/lib/task/qualification-audit.ts +22 -33
  234. package/lib/task/recovery-warning.ts +21 -0
  235. package/lib/task/review-artifacts.ts +1 -20
  236. package/lib/task/review-command.ts +24 -0
  237. package/lib/task/review-finalization.ts +183 -292
  238. package/lib/task/review-fingerprint.ts +2 -2
  239. package/lib/task/sections.ts +33 -54
  240. package/lib/task/short-id.ts +27 -5
  241. package/lib/task/task-execution-lock.ts +1 -1
  242. package/lib/task/verification-engine.ts +113 -383
  243. package/lib/task/verification-types.ts +15 -0
  244. package/lib/task/verification.ts +1 -1
  245. package/lib/task/workflow-command.ts +17 -0
  246. package/lib/task/workflow-warning-intents.ts +0 -13
  247. package/lib/task/workflow-warnings.ts +21 -2
  248. package/lib/update.ts +6 -0
  249. package/lib/version.ts +1 -15
  250. package/package.json +6 -6
  251. package/templates/.agents/hooks/lifecycle-delegation.js +6 -6
  252. package/templates/.agents/rules/create-issue.en.md +1 -1
  253. package/templates/.agents/rules/create-issue.zh-CN.md +1 -1
  254. package/templates/.agents/rules/issue-sync.en.md +4 -2
  255. package/templates/.agents/rules/issue-sync.zh-CN.md +4 -3
  256. package/templates/.agents/rules/local-artifact-repair.en.md +46 -39
  257. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +43 -36
  258. package/templates/.agents/rules/testing-discipline.en.md +2 -0
  259. package/templates/.agents/rules/testing-discipline.zh-CN.md +2 -0
  260. package/templates/.agents/scripts/package.json +3 -0
  261. package/templates/.agents/skills/analyze-task/SKILL.en.md +6 -6
  262. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +6 -6
  263. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -1
  264. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -1
  265. package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
  266. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
  267. package/templates/.agents/skills/block-task/config/verify.json +1 -1
  268. package/templates/.agents/skills/cancel-task/SKILL.en.md +3 -3
  269. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +3 -3
  270. package/templates/.agents/skills/cancel-task/config/verify.json +1 -1
  271. package/templates/.agents/skills/code-task/SKILL.en.md +7 -7
  272. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +7 -7
  273. package/templates/.agents/skills/code-task/config/verify.en.json +1 -1
  274. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -1
  275. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
  276. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
  277. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +33 -21
  278. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +33 -21
  279. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  280. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  281. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
  282. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
  283. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +16 -7
  284. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +16 -7
  285. package/templates/.agents/skills/complete-task/SKILL.en.md +3 -3
  286. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
  287. package/templates/.agents/skills/complete-task/config/verify.en.json +2 -2
  288. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +2 -2
  289. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +1 -1
  290. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +1 -1
  291. package/templates/.agents/skills/create-pr/SKILL.en.md +2 -2
  292. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +2 -2
  293. package/templates/.agents/skills/create-pr/config/verify.json +1 -1
  294. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +2 -2
  295. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +2 -2
  296. package/templates/.agents/skills/create-task/SKILL.en.md +5 -5
  297. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +5 -5
  298. package/templates/.agents/skills/create-task/config/verify.json +1 -1
  299. package/templates/.agents/skills/import-issue/SKILL.en.md +8 -8
  300. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +8 -8
  301. package/templates/.agents/skills/import-issue/config/verify.json +2 -2
  302. package/templates/.agents/skills/plan-task/SKILL.en.md +4 -4
  303. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +4 -4
  304. package/templates/.agents/skills/plan-task/config/verify.en.json +1 -1
  305. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -1
  306. package/templates/.agents/skills/release/SKILL.en.md +7 -3
  307. package/templates/.agents/skills/release/SKILL.zh-CN.md +7 -3
  308. package/templates/.agents/skills/restore-task/SKILL.en.md +2 -2
  309. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +2 -2
  310. package/templates/.agents/skills/restore-task/config/verify.json +1 -1
  311. package/templates/.agents/skills/review-analysis/SKILL.en.md +2 -2
  312. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +2 -2
  313. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -1
  314. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -1
  315. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +7 -7
  316. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +6 -6
  317. package/templates/.agents/skills/review-code/SKILL.en.md +2 -2
  318. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +2 -2
  319. package/templates/.agents/skills/review-code/config/verify.en.json +1 -1
  320. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -1
  321. package/templates/.agents/skills/review-code/reference/report-template.en.md +12 -12
  322. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +12 -12
  323. package/templates/.agents/skills/review-plan/SKILL.en.md +2 -2
  324. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +2 -2
  325. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -1
  326. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -1
  327. package/templates/.agents/skills/review-plan/reference/report-template.en.md +7 -7
  328. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +7 -7
  329. package/templates/.agents/skills/review-pr/config/verify.en.json +1 -1
  330. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +1 -1
  331. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +3 -3
  332. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +3 -3
  333. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +20 -3
  334. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +20 -3
  335. package/templates/.agents/skills/run-manual-validation/config/verify.en.json +1 -1
  336. package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +1 -1
  337. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +4 -1
  338. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +4 -1
  339. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -0
  340. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -0
  341. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  342. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  343. package/templates/.agents/skills/test/SKILL.en.md +17 -6
  344. package/templates/.agents/skills/test/SKILL.zh-CN.md +17 -6
  345. package/templates/.agents/templates/task.en.md +1 -1
  346. package/templates/.agents/templates/task.zh-CN.md +1 -1
  347. package/templates/.claude/commands/import-issue.en.md +1 -1
  348. package/templates/.claude/commands/import-issue.zh-CN.md +1 -1
  349. package/templates/.claude/commands/restore-task.en.md +1 -1
  350. package/templates/.claude/commands/restore-task.zh-CN.md +1 -1
  351. package/templates/.claude/commands/run-manual-validation.en.md +1 -1
  352. package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
  353. package/dist/lib/platform/adapters.js +0 -56
  354. package/lib/platform/adapters.ts +0 -197
@@ -1,8 +1,13 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { readFileSync } from 'node:fs';
3
+ import path from 'node:path';
1
4
  import {
2
5
  recoverSandboxControl,
3
6
  requestSandboxControl,
4
7
  requestSandboxTaskFinalization,
5
8
  requestSandboxTaskControl,
9
+ requestSandboxTaskWorkflow,
10
+ resolveVisibleActiveShortId,
6
11
  SandboxControlClientError
7
12
  } from '../sandbox/control/client.ts';
8
13
  import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.ts';
@@ -14,6 +19,113 @@ import {
14
19
  } from '../agent-clients/adapters/codex-lifecycle/sandbox-controller.ts';
15
20
  import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
16
21
  import { parseTaskCreateResult, taskCreateExitCode } from '../task/create-service.ts';
22
+ import { createTaskWorkflowRequest } from '../sandbox/control/task-workflow.ts';
23
+ import { computeLifecycleBuildIdentity } from '../agent-clients/adapters/codex-lifecycle/build-identity.ts';
24
+ import { routeOrchestration } from '../task/orchestration.ts';
25
+ import { parseArtifactName } from '../task/artifact-name.ts';
26
+ import type { LifecycleAuthorityRequestV1 } from '../task/control-authority.ts';
27
+
28
+ function valueAfter(args: readonly string[], flag: string): string | undefined {
29
+ for (let index = 0; index < args.length; index += 1) {
30
+ if (args[index] === flag) return args[index + 1];
31
+ if (args[index]?.startsWith(`${flag}=`)) return args[index]!.slice(flag.length + 1);
32
+ }
33
+ return undefined;
34
+ }
35
+
36
+ function withoutValue(args: readonly string[], flag: string): string[] {
37
+ const result: string[] = [];
38
+ for (let index = 0; index < args.length; index += 1) {
39
+ if (args[index] === flag) { index += 1; continue; }
40
+ if (args[index]?.startsWith(`${flag}=`)) continue;
41
+ result.push(args[index]!);
42
+ }
43
+ return result;
44
+ }
45
+
46
+ function lifecycleIds(authorityRef: string, taskId: string): Readonly<{ operationId: string; lifecycleRequestId: string }> {
47
+ const digest = (label: string) => createHash('sha256')
48
+ .update(`${label}\0${taskId}\0${authorityRef}`, 'utf8')
49
+ .digest('hex');
50
+ return { operationId: digest('operation'), lifecycleRequestId: digest('lifecycle-request') };
51
+ }
52
+
53
+ function lifecycleAuthorityIdentity(
54
+ authorityRef: string,
55
+ taskId: string,
56
+ requestId: string,
57
+ phase: LifecycleAuthorityRequestV1['phase'],
58
+ family: LifecycleAuthorityRequestV1['family'],
59
+ artifact: string,
60
+ round: number
61
+ ): LifecycleAuthorityRequestV1 | undefined {
62
+ const contextPath = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
63
+ if (!authorityRef || !contextPath) return undefined;
64
+ const routed = verifyCodexSandboxControllerContextWithWarnings(contextPath, { repoRoot: process.cwd() });
65
+ const buildIdentity = computeLifecycleBuildIdentity(process.cwd());
66
+ const hookDefinitionHash = createHash('sha256')
67
+ .update(readFileSync(path.join(process.cwd(), '.codex', 'hooks.json')))
68
+ .digest('hex');
69
+ const ids = lifecycleIds(authorityRef, taskId);
70
+ return {
71
+ version: 1,
72
+ requestId,
73
+ operationId: ids.operationId,
74
+ phase,
75
+ taskId,
76
+ family,
77
+ artifact,
78
+ round,
79
+ lifecycleRequestId: ids.lifecycleRequestId,
80
+ authorityRef,
81
+ expectedControlGeneration: routed.context.controlGeneration,
82
+ expectedControllerInstanceDigest: routed.context.controllerInstanceDigest,
83
+ expectedBuildIdentityDigest: createHash('sha256').update(JSON.stringify(buildIdentity)).digest('hex'),
84
+ expectedHookDefinitionHash: hookDefinitionHash
85
+ };
86
+ }
87
+
88
+ function lifecycleAuthoritySelector(args: readonly string[]): LifecycleAuthorityRequestV1 | undefined {
89
+ if (!isCanonicalCodexPrepare(args)) return undefined;
90
+ const authorityRef = valueAfter(args, '--capability-ref');
91
+ const taskId = args[0];
92
+ if (!authorityRef || !taskId) return undefined;
93
+ const routed = routeOrchestration(taskId);
94
+ if (!routed.next || !['analysis', 'plan', 'code'].includes(routed.next.stage)) return undefined;
95
+ return lifecycleAuthorityIdentity(
96
+ authorityRef,
97
+ taskId,
98
+ randomUUID(),
99
+ 'orchestration.prepare',
100
+ routed.next.stage === 'analysis' ? 'analysis' : routed.next.stage === 'plan' ? 'plan' : 'code',
101
+ routed.next.artifact,
102
+ routed.next.round
103
+ );
104
+ }
105
+
106
+ function lifecycleWorkflowAuthoritySelector(
107
+ originalArgs: readonly string[],
108
+ workflow: ReturnType<typeof createTaskWorkflowRequest>
109
+ ): LifecycleAuthorityRequestV1 | undefined {
110
+ const authorityRef = valueAfter(originalArgs, '--capability-ref');
111
+ if (!authorityRef) return undefined;
112
+ if (workflow.operation === 'artifact-finalize-local') {
113
+ const family = valueAfter(workflow.args, '--family');
114
+ const artifact = valueAfter(workflow.args, '--artifact');
115
+ const parsed = artifact ? parseArtifactName(artifact) : null;
116
+ if ((family !== 'analysis' && family !== 'plan' && family !== 'code')
117
+ || !parsed || parsed.family !== family) return undefined;
118
+ return lifecycleAuthorityIdentity(authorityRef, workflow.taskId, workflow.id,
119
+ 'artifact.finalize-local', family, artifact!, parsed.round);
120
+ }
121
+ if (workflow.operation !== 'event') return undefined;
122
+ const completed = /^(analysis|plan|code)\.completed$/u.exec(workflow.args[1] ?? '');
123
+ const artifact = valueAfter(workflow.args, '--artifact');
124
+ const parsed = artifact ? parseArtifactName(artifact) : null;
125
+ if (!completed || !parsed || parsed.family !== completed[1]) return undefined;
126
+ return lifecycleAuthorityIdentity(authorityRef, workflow.taskId, workflow.id,
127
+ 'task-event.completed', completed[1] as LifecycleAuthorityRequestV1['family'], artifact!, parsed.round);
128
+ }
17
129
 
18
130
  function isCanonicalCodexPrepare(args: readonly string[]): boolean {
19
131
  if (args[1] !== 'prepare') return false;
@@ -151,6 +263,49 @@ async function sandboxControl(args: string[]): Promise<void> {
151
263
  sandboxFinalizationClient(commandArgs);
152
264
  return;
153
265
  }
266
+ if (family === 'task-workflow') {
267
+ const command = commandArgs[0] as Parameters<typeof createTaskWorkflowRequest>[0] | undefined;
268
+ const taskId = process.env.AGENT_INFRA_TASK_ID;
269
+ const generation = process.env.AGENT_INFRA_CONTROL_GENERATION;
270
+ if (!command || !taskId || !generation) {
271
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'SANDBOX_CONTROL_REQUEST_INVALID', message: 'task-workflow requires a bound task and generation' } })}\n`);
272
+ process.exitCode = 1;
273
+ return;
274
+ }
275
+ let workflow;
276
+ try {
277
+ const args = withoutValue(commandArgs.slice(1), '--capability-ref');
278
+ if (/^\d+$/.test(args[0] ?? '')) {
279
+ const resolved = resolveVisibleActiveShortId(args[0]!);
280
+ if (resolved !== taskId) throw new Error('SANDBOX_TASK_REF_MISMATCH');
281
+ args[0] = resolved;
282
+ }
283
+ workflow = createTaskWorkflowRequest(command, args, taskId, generation);
284
+ }
285
+ catch (error) {
286
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'SANDBOX_CONTROL_REQUEST_INVALID', message: error instanceof Error ? error.message : String(error) } })}\n`);
287
+ process.exitCode = 1;
288
+ return;
289
+ }
290
+ let response;
291
+ try {
292
+ const authority = lifecycleWorkflowAuthoritySelector(commandArgs, workflow);
293
+ response = requestSandboxTaskWorkflow({
294
+ workflow,
295
+ ...(authority ? { authority } : {})
296
+ });
297
+ }
298
+ catch (error) {
299
+ if (!(error instanceof SandboxControlClientError)) throw error;
300
+ writeClientError(error);
301
+ process.exitCode = error.detail.retryable ? 75 : 1;
302
+ return;
303
+ }
304
+ process.stdout.write(response.stdout);
305
+ process.stderr.write(response.stderr);
306
+ process.exitCode = response.phase === 'rejected' ? response.error?.retryable ? 75 : 1 : response.exitCode ?? 1;
307
+ return;
308
+ }
154
309
  let response;
155
310
  try {
156
311
  if (family === 'task-orchestration' && isCanonicalCodexPrepare(commandArgs)) {
@@ -158,7 +313,13 @@ async function sandboxControl(args: string[]): Promise<void> {
158
313
  const proof = contextPath
159
314
  ? controllerProofFromContext(verifyCodexSandboxControllerContextWithWarnings(contextPath).context)
160
315
  : null;
161
- response = requestSandboxTaskControl({ family, args: commandArgs, controllerProof: proof });
316
+ const authority = lifecycleAuthoritySelector(commandArgs);
317
+ response = requestSandboxTaskControl({
318
+ family,
319
+ args: commandArgs,
320
+ controllerProof: authority ? null : proof,
321
+ ...(authority ? { authority } : {})
322
+ });
162
323
  } else {
163
324
  response = requestSandboxControl({ family, args: commandArgs });
164
325
  }
@@ -1,229 +1,26 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
1
+ import { parseArtifactCommand, executeArtifactCommand } from '../task/artifact-command.ts';
2
+ import { ensureInternalHandlerRoute } from './cli-route-inventory.ts';
3
3
 
4
- import { resolveArtifactContext } from '../task/artifact-lifecycle.ts';
5
- import { parseArtifactName } from '../task/artifact-lifecycle.ts';
6
- import { locateActivityLog, pairEntries, startedBackedRows } from '../task/activity-log.ts';
7
- import { finalizeLocalArtifact } from '../task/local-artifact-finalization.ts';
8
- import type { LocalArtifactFamily } from '../task/local-artifact-finalization.ts';
9
- import { resolveTaskRef } from '../task/resolve-ref.ts';
10
- import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
11
- import { getArtifactSchema } from '../task/artifact-schema.ts';
12
- import {
13
- applyArtifactRepair,
14
- initializeArtifactSkeleton,
15
- inspectArtifactStructure
16
- } from '../task/artifact-operations.ts';
4
+ const USAGE = `Usage: agent-infra-internal task-artifact <N | TASK-id> inspect --family <family>\n agent-infra-internal task-artifact <N | TASK-id> init --family <family> --artifact <artifact> [--locale <zh-CN|en>]\n agent-infra-internal task-artifact <N | TASK-id> finalize-local --family <analysis|plan|code> --artifact <artifact> [--recovery-id <id>]\n\nInspect, initialize, or finalize a workflow artifact without changing task state.\n`;
17
5
 
18
- const USAGE = `Usage: agent-infra-internal task-artifact <N | TASK-id> inspect --family <family>\n agent-infra-internal task-artifact <N | TASK-id> init --family <family> --artifact <artifact> [--locale <zh-CN|en>]\n agent-infra-internal task-artifact <N | TASK-id> repair --family <family> --artifact <artifact> --expected-sha256 <sha256> --expected-semantic-digest <digest>\n agent-infra-internal task-artifact <N | TASK-id> finalize-local --family <analysis|plan|code> --artifact <artifact>\n\nInspect, initialize, repair, or finalize a workflow artifact without changing task state.\n`;
19
-
20
- function failUsage(message: string): void {
21
- process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'ARTIFACT_PAYLOAD_INVALID', message } })}\n`);
22
- process.stderr.write(USAGE);
23
- process.exitCode = 2;
24
- }
25
-
26
- function hasOpenLocalArtifactRound(taskDir: string, family: string, round: number): boolean {
27
- try {
28
- const activity = locateActivityLog(fs.readFileSync(path.join(taskDir, 'task.md'), 'utf8'));
29
- if (!activity) return false;
30
- const label = family === 'analysis'
31
- ? 'Analyze Task'
32
- : family === 'review-analysis'
33
- ? 'Review Analysis'
34
- : family === 'plan'
35
- ? 'Plan Task'
36
- : family === 'review-plan'
37
- ? 'Review Plan'
38
- : family === 'code'
39
- ? 'Code Task'
40
- : 'Review Code';
41
- const qualifier = family === 'code'
42
- ? '(?:, (?:fix for review-code(?:-r\\d+)?\\.md|decision II-[1-9]\\d*))?'
43
- : '';
44
- const expected = new RegExp(`^${label} \\(Round ${round}${qualifier}\\)$`);
45
- return startedBackedRows(pairEntries(activity.entries)).some((row) => expected.test(row.step) && !row.done);
46
- } catch {
47
- return false;
48
- }
49
- }
50
6
 
51
7
  function taskArtifact(args: string[] = []): void {
52
8
  if (!ensureInternalHandlerRoute('task-artifact', args)) return;
53
9
  if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
54
- if (args.length < 2) { failUsage('task ref and operation are required'); return; }
55
- const operation = args[1];
56
- if (!internalHandlerRoute('task-artifact', 'inspect', operation ?? '')
57
- && !internalHandlerRoute('task-artifact', 'init', operation ?? '')
58
- && !internalHandlerRoute('task-artifact', 'repair', operation ?? '')
59
- && !internalHandlerRoute('task-artifact', 'finalize-local', operation ?? '')) { failUsage(`unknown operation '${operation}'`); return; }
60
- let family = '';
61
- let artifact = '';
62
- let locale: 'zh-CN' | 'en' | undefined;
63
- let expectedSha256 = '';
64
- let expectedSemanticDigest = '';
65
- const seen = new Set<string>();
66
- for (let index = 2; index < args.length; index += 1) {
67
- const flag = args[index]!;
68
- if (flag !== '--family' && flag !== '--artifact' && flag !== '--locale' && flag !== '--expected-sha256' && flag !== '--expected-semantic-digest') { failUsage(`unknown option '${flag}'`); return; }
69
- if (seen.has(flag)) { failUsage(`duplicate option '${flag}'`); return; }
70
- const value = args[++index];
71
- if (!value || value.startsWith('--')) { failUsage(`option '${flag}' requires a value`); return; }
72
- seen.add(flag);
73
- if (flag === '--family') family = value;
74
- else if (flag === '--artifact') artifact = value;
75
- else if (flag === '--locale') {
76
- if (value !== 'zh-CN' && value !== 'en') { failUsage("option '--locale' must be 'zh-CN' or 'en'"); return; }
77
- locale = value;
78
- } else if (flag === '--expected-sha256') expectedSha256 = value;
79
- else expectedSemanticDigest = value;
80
- }
81
- if (!family) { failUsage("option '--family' is required"); return; }
82
- if ((operation === 'init' || operation === 'repair' || operation === 'finalize-local') && !artifact) { failUsage("option '--artifact' is required"); return; }
83
- if (internalHandlerRoute('task-artifact', 'inspect', operation ?? '')) {
84
- if (artifact || locale || expectedSha256 || expectedSemanticDigest) { failUsage("artifact options are only valid for init, repair, or finalize-local"); return; }
85
- const result = resolveArtifactContext(args[0]!, family);
86
- const output = family === 'code' && result.codeMode ? {
87
- ...result,
88
- mode: result.codeMode.mode,
89
- code_max: result.codeMode.codeMax,
90
- rev_max: result.codeMode.reviewMax,
91
- verdict: result.codeMode.verdict,
92
- next_round: result.next?.round ?? null,
93
- next_artifact: result.next?.name ?? null,
94
- review_artifact: result.codeMode.reviewArtifact,
95
- implementation_input: result.codeMode.implementationInput,
96
- decision_id: result.codeMode.decisionId,
97
- decision_evidence: result.codeMode.decisionEvidence,
98
- message: result.codeMode.message
99
- } : result;
100
- process.stdout.write(`${JSON.stringify(output)}\n`);
101
- if (result.status === 'refused') process.exitCode = 1;
102
- else if (result.status === 'failed') process.exitCode = 2;
103
- return;
104
- }
105
- if (internalHandlerRoute('task-artifact', 'init', operation ?? '')) {
106
- if (expectedSha256 || expectedSemanticDigest) { failUsage("repair baseline options are only valid for repair"); return; }
107
- const schema = getArtifactSchema(family);
108
- const resolved = resolveTaskRef(args[0]!);
109
- if (!schema) { failUsage(`init does not support artifact family '${family}'`); return; }
110
- if (!resolved.ok) {
111
- process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: resolved.code, message: resolved.message } })}\n`);
112
- process.exitCode = 1;
113
- return;
114
- }
115
- const parsed = parseArtifactName(artifact);
116
- if (!parsed || parsed.family !== family) {
117
- process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'ARTIFACT_INIT_CONTEXT_INVALID', message: `artifact '${artifact}' does not match ${family}` } })}\n`);
118
- process.exitCode = 1;
119
- return;
120
- }
121
- const context = resolveArtifactContext(args[0]!, family);
122
- const isNextArtifact = context.status === 'ready' && context.next?.name === artifact;
123
- const isCurrentOpenArtifact = context.status === 'ready'
124
- && context.taskDir !== null
125
- && hasOpenLocalArtifactRound(context.taskDir, family, parsed.round);
126
- if (!isNextArtifact && !isCurrentOpenArtifact) {
127
- process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'ARTIFACT_INIT_CONTEXT_INVALID', message: context.error?.message ?? `artifact '${artifact}' is not the next ${family} artifact` } })}\n`);
128
- process.exitCode = 1;
129
- return;
130
- }
131
- if (!context.taskId || !context.taskDir) {
132
- process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'ARTIFACT_INIT_CONTEXT_INVALID', message: `artifact '${artifact}' does not match ${family}` } })}\n`);
133
- process.exitCode = 1;
134
- return;
135
- }
136
- try {
137
- const existing = fs.lstatSync(path.join(resolved.taskDir, artifact));
138
- if (existing.isSymbolicLink() || !existing.isFile()) {
139
- process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'ARTIFACT_INIT_TARGET_INVALID', message: 'artifact target is not a regular file' } })}\n`);
140
- process.exitCode = 1;
141
- return;
142
- }
143
- const result = initializeArtifactSkeleton({ repoRoot: resolved.repoRoot, taskId: resolved.taskId, taskDir: resolved.taskDir, family: schema.family, artifact, ...(locale ? { locale } : {}) });
144
- process.stdout.write(`${JSON.stringify({ ...result, taskId: resolved.taskId, taskDir: resolved.taskDir, family, artifact })}\n`);
145
- if (result.status === 'failed') process.exitCode = 1;
146
- return;
147
- } catch (error) {
148
- if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
149
- process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'ARTIFACT_INIT_TARGET_INVALID', message: String(error) } })}\n`);
150
- process.exitCode = 1;
151
- return;
152
- }
153
- }
154
- const result = initializeArtifactSkeleton({
155
- repoRoot: resolved.repoRoot,
156
- taskId: context.taskId,
157
- taskDir: context.taskDir,
158
- family: schema.family,
159
- artifact,
160
- ...(locale ? { locale } : {})
161
- });
162
- process.stdout.write(`${JSON.stringify({ ...result, taskId: context.taskId, taskDir: context.taskDir, family, artifact })}\n`);
163
- if (result.status === 'failed') process.exitCode = 1;
164
- return;
165
- }
166
- if (internalHandlerRoute('task-artifact', 'repair', operation ?? '')) {
167
- if (locale) { failUsage("option '--locale' is only valid for init"); return; }
168
- if (!/^[a-f0-9]{64}$/.test(expectedSha256) || !/^[a-f0-9]{64}$/.test(expectedSemanticDigest)) {
169
- failUsage("repair requires lowercase 64-character '--expected-sha256' and '--expected-semantic-digest'");
170
- return;
171
- }
172
- const schema = getArtifactSchema(family);
173
- const resolved = resolveTaskRef(args[0]!);
174
- const parsed = parseArtifactName(artifact);
175
- if (!schema || !parsed || parsed.family !== family) {
176
- process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'ARTIFACT_REPAIR_TARGET_INVALID', message: `artifact '${artifact}' does not match ${family}` } })}\n`);
177
- process.exitCode = 1;
178
- return;
179
- }
180
- if (!resolved.ok) {
181
- process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: resolved.code, message: resolved.message } })}\n`);
182
- process.exitCode = 1;
183
- return;
184
- }
185
- let content: string;
186
- try { content = fs.readFileSync(path.join(resolved.taskDir, artifact), 'utf8'); }
187
- catch (error) {
188
- process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'ARTIFACT_REPAIR_TARGET_INVALID', message: String(error) } })}\n`);
189
- process.exitCode = 1;
190
- return;
191
- }
192
- const inspection = inspectArtifactStructure(content, schema);
193
- if (!inspection.repair) {
194
- process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, artifact, family, diagnostics: inspection.diagnostics, error: { code: 'ARTIFACT_REPAIR_UNSAFE', message: inspection.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ') || 'no deterministic structural repair is available' } })}\n`);
195
- process.exitCode = 1;
196
- return;
197
- }
198
- const result = applyArtifactRepair({
199
- repoRoot: resolved.repoRoot,
200
- taskId: resolved.taskId,
201
- taskDir: resolved.taskDir,
202
- family: schema.family,
203
- artifact,
204
- expectedSha256,
205
- expectedSemanticDigest,
206
- operation: inspection.repair
207
- });
208
- process.stdout.write(`${JSON.stringify({ ...result, taskId: resolved.taskId, taskDir: resolved.taskDir, family, artifact })}\n`);
209
- if (result.status === 'failed') process.exitCode = 1;
210
- return;
211
- }
212
- const resolved = resolveTaskRef(args[0]!);
213
- const repositoryRoot = resolved.ok ? resolved.repoRoot : process.cwd();
214
- if (!artifact) { failUsage("option '--artifact' is required"); return; }
215
- if (family !== 'analysis' && family !== 'plan' && family !== 'code') {
216
- failUsage("finalize-local only supports 'analysis', 'plan', and 'code'");
10
+ let command;
11
+ try { command = parseArtifactCommand(args); }
12
+ catch (error) {
13
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: {
14
+ code: 'ARTIFACT_PAYLOAD_INVALID', message: error instanceof Error ? error.message : String(error)
15
+ } })}\n`);
16
+ process.stderr.write(USAGE);
17
+ process.exitCode = 2;
217
18
  return;
218
19
  }
219
- const result = finalizeLocalArtifact({
220
- taskRef: args[0]!,
221
- family: family as LocalArtifactFamily,
222
- artifact,
223
- repoRoot: repositoryRoot
224
- });
20
+ const result = executeArtifactCommand(command);
225
21
  process.stdout.write(`${JSON.stringify(result)}\n`);
226
- if (result.status === 'failed') process.exitCode = 1;
22
+ if (result.status === 'refused') process.exitCode = 1;
23
+ else if (result.status === 'failed') process.exitCode = command.operation === 'inspect' ? 2 : 1;
227
24
  }
228
25
 
229
26
  export { taskArtifact };
@@ -1,8 +1,8 @@
1
1
  import fs from 'node:fs';
2
+ import { resolveSandboxControlTransport } from './task-operation-registry.ts';
2
3
  import path from 'node:path';
3
4
 
4
5
  import {
5
- classifySandboxControlEnvironment,
6
6
  requestSandboxTaskCreate,
7
7
  SandboxControlClientError
8
8
  } from '../sandbox/control/client.ts';
@@ -83,12 +83,12 @@ async function taskCreate(args: string[]): Promise<void> {
83
83
  if (!stat.isFile() || stat.isSymbolicLink()) throw new Error('TASK_CREATE_INPUT_INVALID: input must be a regular file');
84
84
  if (stat.size > SANDBOX_CONTROL_MAX_BYTES) throw new Error('TASK_CREATE_INPUT_TOO_LARGE: input exceeds the control limit');
85
85
  const candidate = validateTaskCreateCandidate(JSON.parse(fs.readFileSync(inputPath, 'utf8')));
86
- const environment = classifySandboxControlEnvironment();
87
- if (environment.kind === 'invalid') {
88
- output(failed(environment.code ?? 'TASK_CONTROL_TRANSPORT_INVALID', environment.message ?? 'sandbox client control configuration is invalid'));
86
+ const environment = resolveSandboxControlTransport();
87
+ if (environment.kind === 'fail-closed') {
88
+ output(failed(environment.reasonCode ?? 'TASK_CONTROL_TRANSPORT_INVALID', 'sandbox client control configuration is invalid'));
89
89
  return;
90
90
  }
91
- if (environment.kind === 'controlled') {
91
+ if (environment.kind === 'broker-client') {
92
92
  const response = requestSandboxTaskCreate({ candidate });
93
93
  if (response.phase === 'rejected') {
94
94
  const accepted = response.error?.code === 'SANDBOX_CONTROL_RESULT_UNKNOWN';
@@ -21,6 +21,7 @@ const FLAGS: Record<string, keyof TaskEventRequest> = {
21
21
  '--verdict': 'verdict', '--blockers': 'blockers', '--major': 'major',
22
22
  '--minor': 'minor', '--manual-validation': 'manualValidation', '--files-modified': 'filesModified',
23
23
  '--tests-passed': 'testsPassed', '--summary-result': 'summaryResult',
24
+ '--transaction-id': 'transactionId', '--receipt-digest': 'receiptDigest', '--pr-head-sha': 'prHeadSha',
24
25
  '--override-ticket': 'overrideTicket', '--override-target': 'overrideTarget', '--override-scope': 'overrideScope'
25
26
  };
26
27
  const NUMERIC = new Set(['round', 'question', 'blockers', 'major', 'minor', 'manualValidation', 'filesModified', 'testsPassed']);
@@ -31,37 +32,45 @@ function usageFailure(message: string): void {
31
32
  process.exitCode = 1;
32
33
  }
33
34
 
34
- async function taskEvent(args: string[] = []): Promise<void> {
35
- if (!ensureInternalHandlerRoute('task-event', args)) return;
36
- if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
37
- if (args.length < 2 || !internalHandlerRoute('task-event', 'event', args[1] ? 'event' : '')) { usageFailure('task ref and event are required'); return; }
35
+ export function parseTaskEventRequest(args: readonly string[]): TaskEventRequest {
36
+ if (args.length < 2) throw new Error('task ref and event are required');
38
37
  const request: TaskEventRequest = { taskRef: args[0]!, event: args[1]!, agent: '' };
39
38
  const seen = new Set<string>();
40
39
  for (let index = 2; index < args.length; index += 1) {
41
40
  const flag = args[index]!;
42
41
  if (flag === '--orchestrated') {
43
- if (seen.has(flag)) { usageFailure(`duplicate option '${flag}'`); return; }
42
+ if (seen.has(flag)) throw new Error(`duplicate option '${flag}'`);
44
43
  seen.add(flag); request.orchestrated = true; continue;
45
44
  }
46
45
  if (flag === '--dry-run') {
47
- if (seen.has(flag)) { usageFailure(`duplicate option '${flag}'`); return; }
46
+ if (seen.has(flag)) throw new Error(`duplicate option '${flag}'`);
48
47
  seen.add(flag); request.dryRun = true; continue;
49
48
  }
50
49
  const key = FLAGS[flag];
51
- if (!key) { usageFailure(`unknown option '${flag}'`); return; }
52
- if (seen.has(flag)) { usageFailure(`duplicate option '${flag}'`); return; }
50
+ if (!key) throw new Error(`unknown option '${flag}'`);
51
+ if (seen.has(flag)) throw new Error(`duplicate option '${flag}'`);
53
52
  const value = args[++index];
54
- if (value === undefined || value.startsWith('--')) { usageFailure(`option '${flag}' requires a value`); return; }
53
+ if (value === undefined || value.startsWith('--')) throw new Error(`option '${flag}' requires a value`);
55
54
  seen.add(flag);
56
55
  if (NUMERIC.has(key)) (request as Record<string, unknown>)[key] = Number(value);
57
56
  else if (key === 'verdict') request.verdict = value as Verdict;
58
57
  else (request as Record<string, unknown>)[key] = value;
59
58
  }
60
59
  const agent = normalizeAgentToken(String(request.agent ?? ''));
61
- if (!agent) { usageFailure(`invalid --agent '${request.agent}': ${AGENT_USAGE_HINT}`); return; }
60
+ if (!agent) throw new Error(`invalid --agent '${request.agent}': ${AGENT_USAGE_HINT}`);
62
61
  request.agent = agent;
63
62
  const dryRunConflict = overrideDryRunConflict(request as unknown as Record<string, unknown>);
64
- if (dryRunConflict) { usageFailure(dryRunConflict.message); return; }
63
+ if (dryRunConflict) throw new Error(dryRunConflict.message);
64
+ return request;
65
+ }
66
+
67
+ async function taskEvent(args: string[] = []): Promise<void> {
68
+ if (!ensureInternalHandlerRoute('task-event', args)) return;
69
+ if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
70
+ if (!internalHandlerRoute('task-event', 'event', args[1] ? 'event' : '')) { usageFailure('task ref and event are required'); return; }
71
+ let request: TaskEventRequest;
72
+ try { request = parseTaskEventRequest(args); }
73
+ catch (error) { usageFailure(error instanceof Error ? error.message : String(error)); return; }
65
74
  const resolved = resolveTaskRef(request.taskRef);
66
75
  if (!resolved.ok) {
67
76
  process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: resolved.code, message: resolved.message } })}\n`);
@@ -7,9 +7,10 @@ import {
7
7
  import { lifecycleIntentCatalog } from '../task/lifecycle.ts';
8
8
  import { detectRepoRoot, resolveTaskRef } from '../task/resolve-ref.ts';
9
9
  import type { TaskLifecycleResult } from '../task/lifecycle.ts';
10
+ import type { LifecycleRecoveryResult } from '../task/lifecycle-recovery.ts';
10
11
  import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
11
12
 
12
- 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`;
13
+ const USAGE = `Usage: agent-infra-internal task-lifecycle <N | TASK-id> <intent> --agent <agent> [intent flags] [--dry-run]\n\nIntents: ${lifecycleIntentCatalog.join(', ')}\nrecover-started: --stage <stage> --round <round> --artifact <artifact> --reason <reason>\nOverride: --override-ticket <ticket> --override-target <target> --override-scope <scope>\n`;
13
14
 
14
15
  function usageFailure(message: string): void {
15
16
  process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'LIFECYCLE_PAYLOAD_INVALID', message } })}\n`);
@@ -61,9 +62,9 @@ async function taskLifecycle(args: string[] = []): Promise<void> {
61
62
  const result = await dispatchTaskControlOperation(
62
63
  createDirectHostExecutionContext({ repoRoot }),
63
64
  operation
64
- ) as TaskLifecycleResult & { humanOverride?: unknown };
65
+ ) as (TaskLifecycleResult | LifecycleRecoveryResult) & { humanOverride?: unknown };
65
66
  process.stdout.write(`${JSON.stringify(result)}\n`);
66
- if (result.status === 'failed') process.exitCode = 1;
67
+ if (result.status === 'failed' || result.status === 'owner-unknown' || result.status === 'conflict') process.exitCode = 1;
67
68
  }
68
69
 
69
70
  export { taskLifecycle };