@fitlab-ai/agent-infra 0.9.8 → 0.9.10

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 (182) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dist/bin/internal-cli.js +11 -1
  4. package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +58 -21
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +25 -11
  6. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +173 -10
  7. package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-context.js +127 -0
  8. package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +14 -0
  9. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +63 -92
  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/traecli.js +66 -0
  13. package/dist/lib/agent-clients/tokens.js +2 -2
  14. package/dist/lib/agent-clients/types.js +2 -1
  15. package/dist/lib/defaults.json +5 -0
  16. package/dist/lib/git/workflow.js +10 -1
  17. package/dist/lib/internal/codex-lifecycle.js +20 -6
  18. package/dist/lib/internal/codex-sandbox-controller.js +9 -15
  19. package/dist/lib/internal/git-workflow.js +5 -7
  20. package/dist/lib/internal/platform-pr.js +20 -7
  21. package/dist/lib/internal/release-workflow.js +2 -1
  22. package/dist/lib/internal/sandbox-control.js +79 -2
  23. package/dist/lib/internal/task-finalization.js +54 -0
  24. package/dist/lib/internal/task-orchestration.js +156 -291
  25. package/dist/lib/{task/commands/validate.js → internal/task-validate.js} +75 -42
  26. package/dist/lib/platform/pr-summary.js +48 -10
  27. package/dist/lib/platform/pull-requests.js +205 -41
  28. package/dist/lib/run/tui.js +5 -2
  29. package/dist/lib/sandbox/commands/rm.js +316 -55
  30. package/dist/lib/sandbox/control/client.js +190 -6
  31. package/dist/lib/sandbox/control/controller-registration.js +275 -0
  32. package/dist/lib/sandbox/control/executor.js +140 -5
  33. package/dist/lib/sandbox/control/lifecycle.js +3 -1
  34. package/dist/lib/sandbox/control/protocol.js +67 -6
  35. package/dist/lib/sandbox/index.js +5 -3
  36. package/dist/lib/sandbox/managed-fs.js +5 -0
  37. package/dist/lib/sandbox/task-resolver.js +50 -6
  38. package/dist/lib/sandbox/workspace-identity.js +27 -0
  39. package/dist/lib/sandbox/worktree-safety.js +215 -2
  40. package/dist/lib/task/codex-orchestration.js +161 -39
  41. package/dist/lib/task/commands/status.js +59 -1
  42. package/dist/lib/task/commit-operation.js +335 -0
  43. package/dist/lib/task/commit-policy.js +18 -0
  44. package/dist/lib/task/delegation-receipts.js +248 -6
  45. package/dist/lib/task/finalization.js +593 -0
  46. package/dist/lib/task/index.js +0 -9
  47. package/dist/lib/task/operation-outcome.js +33 -0
  48. package/dist/lib/task/orchestration.js +187 -761
  49. package/dist/lib/task/short-id.js +59 -1
  50. package/dist/lib/task/task-execution-lock.js +6 -1
  51. package/dist/lib/task/verification-engine.js +110 -60
  52. package/dist/lib/task/verification.js +2 -1
  53. package/dist/lib/task/workflow-warning-intents.js +50 -1
  54. package/dist/lifecycle-build-manifest.json +3 -3
  55. package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +61 -19
  56. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +37 -10
  57. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +276 -12
  58. package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +163 -0
  59. package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +19 -0
  60. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +9 -1
  61. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +91 -118
  62. package/lib/agent-clients/adapters/codex-sandbox.ts +89 -14
  63. package/lib/agent-clients/adapters/index.ts +3 -1
  64. package/lib/agent-clients/adapters/traecli.ts +67 -0
  65. package/lib/agent-clients/tokens.ts +2 -2
  66. package/lib/agent-clients/types.ts +2 -1
  67. package/lib/defaults.json +5 -0
  68. package/lib/git/workflow.ts +11 -2
  69. package/lib/internal/codex-lifecycle.ts +19 -6
  70. package/lib/internal/codex-sandbox-controller.ts +9 -14
  71. package/lib/internal/git-workflow.ts +5 -6
  72. package/lib/internal/platform-pr.ts +14 -7
  73. package/lib/internal/release-workflow.ts +2 -1
  74. package/lib/internal/sandbox-control.ts +92 -2
  75. package/lib/internal/task-finalization.ts +68 -0
  76. package/lib/internal/task-orchestration.ts +20 -103
  77. package/lib/{task/commands/validate.ts → internal/task-validate.ts} +75 -40
  78. package/lib/platform/pr-summary.ts +55 -11
  79. package/lib/platform/pull-requests.ts +211 -41
  80. package/lib/run/tui.ts +5 -3
  81. package/lib/sandbox/commands/rm.ts +413 -61
  82. package/lib/sandbox/control/client.ts +255 -6
  83. package/lib/sandbox/control/controller-registration.ts +352 -0
  84. package/lib/sandbox/control/executor.ts +169 -5
  85. package/lib/sandbox/control/lifecycle.ts +2 -1
  86. package/lib/sandbox/control/protocol.ts +80 -7
  87. package/lib/sandbox/index.ts +5 -3
  88. package/lib/sandbox/managed-fs.ts +5 -0
  89. package/lib/sandbox/task-resolver.ts +58 -7
  90. package/lib/sandbox/workspace-identity.ts +50 -2
  91. package/lib/sandbox/workspace-view.ts +3 -3
  92. package/lib/sandbox/worktree-safety.ts +236 -2
  93. package/lib/task/codex-orchestration.ts +168 -40
  94. package/lib/task/commands/status.ts +78 -1
  95. package/lib/task/commit-operation.ts +430 -0
  96. package/lib/task/commit-policy.ts +30 -0
  97. package/lib/task/delegation-receipts.ts +263 -4
  98. package/lib/task/finalization.ts +761 -0
  99. package/lib/task/index.ts +0 -8
  100. package/lib/task/operation-outcome.ts +48 -0
  101. package/lib/task/orchestration.ts +218 -982
  102. package/lib/task/short-id.ts +65 -1
  103. package/lib/task/task-execution-lock.ts +10 -1
  104. package/lib/task/verification-engine.ts +115 -63
  105. package/lib/task/verification.ts +3 -2
  106. package/lib/task/workflow-warning-intents.ts +57 -2
  107. package/package.json +2 -2
  108. package/templates/.agents/QUICKSTART.en.md +3 -4
  109. package/templates/.agents/QUICKSTART.zh-CN.md +3 -4
  110. package/templates/.agents/hooks/lifecycle-delegation.js +1 -21
  111. package/templates/.agents/rules/README.en.md +1 -0
  112. package/templates/.agents/rules/README.zh-CN.md +1 -0
  113. package/templates/.agents/rules/compatibility-policy.en.md +39 -0
  114. package/templates/.agents/rules/compatibility-policy.zh-CN.md +39 -0
  115. package/templates/.agents/rules/lifecycle-orchestration.en.md +4 -4
  116. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +4 -4
  117. package/templates/.agents/rules/pr-sync.en.md +1 -1
  118. package/templates/.agents/rules/pr-sync.github.en.md +2 -1
  119. package/templates/.agents/rules/pr-sync.github.zh-CN.md +2 -0
  120. package/templates/.agents/rules/pr-sync.zh-CN.md +1 -0
  121. package/templates/.agents/rules/review-method.en.md +1 -0
  122. package/templates/.agents/rules/review-method.zh-CN.md +1 -0
  123. package/templates/.agents/rules/task-management.en.md +2 -2
  124. package/templates/.agents/rules/task-management.zh-CN.md +2 -2
  125. package/templates/.agents/skills/analyze-task/SKILL.en.md +1 -0
  126. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +1 -0
  127. package/templates/.agents/skills/block-task/SKILL.en.md +2 -4
  128. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -4
  129. package/templates/.agents/skills/cancel-task/SKILL.en.md +3 -3
  130. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +3 -3
  131. package/templates/.agents/skills/close-codescan/SKILL.en.md +6 -2
  132. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +6 -2
  133. package/templates/.agents/skills/close-dependabot/SKILL.en.md +6 -2
  134. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +6 -2
  135. package/templates/.agents/skills/code-task/SKILL.en.md +1 -0
  136. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +2 -0
  137. package/templates/.agents/skills/commit/SKILL.en.md +41 -125
  138. package/templates/.agents/skills/commit/SKILL.zh-CN.md +52 -123
  139. package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -1
  140. package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -1
  141. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +14 -43
  142. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +14 -49
  143. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  144. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  145. package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -35
  146. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -35
  147. package/templates/.agents/skills/complete-task/SKILL.en.md +31 -38
  148. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +31 -38
  149. package/templates/.agents/skills/complete-task/config/verify.en.json +1 -0
  150. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +1 -0
  151. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +1 -1
  152. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +1 -1
  153. package/templates/.agents/skills/create-pr/SKILL.en.md +17 -9
  154. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +17 -9
  155. package/templates/.agents/skills/create-pr/reference/change-report.en.md +41 -0
  156. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +41 -0
  157. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +2 -2
  158. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +2 -2
  159. package/templates/.agents/skills/plan-task/SKILL.en.md +2 -1
  160. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -1
  161. package/templates/.agents/skills/review-code/reference/migration-risks.en.md +8 -6
  162. package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +8 -6
  163. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +3 -3
  164. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +3 -3
  165. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +1 -1
  166. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +1 -1
  167. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -2
  168. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -2
  169. package/templates/.agents/skills/run-task/SKILL.en.md +6 -6
  170. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +6 -6
  171. package/templates/.agents/skills/run-task/reference/host-validation.en.md +2 -2
  172. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +2 -2
  173. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +24 -0
  174. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +1 -1
  175. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +1 -1
  176. package/templates/.codex/hooks.json +4 -4
  177. package/templates/.trae/skills/update-agent-infra.en.md +8 -0
  178. package/templates/.trae/skills/update-agent-infra.zh-CN.md +8 -0
  179. package/dist/lib/task/commit-finalization.js +0 -305
  180. package/dist/lib/task/commit-intent.js +0 -165
  181. package/lib/task/commit-finalization.ts +0 -419
  182. package/lib/task/commit-intent.ts +0 -230
@@ -1,8 +1,7 @@
1
- import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.js';
2
- import { abortCommitIntent, activateMatchingOrchestrationDelegation, activateOrchestrationDelegation, advanceOrchestration, awaitOrchestrationDelegationActivation, beginCommitIntent, beginOrResumeOrchestration, checkpointCommitIntent, completeCommitIntent, dispatchOrchestrationDelegation, pauseOrchestration, recoverCommitIntent, recoverPreparedOrchestrationDelegation, routeOrchestration, sealMatchingOrchestrationDelegation, sealOrchestrationDelegation, startCommitAttempt, statusCommitIntent, statusOrchestration, terminateCommitAttempt } from '../task/orchestration.js';
1
+ import { activateMatchingOrchestrationDelegation, activateOrchestrationDelegation, advanceOrchestration, awaitOrchestrationDelegationActivation, beginOrResumeOrchestration, dispatchOrchestrationDelegation, OrchestrationStateError, pauseOrchestration, recoverPreparedOrchestrationDelegation, routeOrchestration, sealMatchingOrchestrationDelegation, sealOrchestrationDelegation, statusOrchestration } from '../task/orchestration.js';
3
2
  import { prepareCodexOrchestrationDelegation } from '../task/codex-orchestration.js';
4
3
  import { isAgentClientId } from '../agent-clients/types.js';
5
- const USAGE = 'Usage: agent-infra-internal task-orchestration <task-ref|auto> <begin-or-resume|route|prepare|dispatch|await-activation|recover-prepared|hook-start|hook-stop|advance|pause|status|commit-start|commit-begin|commit-checkpoint|commit-complete|commit-recover|commit-abort|commit-terminate|commit-status> [options]\n';
4
+ const USAGE = 'Usage: agent-infra-internal task-orchestration <task-ref|auto> <begin-or-resume|route|prepare|dispatch|await-activation|recover-prepared|hook-start|hook-stop|advance|pause|status> [options]\n';
6
5
  function usageFailure(message) {
7
6
  process.stdout.write(`${JSON.stringify({
8
7
  status: 'failed', changed: false,
@@ -23,26 +22,15 @@ async function taskOrchestration(args = []) {
23
22
  const [taskRef, intent] = args;
24
23
  if (![
25
24
  'begin-or-resume', 'route', 'prepare', 'dispatch', 'await-activation', 'recover-prepared',
26
- 'hook-start', 'hook-stop', 'advance', 'pause', 'status',
27
- 'commit-start', 'commit-begin', 'commit-checkpoint', 'commit-complete', 'commit-recover', 'commit-abort', 'commit-terminate', 'commit-status'
25
+ 'hook-start', 'hook-stop', 'advance', 'pause', 'status'
28
26
  ].includes(intent)) {
29
27
  usageFailure(`unknown intent '${intent}'`);
30
28
  return;
31
29
  }
32
30
  const values = {};
33
31
  const seen = new Set();
34
- let orchestrated = false;
35
32
  for (let index = 2; index < args.length; index += 1) {
36
33
  const flag = args[index];
37
- if (flag === '--orchestrated') {
38
- if (seen.has(flag)) {
39
- usageFailure(`duplicate option '${flag}'`);
40
- return;
41
- }
42
- seen.add(flag);
43
- orchestrated = true;
44
- continue;
45
- }
46
34
  if (![
47
35
  '--max-steps', '--executor-model', '--executor-reasoning-effort',
48
36
  '--reviewer-model', '--reviewer-reasoning-effort',
@@ -52,8 +40,7 @@ async function taskOrchestration(args = []) {
52
40
  '--native-agent', '--child-id', '--spawn-mode', '--actual-model', '--actual-reasoning-effort',
53
41
  '--model-fallback-reason', '--reasoning-effort-fallback-reason',
54
42
  '--exit-code', '--after-fingerprint', '--changed-paths', '--code', '--message', '--recoverable', '--agent',
55
- '--baseline-head', '--token', '--kind', '--head', '--remote', '--ref', '--expected-head',
56
- '--attempt', '--git-worktree-root'
43
+ '--git-worktree-root'
57
44
  ].includes(flag)) {
58
45
  usageFailure(`unknown option '${flag}'`);
59
46
  return;
@@ -70,33 +57,6 @@ async function taskOrchestration(args = []) {
70
57
  }
71
58
  values[flag] = value;
72
59
  }
73
- const commitIntentFlags = {
74
- 'commit-start': ['--agent', '--git-worktree-root'],
75
- 'commit-begin': ['--agent', '--baseline-head', '--attempt', '--orchestrated', '--git-worktree-root'],
76
- 'commit-checkpoint': ['--token', '--kind', '--head', '--remote', '--ref', '--git-worktree-root'],
77
- 'commit-complete': ['--token', '--agent', '--git-worktree-root'],
78
- 'commit-recover': ['--agent', '--git-worktree-root'],
79
- 'commit-abort': ['--token', '--expected-head', '--git-worktree-root'],
80
- 'commit-terminate': ['--attempt', '--agent', '--code', '--git-worktree-root'],
81
- 'commit-status': ['--git-worktree-root']
82
- };
83
- if (intent in commitIntentFlags) {
84
- const allowed = commitIntentFlags[intent];
85
- const invalid = [...seen].find((flag) => !allowed.includes(flag));
86
- if (invalid) {
87
- usageFailure(`intent '${intent}' does not accept '${invalid}'`);
88
- return;
89
- }
90
- }
91
- else {
92
- const commitOnly = [...seen].find((flag) => [
93
- '--orchestrated', '--baseline-head', '--attempt', '--token', '--kind', '--head', '--remote', '--ref', '--expected-head'
94
- ].includes(flag));
95
- if (commitOnly) {
96
- usageFailure(`intent '${intent}' does not accept '${commitOnly}'`);
97
- return;
98
- }
99
- }
100
60
  const requireValues = (flags) => flags.find((flag) => values[flag] === undefined);
101
61
  const coreOptions = values['--git-worktree-root'] === undefined
102
62
  ? {}
@@ -106,273 +66,178 @@ async function taskOrchestration(args = []) {
106
66
  return;
107
67
  }
108
68
  let result;
109
- if (intent === 'commit-start') {
110
- const missing = requireValues(['--agent']);
111
- if (missing) {
112
- usageFailure(`intent 'commit-start' requires '${missing}'`);
113
- return;
114
- }
115
- const agent = normalizeAgentToken(values['--agent']);
116
- if (!agent) {
117
- usageFailure(`invalid --agent '${values['--agent']}': ${AGENT_USAGE_HINT}`);
118
- return;
119
- }
120
- result = startCommitAttempt(taskRef, { agent }, coreOptions);
121
- }
122
- else if (intent === 'commit-begin') {
123
- const missing = requireValues(['--agent', '--baseline-head', '--attempt']);
124
- if (missing) {
125
- usageFailure(`intent 'commit-begin' requires '${missing}'`);
126
- return;
127
- }
128
- const agent = normalizeAgentToken(values['--agent']);
129
- if (!agent) {
130
- usageFailure(`invalid --agent '${values['--agent']}': ${AGENT_USAGE_HINT}`);
131
- return;
132
- }
133
- result = beginCommitIntent(taskRef, {
134
- agent, orchestrated, baselineHead: values['--baseline-head'], attempt: values['--attempt']
135
- }, coreOptions);
136
- }
137
- else if (intent === 'commit-checkpoint') {
138
- const missing = requireValues(['--token', '--kind', '--head']);
139
- if (missing) {
140
- usageFailure(`intent 'commit-checkpoint' requires '${missing}'`);
141
- return;
142
- }
143
- if (!['committed', 'pushed'].includes(values['--kind'])) {
144
- usageFailure('--kind must be committed or pushed');
145
- return;
146
- }
147
- if (values['--kind'] === 'pushed') {
148
- const pushedMissing = requireValues(['--remote', '--ref']);
149
- if (pushedMissing) {
150
- usageFailure(`pushed checkpoint requires '${pushedMissing}'`);
69
+ try {
70
+ if (intent === 'begin-or-resume') {
71
+ const missing = requireValues(['--client']);
72
+ if (missing) {
73
+ usageFailure(`intent 'begin-or-resume' requires '${missing}'`);
151
74
  return;
152
75
  }
76
+ const maxSteps = values['--max-steps'] === undefined ? undefined : Number(values['--max-steps']);
77
+ if (maxSteps !== undefined && (!Number.isInteger(maxSteps) || maxSteps < 1)) {
78
+ usageFailure('--max-steps must be a positive integer');
79
+ return;
80
+ }
81
+ const policyFlags = [
82
+ '--executor-model', '--executor-reasoning-effort',
83
+ '--reviewer-model', '--reviewer-reasoning-effort'
84
+ ];
85
+ const hasAnyPolicy = policyFlags.some((flag) => values[flag] !== undefined);
86
+ if (hasAnyPolicy && policyFlags.some((flag) => values[flag] === undefined)) {
87
+ usageFailure('explicit model policy requires executor/reviewer model and reasoning effort');
88
+ return;
89
+ }
90
+ result = beginOrResumeOrchestration(taskRef, {
91
+ ...coreOptions,
92
+ maxSteps,
93
+ client: values['--client'],
94
+ modelPolicy: hasAnyPolicy ? {
95
+ executor: {
96
+ model: values['--executor-model'],
97
+ reasoningEffort: values['--executor-reasoning-effort']
98
+ },
99
+ reviewer: {
100
+ model: values['--reviewer-model'],
101
+ reasoningEffort: values['--reviewer-reasoning-effort']
102
+ }
103
+ } : undefined
104
+ });
105
+ }
106
+ else if (intent === 'route') {
107
+ result = routeOrchestration(taskRef, coreOptions);
108
+ }
109
+ else if (intent === 'status') {
110
+ result = statusOrchestration(taskRef, coreOptions);
111
+ }
112
+ else if (intent === 'prepare') {
113
+ const missing = requireValues(['--client']);
114
+ if (missing) {
115
+ usageFailure(`intent 'prepare' requires '${missing}'`);
116
+ return;
117
+ }
118
+ result = await prepareCodexOrchestrationDelegation(taskRef, {
119
+ client: values['--client'],
120
+ requestedModel: values['--requested-model'],
121
+ requestedReasoningEffort: values['--requested-reasoning-effort'],
122
+ capabilityToken: values['--capability-token']
123
+ }, { orchestrationOptions: coreOptions });
124
+ }
125
+ else if (intent === 'dispatch') {
126
+ result = dispatchOrchestrationDelegation(taskRef, coreOptions);
127
+ }
128
+ else if (intent === 'await-activation') {
129
+ const missing = requireValues(['--stage', '--round', '--artifact', '--role']);
130
+ if (missing) {
131
+ usageFailure(`intent 'await-activation' requires '${missing}'`);
132
+ return;
133
+ }
134
+ const round = Number(values['--round']);
135
+ if (!Number.isSafeInteger(round) || round < 1) {
136
+ usageFailure('--round must be a positive integer');
137
+ return;
138
+ }
139
+ if (!['executor', 'reviewer'].includes(values['--role'])) {
140
+ usageFailure('--role must be executor or reviewer');
141
+ return;
142
+ }
143
+ result = await awaitOrchestrationDelegationActivation(taskRef, {
144
+ stage: values['--stage'],
145
+ round,
146
+ artifact: values['--artifact'],
147
+ role: values['--role']
148
+ }, coreOptions);
153
149
  }
154
- else if (values['--remote'] !== undefined || values['--ref'] !== undefined) {
155
- usageFailure('committed checkpoint does not accept --remote or --ref');
156
- return;
157
- }
158
- result = checkpointCommitIntent(taskRef, {
159
- token: values['--token'], kind: values['--kind'],
160
- head: values['--head'], remote: values['--remote'], ref: values['--ref']
161
- }, coreOptions);
162
- }
163
- else if (intent === 'commit-complete') {
164
- const missing = requireValues(['--token', '--agent']);
165
- if (missing) {
166
- usageFailure(`intent 'commit-complete' requires '${missing}'`);
167
- return;
168
- }
169
- const agent = normalizeAgentToken(values['--agent']);
170
- if (!agent) {
171
- usageFailure(`invalid --agent '${values['--agent']}': ${AGENT_USAGE_HINT}`);
172
- return;
173
- }
174
- result = completeCommitIntent(taskRef, { token: values['--token'], agent }, coreOptions);
175
- }
176
- else if (intent === 'commit-recover') {
177
- const missing = requireValues(['--agent']);
178
- if (missing) {
179
- usageFailure(`intent 'commit-recover' requires '${missing}'`);
180
- return;
181
- }
182
- const agent = normalizeAgentToken(values['--agent']);
183
- if (!agent) {
184
- usageFailure(`invalid --agent '${values['--agent']}': ${AGENT_USAGE_HINT}`);
185
- return;
186
- }
187
- result = recoverCommitIntent(taskRef, { agent }, coreOptions);
188
- }
189
- else if (intent === 'commit-abort') {
190
- const missing = requireValues(['--token', '--expected-head']);
191
- if (missing) {
192
- usageFailure(`intent 'commit-abort' requires '${missing}'`);
193
- return;
194
- }
195
- result = abortCommitIntent(taskRef, { token: values['--token'], expectedHead: values['--expected-head'] }, coreOptions);
196
- }
197
- else if (intent === 'commit-terminate') {
198
- const missing = requireValues(['--attempt', '--agent', '--code']);
199
- if (missing) {
200
- usageFailure(`intent 'commit-terminate' requires '${missing}'`);
201
- return;
202
- }
203
- const agent = normalizeAgentToken(values['--agent']);
204
- if (!agent) {
205
- usageFailure(`invalid --agent '${values['--agent']}': ${AGENT_USAGE_HINT}`);
206
- return;
207
- }
208
- if (!/^[A-Z][A-Z0-9_]{2,63}$/.test(values['--code'])) {
209
- usageFailure('--code must be a stable uppercase identifier');
210
- return;
211
- }
212
- result = terminateCommitAttempt(taskRef, {
213
- attempt: values['--attempt'], agent, code: values['--code']
214
- }, coreOptions);
215
- }
216
- else if (intent === 'commit-status') {
217
- result = statusCommitIntent(taskRef, coreOptions);
218
- }
219
- else if (intent === 'begin-or-resume') {
220
- const missing = requireValues(['--client']);
221
- if (missing) {
222
- usageFailure(`intent 'begin-or-resume' requires '${missing}'`);
223
- return;
224
- }
225
- const maxSteps = values['--max-steps'] === undefined ? undefined : Number(values['--max-steps']);
226
- if (maxSteps !== undefined && (!Number.isInteger(maxSteps) || maxSteps < 1)) {
227
- usageFailure('--max-steps must be a positive integer');
228
- return;
229
- }
230
- const policyFlags = [
231
- '--executor-model', '--executor-reasoning-effort',
232
- '--reviewer-model', '--reviewer-reasoning-effort'
233
- ];
234
- const hasAnyPolicy = policyFlags.some((flag) => values[flag] !== undefined);
235
- if (hasAnyPolicy && policyFlags.some((flag) => values[flag] === undefined)) {
236
- usageFailure('explicit model policy requires executor/reviewer model and reasoning effort');
237
- return;
238
- }
239
- result = beginOrResumeOrchestration(taskRef, {
240
- ...coreOptions,
241
- maxSteps,
242
- client: values['--client'],
243
- modelPolicy: hasAnyPolicy ? {
244
- executor: {
245
- model: values['--executor-model'],
246
- reasoningEffort: values['--executor-reasoning-effort']
247
- },
248
- reviewer: {
249
- model: values['--reviewer-model'],
250
- reasoningEffort: values['--reviewer-reasoning-effort']
251
- }
252
- } : undefined
253
- });
254
- }
255
- else if (intent === 'route') {
256
- result = routeOrchestration(taskRef, coreOptions);
257
- }
258
- else if (intent === 'status') {
259
- result = statusOrchestration(taskRef, coreOptions);
260
- }
261
- else if (intent === 'prepare') {
262
- const missing = requireValues(['--client']);
263
- if (missing) {
264
- usageFailure(`intent 'prepare' requires '${missing}'`);
265
- return;
266
- }
267
- result = await prepareCodexOrchestrationDelegation(taskRef, {
268
- client: values['--client'],
269
- requestedModel: values['--requested-model'],
270
- requestedReasoningEffort: values['--requested-reasoning-effort'],
271
- capabilityToken: values['--capability-token']
272
- }, { orchestrationOptions: coreOptions });
273
- }
274
- else if (intent === 'dispatch') {
275
- result = dispatchOrchestrationDelegation(taskRef, coreOptions);
276
- }
277
- else if (intent === 'await-activation') {
278
- const missing = requireValues(['--stage', '--round', '--artifact', '--role']);
279
- if (missing) {
280
- usageFailure(`intent 'await-activation' requires '${missing}'`);
281
- return;
282
- }
283
- const round = Number(values['--round']);
284
- if (!Number.isSafeInteger(round) || round < 1) {
285
- usageFailure('--round must be a positive integer');
286
- return;
287
- }
288
- if (!['executor', 'reviewer'].includes(values['--role'])) {
289
- usageFailure('--role must be executor or reviewer');
290
- return;
291
- }
292
- result = await awaitOrchestrationDelegationActivation(taskRef, {
293
- stage: values['--stage'],
294
- round,
295
- artifact: values['--artifact'],
296
- role: values['--role']
297
- }, coreOptions);
298
- }
299
- else if (intent === 'recover-prepared') {
300
- result = recoverPreparedOrchestrationDelegation(taskRef, coreOptions);
301
- }
302
- else if (intent === 'hook-start') {
303
- const missing = requireValues([
304
- ...(taskRef === 'auto' ? ['--client'] : []),
305
- '--native-agent', '--child-id', '--parent-id'
306
- ]);
307
- if (missing) {
308
- usageFailure(`intent 'hook-start' requires '${missing}'`);
309
- return;
150
+ else if (intent === 'recover-prepared') {
151
+ result = recoverPreparedOrchestrationDelegation(taskRef, coreOptions);
310
152
  }
311
- const event = {
312
- nativeAgent: values['--native-agent'], childId: values['--child-id'],
313
- parentId: values['--parent-id'], spawnMode: values['--spawn-mode'],
314
- actualModel: values['--actual-model'],
315
- actualReasoningEffort: values['--actual-reasoning-effort'],
316
- modelFallbackReason: values['--model-fallback-reason'],
317
- reasoningEffortFallbackReason: values['--reasoning-effort-fallback-reason']
318
- };
319
- result = taskRef === 'auto'
320
- ? activateMatchingOrchestrationDelegation(values['--client'], event, coreOptions)
321
- : activateOrchestrationDelegation(taskRef, event, coreOptions);
322
- }
323
- else if (intent === 'hook-stop') {
324
- if (taskRef === 'auto') {
325
- const missing = requireValues(['--client', '--native-agent', '--child-id']);
153
+ else if (intent === 'hook-start') {
154
+ const missing = requireValues([
155
+ ...(taskRef === 'auto' ? ['--client'] : []),
156
+ '--native-agent', '--child-id', '--parent-id'
157
+ ]);
326
158
  if (missing) {
327
- usageFailure(`intent 'hook-stop' requires '${missing}'`);
159
+ usageFailure(`intent 'hook-start' requires '${missing}'`);
328
160
  return;
329
161
  }
330
- result = sealMatchingOrchestrationDelegation(values['--client'], {
162
+ const event = {
331
163
  nativeAgent: values['--native-agent'], childId: values['--child-id'],
164
+ parentId: values['--parent-id'], spawnMode: values['--spawn-mode'],
332
165
  actualModel: values['--actual-model'],
333
166
  actualReasoningEffort: values['--actual-reasoning-effort'],
334
167
  modelFallbackReason: values['--model-fallback-reason'],
335
168
  reasoningEffortFallbackReason: values['--reasoning-effort-fallback-reason']
336
- }, coreOptions);
169
+ };
170
+ result = taskRef === 'auto'
171
+ ? activateMatchingOrchestrationDelegation(values['--client'], event, coreOptions)
172
+ : activateOrchestrationDelegation(taskRef, event, coreOptions);
173
+ }
174
+ else if (intent === 'hook-stop') {
175
+ if (taskRef === 'auto') {
176
+ const missing = requireValues(['--client', '--native-agent', '--child-id']);
177
+ if (missing) {
178
+ usageFailure(`intent 'hook-stop' requires '${missing}'`);
179
+ return;
180
+ }
181
+ result = sealMatchingOrchestrationDelegation(values['--client'], {
182
+ nativeAgent: values['--native-agent'], childId: values['--child-id'],
183
+ actualModel: values['--actual-model'],
184
+ actualReasoningEffort: values['--actual-reasoning-effort'],
185
+ modelFallbackReason: values['--model-fallback-reason'],
186
+ reasoningEffortFallbackReason: values['--reasoning-effort-fallback-reason']
187
+ }, coreOptions);
188
+ }
189
+ else {
190
+ const missing = requireValues(['--child-id', '--exit-code', '--after-fingerprint']);
191
+ if (missing) {
192
+ usageFailure(`intent 'hook-stop' requires '${missing}'`);
193
+ return;
194
+ }
195
+ const exitCode = Number(values['--exit-code']);
196
+ if (!Number.isInteger(exitCode)) {
197
+ usageFailure('--exit-code must be an integer');
198
+ return;
199
+ }
200
+ result = sealOrchestrationDelegation(taskRef, {
201
+ childId: values['--child-id'], exitCode,
202
+ afterFingerprint: values['--after-fingerprint'],
203
+ changedPaths: values['--changed-paths'] ? values['--changed-paths'].split(',').filter(Boolean) : [],
204
+ actualModel: values['--actual-model'],
205
+ actualReasoningEffort: values['--actual-reasoning-effort'],
206
+ modelFallbackReason: values['--model-fallback-reason'],
207
+ reasoningEffortFallbackReason: values['--reasoning-effort-fallback-reason']
208
+ }, coreOptions);
209
+ }
210
+ }
211
+ else if (intent === 'advance') {
212
+ result = advanceOrchestration(taskRef, coreOptions);
337
213
  }
338
214
  else {
339
- const missing = requireValues(['--child-id', '--exit-code', '--after-fingerprint']);
215
+ const missing = requireValues(['--code', '--message', '--recoverable']);
340
216
  if (missing) {
341
- usageFailure(`intent 'hook-stop' requires '${missing}'`);
217
+ usageFailure(`intent 'pause' requires '${missing}'`);
342
218
  return;
343
219
  }
344
- const exitCode = Number(values['--exit-code']);
345
- if (!Number.isInteger(exitCode)) {
346
- usageFailure('--exit-code must be an integer');
220
+ if (!['true', 'false'].includes(values['--recoverable'])) {
221
+ usageFailure('--recoverable must be true or false');
347
222
  return;
348
223
  }
349
- result = sealOrchestrationDelegation(taskRef, {
350
- childId: values['--child-id'], exitCode,
351
- afterFingerprint: values['--after-fingerprint'],
352
- changedPaths: values['--changed-paths'] ? values['--changed-paths'].split(',').filter(Boolean) : [],
353
- actualModel: values['--actual-model'],
354
- actualReasoningEffort: values['--actual-reasoning-effort'],
355
- modelFallbackReason: values['--model-fallback-reason'],
356
- reasoningEffortFallbackReason: values['--reasoning-effort-fallback-reason']
357
- }, coreOptions);
358
- }
359
- }
360
- else if (intent === 'advance') {
361
- result = advanceOrchestration(taskRef, coreOptions);
362
- }
363
- else {
364
- const missing = requireValues(['--code', '--message', '--recoverable']);
365
- if (missing) {
366
- usageFailure(`intent 'pause' requires '${missing}'`);
367
- return;
368
- }
369
- if (!['true', 'false'].includes(values['--recoverable'])) {
370
- usageFailure('--recoverable must be true or false');
371
- return;
372
- }
373
- result = pauseOrchestration(taskRef, values['--code'], values['--message'], values['--recoverable'] === 'true', coreOptions);
224
+ result = pauseOrchestration(taskRef, values['--code'], values['--message'], values['--recoverable'] === 'true', coreOptions);
225
+ }
226
+ }
227
+ catch (error) {
228
+ if (!(error instanceof OrchestrationStateError))
229
+ throw error;
230
+ result = {
231
+ status: 'failed',
232
+ changed: false,
233
+ taskId: error.taskId,
234
+ run: null,
235
+ next: null,
236
+ error: { code: error.code, message: error.message }
237
+ };
374
238
  }
375
- process.stdout.write(`${JSON.stringify(result)}\n`);
239
+ const output = result;
240
+ process.stdout.write(`${JSON.stringify(output)}\n`);
376
241
  if (result.status === 'failed')
377
242
  process.exitCode = 1;
378
243
  }
@@ -3,19 +3,19 @@ import fs from 'node:fs';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { randomUUID } from 'node:crypto';
6
- import { loadConfig } from '../../sandbox/config.js';
7
- import { detectEngine } from '../../sandbox/engine.js';
8
- import { runEngine } from '../../sandbox/shell.js';
9
- import { sandboxBranchLabel, sandboxLabel } from '../../sandbox/constants.js';
10
- import { fetchSandboxRows, selectSandboxContainer } from '../../sandbox/commands/list-running.js';
11
- import { containerNameCandidates } from '../../sandbox/constants.js';
12
- import { resolveSandboxTarget } from '../../sandbox/workspace-identity.js';
13
- import { sandboxControlPaths } from '../../sandbox/workspace-view.js';
14
- import { appendSandboxControlAudit, readActiveLease, readSandboxControlStatus } from '../../sandbox/control/state.js';
15
- import { SANDBOX_CONTROL_FUTURE_SKEW_MS, SANDBOX_CONTROL_STATUS_STALE_MS } from '../../sandbox/control/protocol.js';
16
- import { getProcessStartTime } from '../../server/process-state.js';
17
- import { assertGitWorktreeBinding } from '../../git/worktree-identity.js';
18
- const USAGE = `Usage: ai task validate <branch | TASK-id | N> [--scope snapshot|inplace] [--timeout <ms>] [--format text|json] -- <command> [args...]`;
6
+ import { loadConfig } from '../sandbox/config.js';
7
+ import { detectEngine } from '../sandbox/engine.js';
8
+ import { runEngine } from '../sandbox/shell.js';
9
+ import { sandboxBranchLabel, sandboxLabel } from '../sandbox/constants.js';
10
+ import { fetchSandboxRows, selectSandboxContainer } from '../sandbox/commands/list-running.js';
11
+ import { containerNameCandidates } from '../sandbox/constants.js';
12
+ import { resolveSandboxTarget } from '../sandbox/workspace-identity.js';
13
+ import { sandboxControlPaths } from '../sandbox/workspace-view.js';
14
+ import { appendSandboxControlAudit, readActiveLease, readSandboxControlStatus } from '../sandbox/control/state.js';
15
+ import { SANDBOX_CONTROL_FUTURE_SKEW_MS, SANDBOX_CONTROL_STATUS_STALE_MS } from '../sandbox/control/protocol.js';
16
+ import { getProcessStartTime } from '../server/process-state.js';
17
+ import { assertGitWorktreeBinding } from '../git/worktree-identity.js';
18
+ const USAGE = `Usage: agent-infra-internal task-validate <branch | TASK-id | N> [--scope snapshot|inplace] [--timeout <ms>] [--format text|json] -- <command> [args...]`;
19
19
  const MAX_TIMEOUT_MS = 60 * 60 * 1000;
20
20
  const RECOVERY_GRACE_MS = 30_000;
21
21
  export function parseValidateArgs(args) {
@@ -254,36 +254,69 @@ function inplaceValidation(config, target, options) {
254
254
  }
255
255
  }
256
256
  }
257
- export async function validate(args) {
258
- const options = parseValidateArgs(args);
257
+ function errorCode(message) {
258
+ const match = message.match(/^([A-Z][A-Z0-9_]*)/);
259
+ return match && match[1].length >= 3 ? match[1] : 'TASK_VALIDATE_FAILED';
260
+ }
261
+ function fail(format, code, message) {
262
+ if (format === 'json') {
263
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code, message } })}\n`);
264
+ }
265
+ else {
266
+ process.stderr.write(`${message}\n`);
267
+ }
268
+ process.exitCode = 1;
269
+ }
270
+ function sniffFormat(args) {
271
+ const index = args.indexOf('--format');
272
+ return index >= 0 && args[index + 1] === 'json' ? 'json' : 'text';
273
+ }
274
+ function taskValidate(args) {
275
+ let options;
276
+ try {
277
+ options = parseValidateArgs(args);
278
+ }
279
+ catch (error) {
280
+ fail(sniffFormat(args), 'TASK_VALIDATE_ARGS_INVALID', error instanceof Error ? error.message : String(error));
281
+ return;
282
+ }
259
283
  if (options.help) {
260
284
  process.stdout.write(`${USAGE}\n`);
261
- return 0;
285
+ return;
286
+ }
287
+ try {
288
+ const config = loadConfig();
289
+ const target = resolveSandboxTarget(options.target, config.repoRoot);
290
+ const commit = git(config.repoRoot, ['rev-parse', target.branch]);
291
+ const startedAt = new Date().toISOString();
292
+ const result = options.scope === 'snapshot'
293
+ ? snapshotValidation(config.repoRoot, commit, options)
294
+ : inplaceValidation(config, target, options);
295
+ const evidence = {
296
+ version: 1,
297
+ taskId: target.workspace.mode === 'task-bound' ? target.workspace.taskId : null,
298
+ branch: target.branch,
299
+ scope: options.scope,
300
+ commit,
301
+ command: path.basename(options.command[0]),
302
+ startedAt,
303
+ completedAt: new Date().toISOString(),
304
+ exitCode: result.exitCode,
305
+ signal: result.signal,
306
+ cleanup: result.cleanup()
307
+ };
308
+ if (options.format === 'json') {
309
+ process.stdout.write(`${JSON.stringify({ status: 'applied', changed: false, evidence, error: null })}\n`);
310
+ }
311
+ else {
312
+ process.stdout.write(`Validation ${result.exitCode === 0 ? 'passed' : 'failed'} (${options.scope}, ${evidence.command}, cleanup=${evidence.cleanup}).\n`);
313
+ }
314
+ process.exitCode = result.exitCode;
315
+ }
316
+ catch (error) {
317
+ const message = error instanceof Error ? error.message : String(error);
318
+ fail(options.format, errorCode(message), message);
262
319
  }
263
- const config = loadConfig();
264
- const target = resolveSandboxTarget(options.target, config.repoRoot);
265
- const commit = git(config.repoRoot, ['rev-parse', target.branch]);
266
- const startedAt = new Date().toISOString();
267
- const result = options.scope === 'snapshot'
268
- ? snapshotValidation(config.repoRoot, commit, options)
269
- : inplaceValidation(config, target, options);
270
- const evidence = {
271
- version: 1,
272
- taskId: target.workspace.mode === 'task-bound' ? target.workspace.taskId : null,
273
- branch: target.branch,
274
- scope: options.scope,
275
- commit,
276
- command: path.basename(options.command[0]),
277
- startedAt,
278
- completedAt: new Date().toISOString(),
279
- exitCode: result.exitCode,
280
- signal: result.signal,
281
- cleanup: result.cleanup()
282
- };
283
- if (options.format === 'json')
284
- process.stdout.write(`${JSON.stringify(evidence)}\n`);
285
- else
286
- process.stdout.write(`Validation ${result.exitCode === 0 ? 'passed' : 'failed'} (${options.scope}, ${evidence.command}, cleanup=${evidence.cleanup}).\n`);
287
- return result.exitCode;
288
320
  }
289
- //# sourceMappingURL=validate.js.map
321
+ export { taskValidate };
322
+ //# sourceMappingURL=task-validate.js.map