@fitlab-ai/agent-infra 0.11.1 → 0.11.3

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 (131) hide show
  1. package/dist/bin/internal-cli.js +7 -2
  2. package/dist/lib/agent-clients/adapter.js +3 -0
  3. package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +234 -0
  4. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +8 -35
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +1 -34
  6. package/dist/lib/agent-clients/adapters/codex.js +10 -0
  7. package/dist/lib/internal/cli-route-inventory.js +1 -1
  8. package/dist/lib/internal/manual-validation.js +22 -27
  9. package/dist/lib/internal/platform-comment.js +59 -0
  10. package/dist/lib/internal/sandbox-control.js +2 -171
  11. package/dist/lib/internal/task-artifact.js +1 -1
  12. package/dist/lib/internal/task-lifecycle.js +1 -1
  13. package/dist/lib/internal/task-operation-registry.js +7 -2
  14. package/dist/lib/internal/task-review.js +5 -5
  15. package/dist/lib/internal/task-validate.js +0 -6
  16. package/dist/lib/platform/comment-safety.js +7 -1
  17. package/dist/lib/platform/github-provider.js +13 -3
  18. package/dist/lib/platform/issue-comments.js +93 -15
  19. package/dist/lib/platform/pr-summary.js +7 -2
  20. package/dist/lib/platform/provider-contract.d.ts +2 -0
  21. package/dist/lib/platform/provider-validation.js +7 -2
  22. package/dist/lib/platform/verification-sync.js +19 -2
  23. package/dist/lib/sandbox/control/client.js +3 -44
  24. package/dist/lib/sandbox/control/executor.js +14 -117
  25. package/dist/lib/sandbox/control/finalization-response.js +8 -2
  26. package/dist/lib/sandbox/control/protocol.js +5 -64
  27. package/dist/lib/sandbox/control/server.js +29 -206
  28. package/dist/lib/sandbox/control/state.js +1 -7
  29. package/dist/lib/sandbox/control/task-view.js +2 -1
  30. package/dist/lib/task/artifact-command.js +6 -6
  31. package/dist/lib/task/codex-orchestration.js +10 -208
  32. package/dist/lib/task/commit-operation.js +3 -18
  33. package/dist/lib/task/control-authority.js +35 -44
  34. package/dist/lib/task/control-recovery.js +3 -42
  35. package/dist/lib/task/delegation-receipts.js +16 -78
  36. package/dist/lib/task/events.js +89 -237
  37. package/dist/lib/task/finalization-artifacts.js +1 -3
  38. package/dist/lib/task/finalization-state.js +2 -1
  39. package/dist/lib/task/finalization.js +208 -57
  40. package/dist/lib/task/lifecycle-execution.js +2 -11
  41. package/dist/lib/task/lifecycle.js +1 -1
  42. package/dist/lib/task/local-artifact-finalization.js +25 -242
  43. package/dist/lib/task/manual-validation-receipt.js +8 -3
  44. package/dist/lib/task/orchestration.js +12 -24
  45. package/dist/lib/task/review-command.js +0 -1
  46. package/dist/lib/task/review-finalization.js +46 -211
  47. package/dist/lifecycle-build-manifest.json +3 -3
  48. package/lib/agent-clients/adapter.ts +46 -0
  49. package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +297 -0
  50. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +13 -33
  51. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +1 -44
  52. package/lib/agent-clients/adapters/codex.ts +10 -0
  53. package/lib/internal/cli-route-inventory.ts +1 -1
  54. package/lib/internal/manual-validation.ts +22 -26
  55. package/lib/internal/platform-comment.ts +38 -0
  56. package/lib/internal/sandbox-control.ts +1 -185
  57. package/lib/internal/task-artifact.ts +1 -1
  58. package/lib/internal/task-lifecycle.ts +2 -2
  59. package/lib/internal/task-operation-registry.ts +8 -4
  60. package/lib/internal/task-review.ts +5 -5
  61. package/lib/internal/task-validate.ts +0 -5
  62. package/lib/platform/comment-safety.ts +8 -0
  63. package/lib/platform/github-provider.ts +11 -2
  64. package/lib/platform/issue-comments.ts +102 -17
  65. package/lib/platform/pr-summary.ts +10 -2
  66. package/lib/platform/provider-contract.ts +2 -0
  67. package/lib/platform/provider-validation.ts +6 -2
  68. package/lib/platform/verification-sync.ts +19 -2
  69. package/lib/sandbox/control/client.ts +5 -68
  70. package/lib/sandbox/control/executor.ts +14 -125
  71. package/lib/sandbox/control/finalization-response.ts +8 -2
  72. package/lib/sandbox/control/protocol.ts +7 -83
  73. package/lib/sandbox/control/server.ts +30 -220
  74. package/lib/sandbox/control/state.ts +1 -9
  75. package/lib/sandbox/control/task-view.ts +2 -1
  76. package/lib/task/artifact-command.ts +6 -7
  77. package/lib/task/codex-orchestration.ts +8 -241
  78. package/lib/task/commit-operation.ts +3 -23
  79. package/lib/task/control-authority.ts +39 -55
  80. package/lib/task/control-recovery.ts +3 -43
  81. package/lib/task/delegation-receipts.ts +14 -81
  82. package/lib/task/events.ts +106 -255
  83. package/lib/task/finalization-artifacts.ts +1 -3
  84. package/lib/task/finalization-state.ts +2 -1
  85. package/lib/task/finalization.ts +221 -65
  86. package/lib/task/lifecycle-execution.ts +10 -21
  87. package/lib/task/lifecycle.ts +2 -2
  88. package/lib/task/local-artifact-finalization.ts +23 -281
  89. package/lib/task/manual-validation-receipt.ts +8 -2
  90. package/lib/task/orchestration.ts +30 -53
  91. package/lib/task/review-command.ts +0 -1
  92. package/lib/task/review-finalization.ts +45 -193
  93. package/package.json +2 -2
  94. package/templates/.agents/rules/lifecycle-orchestration.en.md +23 -9
  95. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +23 -9
  96. package/templates/.agents/rules/local-artifact-repair.en.md +14 -60
  97. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +13 -60
  98. package/templates/.agents/skills/analyze-task/SKILL.en.md +3 -3
  99. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +3 -3
  100. package/templates/.agents/skills/code-task/SKILL.en.md +3 -3
  101. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +3 -3
  102. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +2 -2
  103. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +2 -2
  104. package/templates/.agents/skills/complete-task/SKILL.en.md +7 -8
  105. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +7 -8
  106. package/templates/.agents/skills/plan-task/SKILL.en.md +3 -3
  107. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +3 -3
  108. package/templates/.agents/skills/review-analysis/SKILL.en.md +2 -2
  109. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +2 -2
  110. package/templates/.agents/skills/review-code/SKILL.en.md +3 -3
  111. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +3 -3
  112. package/templates/.agents/skills/review-plan/SKILL.en.md +2 -2
  113. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +2 -2
  114. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +2 -2
  115. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +2 -2
  116. package/templates/.agents/skills/run-task/SKILL.en.md +10 -9
  117. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +10 -9
  118. package/templates/.agents/skills/run-task/reference/host-validation.en.md +2 -2
  119. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +2 -2
  120. package/dist/lib/sandbox/control/task-workflow.js +0 -74
  121. package/dist/lib/sandbox/control/workflow-executor.js +0 -157
  122. package/dist/lib/task/lifecycle-recovery.js +0 -549
  123. package/dist/lib/task/recovery-warning.js +0 -19
  124. package/dist/lib/task/workflow-command.js +0 -18
  125. package/dist/lib/task/workflow-dispatch.js +0 -161
  126. package/lib/sandbox/control/task-workflow.ts +0 -95
  127. package/lib/sandbox/control/workflow-executor.ts +0 -183
  128. package/lib/task/lifecycle-recovery.ts +0 -691
  129. package/lib/task/recovery-warning.ts +0 -21
  130. package/lib/task/workflow-command.ts +0 -19
  131. package/lib/task/workflow-dispatch.ts +0 -171
@@ -81,10 +81,6 @@ function preflight(statusDir, generation, taskViewEffect = null, now = Date.now(
81
81
  function taskViewEffectForRequest(request) {
82
82
  if (request.family === 'task-lifecycle' || request.family === 'task-finalization')
83
83
  return 'progress';
84
- if (request.family === 'task-orchestration')
85
- return request.args[1] === 'status' ? 'diagnostic' : 'progress';
86
- if (request.family === 'task-workflow')
87
- return request.workflow.operation === 'artifact-inspect' || request.workflow.operation === 'decision-next-id' ? 'diagnostic' : 'progress';
88
84
  return null;
89
85
  }
90
86
  function parseResponse(raw, id, accepted = false) {
@@ -152,9 +148,7 @@ export function resolveVisibleActiveShortId(ref) {
152
148
  // may be a documented short id. Compare canonical ids so a bound sandbox keeps
153
149
  // refusing other tasks without rejecting its own task's short id.
154
150
  function canonicalRequestTask(request) {
155
- const ref = request.family === 'task-workflow'
156
- ? request.workflow.taskId
157
- : 'args' in request ? request.args[0] ?? null : null;
151
+ const ref = 'args' in request ? request.args[0] ?? null : null;
158
152
  if (!ref)
159
153
  return { kind: 'none' };
160
154
  if (CONTROL_TASK_ID_RE.test(ref))
@@ -179,7 +173,7 @@ function exchangeSandboxControl(request, params) {
179
173
  || (requestTask.kind === 'task' && requestTask.taskId !== identity.taskId))) {
180
174
  clientError('SANDBOX_CONTROL_IDENTITY_TOPOLOGY_MISMATCH', 'request task does not match the sandbox identity', false);
181
175
  }
182
- if (identity.mode === 'branch-only' && (request.family === 'task-finalization' || request.family === 'task-workflow')) {
176
+ if (identity.mode === 'branch-only' && request.family === 'task-finalization') {
183
177
  clientError('SANDBOX_CONTROL_BRANCH_ONLY', 'branch-only sandboxes cannot finalize tasks', false);
184
178
  }
185
179
  }
@@ -326,7 +320,7 @@ function authority(params) {
326
320
  export function requestSandboxControl(params) {
327
321
  if (!isSandboxControlFamily(params.family))
328
322
  clientError('SANDBOX_CONTROL_COMMAND_DENIED', `'${params.family}' is not allowed`, false);
329
- if (params.family === 'task-create' || params.family === 'codex-controller' || params.family === 'task-finalization' || params.family === 'task-workflow') {
323
+ if (params.family === 'task-create' || params.family === 'codex-controller' || params.family === 'task-finalization') {
330
324
  clientError('SANDBOX_CONTROL_COMMAND_DENIED', `'${params.family}' requires a typed request`, false);
331
325
  }
332
326
  const auth = authority(params);
@@ -340,23 +334,6 @@ export function requestSandboxControl(params) {
340
334
  };
341
335
  return exchangeSandboxControl(request, params);
342
336
  }
343
- export function requestSandboxTaskControl(params) {
344
- const auth = authority(params);
345
- const issuedAt = Date.now();
346
- const request = {
347
- version: 3,
348
- id: params.authority?.requestId ?? randomUUID(),
349
- ...auth,
350
- issuedAt,
351
- expiresAt: issuedAt + SANDBOX_CONTROL_ADMISSION_WINDOW_MS,
352
- family: params.family,
353
- args: params.args,
354
- controllerProcess: null,
355
- controllerProof: params.authority ? null : params.controllerProof,
356
- ...(params.authority ? { authority: params.authority } : {})
357
- };
358
- return exchangeSandboxControl(request, params);
359
- }
360
337
  export function requestSandboxTaskFinalization(params) {
361
338
  const agent = normalizeAgentToken(params.agent);
362
339
  if (!agent)
@@ -378,24 +355,6 @@ export function requestSandboxTaskFinalization(params) {
378
355
  };
379
356
  return exchangeSandboxControl(request, params);
380
357
  }
381
- export function requestSandboxTaskWorkflow(params) {
382
- const auth = authority(params);
383
- const issuedAt = Date.now();
384
- const request = {
385
- version: 3,
386
- id: params.workflow.id,
387
- ...auth,
388
- issuedAt,
389
- expiresAt: issuedAt + SANDBOX_CONTROL_ADMISSION_WINDOW_MS,
390
- family: 'task-workflow',
391
- args: [],
392
- controllerProcess: null,
393
- controllerProof: null,
394
- workflow: params.workflow,
395
- ...(params.authority ? { authority: params.authority } : {})
396
- };
397
- return exchangeSandboxControl(request, params);
398
- }
399
358
  function exactKeys(value, keys) {
400
359
  return Object.keys(value).sort().join(',') === [...keys].sort().join(',');
401
360
  }
@@ -9,8 +9,7 @@ import { bindSandboxControlTask, validateSandboxControlRequest } from './protoco
9
9
  import { atomicWriteJson, executionPath, readActiveLease, terminateSandboxControlExecution } from './state.js';
10
10
  import { requestAuditFields, resultAuditFields, appendDiagnosticAudit, createSandboxControlAuditContext, appendCriticalAudit, writeSandboxControlTransition } from './audit.js';
11
11
  import { validateSandboxControlIdentity } from './identity-sentinel.js';
12
- import { createSandboxExecutorExecutionContext, dispatchTaskControlOperation, parseTaskControlOperation, validateLifecycleRecoveryAttestation } from '../../task/control-authority.js';
13
- import { executeTaskWorkflow } from './workflow-executor.js';
12
+ import { createSandboxExecutorExecutionContext, dispatchTaskControlOperation, parseTaskControlOperation } from '../../task/control-authority.js';
14
13
  import { assertSandboxControlBrokerOwner, readSandboxControlManifest } from './lifecycle.js';
15
14
  import { computeLifecycleBuildIdentity } from '../../agent-clients/adapters/codex-lifecycle/build-identity.js';
16
15
  import { closeCodexControllerRegistration, CodexControllerRegistrationError, openCodexControllerRegistration, resolveCodexControllerBinding } from './controller-registration.js';
@@ -118,17 +117,11 @@ export async function prepareSandboxControlExecution(params) {
118
117
  atomicWriteJson(executionPath(params.manifest, params.request.id), { ...execution, phase: 'running', updatedAt: Date.now() });
119
118
  if (!canWrite())
120
119
  throw new Error('SANDBOX_CONTROL_OWNER_LOST');
121
- const authority = params.lifecycleAuthority?.attestation ?? null;
122
120
  child.send({
123
121
  version: 2,
124
122
  nonce,
125
123
  owner: gateOwner,
126
- requestId: params.request.id,
127
- operationId: authority?.operationId ?? params.request.id,
128
- phase: authority?.phase ?? (params.request.family === 'task-workflow'
129
- && params.request.workflow?.operation === 'artifact-preflight' ? 'artifact.preflight'
130
- : params.request.family === 'task-workflow' ? 'artifact.finalize-local' : 'orchestration.prepare'),
131
- authority
124
+ requestId: params.request.id
132
125
  });
133
126
  },
134
127
  completion,
@@ -155,7 +148,7 @@ function waitForGate(nonce, timeoutMs = 2_000) {
155
148
  process.off('disconnect', onDisconnect);
156
149
  const value = message;
157
150
  const owner = value?.owner;
158
- if (!value || Object.keys(value).sort().join(',') !== 'authority,nonce,operationId,owner,phase,requestId,version'
151
+ if (!value || Object.keys(value).sort().join(',') !== 'nonce,owner,requestId,version'
159
152
  || value.version !== 2 || value.nonce !== nonce
160
153
  || !owner || owner.version !== 3 || !Number.isSafeInteger(owner.pid) || (owner.pid ?? 0) <= 0
161
154
  || typeof owner.startTime !== 'number' || !Number.isSafeInteger(owner.startTime)
@@ -164,26 +157,13 @@ function waitForGate(nonce, timeoutMs = 2_000) {
164
157
  reject(new Error('SANDBOX_CONTROL_EXECUTOR_GATE_INVALID'));
165
158
  return;
166
159
  }
167
- if (typeof value.requestId !== 'string' || typeof value.operationId !== 'string'
168
- || !['orchestration.prepare', 'artifact.preflight', 'artifact.finalize-local', 'task-event.completed'].includes(value.phase)
169
- || (value.authority !== null && value.authority !== undefined && (() => {
170
- try {
171
- validateLifecycleRecoveryAttestation(value.authority);
172
- return false;
173
- }
174
- catch {
175
- return true;
176
- }
177
- })())) {
160
+ if (typeof value.requestId !== 'string') {
178
161
  reject(new Error('SANDBOX_CONTROL_EXECUTOR_GATE_INVALID'));
179
162
  return;
180
163
  }
181
164
  resolve({
182
165
  owner: owner,
183
- authority: value.authority === null || value.authority === undefined ? null : value.authority,
184
- requestId: value.requestId,
185
- operationId: value.operationId,
186
- phase: value.phase
166
+ requestId: value.requestId
187
167
  });
188
168
  });
189
169
  });
@@ -205,16 +185,6 @@ function controllerFailure(error) {
205
185
  };
206
186
  return { exitCode: 1, stdout: `${JSON.stringify(payload)}\n`, stderr: '' };
207
187
  }
208
- function orchestrationFailure(code, message) {
209
- return {
210
- exitCode: 1,
211
- stdout: `${JSON.stringify({
212
- status: 'failed', changed: false, taskId: null, run: null, next: null,
213
- error: { code, message }
214
- })}\n`,
215
- stderr: ''
216
- };
217
- }
218
188
  function lifecycleFailure(code, message) {
219
189
  return {
220
190
  exitCode: 1,
@@ -324,8 +294,6 @@ async function executeRequestInner(manifest, manifestPath, request, options = {}
324
294
  return controllerFailure(error);
325
295
  }
326
296
  }
327
- if (request.family === 'task-workflow')
328
- return executeTaskWorkflow(manifest, request.workflow, options.lifecycleRecoveryAttestation ?? null);
329
297
  if (request.family === 'task-finalization') {
330
298
  const operation = parseTaskControlOperation('task-finalization', [manifest.taskId, 'complete', '--agent', request.agent]);
331
299
  if (operation.family !== 'task-finalization')
@@ -337,15 +305,11 @@ async function executeRequestInner(manifest, manifestPath, request, options = {}
337
305
  taskId: manifest.taskId,
338
306
  generation: manifest.generation,
339
307
  manifestPath,
340
- requestId: request.id,
341
- lifecycleRecoveryAttestation: options.lifecycleRecoveryAttestation ?? null
308
+ requestId: request.id
342
309
  }), operation);
343
310
  return finalizationResult(await result);
344
311
  }
345
312
  const boundArgs = bindSandboxControlTask(request, manifest.taskId);
346
- if (request.family === 'task-orchestration') {
347
- boundArgs.push('--git-worktree-root', manifest.worktreeRoot);
348
- }
349
313
  let operation;
350
314
  try {
351
315
  operation = parseTaskControlOperation(request.family, boundArgs);
@@ -353,55 +317,8 @@ async function executeRequestInner(manifest, manifestPath, request, options = {}
353
317
  catch (error) {
354
318
  const message = error instanceof Error ? error.message : String(error);
355
319
  const code = /^([A-Z][A-Z0-9_]+)/u.exec(message)?.[1] ?? 'TASK_CONTROL_OPERATION_INVALID';
356
- return request.family === 'task-lifecycle'
357
- ? lifecycleFailure('LIFECYCLE_PAYLOAD_INVALID', message)
358
- : orchestrationFailure(code, message);
359
- }
360
- let controllerBinding = null;
361
- if (request.family === 'task-orchestration') {
362
- const codexPrepare = operation.family === 'task-orchestration'
363
- && operation.intent === 'prepare'
364
- && operation.input.client === 'codex';
365
- if (codexPrepare) {
366
- if (!request.controllerProof) {
367
- const authority = options.lifecycleRecoveryAttestation;
368
- if (!authority || authority.phase !== 'orchestration.prepare') {
369
- return orchestrationFailure('CODEX_SANDBOX_CONTROLLER_PROOF_REQUIRED', 'Codex prepare requires a current controller lease proof');
370
- }
371
- controllerBinding = {
372
- instanceDigest: authority.controllerInstanceDigest,
373
- controlGeneration: authority.controlGeneration
374
- };
375
- }
376
- else {
377
- try {
378
- controllerBinding = (options.resolveControllerBinding ?? resolveCodexControllerBinding)({
379
- manifest,
380
- manifestPath,
381
- proof: request.controllerProof,
382
- buildIdentity: (options.buildIdentity ?? computeLifecycleBuildIdentity)(manifest.repoRoot)
383
- });
384
- }
385
- catch (error) {
386
- const code = error instanceof CodexControllerRegistrationError
387
- ? error.code
388
- : 'CODEX_SANDBOX_CONTROLLER_PROOF_INVALID';
389
- return orchestrationFailure(code, `${code}: Codex controller proof was rejected`);
390
- }
391
- }
392
- }
393
- else if (request.controllerProof !== null) {
394
- return orchestrationFailure('CODEX_SANDBOX_CONTROLLER_PROOF_INVALID', 'Controller proof is only accepted for canonical Codex prepare');
395
- }
320
+ return lifecycleFailure('LIFECYCLE_PAYLOAD_INVALID', `${code}: ${message}`);
396
321
  }
397
- const diagnosticLog = (event, fields) => {
398
- appendExecutorAudit(manifest, event.startsWith('orchestration-') ? event : `orchestration-${event}`, {
399
- requestId: request.id,
400
- requestFamily: request.family,
401
- sandboxTaskId: manifest.taskId,
402
- ...fields
403
- });
404
- };
405
322
  const context = createSandboxExecutorExecutionContext({
406
323
  repoRoot: manifest.repoRoot,
407
324
  worktreeRoot: manifest.worktreeRoot,
@@ -409,10 +326,7 @@ async function executeRequestInner(manifest, manifestPath, request, options = {}
409
326
  taskId: manifest.taskId,
410
327
  generation: manifest.generation,
411
328
  manifestPath,
412
- requestId: request.id,
413
- diagnosticLog,
414
- ...(controllerBinding ? { controllerBinding } : {}),
415
- lifecycleRecoveryAttestation: options.lifecycleRecoveryAttestation ?? null
329
+ requestId: request.id
416
330
  });
417
331
  const format = (value) => {
418
332
  const result = value;
@@ -422,11 +336,6 @@ async function executeRequestInner(manifest, manifestPath, request, options = {}
422
336
  stderr: ''
423
337
  };
424
338
  };
425
- if (request.family === 'task-orchestration') {
426
- if (operation.family !== 'task-orchestration')
427
- throw new Error('SANDBOX_CONTROL_ORCHESTRATION_OPERATION_INVALID');
428
- return format(await dispatchTaskControlOperation(context, operation));
429
- }
430
339
  if (operation.family !== 'task-lifecycle')
431
340
  throw new Error('SANDBOX_CONTROL_LIFECYCLE_OPERATION_INVALID');
432
341
  return format(await dispatchTaskControlOperation(context, operation));
@@ -487,12 +396,6 @@ export async function runSandboxControlExecutor(requestPath, nonce) {
487
396
  const request = validateSandboxControlRequest(raw, manifest);
488
397
  if (gate.requestId !== request.id)
489
398
  throw new Error('SANDBOX_CONTROL_EXECUTOR_GATE_REQUEST_MISMATCH');
490
- if (gate.authority !== null
491
- && (gate.authority.requestId !== request.id
492
- || gate.authority.operationId !== gate.operationId
493
- || gate.authority.phase !== gate.phase)) {
494
- throw new Error('SANDBOX_CONTROL_EXECUTOR_GATE_AUTHORITY_MISMATCH');
495
- }
496
399
  appendExecutorAudit(manifest, 'executor-request-validated', requestAuditFields(manifest, request));
497
400
  const requestDirectory = path.resolve(path.dirname(requestPath));
498
401
  const processingDirectory = path.resolve(path.join(manifest.processingDir, request.id));
@@ -510,7 +413,7 @@ export async function runSandboxControlExecutor(requestPath, nonce) {
510
413
  let result;
511
414
  try {
512
415
  assertSandboxControlExecutorAuthority(manifest, gateOwner);
513
- const operation = request.family === 'task-lifecycle' || request.family === 'task-orchestration'
416
+ const operation = request.family === 'task-lifecycle'
514
417
  ? (() => {
515
418
  try {
516
419
  return parseTaskControlOperation(request.family, request.args);
@@ -523,11 +426,9 @@ export async function runSandboxControlExecutor(requestPath, nonce) {
523
426
  const context = createSandboxControlAuditContext(manifest, {
524
427
  requestId: request.id,
525
428
  family: request.family,
526
- operation: operation?.family === 'task-orchestration'
527
- ? operation.intent
528
- : operation?.family === 'task-lifecycle'
529
- ? operation.request.intent
530
- : request.family === 'task-finalization' ? request.operation : null,
429
+ operation: operation?.family === 'task-lifecycle'
430
+ ? operation.request.intent
431
+ : request.family === 'task-finalization' ? request.operation : null,
531
432
  phase: 'started-committed',
532
433
  outcome: 'in-progress'
533
434
  });
@@ -535,9 +436,7 @@ export async function runSandboxControlExecutor(requestPath, nonce) {
535
436
  writeSandboxControlTransition(manifest, { requestId: request.id, phase: 'started-committed' });
536
437
  const execution = readJsonExecution(executionPath(manifest, request.id));
537
438
  atomicWriteJson(executionPath(manifest, request.id), { ...execution, phase: 'running', updatedAt: Date.now() });
538
- result = await executeRequest(manifest, manifestPath, request, {
539
- lifecycleRecoveryAttestation: gate.authority
540
- });
439
+ result = await executeRequest(manifest, manifestPath, request);
541
440
  }
542
441
  catch (error) {
543
442
  appendExecutorAudit(manifest, 'executor-authority-or-dispatch-failed', {
@@ -557,9 +456,7 @@ export async function runSandboxControlExecutor(requestPath, nonce) {
557
456
  }
558
457
  : request.family === 'task-create'
559
458
  ? taskCreateExecutionFailure(request.id, code, detail)
560
- : request.family === 'task-lifecycle'
561
- ? lifecycleFailure(code, detail)
562
- : orchestrationFailure(code, detail);
459
+ : lifecycleFailure(code, detail);
563
460
  }
564
461
  process.stdout.write(result.stdout);
565
462
  process.stderr.write(result.stderr);
@@ -1,18 +1,24 @@
1
1
  export function finalizationTerminalResponse(taskId, requestId, receipt) {
2
2
  const pendingSteps = [
3
3
  receipt.taskComment === 'pending' ? 'task-comment' : null,
4
- receipt.verification === 'pending' ? 'verification' : null
4
+ receipt.verification === 'pending' ? 'verification' : null,
5
+ receipt.summary === 'pending' ? 'summary' : null
5
6
  ].filter((step) => step !== null);
6
- const completedSteps = ['lifecycle', receipt.taskComment === 'pending' ? null : 'task-comment', receipt.verification === 'pending' ? null : 'verification']
7
+ const completedSteps = [
8
+ 'lifecycle', receipt.taskComment === 'pending' ? null : 'task-comment',
9
+ receipt.verification === 'pending' ? null : 'verification', receipt.summary === 'pending' ? null : 'summary'
10
+ ]
7
11
  .filter((step) => step !== null);
8
12
  const warnings = receipt.warnings
9
13
  .filter((warning) => warning.status === 'open')
10
14
  .map(({ status: _status, resolvedAt: _resolvedAt, ...warning }) => warning);
11
15
  const result = {
12
16
  status: 'completed', changed: false, taskId,
17
+ backfill: { status: 'no-op', changed: false, error: null },
13
18
  lifecycle: { status: 'no-op', changed: false, error: null },
14
19
  taskComment: receipt.taskComment === 'pending' ? null : { status: 'no-op', changed: false, error: null },
15
20
  verification: receipt.verification === 'pending' ? null : { status: 'no-op', changed: false, error: null },
21
+ summary: receipt.summary === 'pending' ? null : { status: 'no-op', changed: false, error: null },
16
22
  completedSteps, pendingSteps,
17
23
  result: pendingSteps.length > 0 || receipt.warningProjection === 'pending' || warnings.length > 0
18
24
  ? 'completed_with_warnings' : 'completed',
@@ -1,8 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { validateTaskCreateCandidate } from '../../task/create.js';
3
3
  import { normalizeAgentToken } from '../../agent-clients/tokens.js';
4
- import { validateTaskWorkflowRequest } from './task-workflow.js';
5
- import { validateLifecycleAuthorityRequest } from '../../task/control-authority.js';
6
4
  export const SANDBOX_CONTROL_MAX_BYTES = 64 * 1024;
7
5
  export const SANDBOX_CONTROL_MAX_LOGICAL_RECORDS = 1024;
8
6
  export const SANDBOX_CONTROL_MAX_RESPONSE_BYTES = 64 * 1024 * 1024;
@@ -12,7 +10,7 @@ export const SANDBOX_CONTROL_ADMISSION_WINDOW_MS = 2_000;
12
10
  export const SANDBOX_CONTROL_STATUS_INTERVAL_MS = 250;
13
11
  export const SANDBOX_CONTROL_STATUS_STALE_MS = 1_500;
14
12
  export const SANDBOX_CONTROL_FUTURE_SKEW_MS = 1_000;
15
- export const SANDBOX_CONTROL_FAMILIES = ['task-lifecycle', 'task-orchestration', 'task-finalization', 'task-create', 'codex-controller', 'task-workflow'];
13
+ export const SANDBOX_CONTROL_FAMILIES = ['task-lifecycle', 'task-finalization', 'task-create', 'codex-controller'];
16
14
  export const DEFAULT_SANDBOX_CONTROL_TIMING = Object.freeze({
17
15
  controlTickMs: 250,
18
16
  parkedBindingInitialMs: 1_000,
@@ -173,78 +171,21 @@ export function validateSandboxControlRequest(value, manifest, options = {}) {
173
171
  }
174
172
  return request;
175
173
  }
176
- if (request.family === 'task-workflow') {
177
- const expected = ['args', 'authority', 'controllerProcess', 'controllerProof', 'expiresAt', 'family', 'generation', 'id', 'issuedAt', 'token', 'version', 'workflow'];
178
- const baseExpected = expected.filter((key) => key !== 'authority');
179
- if (![baseExpected, expected].some((keys) => Object.keys(request).sort().join(',') === keys.sort().join(','))
180
- || !Array.isArray(request.args) || request.args.length !== 0
181
- || request.controllerProcess !== null || request.controllerProof !== null) {
182
- fail('SANDBOX_CONTROL_REQUEST_INVALID', 'task-workflow request schema is invalid');
183
- }
184
- if (manifest.mode !== 'task-bound' || !manifest.taskId)
185
- fail('SANDBOX_CONTROL_BRANCH_ONLY', 'branch-only sandboxes cannot use task-workflow');
186
- const workflow = validateTaskWorkflowRequest(request.workflow);
187
- if (workflow.taskId !== manifest.taskId || workflow.generation !== manifest.generation || workflow.id !== request.id) {
188
- fail('SANDBOX_CONTROL_REQUEST_INVALID', 'task-workflow binding does not match the sandbox manifest');
189
- }
190
- if (request.authority !== undefined)
191
- validateAuthoritySelector(request.authority, request, manifest);
192
- return { ...request, workflow };
193
- }
194
- const expected = ['args', 'authority', 'controllerProcess', 'controllerProof', 'expiresAt', 'family', 'generation', 'id', 'issuedAt', 'token', 'version'];
195
- const baseExpected = expected.filter((key) => key !== 'authority');
196
- if (![baseExpected, expected].some((keys) => Object.keys(request).sort().join(',') === keys.sort().join(','))
174
+ const expected = ['args', 'controllerProcess', 'controllerProof', 'expiresAt', 'family', 'generation', 'id', 'issuedAt', 'token', 'version'];
175
+ if (Object.keys(request).sort().join(',') !== expected.sort().join(',')
197
176
  || !Array.isArray(request.args) || !request.args.every((arg) => typeof arg === 'string')) {
198
177
  fail('SANDBOX_CONTROL_REQUEST_INVALID', 'request schema or authorization is invalid');
199
178
  }
200
179
  if (manifest.mode !== 'task-bound' || !manifest.taskId) {
201
180
  fail('SANDBOX_CONTROL_BRANCH_ONLY', "branch-only sandboxes cannot coordinate tasks; return to the host and run 'ai sandbox start --recreate <task-ref-or-correct-branch>'");
202
181
  }
203
- if (request.family === 'task-orchestration'
204
- && request.args.some((arg) => arg === '--git-worktree-root' || arg.startsWith('--git-worktree-root='))) {
205
- fail('SANDBOX_CONTROL_REQUEST_INVALID', 'worktree binding is reserved for the control broker');
206
- }
207
- if (request.controllerProcess !== null
208
- || (request.controllerProof !== null && !validControllerProof(request.controllerProof))) {
182
+ if (request.controllerProcess !== null || request.controllerProof !== null) {
209
183
  fail('SANDBOX_CONTROL_REQUEST_INVALID', 'controller authority is invalid');
210
184
  }
211
- if (request.family !== 'task-orchestration' && request.controllerProof !== null) {
212
- fail('SANDBOX_CONTROL_REQUEST_INVALID', 'controller proof is not allowed for this family');
213
- }
214
- if (request.authority !== undefined)
215
- validateAuthoritySelector(request.authority, request, manifest);
216
185
  return request;
217
186
  }
218
- function validateAuthoritySelector(value, request, manifest) {
219
- let authority;
220
- try {
221
- authority = validateLifecycleAuthorityRequest(value);
222
- }
223
- catch {
224
- fail('SANDBOX_CONTROL_AUTHORITY_INVALID', 'lifecycle authority selector is invalid');
225
- }
226
- if (authority.requestId !== request.id
227
- || authority.taskId !== manifest.taskId
228
- || authority.expectedControlGeneration !== manifest.generation) {
229
- fail('SANDBOX_CONTROL_AUTHORITY_INVALID', 'lifecycle authority selector is not bound to this request');
230
- }
231
- const args = Array.isArray(request.args) ? request.args : [];
232
- if (request.family === 'task-orchestration'
233
- && (args[1] !== 'prepare' || authority.phase !== 'orchestration.prepare')) {
234
- fail('SANDBOX_CONTROL_AUTHORITY_INVALID', 'orchestration authority is only valid for prepare');
235
- }
236
- const workflow = request.workflow;
237
- if (request.family === 'task-workflow') {
238
- const expectedPhase = workflow?.operation === 'artifact-finalize-local'
239
- ? 'artifact.finalize-local'
240
- : workflow?.operation === 'event' ? 'task-event.completed' : null;
241
- if (authority.phase !== expectedPhase) {
242
- fail('SANDBOX_CONTROL_AUTHORITY_INVALID', 'workflow authority phase does not match the workflow operation');
243
- }
244
- }
245
- }
246
187
  export function bindSandboxControlTask(request, taskId) {
247
- if (request.family === 'task-create' || request.family === 'codex-controller' || request.family === 'task-finalization' || request.family === 'task-workflow') {
188
+ if (request.family === 'task-create' || request.family === 'codex-controller' || request.family === 'task-finalization') {
248
189
  fail('SANDBOX_CONTROL_REQUEST_INVALID', `${request.family} requests do not bind a current task`);
249
190
  }
250
191
  if (request.args.length === 0)