@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
@@ -1,5 +1,4 @@
1
1
  import { finalizationTerminalResponse } from './finalization-response.js';
2
- import { isDeepStrictEqual } from 'node:util';
3
2
  import { completedReentryView } from './completed-reentry.js';
4
3
  import fs from 'node:fs';
5
4
  import path from 'node:path';
@@ -13,10 +12,6 @@ import { validateSandboxControlRequest } from './protocol.js';
13
12
  import { requestAuditFields, resultAuditFields, appendCriticalAudit, appendDiagnosticAudit, createSandboxControlAuditContext, writeSandboxControlTransition, readSandboxControlTransition } from './audit.js';
14
13
  import { parseTaskControlOperation } from '../../task/control-authority.js';
15
14
  import { parseControlOutput, classifySandboxControlRecovery, findSandboxControlRecoveryOperation, operationRecoveryBinding, SANDBOX_CONTROL_REQUIRED_COMPLETION_PHASES } from '../../task/control-recovery.js';
16
- import { readRun } from '../../task/orchestration.js';
17
- import { readLifecycleRecoveryDomainEvidence } from '../../task/lifecycle-recovery.js';
18
- import { captureRepositorySnapshot } from '../../task/workspace-snapshot.js';
19
- import { parseTypedTaskFrontmatter } from '../../task/frontmatter.js';
20
15
  import { readLifecycleJournalEvidence } from '../../task/lifecycle.js';
21
16
  import { resolveTaskRef } from '../../task/resolve-ref.js';
22
17
  import { loadShortIdByTaskId } from '../../task/short-id.js';
@@ -28,94 +23,32 @@ import { readCodexControllerRegistration } from './controller-registration.js';
28
23
  import { validateSandboxControlIdentity } from './identity-sentinel.js';
29
24
  import { mergeSandboxTaskView, taskViewAfterFinalization, taskViewForManifest } from './task-view.js';
30
25
  import { taskCreateOutputUnavailableResult } from '../../task/create-service.js';
31
- import { consumeLifecycleRecoveryAttestation, issueLifecycleRecoveryAttestation, recoverLifecycleRecoveryOperation } from '../../task/control-authority.js';
32
- import { createCodexCapabilityStore } from '../../agent-clients/adapters/codex-lifecycle/capability-store.js';
33
- import { computeLifecycleBuildIdentity } from '../../agent-clients/adapters/codex-lifecycle/build-identity.js';
34
- function consumeLifecycleAuthorityForResult(manifest, execution) {
35
- const authority = execution.lifecycleAuthority?.attestation;
36
- if (!authority || execution.result?.exitCode !== 0)
37
- return true;
38
- try {
39
- consumeLifecycleRecoveryAttestation(authority);
40
- return true;
41
- }
42
- catch (error) {
43
- appendBrokerAudit(manifest, 'lifecycle-authority-consume-retry', {
44
- ...requestAuditFields(manifest, execution.request),
45
- errorCode: error instanceof Error ? error.name : 'LIFECYCLE_AUTHORITY_CONSUME_FAILED'
46
- });
47
- return false;
48
- }
49
- }
50
- function lifecycleAuthorityForRequest(manifest, manifestPath, request) {
51
- const selector = request.family === 'task-workflow' || request.family === 'task-orchestration'
52
- ? request.authority
53
- : undefined;
54
- if (!selector)
55
- return undefined;
56
- let controllerBinding = null;
57
- try {
58
- const registration = readCodexControllerRegistration(manifestPath);
59
- controllerBinding = {
60
- instanceDigest: registration.controllerInstanceDigest,
61
- controlGeneration: registration.controlGeneration
62
- };
63
- }
64
- catch {
65
- // The issuer reports the stable unavailable result; the broker never trusts
66
- // a controller binding supplied by the request.
67
- }
68
- return issueLifecycleRecoveryAttestation(selector, {
69
- controllerBinding,
70
- capabilityStore: createCodexCapabilityStore(),
71
- buildIdentity: computeLifecycleBuildIdentity(manifest.repoRoot)
72
- });
73
- }
74
26
  function appendBrokerAudit(manifest, event, fields = {}) {
75
27
  appendDiagnosticAudit(manifest, event, { source: 'broker', ...fields });
76
28
  }
77
- function operationKey(request, output) {
29
+ function operationKey(request) {
78
30
  if (request.family === 'task-finalization')
79
31
  return request.operation;
80
32
  if (request.family === 'task-create')
81
33
  return 'create';
82
34
  if (request.family === 'codex-controller')
83
35
  return request.command;
84
- if (request.family === 'task-workflow')
85
- return request.workflow.operation;
86
- if (request.family !== 'task-lifecycle' && request.family !== 'task-orchestration')
36
+ if (request.family !== 'task-lifecycle')
87
37
  return null;
88
- if (request.family === 'task-orchestration' && request.args[1] === 'route') {
89
- if (!output)
90
- return 'route';
91
- const result = parseControlOutput(output);
92
- return result?.changed === true && result.status === 'completed' ? 'route.clean-completion' : 'route.read';
93
- }
94
38
  try {
95
39
  const operation = parseTaskControlOperation(request.family, request.args);
96
- return operation.family === 'task-orchestration' ? operation.intent : operation.request.intent;
40
+ return operation.family === 'task-lifecycle' ? operation.request.intent : null;
97
41
  }
98
42
  catch {
99
43
  return null;
100
44
  }
101
45
  }
102
- function recoveryOperationKey(request, terminalResult, output) {
103
- const operation = operationKey(request, output);
104
- if (operation !== 'route')
105
- return operation;
106
- const digest = terminalResult?.intentDigest;
107
- for (const candidate of ['route.read', 'route.clean-completion']) {
108
- const expected = operationRecoveryBinding(request.id, request.generation, null, request.family, candidate).intentDigest;
109
- if (digest === expected)
110
- return candidate;
111
- }
112
- return null;
46
+ function recoveryOperationKey(request) {
47
+ return operationKey(request);
113
48
  }
114
49
  function terminalResultMatchesRequest(request, terminalResult) {
115
50
  const operation = operationKey(request);
116
- const candidates = operation === 'route'
117
- ? ['route.read', 'route.clean-completion']
118
- : operation ? [operation] : [];
51
+ const candidates = operation ? [operation] : [];
119
52
  return candidates.some((candidate) => createHash('sha256').update(`${request.family}\0${candidate}`, 'utf8').digest('hex') === terminalResult.intentDigest);
120
53
  }
121
54
  function criticalRequestPhase(manifest, request, phase, outcome, reference) {
@@ -257,7 +190,7 @@ function outputMatchesEvidence(output, bytes, sha256) {
257
190
  return Buffer.byteLength(output, 'utf8') === bytes
258
191
  && createHash('sha256').update(output, 'utf8').digest('hex') === sha256;
259
192
  }
260
- export function genericRecoveryResponse(request, exitCode, payload, cause = 'recovery', warning = null) {
193
+ export function genericRecoveryResponse(request, exitCode, payload, cause = 'recovery') {
261
194
  const outputUnavailable = request.family === 'task-create' && !payload;
262
195
  return {
263
196
  version: 2,
@@ -265,11 +198,9 @@ export function genericRecoveryResponse(request, exitCode, payload, cause = 'rec
265
198
  phase: 'completed',
266
199
  exitCode,
267
200
  stdout: outputUnavailable ? `${JSON.stringify(taskCreateOutputUnavailableResult(request.id))}\n` : '',
268
- stderr: payload ? '' : warning
269
- ? `${warning.code}: ${warning.message}\nAction: ${warning.action}\n`
270
- : cause === 'publish'
271
- ? 'SANDBOX_CONTROL_OUTPUT_UNAVAILABLE: output payload was not retained\n'
272
- : 'SANDBOX_CONTROL_OUTPUT_UNAVAILABLE: broker restarted after executor completion\n',
201
+ stderr: payload ? '' : cause === 'publish'
202
+ ? 'SANDBOX_CONTROL_OUTPUT_UNAVAILABLE: output payload was not retained\n'
203
+ : 'SANDBOX_CONTROL_OUTPUT_UNAVAILABLE: broker restarted after executor completion\n',
273
204
  error: null,
274
205
  outputState: payload ? 'available' : 'unavailable',
275
206
  payload: payload ? payloadReference(payload) : null
@@ -335,32 +266,10 @@ function controllerDomainEvidence(manifest, manifestPath, request, output) {
335
266
  && output?.status === 'closed' && typeof output.changed === 'boolean' };
336
267
  }
337
268
  }
338
- function orchestrationDomainEvidence(operation, terminalResult, output, run) {
339
- if (!operation || !output)
340
- return { consistent: false };
341
- const outputRun = output.run && typeof output.run === 'object' && !Array.isArray(output.run)
342
- ? output.run : null;
343
- const runMatches = outputRun === null ? run === null : run !== null && JSON.stringify(run) === JSON.stringify(outputRun);
344
- if (operation.class === 'read-only') {
345
- return {
346
- consistent: output.status === terminalResult.status && output.changed === terminalResult.changed && runMatches,
347
- snapshotValid: true,
348
- status: run?.status ?? terminalResult.status,
349
- pendingDelegation: run?.pendingDelegation ?? null
350
- };
351
- }
352
- if (!run || !outputRun)
353
- return { consistent: false };
354
- return {
355
- consistent: output.status === terminalResult.status && output.changed === terminalResult.changed && runMatches,
356
- status: run.status,
357
- pendingDelegation: run.pendingDelegation
358
- };
359
- }
360
- function readRecoveryDomain(manifest, manifestPath, request, operation, terminalResult, payloadOutput) {
269
+ async function readRecoveryDomain(manifest, manifestPath, request, operation, terminalResult, payloadOutput) {
361
270
  if (!operation)
362
271
  return { domain: null };
363
- const taskRef = request.family === 'task-finalization' || request.family === 'task-workflow'
272
+ const taskRef = request.family === 'task-finalization'
364
273
  ? manifest.taskId
365
274
  : 'args' in request ? request.args[0] ?? null : manifest.taskId;
366
275
  const output = parseControlOutput(payloadOutput);
@@ -369,21 +278,7 @@ function readRecoveryDomain(manifest, manifestPath, request, operation, terminal
369
278
  }
370
279
  if (operation.family === 'task-lifecycle') {
371
280
  if (operation.intent === 'recover-started') {
372
- try {
373
- if (!('args' in request))
374
- return { domain: null };
375
- const parsed = parseTaskControlOperation('task-lifecycle', request.args);
376
- if (parsed.family !== 'task-lifecycle' || parsed.request.intent !== 'recover-started') {
377
- return { domain: null };
378
- }
379
- return {
380
- domain: readLifecycleRecoveryDomainEvidence(manifest.repoRoot, parsed.request, terminalResult),
381
- journal: readLifecycleJournalEvidence(manifest.repoRoot, taskRef)
382
- };
383
- }
384
- catch {
385
- return { domain: null };
386
- }
281
+ return { domain: null };
387
282
  }
388
283
  if (!taskRef || !terminalResult.targetState)
389
284
  return { domain: null };
@@ -403,51 +298,12 @@ function readRecoveryDomain(manifest, manifestPath, request, operation, terminal
403
298
  return { domain: { consistent: false }, journal };
404
299
  }
405
300
  }
406
- if (operation.family === 'task-orchestration') {
407
- if (!taskRef)
408
- return { domain: null };
409
- try {
410
- const resolved = resolveTaskRef(taskRef, { repoRoot: manifest.repoRoot });
411
- if (!resolved.ok)
412
- return { domain: { consistent: false } };
413
- const run = readRun(resolved.taskDir);
414
- if (!run && operation.class !== 'read-only')
415
- return { domain: { consistent: false } };
416
- if (operation.class === 'route.clean-completion') {
417
- const snapshot = captureRepositorySnapshot(manifest.repoRoot);
418
- const metadata = parseTypedTaskFrontmatter(fs.readFileSync(resolved.taskMdPath, 'utf8'));
419
- const completion = run?.completionEvidence ?? null;
420
- const consistent = run !== null && completion !== null
421
- && terminalResult.completionEvidence !== null
422
- && isDeepStrictEqual(completion, terminalResult.completionEvidence);
423
- return {
424
- domain: {
425
- consistent,
426
- status: run?.status ?? null,
427
- pendingDelegation: run?.pendingDelegation ?? null,
428
- completionEvidence: completion,
429
- snapshot,
430
- lastReviewedCommit: metadata.last_reviewed_commit
431
- }
432
- };
433
- }
434
- return { domain: orchestrationDomainEvidence(operation, terminalResult, output, run) };
435
- }
436
- catch {
437
- return { domain: { consistent: false } };
438
- }
439
- }
440
301
  if (operation.family === 'task-create') {
441
302
  return { domain: taskCreateDomainEvidence(manifest, output) };
442
303
  }
443
304
  if (operation.family === 'codex-controller') {
444
305
  return { domain: controllerDomainEvidence(manifest, manifestPath, request, output) };
445
306
  }
446
- if (operation.family === 'task-workflow') {
447
- return {
448
- domain: { consistent: output?.status === terminalResult.status && output.changed === terminalResult.changed, snapshotValid: true }
449
- };
450
- }
451
307
  return { domain: null };
452
308
  }
453
309
  function readCommittedCriticalPhases(manifest, requestId) {
@@ -461,8 +317,8 @@ function readCommittedCriticalPhases(manifest, requestId) {
461
317
  }
462
318
  });
463
319
  }
464
- export function recoveryResponse(manifest, manifestPath, request, evidence, payload, terminalResult) {
465
- const operationName = recoveryOperationKey(request, terminalResult, payload?.stdout);
320
+ export async function recoveryResponse(manifest, manifestPath, request, evidence, payload, terminalResult) {
321
+ const operationName = recoveryOperationKey(request);
466
322
  const operation = operationName ? findSandboxControlRecoveryOperation(request.family, operationName) : null;
467
323
  if (!operation)
468
324
  return null;
@@ -476,32 +332,9 @@ export function recoveryResponse(manifest, manifestPath, request, evidence, payl
476
332
  const finalization = request.family === 'task-finalization' ? finalizationRecoveryResponse(manifest, request.id, 0) : null;
477
333
  if (evidence.exitCode === 0 && finalization?.status === 'deferred')
478
334
  return null;
479
- if (evidence.exitCode === 0 && request.family === 'task-workflow' && request.authority?.phase === 'task-event.completed') {
480
- try {
481
- const registration = readCodexControllerRegistration(manifestPath);
482
- const recovered = recoverLifecycleRecoveryOperation(request.authority, {
483
- repoRoot: manifest.repoRoot,
484
- capabilityStore: createCodexCapabilityStore(),
485
- buildIdentity: computeLifecycleBuildIdentity(manifest.repoRoot),
486
- controllerBinding: {
487
- instanceDigest: registration.controllerInstanceDigest,
488
- controlGeneration: registration.controlGeneration
489
- }
490
- });
491
- if (recovered.status !== 'committed')
492
- return null;
493
- }
494
- catch (error) {
495
- appendBrokerAudit(manifest, 'lifecycle-authority-recovery-failed', {
496
- ...requestAuditFields(manifest, request),
497
- errorCode: error instanceof Error ? error.name : 'LIFECYCLE_AUTHORITY_RECOVERY_FAILED'
498
- });
499
- return null;
500
- }
501
- }
502
335
  const recovery = finalization
503
336
  ? { domain: { consistent: finalization.status === 'matched' } }
504
- : readRecoveryDomain(manifest, manifestPath, request, operation, terminalResult, payload?.stdout ?? null);
337
+ : await readRecoveryDomain(manifest, manifestPath, request, operation, terminalResult, payload?.stdout ?? null);
505
338
  const binding = operationRecoveryBinding(request.id, manifest.generation, manifest.taskId, request.family, operationName);
506
339
  const decision = classifySandboxControlRecovery({
507
340
  operation,
@@ -523,13 +356,13 @@ export function recoveryResponse(manifest, manifestPath, request, evidence, payl
523
356
  return null;
524
357
  return finalization.response ?? null;
525
358
  }
526
- return genericRecoveryResponse(request, evidence.exitCode, payload, 'recovery', terminalResult.warning ?? null);
359
+ return genericRecoveryResponse(request, evidence.exitCode, payload);
527
360
  }
528
- function terminalMatchesEvidence(manifest, manifestPath, request, response, evidence, payload, payloadInvalid, terminalResult) {
361
+ async function terminalMatchesEvidence(manifest, manifestPath, request, response, evidence, payload, payloadInvalid, terminalResult) {
529
362
  if (request.family === 'task-finalization' && evidence.exitCode === 0) {
530
363
  if (!terminalResult)
531
364
  return { valid: false, payloadReferenced: false };
532
- const expected = recoveryResponse(manifest, manifestPath, request, evidence, payload, terminalResult);
365
+ const expected = await recoveryResponse(manifest, manifestPath, request, evidence, payload, terminalResult);
533
366
  return {
534
367
  valid: expected !== null && JSON.stringify(response) === JSON.stringify(expected),
535
368
  payloadReferenced: false
@@ -558,7 +391,7 @@ function terminalMatchesEvidence(manifest, manifestPath, request, response, evid
558
391
  if (response.outputState === 'unavailable') {
559
392
  const causes = ['recovery', 'publish'];
560
393
  const valid = causes.some((cause) => JSON.stringify(response)
561
- === JSON.stringify(genericRecoveryResponse(request, evidence.exitCode, null, cause, terminalResult?.warning ?? null)));
394
+ === JSON.stringify(genericRecoveryResponse(request, evidence.exitCode, null, cause)));
562
395
  return { valid, payloadReferenced: false };
563
396
  }
564
397
  return {
@@ -573,7 +406,7 @@ function publishExecutionResult(manifest, request, result, broker, brokerOwns) {
573
406
  const terminalResult = writeSandboxControlTerminalResult(manifest, {
574
407
  id: request.id,
575
408
  family: request.family,
576
- operation: operationKey(request, normalized.stdout)
409
+ operation: operationKey(request)
577
410
  }, normalized.stdout);
578
411
  if (fs.existsSync(path.join(manifest.processingDir, request.id, 'transitions'))) {
579
412
  criticalRequestPhase(manifest, request, 'completed', normalized.exitCode === 0 ? 'success' : 'failure');
@@ -610,7 +443,7 @@ function publishExecutionResult(manifest, request, result, broker, brokerOwns) {
610
443
  catch {
611
444
  payload = null;
612
445
  }
613
- terminal = genericRecoveryResponse(request, normalized.exitCode, payload, 'publish', terminalResult.warning ?? null);
446
+ terminal = genericRecoveryResponse(request, normalized.exitCode, payload, 'publish');
614
447
  }
615
448
  }
616
449
  if (!brokerOwns())
@@ -697,7 +530,7 @@ function assertCurrentSandboxControlIdentity(manifest, manifestPath) {
697
530
  throw new Error(`SANDBOX_CONTROL_IDENTITY_${result.state.replaceAll('-', '_').toUpperCase()}`);
698
531
  }
699
532
  }
700
- function recoverProcessing(manifest, manifestPath, broker, brokerOwns) {
533
+ async function recoverProcessing(manifest, manifestPath, broker, brokerOwns) {
701
534
  for (const entry of fs.readdirSync(manifest.processingDir, { withFileTypes: true })) {
702
535
  if (!entry.isDirectory() || !/^[a-f0-9-]{16,64}$/.test(entry.name))
703
536
  continue;
@@ -819,7 +652,7 @@ function recoverProcessing(manifest, manifestPath, broker, brokerOwns) {
819
652
  if (terminal && request && resultEvidence) {
820
653
  if (!terminalResult && request.family !== 'task-create')
821
654
  continue;
822
- const reconciliation = terminalMatchesEvidence(manifest, manifestPath, request, existingTerminalResponse, resultEvidence, payload, payloadInvalid, terminalResult);
655
+ const reconciliation = await terminalMatchesEvidence(manifest, manifestPath, request, existingTerminalResponse, resultEvidence, payload, payloadInvalid, terminalResult);
823
656
  if (!reconciliation.valid)
824
657
  continue;
825
658
  terminalReconciled = true;
@@ -852,7 +685,7 @@ function recoverProcessing(manifest, manifestPath, broker, brokerOwns) {
852
685
  return false;
853
686
  if (!resultEvidence || !request || payloadInvalid)
854
687
  continue;
855
- const recovered = recoveryResponse(manifest, manifestPath, request, resultEvidence, payload, terminalResult);
688
+ const recovered = await recoveryResponse(manifest, manifestPath, request, resultEvidence, payload, terminalResult);
856
689
  if (!recovered)
857
690
  continue;
858
691
  if (request.family === 'task-finalization' && resultEvidence.exitCode === 0) {
@@ -1008,7 +841,7 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
1008
841
  pid: broker.pid,
1009
842
  brokerId: broker.brokerId
1010
843
  });
1011
- if (!recoverProcessing(manifest, manifestPath, broker, brokerOwns))
844
+ if (!await recoverProcessing(manifest, manifestPath, broker, brokerOwns))
1012
845
  return;
1013
846
  try {
1014
847
  const published = readSandboxControlStatus(manifest.publicStatusDir);
@@ -1150,10 +983,6 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
1150
983
  break;
1151
984
  let terminalCommitted = false;
1152
985
  if (settledExecution.result && settledExecution.resultEvidenceWritten) {
1153
- if (!consumeLifecycleAuthorityForResult(manifest, settledExecution)) {
1154
- active = settledExecution;
1155
- continue;
1156
- }
1157
986
  terminalCommitted = publishExecutionResult(manifest, settledExecution.request, settledExecution.result, broker, brokerOwns);
1158
987
  if (terminalCommitted && settledExecution.request.family === 'task-finalization') {
1159
988
  try {
@@ -1247,14 +1076,9 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
1247
1076
  executorCwd: manifest.repoRoot,
1248
1077
  executorEntry: options.internalCliPath ?? process.argv[1] ?? null
1249
1078
  });
1250
- const lifecycleAuthority = lifecycleAuthorityForRequest(manifest, manifestPath, request);
1251
- if (lifecycleAuthority?.status === 'rejected') {
1252
- throw Object.assign(new Error(lifecycleAuthority.error?.message ?? 'lifecycle authority was rejected'), { code: lifecycleAuthority.error?.code ?? 'LIFECYCLE_AUTHORITY_REJECTED' });
1253
- }
1254
1079
  prepared = await prepareExecution({
1255
1080
  manifest, manifestPath, request, requestPath: claimed,
1256
- internalCliPath: options.internalCliPath ?? process.argv[1],
1257
- ...(lifecycleAuthority ? { lifecycleAuthority } : {})
1081
+ internalCliPath: options.internalCliPath ?? process.argv[1]
1258
1082
  });
1259
1083
  const preparedExecution = prepared;
1260
1084
  if (!preparedExecution)
@@ -1270,7 +1094,7 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
1270
1094
  executionPath: executionPath(manifest, request.id)
1271
1095
  });
1272
1096
  const execution = {
1273
- request, prepared: preparedExecution, lifecycleAuthority, result: null,
1097
+ request, prepared: preparedExecution, result: null,
1274
1098
  resultEvidenceWritten: false, failure: null, settled: false
1275
1099
  };
1276
1100
  active = execution;
@@ -1431,8 +1255,7 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
1431
1255
  }
1432
1256
  }
1433
1257
  if (owned && active.result && active.resultEvidenceWritten) {
1434
- if (consumeLifecycleAuthorityForResult(manifest, active)
1435
- && publishExecutionResult(manifest, active.request, active.result, broker, brokerOwns)) {
1258
+ if (publishExecutionResult(manifest, active.request, active.result, broker, brokerOwns)) {
1436
1259
  if (brokerOwns()) {
1437
1260
  removeAcceptedResponse(manifest, active.request.id);
1438
1261
  fs.rmSync(path.join(manifest.processingDir, active.request.id), { recursive: true, force: true });
@@ -1,6 +1,5 @@
1
1
  import { isCompletionEvidence } from '../../task/orchestration.js';
2
2
  import { parseControlOutput } from '../../task/control-recovery.js';
3
- import { isRecoveryWarning } from '../../task/recovery-warning.js';
4
3
  import { execFileSync } from 'node:child_process';
5
4
  import fs from 'node:fs';
6
5
  import path from 'node:path';
@@ -84,7 +83,6 @@ export function createSandboxControlTerminalResult(manifest, request, output) {
84
83
  ? nested.run : null;
85
84
  const rawCompletion = nested.completionEvidence ?? run?.completionEvidence;
86
85
  const operation = request.operation ?? (typeof nested.intent === 'string' ? nested.intent : null) ?? '';
87
- const warning = isRecoveryWarning(nested.warning) ? nested.warning : null;
88
86
  return {
89
87
  version: 1,
90
88
  requestId: request.id,
@@ -94,8 +92,7 @@ export function createSandboxControlTerminalResult(manifest, request, output) {
94
92
  targetState: typeof nested.targetState === 'string' ? nested.targetState : null,
95
93
  status: typeof nested.status === 'string' ? nested.status : 'completed',
96
94
  changed: typeof nested.changed === 'boolean' ? nested.changed : null,
97
- completionEvidence: isCompletionEvidence(rawCompletion) ? rawCompletion : null,
98
- ...(warning ? { warning } : {})
95
+ completionEvidence: isCompletionEvidence(rawCompletion) ? rawCompletion : null
99
96
  };
100
97
  }
101
98
  export function writeSandboxControlTerminalResult(manifest, request, output) {
@@ -126,9 +123,6 @@ export function readSandboxControlTerminalResult(filePath) {
126
123
  if (value.completionEvidence !== null && !isCompletionEvidence(value.completionEvidence)) {
127
124
  throw new Error('SANDBOX_CONTROL_TERMINAL_RESULT_INVALID');
128
125
  }
129
- if (value.warning !== undefined && value.warning !== null && !isRecoveryWarning(value.warning)) {
130
- throw new Error('SANDBOX_CONTROL_TERMINAL_RESULT_INVALID');
131
- }
132
126
  if (value.changed === undefined) {
133
127
  throw new Error('SANDBOX_CONTROL_TERMINAL_RESULT_INVALID');
134
128
  }
@@ -13,9 +13,10 @@ function receiptIdentity(value, generation, requestId) {
13
13
  if (!binding || typeof binding !== 'object' || Array.isArray(binding))
14
14
  return null;
15
15
  const controlBinding = binding;
16
- if (receipt.version !== 2 || typeof receipt.receiptId !== 'string' || receipt.receiptId.length === 0
16
+ if (receipt.version !== 4 || typeof receipt.receiptId !== 'string' || receipt.receiptId.length === 0
17
17
  || !Number.isSafeInteger(receipt.revision) || receipt.revision < 0
18
18
  || receipt.lifecycle !== 'done'
19
+ || !['pending', 'done', 'skipped'].includes(String(receipt.summary))
19
20
  || controlBinding.generation !== generation
20
21
  || typeof controlBinding.requestId !== 'string'
21
22
  || !/^[a-f0-9-]{16,64}$/u.test(controlBinding.requestId)
@@ -15,8 +15,8 @@ export function parseArtifactCommand(args) {
15
15
  const allowed = {
16
16
  inspect: ['--family'],
17
17
  init: ['--family', '--artifact', '--locale'],
18
- 'preflight': ['--family', '--artifact', '--recovery-id'],
19
- 'finalize-local': ['--family', '--artifact', '--recovery-id']
18
+ 'preflight': ['--family', '--artifact'],
19
+ 'finalize-local': ['--family', '--artifact']
20
20
  }[operation];
21
21
  for (let index = 2; index < args.length; index += 1) {
22
22
  const flag = args[index];
@@ -38,12 +38,12 @@ export function parseArtifactCommand(args) {
38
38
  throw new Error("option '--locale' must be 'zh-CN' or 'en'");
39
39
  return {
40
40
  taskRef, operation: operation, family: fields['--family'],
41
- artifact: fields['--artifact'] ?? '', locale, recoveryId: fields['--recovery-id']
41
+ artifact: fields['--artifact'] ?? '', locale
42
42
  };
43
43
  }
44
44
  /** Resolve authoritative task metadata separately from a trusted candidate directory. */
45
45
  export function executeArtifactCommand(command, options = {}) {
46
- const { taskRef, operation, family, artifact, locale, recoveryId } = command;
46
+ const { taskRef, operation, family, artifact, locale } = command;
47
47
  const fail = (code, message) => ({ status: 'failed', changed: false, error: { code, message } });
48
48
  if (operation === 'inspect') {
49
49
  const result = resolveArtifactContext(taskRef, family, { repoRoot: options.repoRoot });
@@ -76,7 +76,7 @@ export function executeArtifactCommand(command, options = {}) {
76
76
  return fail('ARTIFACT_PAYLOAD_INVALID', "preflight and finalize-local only support 'analysis', 'plan', and 'code'");
77
77
  }
78
78
  if (operation === 'preflight')
79
- return { ...preflightLocalArtifact({ taskRef, family, artifact, repoRoot: resolved.repoRoot, recoveryId }) };
80
- return { ...finalizeLocalArtifact({ taskRef, family, artifact, repoRoot: resolved.repoRoot, recoveryId }) };
79
+ return { ...preflightLocalArtifact({ taskRef, family, artifact, repoRoot: resolved.repoRoot }) };
80
+ return { ...finalizeLocalArtifact({ taskRef, family, artifact, repoRoot: resolved.repoRoot }) };
81
81
  }
82
82
  //# sourceMappingURL=artifact-command.js.map