@fitlab-ai/agent-infra 0.9.9 → 0.9.11

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 (309) hide show
  1. package/README.md +13 -3
  2. package/README.zh-CN.md +13 -3
  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 +17 -10
  8. package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-context.js +11 -31
  9. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +15 -33
  10. package/dist/lib/agent-clients/adapters/codex-sandbox.js +72 -11
  11. package/dist/lib/agent-clients/adapters/index.js +3 -1
  12. package/dist/lib/agent-clients/adapters/opencode-sandbox.js +0 -4
  13. package/dist/lib/agent-clients/adapters/traecli.js +65 -0
  14. package/dist/lib/agent-clients/config.js +14 -99
  15. package/dist/lib/agent-clients/reconcile.js +1 -11
  16. package/dist/lib/agent-clients/schema.js +5 -4
  17. package/dist/lib/agent-clients/tokens.js +7 -17
  18. package/dist/lib/agent-clients/types.js +2 -1
  19. package/dist/lib/decide.js +14 -30
  20. package/dist/lib/defaults.json +9 -0
  21. package/dist/lib/init.js +2 -2
  22. package/dist/lib/internal/codex-lifecycle.js +2 -2
  23. package/dist/lib/internal/codex-sandbox-controller.js +4 -3
  24. package/dist/lib/internal/release-workflow.js +0 -1
  25. package/dist/lib/internal/sandbox-control.js +2 -2
  26. package/dist/lib/internal/task-finalization.js +19 -9
  27. package/dist/lib/internal/task-ledger.js +8 -2
  28. package/dist/lib/internal/task-lifecycle.js +17 -93
  29. package/dist/lib/internal/task-orchestration.js +30 -216
  30. package/dist/lib/{task/commands/validate.js → internal/task-validate.js} +77 -43
  31. package/dist/lib/merge.js +205 -103
  32. package/dist/lib/process-data/normalize.js +2 -9
  33. package/dist/lib/run/host.js +46 -16
  34. package/dist/lib/run/tui.js +5 -2
  35. package/dist/lib/sandbox/agent-client-reconciler.js +4 -12
  36. package/dist/lib/sandbox/commands/create.js +3 -3
  37. package/dist/lib/sandbox/commands/enter.js +18 -4
  38. package/dist/lib/sandbox/config.js +3 -12
  39. package/dist/lib/sandbox/control/controller-registration.js +4 -2
  40. package/dist/lib/sandbox/control/executor.js +135 -40
  41. package/dist/lib/sandbox/control/lifecycle.js +29 -20
  42. package/dist/lib/sandbox/control/server.js +18 -16
  43. package/dist/lib/sandbox/mounts.js +3 -2
  44. package/dist/lib/sandbox/recovery.js +123 -22
  45. package/dist/lib/sandbox/workspace-identity.js +14 -0
  46. package/dist/lib/sandbox/workspace-view.js +8 -9
  47. package/dist/lib/self-update.js +278 -0
  48. package/dist/lib/server/protocol.js +5 -5
  49. package/dist/lib/task/activity-log.js +4 -1
  50. package/dist/lib/task/artifact-lifecycle.js +4 -2
  51. package/dist/lib/task/codex-orchestration.js +32 -35
  52. package/dist/lib/task/command-options.js +1 -3
  53. package/dist/lib/task/commands/cat.js +0 -5
  54. package/dist/lib/task/commands/decisions.js +76 -92
  55. package/dist/lib/task/commands/files.js +6 -6
  56. package/dist/lib/task/commands/grep.js +25 -61
  57. package/dist/lib/task/commands/issue-body.js +6 -6
  58. package/dist/lib/task/commands/log.js +25 -10
  59. package/dist/lib/task/commands/show.js +5 -6
  60. package/dist/lib/task/commands/status.js +8 -8
  61. package/dist/lib/task/commit-operation.js +21 -25
  62. package/dist/lib/task/commit-policy.js +1 -1
  63. package/dist/lib/task/control-authority.js +431 -0
  64. package/dist/lib/task/create.js +6 -1
  65. package/dist/lib/task/current-contract.js +35 -0
  66. package/dist/lib/task/decision-details.js +263 -0
  67. package/dist/lib/task/decision-intents.js +5 -2
  68. package/dist/lib/task/delegation-receipts.js +8 -7
  69. package/dist/lib/task/events.js +11 -5
  70. package/dist/lib/task/finalization.js +72 -46
  71. package/dist/lib/task/index.js +19 -29
  72. package/dist/lib/task/ledger-intents.js +8 -9
  73. package/dist/lib/task/ledger.js +13 -6
  74. package/dist/lib/task/lifecycle.js +16 -0
  75. package/dist/lib/task/orchestration.js +51 -14
  76. package/dist/lib/task/review-artifacts.js +31 -12
  77. package/dist/lib/task/review-finalization.js +19 -6
  78. package/dist/lib/task/verification-engine.js +38 -18
  79. package/dist/lib/task/verification-review.js +1 -1
  80. package/dist/lib/task/workspace-snapshot.js +5 -11
  81. package/dist/lib/task/write.js +11 -1
  82. package/dist/lib/update.js +6 -37
  83. package/dist/lib/version.js +5 -1
  84. package/dist/lifecycle-build-manifest.json +3 -3
  85. package/lib/agent-client.ts +0 -1
  86. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +25 -10
  87. package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +16 -33
  88. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +16 -35
  89. package/lib/agent-clients/adapters/codex-sandbox.ts +89 -14
  90. package/lib/agent-clients/adapters/index.ts +3 -1
  91. package/lib/agent-clients/adapters/opencode-sandbox.ts +0 -5
  92. package/lib/agent-clients/adapters/traecli.ts +66 -0
  93. package/lib/agent-clients/config.ts +14 -144
  94. package/lib/agent-clients/reconcile.ts +1 -12
  95. package/lib/agent-clients/schema.ts +5 -4
  96. package/lib/agent-clients/tokens.ts +7 -20
  97. package/lib/agent-clients/types.ts +2 -1
  98. package/lib/decide.ts +12 -22
  99. package/lib/defaults.json +9 -0
  100. package/lib/init.ts +2 -2
  101. package/lib/internal/codex-lifecycle.ts +2 -2
  102. package/lib/internal/codex-sandbox-controller.ts +4 -3
  103. package/lib/internal/release-workflow.ts +0 -1
  104. package/lib/internal/sandbox-control.ts +2 -2
  105. package/lib/internal/task-finalization.ts +27 -13
  106. package/lib/internal/task-ledger.ts +8 -2
  107. package/lib/internal/task-lifecycle.ts +33 -76
  108. package/lib/internal/task-orchestration.ts +33 -190
  109. package/lib/{task/commands/validate.ts → internal/task-validate.ts} +77 -41
  110. package/lib/merge.ts +236 -120
  111. package/lib/process-data/normalize.ts +2 -8
  112. package/lib/run/host.ts +63 -14
  113. package/lib/run/tui.ts +5 -3
  114. package/lib/sandbox/agent-client-reconciler.ts +5 -15
  115. package/lib/sandbox/commands/create.ts +4 -4
  116. package/lib/sandbox/commands/enter.ts +24 -4
  117. package/lib/sandbox/config.ts +2 -14
  118. package/lib/sandbox/control/container-identity.ts +2 -2
  119. package/lib/sandbox/control/controller-registration.ts +8 -3
  120. package/lib/sandbox/control/executor.ts +156 -53
  121. package/lib/sandbox/control/lifecycle.ts +34 -28
  122. package/lib/sandbox/control/protocol.ts +1 -3
  123. package/lib/sandbox/control/server.ts +15 -12
  124. package/lib/sandbox/control/state.ts +7 -7
  125. package/lib/sandbox/mounts.ts +4 -3
  126. package/lib/sandbox/recovery.ts +162 -34
  127. package/lib/sandbox/tools.ts +1 -1
  128. package/lib/sandbox/workspace-identity.ts +28 -0
  129. package/lib/sandbox/workspace-view.ts +14 -10
  130. package/lib/self-update.ts +341 -0
  131. package/lib/server/protocol.ts +5 -5
  132. package/lib/task/activity-log.ts +6 -1
  133. package/lib/task/artifact-lifecycle.ts +5 -3
  134. package/lib/task/codex-orchestration.ts +40 -45
  135. package/lib/task/command-options.ts +1 -2
  136. package/lib/task/commands/cat.ts +0 -4
  137. package/lib/task/commands/decisions.ts +80 -75
  138. package/lib/task/commands/files.ts +6 -6
  139. package/lib/task/commands/grep.ts +23 -51
  140. package/lib/task/commands/issue-body.ts +6 -6
  141. package/lib/task/commands/log.ts +22 -10
  142. package/lib/task/commands/show.ts +5 -6
  143. package/lib/task/commands/status.ts +8 -8
  144. package/lib/task/commit-operation.ts +25 -30
  145. package/lib/task/commit-policy.ts +1 -2
  146. package/lib/task/control-authority.ts +563 -0
  147. package/lib/task/create.ts +6 -1
  148. package/lib/task/current-contract.ts +49 -0
  149. package/lib/task/decision-details.ts +340 -0
  150. package/lib/task/decision-intents.ts +7 -2
  151. package/lib/task/delegation-receipts.ts +8 -6
  152. package/lib/task/events.ts +10 -5
  153. package/lib/task/finalization.ts +84 -42
  154. package/lib/task/index.ts +19 -28
  155. package/lib/task/ledger-intents.ts +6 -8
  156. package/lib/task/ledger.ts +17 -7
  157. package/lib/task/lifecycle.ts +20 -0
  158. package/lib/task/orchestration.ts +42 -16
  159. package/lib/task/review-artifacts.ts +53 -15
  160. package/lib/task/review-finalization.ts +33 -7
  161. package/lib/task/verification-engine.ts +33 -21
  162. package/lib/task/verification-review.ts +1 -1
  163. package/lib/task/workspace-snapshot.ts +4 -13
  164. package/lib/task/write.ts +20 -1
  165. package/lib/update.ts +6 -40
  166. package/lib/version.ts +6 -1
  167. package/package.json +1 -1
  168. package/templates/.agents/QUICKSTART.en.md +2 -3
  169. package/templates/.agents/QUICKSTART.zh-CN.md +2 -3
  170. package/templates/.agents/README.en.md +5 -3
  171. package/templates/.agents/README.zh-CN.md +5 -3
  172. package/templates/.agents/rules/README.en.md +1 -0
  173. package/templates/.agents/rules/README.zh-CN.md +1 -0
  174. package/templates/.agents/rules/compatibility-policy.en.md +40 -0
  175. package/templates/.agents/rules/compatibility-policy.zh-CN.md +40 -0
  176. package/templates/.agents/rules/create-issue.github.en.md +1 -1
  177. package/templates/.agents/rules/create-issue.github.zh-CN.md +1 -1
  178. package/templates/.agents/rules/human-decision-context.en.md +9 -7
  179. package/templates/.agents/rules/human-decision-context.zh-CN.md +9 -7
  180. package/templates/.agents/rules/issue-fields.github.en.md +1 -1
  181. package/templates/.agents/rules/issue-fields.github.zh-CN.md +1 -1
  182. package/templates/.agents/rules/issue-pr-commands.en.md +1 -1
  183. package/templates/.agents/rules/issue-pr-commands.github.en.md +1 -1
  184. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +1 -1
  185. package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
  186. package/templates/.agents/rules/issue-sync.github.en.md +1 -1
  187. package/templates/.agents/rules/issue-sync.github.zh-CN.md +2 -2
  188. package/templates/.agents/rules/lifecycle-orchestration.en.md +4 -4
  189. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +4 -4
  190. package/templates/.agents/rules/milestone-inference.github.en.md +1 -1
  191. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +1 -1
  192. package/templates/.agents/rules/next-step-output.en.md +3 -3
  193. package/templates/.agents/rules/next-step-output.zh-CN.md +3 -3
  194. package/templates/.agents/rules/no-mid-flow-questions.en.md +1 -1
  195. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +1 -1
  196. package/templates/.agents/rules/pr-sync.en.md +2 -2
  197. package/templates/.agents/rules/pr-sync.github.en.md +3 -2
  198. package/templates/.agents/rules/pr-sync.github.zh-CN.md +3 -1
  199. package/templates/.agents/rules/pr-sync.zh-CN.md +2 -1
  200. package/templates/.agents/rules/release-commands.github.en.md +6 -0
  201. package/templates/.agents/rules/release-commands.github.zh-CN.md +6 -0
  202. package/templates/.agents/rules/review-handshake.en.md +1 -1
  203. package/templates/.agents/rules/review-handshake.zh-CN.md +1 -1
  204. package/templates/.agents/rules/review-method.en.md +1 -0
  205. package/templates/.agents/rules/review-method.zh-CN.md +1 -0
  206. package/templates/.agents/rules/task-management.en.md +1 -2
  207. package/templates/.agents/rules/task-management.zh-CN.md +1 -2
  208. package/templates/.agents/skills/analyze-task/SKILL.en.md +4 -3
  209. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +4 -3
  210. package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
  211. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
  212. package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
  213. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
  214. package/templates/.agents/skills/check-task/SKILL.en.md +2 -2
  215. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +2 -2
  216. package/templates/.agents/skills/close-codescan/SKILL.en.md +1 -1
  217. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +1 -1
  218. package/templates/.agents/skills/close-dependabot/SKILL.en.md +1 -1
  219. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +1 -1
  220. package/templates/.agents/skills/code-task/SKILL.en.md +4 -3
  221. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +5 -3
  222. package/templates/.agents/skills/commit/SKILL.en.md +27 -7
  223. package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -4
  224. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +5 -5
  225. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +5 -5
  226. package/templates/.agents/skills/complete-task/SKILL.en.md +3 -3
  227. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
  228. package/templates/.agents/skills/create-pr/SKILL.en.md +15 -11
  229. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +15 -11
  230. package/templates/.agents/skills/create-pr/reference/change-report.en.md +46 -0
  231. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +46 -0
  232. package/templates/.agents/skills/create-pr/scripts/change-report.mjs +203 -0
  233. package/templates/.agents/skills/create-release-note/SKILL.en.md +5 -6
  234. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +5 -6
  235. package/templates/.agents/skills/create-task/SKILL.en.md +1 -1
  236. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -1
  237. package/templates/.agents/skills/import-issue/SKILL.en.md +1 -1
  238. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +1 -1
  239. package/templates/.agents/skills/plan-task/SKILL.en.md +5 -4
  240. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +5 -4
  241. package/templates/.agents/skills/restore-task/SKILL.en.md +1 -1
  242. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +1 -1
  243. package/templates/.agents/skills/review-analysis/SKILL.en.md +5 -3
  244. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +5 -3
  245. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -0
  246. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -0
  247. package/templates/.agents/skills/review-code/SKILL.en.md +5 -3
  248. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -3
  249. package/templates/.agents/skills/review-code/config/verify.en.json +1 -0
  250. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -0
  251. package/templates/.agents/skills/review-code/reference/migration-risks.en.md +9 -6
  252. package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +9 -6
  253. package/templates/.agents/skills/review-plan/SKILL.en.md +5 -3
  254. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +5 -3
  255. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -0
  256. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -0
  257. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +7 -3
  258. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +7 -3
  259. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +1 -1
  260. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +1 -1
  261. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -2
  262. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -2
  263. package/templates/.agents/skills/run-task/SKILL.en.md +6 -2
  264. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +6 -2
  265. package/templates/.agents/skills/run-task/reference/host-validation.en.md +2 -2
  266. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +2 -2
  267. package/templates/.agents/skills/update-agent-infra/SKILL.en.md +2 -2
  268. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +2 -2
  269. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +159 -104
  270. package/templates/.agents/skills/watch-pr/SKILL.en.md +2 -2
  271. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +2 -2
  272. package/templates/.agents/templates/task.en.md +1 -1
  273. package/templates/.agents/templates/task.zh-CN.md +1 -1
  274. package/templates/.claude/commands/analyze-task.en.md +1 -1
  275. package/templates/.claude/commands/analyze-task.zh-CN.md +1 -1
  276. package/templates/.claude/commands/block-task.en.md +1 -1
  277. package/templates/.claude/commands/block-task.zh-CN.md +1 -1
  278. package/templates/.claude/commands/cancel-task.en.md +1 -1
  279. package/templates/.claude/commands/cancel-task.zh-CN.md +1 -1
  280. package/templates/.claude/commands/check-task.en.md +1 -1
  281. package/templates/.claude/commands/check-task.zh-CN.md +1 -1
  282. package/templates/.claude/commands/code-task.en.md +1 -1
  283. package/templates/.claude/commands/code-task.zh-CN.md +1 -1
  284. package/templates/.claude/commands/commit.en.md +1 -1
  285. package/templates/.claude/commands/commit.zh-CN.md +1 -1
  286. package/templates/.claude/commands/complete-manual-validation.en.md +1 -1
  287. package/templates/.claude/commands/complete-manual-validation.zh-CN.md +1 -1
  288. package/templates/.claude/commands/complete-task.en.md +1 -1
  289. package/templates/.claude/commands/complete-task.zh-CN.md +1 -1
  290. package/templates/.claude/commands/create-pr.en.md +1 -1
  291. package/templates/.claude/commands/create-pr.zh-CN.md +1 -1
  292. package/templates/.claude/commands/plan-task.en.md +1 -1
  293. package/templates/.claude/commands/plan-task.zh-CN.md +1 -1
  294. package/templates/.claude/commands/review-analysis.en.md +1 -1
  295. package/templates/.claude/commands/review-analysis.zh-CN.md +1 -1
  296. package/templates/.claude/commands/review-code.en.md +1 -1
  297. package/templates/.claude/commands/review-code.zh-CN.md +1 -1
  298. package/templates/.claude/commands/review-plan.en.md +1 -1
  299. package/templates/.claude/commands/review-plan.zh-CN.md +1 -1
  300. package/templates/.claude/commands/run-manual-validation.en.md +1 -1
  301. package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
  302. package/templates/.claude/commands/run-task.en.md +1 -1
  303. package/templates/.claude/commands/run-task.zh-CN.md +1 -1
  304. package/templates/.claude/commands/watch-pr.en.md +1 -1
  305. package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
  306. package/templates/.traecli/commands/update-agent-infra.en.md +7 -0
  307. package/templates/.traecli/commands/update-agent-infra.zh-CN.md +7 -0
  308. package/dist/lib/builtin-tuis.js +0 -40
  309. package/lib/builtin-tuis.ts +0 -56
@@ -0,0 +1,341 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ import { err, info, ok } from './log.ts';
6
+ import { needsShell, resolveCommandFromAbsolutePath } from './run/host.ts';
7
+
8
+ type CommandResult = {
9
+ status: number | null;
10
+ signal?: NodeJS.Signals | null;
11
+ stdout?: string;
12
+ stderr?: string;
13
+ error?: Error;
14
+ };
15
+
16
+ export type SelfUpdateOptions = Readonly<{
17
+ platform?: NodeJS.Platform;
18
+ env?: NodeJS.ProcessEnv;
19
+ argv?: readonly string[];
20
+ run?: (command: readonly string[]) => CommandResult;
21
+ }>;
22
+
23
+ export type UpdateSource = Readonly<{
24
+ kind: 'npm' | 'brew';
25
+ managerPath: string;
26
+ packageRoot: string;
27
+ updateArgs: readonly string[];
28
+ }>;
29
+
30
+ export type UpdateSourceResult = Readonly<{
31
+ source: UpdateSource | null;
32
+ error?: string;
33
+ }>;
34
+
35
+ type PackageInfo = Readonly<{
36
+ root: string;
37
+ name: string;
38
+ }>;
39
+
40
+ function canonicalPath(target: string): string | null {
41
+ try {
42
+ return fs.realpathSync.native(target);
43
+ } catch {
44
+ return null;
45
+ }
46
+ }
47
+
48
+ function comparable(target: string, platform: NodeJS.Platform): string {
49
+ const resolved = path.resolve(target).replaceAll('\\', '/');
50
+ return platform === 'win32' ? resolved.toLowerCase() : resolved;
51
+ }
52
+
53
+ function samePath(left: string, right: string, platform: NodeJS.Platform): boolean {
54
+ return comparable(left, platform) === comparable(right, platform);
55
+ }
56
+
57
+ function isWithin(root: string, target: string, platform: NodeJS.Platform): boolean {
58
+ const normalizedRoot = comparable(root, platform).replace(/\/$/, '');
59
+ const normalizedTarget = comparable(target, platform).replace(/\/$/, '');
60
+ return normalizedTarget === normalizedRoot
61
+ || normalizedTarget.startsWith(`${normalizedRoot}/`);
62
+ }
63
+
64
+ function packageInfoFromRoot(root: string): PackageInfo | null {
65
+ try {
66
+ const packageJson = JSON.parse(
67
+ fs.readFileSync(path.join(root, 'package.json'), 'utf8')
68
+ ) as { name?: unknown };
69
+ return typeof packageJson.name === 'string'
70
+ ? { root, name: packageJson.name }
71
+ : null;
72
+ } catch {
73
+ return null;
74
+ }
75
+ }
76
+
77
+ function findPackageInfo(entry: string, platform: NodeJS.Platform): PackageInfo | null {
78
+ const canonicalEntry = canonicalPath(entry);
79
+ if (!canonicalEntry) return null;
80
+
81
+ let current = path.dirname(canonicalEntry);
82
+ while (true) {
83
+ const canonicalRoot = canonicalPath(current);
84
+ const info = canonicalRoot ? packageInfoFromRoot(canonicalRoot) : null;
85
+ if (info && isWithin(info.root, canonicalEntry, platform)) return info;
86
+ const parent = path.dirname(current);
87
+ if (parent === current) return null;
88
+ current = parent;
89
+ }
90
+ }
91
+
92
+ function packageInfoFromCommand(commandPath: string, platform: NodeJS.Platform): PackageInfo | null {
93
+ const direct = findPackageInfo(commandPath, platform);
94
+ if (direct) return direct;
95
+ if (!/\.(?:cmd|bat)$/i.test(commandPath)) return null;
96
+
97
+ const globalPackageRoot = canonicalPath(path.join(
98
+ path.dirname(commandPath),
99
+ 'node_modules',
100
+ '@fitlab-ai',
101
+ 'agent-infra'
102
+ ));
103
+ return globalPackageRoot ? packageInfoFromRoot(globalPackageRoot) : null;
104
+ }
105
+
106
+ function visibleAliasError(
107
+ packageRoot: string,
108
+ platform: NodeJS.Platform,
109
+ env: NodeJS.ProcessEnv
110
+ ): string | null {
111
+ for (const alias of ['ai', 'agent-infra']) {
112
+ const absolute = resolveCommandFromAbsolutePath(alias, platform, env);
113
+ if (!absolute) continue;
114
+ if (!canonicalPath(absolute)) continue;
115
+ const info = packageInfoFromCommand(absolute, platform);
116
+ if (info && !samePath(info.root, packageRoot, platform)) {
117
+ return `PATH shadowing detected: ${alias} resolves to ${info.root}, not ${packageRoot}.`;
118
+ }
119
+ }
120
+ return null;
121
+ }
122
+
123
+ function resolveManager(
124
+ name: string,
125
+ expectedBasenames: readonly string[],
126
+ platform: NodeJS.Platform,
127
+ env: NodeJS.ProcessEnv
128
+ ): { path: string } | { error: string } | null {
129
+ const absolute = resolveCommandFromAbsolutePath(name, platform, env);
130
+ if (!absolute) {
131
+ return { error: `${name} manager was not found on PATH.` };
132
+ }
133
+ let stat: fs.Stats;
134
+ try {
135
+ stat = fs.statSync(absolute);
136
+ } catch {
137
+ return { error: `Cannot inspect manager executable: ${absolute}.` };
138
+ }
139
+ if (!stat.isFile()) return { error: `Manager executable is not a regular file: ${absolute}.` };
140
+ if (!expectedBasenames.includes(path.basename(absolute).toLowerCase())) {
141
+ return { error: `Unexpected manager executable: ${absolute}.` };
142
+ }
143
+ const canonical = canonicalPath(absolute);
144
+ return canonical ? { path: canonical } : null;
145
+ }
146
+
147
+ function defaultRun(command: readonly string[], platform: NodeJS.Platform): CommandResult {
148
+ const [file, ...args] = command;
149
+ if (!file) return { status: null, error: new Error('run: missing command') };
150
+ const result = spawnSync(file, args, {
151
+ encoding: 'utf8',
152
+ shell: needsShell(file, platform),
153
+ stdio: ['ignore', 'pipe', 'pipe']
154
+ });
155
+ return {
156
+ status: result.status,
157
+ signal: result.signal,
158
+ stdout: result.stdout || '',
159
+ stderr: result.stderr || '',
160
+ error: result.error
161
+ };
162
+ }
163
+
164
+ function runCommand(
165
+ command: readonly string[],
166
+ options: SelfUpdateOptions,
167
+ platform: NodeJS.Platform
168
+ ): CommandResult {
169
+ return options.run ? options.run(command) : defaultRun(command, platform);
170
+ }
171
+
172
+ function probe(
173
+ command: readonly string[],
174
+ options: SelfUpdateOptions,
175
+ platform: NodeJS.Platform,
176
+ label: string
177
+ ): string | { error: string } {
178
+ const result = runCommand(command, options, platform);
179
+ if (result.error) return { error: `${label} failed: ${result.error.message}` };
180
+ if (result.signal) return { error: `${label} terminated by ${result.signal}.` };
181
+ if (result.status !== 0) {
182
+ const detail = result.stderr?.trim();
183
+ return { error: `${label} exited with ${result.status ?? 1}${detail ? `: ${detail}` : '.'}` };
184
+ }
185
+ const output = result.stdout?.trim() || '';
186
+ return output ? output : { error: `${label} returned no path.` };
187
+ }
188
+
189
+ function npmSource(
190
+ packageInfo: PackageInfo,
191
+ options: SelfUpdateOptions,
192
+ platform: NodeJS.Platform,
193
+ env: NodeJS.ProcessEnv
194
+ ): UpdateSource | { error: string } | null {
195
+ const manager = resolveManager(
196
+ 'npm',
197
+ platform === 'win32' ? ['npm.cmd', 'npm.bat'] : ['npm'],
198
+ platform,
199
+ env
200
+ );
201
+ if (!manager) return null;
202
+ if ('error' in manager) return manager;
203
+
204
+ const prefixOutput = probe([manager.path, 'prefix', '--global'], options, platform, 'npm prefix --global');
205
+ if (typeof prefixOutput !== 'string') return prefixOutput;
206
+ const rootOutput = probe([manager.path, 'root', '--global'], options, platform, 'npm root --global');
207
+ if (typeof rootOutput !== 'string') return rootOutput;
208
+ const prefix = canonicalPath(prefixOutput);
209
+ const globalRoot = canonicalPath(rootOutput);
210
+ if (!prefix || !globalRoot) return { error: 'npm global prefix or root is not an existing directory.' };
211
+ if (!isWithin(prefix, globalRoot, platform)) {
212
+ return { error: `npm global root ${globalRoot} is outside prefix ${prefix}.` };
213
+ }
214
+ const expectedPackageRoot = canonicalPath(path.join(globalRoot, '@fitlab-ai', 'agent-infra'));
215
+ if (!expectedPackageRoot || !samePath(expectedPackageRoot, packageInfo.root, platform)) {
216
+ return { error: `Current CLI package is not owned by npm global root ${globalRoot}.` };
217
+ }
218
+ if (packageInfo.name !== '@fitlab-ai/agent-infra') {
219
+ return { error: `Unexpected package name at ${packageInfo.root}: ${packageInfo.name}.` };
220
+ }
221
+ if (platform !== 'win32' && !isWithin(prefix, manager.path, platform)) {
222
+ return { error: `npm manager ${manager.path} is outside global prefix ${prefix}.` };
223
+ }
224
+ return {
225
+ kind: 'npm',
226
+ managerPath: manager.path,
227
+ packageRoot: packageInfo.root,
228
+ updateArgs: ['update', '--global', '@fitlab-ai/agent-infra']
229
+ };
230
+ }
231
+
232
+ function brewSource(
233
+ packageInfo: PackageInfo,
234
+ options: SelfUpdateOptions,
235
+ platform: NodeJS.Platform,
236
+ env: NodeJS.ProcessEnv
237
+ ): UpdateSource | { error: string } | null {
238
+ const manager = resolveManager('brew', ['brew', 'brew.exe', 'brew.cmd'], platform, env);
239
+ if (!manager) return null;
240
+ if ('error' in manager) return manager;
241
+
242
+ const homebrewOutput = probe([manager.path, '--prefix'], options, platform, 'brew --prefix');
243
+ if (typeof homebrewOutput !== 'string') return homebrewOutput;
244
+ const formulaOutput = probe([manager.path, '--prefix', 'agent-infra'], options, platform, 'brew --prefix agent-infra');
245
+ if (typeof formulaOutput !== 'string') return formulaOutput;
246
+ const homebrewRoot = canonicalPath(homebrewOutput);
247
+ const formulaRoot = canonicalPath(formulaOutput);
248
+ if (!homebrewRoot || !formulaRoot) return { error: 'Homebrew prefix is not an existing directory.' };
249
+ if (!isWithin(homebrewRoot, manager.path, platform)) {
250
+ return { error: `brew manager ${manager.path} is outside Homebrew prefix ${homebrewRoot}.` };
251
+ }
252
+ if (!isWithin(homebrewRoot, formulaRoot, platform)) {
253
+ return { error: `agent-infra formula prefix ${formulaRoot} is outside Homebrew prefix ${homebrewRoot}.` };
254
+ }
255
+ if (!isWithin(formulaRoot, packageInfo.root, platform)) {
256
+ return { error: `Current CLI package is outside agent-infra formula prefix ${formulaRoot}.` };
257
+ }
258
+ if (packageInfo.name !== '@fitlab-ai/agent-infra') {
259
+ return { error: `Unexpected package name at ${packageInfo.root}: ${packageInfo.name}.` };
260
+ }
261
+ return {
262
+ kind: 'brew',
263
+ managerPath: manager.path,
264
+ packageRoot: packageInfo.root,
265
+ updateArgs: ['upgrade', 'agent-infra']
266
+ };
267
+ }
268
+
269
+ export function detectUpdateSource(options: SelfUpdateOptions = {}): UpdateSourceResult {
270
+ const platform = options.platform ?? process.platform;
271
+ const env = options.env ?? process.env;
272
+ const entry = options.argv?.[1] ?? process.argv[1];
273
+ if (!entry) return { source: null, error: 'Cannot determine the running CLI entry.' };
274
+ const packageInfo = findPackageInfo(entry, platform);
275
+ if (!packageInfo || packageInfo.name !== '@fitlab-ai/agent-infra') {
276
+ return { source: null, error: 'Running CLI is not a persistent @fitlab-ai/agent-infra package installation.' };
277
+ }
278
+ const aliasError = visibleAliasError(packageInfo.root, platform, env);
279
+ if (aliasError) return { source: null, error: aliasError };
280
+
281
+ const candidates: UpdateSource[] = [];
282
+ const errors: string[] = [];
283
+ for (const candidate of [
284
+ npmSource(packageInfo, options, platform, env),
285
+ brewSource(packageInfo, options, platform, env)
286
+ ]) {
287
+ if (!candidate) continue;
288
+ if ('error' in candidate) errors.push(candidate.error);
289
+ else candidates.push(candidate);
290
+ }
291
+ if (candidates.length === 1) {
292
+ const [source] = candidates;
293
+ if (source) return { source };
294
+ }
295
+ if (candidates.length > 1) return { source: null, error: 'Multiple package managers claim the running CLI; refusing to choose.' };
296
+ return {
297
+ source: null,
298
+ error: errors.length > 0
299
+ ? errors.join(' ')
300
+ : 'No supported persistent npm or Homebrew installation owns the running CLI.'
301
+ };
302
+ }
303
+
304
+ function managerStable(source: UpdateSource, platform: NodeJS.Platform): boolean {
305
+ const current = canonicalPath(source.managerPath);
306
+ return current !== null && samePath(current, source.managerPath, platform);
307
+ }
308
+
309
+ export async function cmdUpdate(options: SelfUpdateOptions = {}): Promise<number> {
310
+ const platform = options.platform ?? process.platform;
311
+ const detected = detectUpdateSource(options);
312
+ if (!detected.source) {
313
+ err(`Cannot update agent-infra CLI: ${detected.error ?? 'unknown source'}`);
314
+ err('Install persistently with "npm install -g @fitlab-ai/agent-infra" or "brew install fitlab-ai/tap/agent-infra".');
315
+ return 1;
316
+ }
317
+
318
+ const source = detected.source;
319
+ if (!managerStable(source, platform)) {
320
+ err(`Cannot update agent-infra CLI: manager path changed: ${source.managerPath}.`);
321
+ return 1;
322
+ }
323
+ info(`Updating agent-infra CLI via ${source.kind}.`);
324
+ const result = runCommand([source.managerPath, ...source.updateArgs], options, platform);
325
+ if (result.error) {
326
+ err(`agent-infra CLI update failed: ${result.error.message}`);
327
+ return 1;
328
+ }
329
+ if (result.signal) {
330
+ err(`agent-infra CLI update terminated by ${result.signal}.`);
331
+ return 1;
332
+ }
333
+ if (result.status !== 0) {
334
+ err(`agent-infra CLI update failed with exit code ${result.status ?? 1}.`);
335
+ const detail = result.stderr?.trim();
336
+ if (detail) err(detail);
337
+ return result.status && result.status > 0 ? result.status : 1;
338
+ }
339
+ ok('agent-infra CLI updated successfully!');
340
+ return 0;
341
+ }
@@ -31,16 +31,16 @@ export function commandHelp(): string {
31
31
  '/sandbox ls',
32
32
  '/sandbox show {ref}',
33
33
  '/sandbox vm status',
34
- '/task decisions [--task {ref}] [--item {selector}]',
35
- '/task log [--task {ref}]',
34
+ '/task decisions [--task {ref} | -t {ref}] [--item {selector} | -i {selector}]',
35
+ '/task log [--task {ref} | -t {ref}]',
36
36
  '/task ls',
37
- '/task show [--task {ref}]',
38
- '/task status [--task {ref}]',
37
+ '/task show [--task {ref} | -t {ref}]',
38
+ '/task status [--task {ref} | -t {ref}]',
39
39
  'Write:',
40
40
  '/sandbox create {ref}',
41
41
  '/sandbox start {ref}',
42
42
  'Exec:',
43
- '/decide [--task {ref}] --item {ordinal|ledger-id} [--needs-implementation true|false] {decision}',
43
+ '/decide [--task {ref} | -t {ref}] (--item {ordinal|ledger-id} | -i {ordinal|ledger-id}) [--needs-implementation true|false] {decision}',
44
44
  '/run create-task {description}',
45
45
  '/run {skill} {task-ref}'
46
46
  ].join('\n');
@@ -89,6 +89,10 @@ function pairEntries(entries: LogEntry[]): StepRow[] {
89
89
  return rows;
90
90
  }
91
91
 
92
+ function startedBackedRows(rows: StepRow[]): StepRow[] {
93
+ return rows.filter((row) => row.started !== '');
94
+ }
95
+
92
96
  export {
93
97
  activityAttempt,
94
98
  appendActivityEntry,
@@ -96,6 +100,7 @@ export {
96
100
  locateActivityLog,
97
101
  pairEntries,
98
102
  parseActivityLog,
99
- parseCommitAttemptStarted
103
+ parseCommitAttemptStarted,
104
+ startedBackedRows
100
105
  };
101
106
  export type { ActivityLogSection, CommitAttempt, LogEntry, StepRow };
@@ -46,7 +46,8 @@ type ArtifactErrorCode =
46
46
  | 'ARTIFACT_TOPOLOGY_CONFLICT' | 'ARTIFACT_INPUT_MISSING'
47
47
  | 'ARTIFACT_REFERENCE_INVALID' | 'ARTIFACT_PATH_INVALID'
48
48
  | 'ARTIFACT_IDENTITY_INVALID' | 'ARTIFACT_NOT_FOUND'
49
- | 'ARTIFACT_NOT_REGULAR' | 'ARTIFACT_NOT_READABLE' | 'ARTIFACT_MODE_REFUSED';
49
+ | 'ARTIFACT_NOT_REGULAR' | 'ARTIFACT_NOT_READABLE' | 'ARTIFACT_VERDICT_INVALID'
50
+ | 'ARTIFACT_MODE_REFUSED';
50
51
  type ArtifactError = { code: ArtifactErrorCode; message: string };
51
52
  type ArtifactInventoryResult = {
52
53
  status: 'ready' | 'failed';
@@ -357,7 +358,7 @@ function resolveCodeContext(inventory: ArtifactInventoryResult, options: Inspect
357
358
  return contextFailure(inventory, 'ARTIFACT_INPUT_MISSING', `latest plan '${plan.latest.name}' requires a matching approved review-plan`);
358
359
  }
359
360
  const verdict = parseVerdict(reviewPlan.latest.path);
360
- if (!verdict.ok) return contextFailure(inventory, 'ARTIFACT_REFERENCE_INVALID', verdict.message, reviewPlan.latest.name);
361
+ if (!verdict.ok) return contextFailure(inventory, 'ARTIFACT_VERDICT_INVALID', `${verdict.code}: ${verdict.message}`, reviewPlan.latest.name);
361
362
  if (verdict.verdict !== 'Approved') {
362
363
  return contextFailure(inventory, 'ARTIFACT_REFERENCE_INVALID', `latest ${reviewPlan.latest.name} is not approved`, reviewPlan.latest.name);
363
364
  }
@@ -373,6 +374,7 @@ function resolveCodeContext(inventory: ArtifactInventoryResult, options: Inspect
373
374
  }
374
375
  if (reviewPlan.latest && reviewPlan.reviewedInput?.name === plan.latest.name) {
375
376
  const verdict = parseVerdict(reviewPlan.latest.path);
377
+ if (!verdict.ok) return contextFailure(inventory, 'ARTIFACT_VERDICT_INVALID', `${verdict.code}: ${verdict.message}`, reviewPlan.latest.name);
376
378
  const reviewedPlanSha256 = sha256File(reviewPlan.reviewedInput.path);
377
379
  if (verdict.ok && verdict.verdict === 'Approved' && (
378
380
  codePlanInput.input.name !== plan.latest.name || codePlanInput.inputSha256 !== reviewedPlanSha256
@@ -388,7 +390,7 @@ function resolveCodeContext(inventory: ArtifactInventoryResult, options: Inspect
388
390
  const review = reviewCode.latest;
389
391
  if (!review) return contextFailure(inventory, 'ARTIFACT_INPUT_MISSING', 'latest review-code artifact is required');
390
392
  const verdict = parseVerdict(review.path);
391
- if (!verdict.ok) return contextFailure(inventory, 'ARTIFACT_REFERENCE_INVALID', verdict.message);
393
+ if (!verdict.ok) return contextFailure(inventory, 'ARTIFACT_VERDICT_INVALID', `${verdict.code}: ${verdict.message}`, review.name);
392
394
  if (verdict.verdict === 'Approved') {
393
395
  const decision = resolveDecisionImplementationInput(inventory, review);
394
396
  if ('error' in decision) return contextFailure(inventory, 'ARTIFACT_REFERENCE_INVALID', decision.error, review.name);
@@ -10,10 +10,16 @@ import {
10
10
  isCodexCapabilityProvenanceDetail
11
11
  } from '../agent-clients/adapters/codex-lifecycle/capability-store.ts';
12
12
  import type { CodexCapabilityProvenanceDetail } from '../agent-clients/adapters/codex-lifecycle/capability-store.ts';
13
- import { computeLifecycleBuildIdentity } from '../agent-clients/adapters/codex-lifecycle/build-identity.ts';
14
- import type { LifecycleBuildIdentity } from '../agent-clients/adapters/codex-lifecycle/build-identity.ts';
15
- import { verifyCodexSandboxControllerContext } from '../agent-clients/adapters/codex-lifecycle/sandbox-controller.ts';
16
- import { verifyCodexSandboxControllerContext as verifyControllerContextFile } from '../agent-clients/adapters/codex-lifecycle/controller-context.ts';
13
+ import {
14
+ computeLifecycleBuildIdentity,
15
+ verifyLifecycleBuildIdentity,
16
+ type LifecycleBuildIdentity,
17
+ type LifecycleIdentityWarning
18
+ } from '../agent-clients/adapters/codex-lifecycle/build-identity.ts';
19
+ import { verifyCodexSandboxControllerContextWithWarnings as verifySandboxControllerWithWarnings } from '../agent-clients/adapters/codex-lifecycle/sandbox-controller.ts';
20
+ import {
21
+ verifyCodexSandboxControllerContextWithWarnings as verifyControllerContextFileWithWarnings
22
+ } from '../agent-clients/adapters/codex-lifecycle/controller-context.ts';
17
23
  import type { AgentClientId } from '../agent-clients/types.ts';
18
24
  import { resolveTaskRef } from './resolve-ref.ts';
19
25
  import {
@@ -39,6 +45,7 @@ type CodexBridgeOptions = Readonly<{
39
45
  capabilityStore?: CapabilityStore;
40
46
  buildIdentity?: LifecycleBuildIdentity;
41
47
  orchestrationOptions?: OrchestrationOptions;
48
+ controllerBinding?: Readonly<{ instanceDigest: string; controlGeneration: string }>;
42
49
  }>;
43
50
 
44
51
  type CodexSpawnIdentity = Readonly<{
@@ -92,35 +99,6 @@ function requiredStore(options: CodexBridgeOptions): LifecycleStore {
92
99
  return options.store;
93
100
  }
94
101
 
95
- function controllerContext(
96
- repoRoot: string,
97
- brokerController: Readonly<{ instanceDigest: string; controlGeneration: string }> | null
98
- ) {
99
- const contextPath = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
100
- if (!contextPath) return null;
101
- if (brokerController) {
102
- return verifyControllerContextFile(contextPath, {
103
- repoRoot,
104
- generation: process.env.AGENT_INFRA_CONTROL_GENERATION ?? brokerController.controlGeneration
105
- });
106
- }
107
- return verifyCodexSandboxControllerContext(contextPath, { repoRoot });
108
- }
109
-
110
- function brokerBindingConflictsWithContext(
111
- repoRoot: string,
112
- brokerController: Readonly<{ instanceDigest: string; controlGeneration: string }> | null
113
- ): boolean {
114
- const contextPath = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
115
- if (!contextPath || !brokerController) return false;
116
- const context = verifyControllerContextFile(contextPath, {
117
- repoRoot,
118
- generation: process.env.AGENT_INFRA_CONTROL_GENERATION ?? brokerController.controlGeneration
119
- });
120
- return context.controllerInstanceDigest !== brokerController.instanceDigest
121
- || context.controlGeneration !== brokerController.controlGeneration;
122
- }
123
-
124
102
  function brokerControllerBinding(): Readonly<{ instanceDigest: string; controlGeneration: string }> | null {
125
103
  const raw = process.env.AGENT_INFRA_CONTROL_CONTROLLER_BINDING;
126
104
  if (!raw) return null;
@@ -165,14 +143,18 @@ async function prepareCodexOrchestrationDelegation(
165
143
  );
166
144
  }
167
145
  const buildIdentity = options.buildIdentity ?? computeLifecycleBuildIdentity(repoRoot);
168
- const brokerController = brokerControllerBinding();
169
- if (brokerBindingConflictsWithContext(repoRoot, brokerController)) {
170
- return bridgeFailure(
171
- 'CODEX_SANDBOX_CONTROLLER_BINDING_MISMATCH',
172
- 'broker and local controller bindings do not match'
173
- );
174
- }
175
- const localController = controllerContext(repoRoot, brokerController);
146
+ const brokerController = options.controllerBinding ?? brokerControllerBinding();
147
+ const contextPath = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
148
+ const contextVerification = contextPath
149
+ ? (brokerController
150
+ ? verifyControllerContextFileWithWarnings(contextPath, {
151
+ repoRoot,
152
+ generation: process.env.AGENT_INFRA_CONTROL_GENERATION ?? brokerController.controlGeneration
153
+ })
154
+ : verifySandboxControllerWithWarnings(contextPath, { repoRoot }))
155
+ : null;
156
+ const identityWarnings: LifecycleIdentityWarning[] = [...(contextVerification?.warnings ?? [])];
157
+ const localController = contextVerification?.context ?? null;
176
158
  if (localController && brokerController
177
159
  && (localController.controllerInstanceDigest !== brokerController.instanceDigest
178
160
  || localController.controlGeneration !== brokerController.controlGeneration)) {
@@ -187,6 +169,11 @@ async function prepareCodexOrchestrationDelegation(
187
169
  } : null);
188
170
  const capabilityStore = options.capabilityStore ?? createCodexCapabilityStore();
189
171
  const attested = capabilityStore.inspect(input.capabilityToken);
172
+ const capabilityIdentity = verifyLifecycleBuildIdentity(attested.buildIdentity, buildIdentity);
173
+ if (!capabilityIdentity.ok) {
174
+ return bridgeFailure(capabilityIdentity.code!, capabilityIdentity.message!);
175
+ }
176
+ identityWarnings.push(...capabilityIdentity.warnings);
190
177
  const lifecycleProvenance = {
191
178
  ...attested.buildIdentity,
192
179
  hookDefinitionHash: preflight.hookDefinitionHash,
@@ -206,7 +193,7 @@ async function prepareCodexOrchestrationDelegation(
206
193
  controlGeneration: controller.controlGeneration
207
194
  } } : {})
208
195
  };
209
- return prepareOrchestrationDelegation(taskRef, {
196
+ const prepared = prepareOrchestrationDelegation(taskRef, {
210
197
  ...input,
211
198
  lifecycleProvenance
212
199
  }, {
@@ -244,6 +231,9 @@ async function prepareCodexOrchestrationDelegation(
244
231
  }
245
232
  }
246
233
  });
234
+ return identityWarnings.length > 0 && prepared.status !== 'failed'
235
+ ? { ...prepared, warnings: Object.freeze(identityWarnings) }
236
+ : prepared;
247
237
  } catch (error) {
248
238
  if (error instanceof OrchestrationStateError) return bridgeFailure(error.code, error.message);
249
239
  const detailValue = error instanceof Error
@@ -290,10 +280,11 @@ async function activateCodexOrchestrationDelegation(
290
280
  });
291
281
  const buildIdentity = options.buildIdentity ?? computeLifecycleBuildIdentity(repoRoot);
292
282
  const contextPath = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
293
- const controller = contextPath
294
- ? verifyCodexSandboxControllerContext(contextPath, { repoRoot })
283
+ const contextVerification = contextPath
284
+ ? verifySandboxControllerWithWarnings(contextPath, { repoRoot })
295
285
  : null;
296
- return activateMatchingOrchestrationDelegation('codex', {
286
+ const controller = contextVerification?.context ?? null;
287
+ const activated = activateMatchingOrchestrationDelegation('codex', {
297
288
  nativeAgent: evidence.nativeAgent,
298
289
  childId: evidence.childThreadId,
299
290
  parentId: evidence.parentThreadId,
@@ -318,6 +309,10 @@ async function activateCodexOrchestrationDelegation(
318
309
  controlGeneration: controller?.controlGeneration ?? null
319
310
  }
320
311
  }, coreOptions(options));
312
+ const warnings = contextVerification?.warnings ?? [];
313
+ return warnings.length > 0 && activated.status !== 'failed'
314
+ ? { ...activated, warnings: Object.freeze(warnings) }
315
+ : activated;
321
316
  } catch (error) {
322
317
  if (error instanceof OrchestrationStateError) return bridgeFailure(error.code, error.message);
323
318
  return pauseBridge('ORCHESTRATION_CODEX_START_FAILED', error instanceof Error ? error.message : String(error), options);
@@ -15,8 +15,7 @@ function parseTaskScope(args: string[]): TaskScope {
15
15
  value = args[++index];
16
16
  if (value === undefined || value === '' || value.startsWith('-')) throw new Error(`${arg} requires a value`);
17
17
  } else if (arg.startsWith('--task=')) {
18
- value = arg.slice('--task='.length);
19
- if (value === '') throw new Error('--task requires a value');
18
+ throw new Error("--task=... is not supported; use --task <ref> or -t <ref>");
20
19
  } else {
21
20
  positionals.push(arg);
22
21
  continue;
@@ -5,11 +5,9 @@ import { resolveArtifact } from '../artifacts.ts';
5
5
 
6
6
  const USAGE = `Usage: ai task cat <artifact | N>
7
7
  ai task cat (--task <ref> | -t <ref>) <artifact | N>
8
- ai task cat <ref> <artifact | N>
9
8
 
10
9
  Prints a task artifact's raw content to stdout.
11
10
  One positional Uses current task context and treats the operand as the artifact.
12
- <ref> Bare numeric short id, or a full TASK-YYYYMMDD-HHMMSS id.
13
11
  <artifact | N> Artifact filename (with or without '.md'), or the number from 'ai task files'.
14
12
  `;
15
13
 
@@ -29,8 +27,6 @@ function cat(args: string[] = []): void {
29
27
  taskRef = scope.taskRef; artifact = scope.positionals[0];
30
28
  } else if (scope.positionals.length === 1) {
31
29
  artifact = scope.positionals[0];
32
- } else if (scope.positionals.length === 2) {
33
- [taskRef, artifact] = scope.positionals;
34
30
  } else { process.stdout.write(USAGE); process.exitCode = 1; return; }
35
31
  const resolved = resolveTaskContext(taskRef);
36
32
  if (!resolved.ok) {