@fitlab-ai/agent-infra 0.11.0 → 0.11.2

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 (146) hide show
  1. package/dist/lib/internal/cli-route-inventory.js +1 -1
  2. package/dist/lib/internal/manual-validation.js +6 -2
  3. package/dist/lib/internal/platform-comment.js +59 -0
  4. package/dist/lib/internal/sandbox-control.js +4 -131
  5. package/dist/lib/internal/task-artifact.js +1 -1
  6. package/dist/lib/internal/task-operation-registry.js +1 -0
  7. package/dist/lib/internal/task-review.js +5 -5
  8. package/dist/lib/internal/task-validate.js +0 -6
  9. package/dist/lib/platform/comment-safety.js +7 -1
  10. package/dist/lib/platform/github-provider.js +13 -3
  11. package/dist/lib/platform/issue-comments.js +120 -13
  12. package/dist/lib/platform/issues.js +3 -4
  13. package/dist/lib/platform/provider-contract.d.ts +2 -0
  14. package/dist/lib/platform/provider-validation.js +7 -2
  15. package/dist/lib/platform/verification-sync.js +161 -156
  16. package/dist/lib/sandbox/control/executor.js +0 -38
  17. package/dist/lib/sandbox/control/finalization-response.js +10 -2
  18. package/dist/lib/sandbox/control/task-view.js +3 -1
  19. package/dist/lib/sandbox/control/workflow-executor.js +32 -41
  20. package/dist/lib/task/artifact-command.js +6 -6
  21. package/dist/lib/task/artifact-lifecycle.js +15 -52
  22. package/dist/lib/task/artifact-operations.js +27 -1
  23. package/dist/lib/task/capabilities.js +0 -2
  24. package/dist/lib/task/codex-orchestration.js +10 -208
  25. package/dist/lib/task/commit-operation.js +3 -18
  26. package/dist/lib/task/control-authority.js +1 -8
  27. package/dist/lib/task/delegation-receipts.js +14 -76
  28. package/dist/lib/task/events.js +147 -278
  29. package/dist/lib/task/finalization-state.js +2 -1
  30. package/dist/lib/task/finalization.js +273 -49
  31. package/dist/lib/task/gate-policy.js +94 -0
  32. package/dist/lib/task/lifecycle-execution.js +2 -11
  33. package/dist/lib/task/local-artifact-finalization.js +31 -245
  34. package/dist/lib/task/orchestration.js +8 -24
  35. package/dist/lib/task/review-artifacts.js +12 -6
  36. package/dist/lib/task/review-command.js +0 -1
  37. package/dist/lib/task/review-finalization.js +47 -218
  38. package/dist/lib/task/verification-engine.js +28 -17
  39. package/dist/lib/task/verification.js +25 -9
  40. package/dist/lib/task/workflow-command.js +4 -1
  41. package/dist/lib/task/workflow-dispatch.js +55 -3
  42. package/dist/lifecycle-build-manifest.json +3 -3
  43. package/lib/internal/cli-route-inventory.ts +1 -1
  44. package/lib/internal/manual-validation.ts +6 -2
  45. package/lib/internal/platform-comment.ts +38 -0
  46. package/lib/internal/sandbox-control.ts +3 -145
  47. package/lib/internal/task-artifact.ts +1 -1
  48. package/lib/internal/task-operation-registry.ts +1 -0
  49. package/lib/internal/task-review.ts +5 -5
  50. package/lib/internal/task-validate.ts +0 -5
  51. package/lib/platform/comment-safety.ts +8 -0
  52. package/lib/platform/github-provider.ts +11 -2
  53. package/lib/platform/issue-comments.ts +132 -13
  54. package/lib/platform/issues.ts +3 -4
  55. package/lib/platform/provider-contract.ts +2 -0
  56. package/lib/platform/provider-validation.ts +6 -2
  57. package/lib/platform/verification-sync.ts +178 -179
  58. package/lib/sandbox/control/executor.ts +0 -44
  59. package/lib/sandbox/control/finalization-response.ts +10 -2
  60. package/lib/sandbox/control/task-view.ts +3 -1
  61. package/lib/sandbox/control/workflow-executor.ts +31 -48
  62. package/lib/task/artifact-command.ts +6 -7
  63. package/lib/task/artifact-lifecycle.ts +12 -49
  64. package/lib/task/artifact-operations.ts +27 -1
  65. package/lib/task/capabilities.ts +0 -1
  66. package/lib/task/codex-orchestration.ts +8 -241
  67. package/lib/task/commit-operation.ts +3 -23
  68. package/lib/task/control-authority.ts +1 -8
  69. package/lib/task/delegation-receipts.ts +12 -79
  70. package/lib/task/events.ts +155 -287
  71. package/lib/task/finalization-state.ts +2 -1
  72. package/lib/task/finalization.ts +277 -57
  73. package/lib/task/gate-policy.ts +133 -0
  74. package/lib/task/lifecycle-execution.ts +10 -21
  75. package/lib/task/local-artifact-finalization.ts +29 -285
  76. package/lib/task/orchestration.ts +12 -41
  77. package/lib/task/review-artifacts.ts +8 -2
  78. package/lib/task/review-command.ts +0 -1
  79. package/lib/task/review-finalization.ts +46 -200
  80. package/lib/task/verification-engine.ts +24 -14
  81. package/lib/task/verification-types.ts +7 -0
  82. package/lib/task/verification.ts +25 -9
  83. package/lib/task/workflow-command.ts +4 -1
  84. package/lib/task/workflow-dispatch.ts +46 -3
  85. package/package.json +2 -2
  86. package/templates/.agents/rules/issue-sync.en.md +2 -0
  87. package/templates/.agents/rules/issue-sync.zh-CN.md +5 -8
  88. package/templates/.agents/rules/lifecycle-orchestration.en.md +7 -7
  89. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +7 -7
  90. package/templates/.agents/rules/local-artifact-repair.en.md +14 -52
  91. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +13 -52
  92. package/templates/.agents/skills/analyze-task/SKILL.en.md +3 -3
  93. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +3 -3
  94. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -10
  95. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -10
  96. package/templates/.agents/skills/block-task/config/verify.json +1 -3
  97. package/templates/.agents/skills/cancel-task/config/verify.json +1 -4
  98. package/templates/.agents/skills/code-task/SKILL.en.md +3 -3
  99. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +3 -3
  100. package/templates/.agents/skills/code-task/config/verify.en.json +1 -12
  101. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -12
  102. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
  103. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
  104. package/templates/.agents/skills/code-task/reference/report-template.en.md +11 -0
  105. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +11 -0
  106. package/templates/.agents/skills/commit/config/verify.json +1 -5
  107. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +6 -6
  108. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +6 -6
  109. package/templates/.agents/skills/complete-task/SKILL.en.md +3 -3
  110. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
  111. package/templates/.agents/skills/complete-task/config/verify.en.json +3 -14
  112. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +3 -14
  113. package/templates/.agents/skills/create-pr/config/verify.json +1 -10
  114. package/templates/.agents/skills/create-task/config/verify.json +1 -4
  115. package/templates/.agents/skills/import-issue/config/verify.json +1 -2
  116. package/templates/.agents/skills/plan-task/SKILL.en.md +3 -3
  117. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +3 -3
  118. package/templates/.agents/skills/plan-task/config/verify.en.json +1 -10
  119. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -10
  120. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +4 -4
  121. package/templates/.agents/skills/review-analysis/SKILL.en.md +2 -2
  122. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +2 -2
  123. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -10
  124. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -10
  125. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +2 -0
  126. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +2 -0
  127. package/templates/.agents/skills/review-code/SKILL.en.md +3 -3
  128. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +3 -3
  129. package/templates/.agents/skills/review-code/config/verify.en.json +1 -10
  130. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -10
  131. package/templates/.agents/skills/review-code/reference/report-template.en.md +2 -0
  132. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +2 -0
  133. package/templates/.agents/skills/review-plan/SKILL.en.md +2 -2
  134. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +2 -2
  135. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -10
  136. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -10
  137. package/templates/.agents/skills/review-plan/reference/report-template.en.md +2 -0
  138. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +2 -0
  139. package/templates/.agents/skills/review-pr/config/verify.en.json +1 -8
  140. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +1 -8
  141. package/templates/.agents/skills/run-manual-validation/config/verify.en.json +38 -13
  142. package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +38 -13
  143. package/templates/.agents/skills/run-task/SKILL.en.md +6 -6
  144. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +6 -6
  145. package/templates/.agents/skills/run-task/reference/host-validation.en.md +2 -2
  146. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +2 -2
@@ -5,21 +5,10 @@ import {
5
5
  resolveCodexThread
6
6
  } from '../agent-clients/adapters/codex-lifecycle/app-server.ts';
7
7
  import { createCodexLifecycleStore } from '../agent-clients/adapters/codex-lifecycle/store.ts';
8
- import {
9
- createCodexCapabilityStore,
10
- isCodexCapabilityProvenanceDetail
11
- } from '../agent-clients/adapters/codex-lifecycle/capability-store.ts';
12
- import type { CodexCapabilityProvenanceDetail } from '../agent-clients/adapters/codex-lifecycle/capability-store.ts';
13
8
  import {
14
9
  computeLifecycleBuildIdentity,
15
- verifyLifecycleBuildIdentity,
16
10
  type LifecycleBuildIdentity,
17
- type LifecycleIdentityWarning
18
11
  } from '../agent-clients/adapters/codex-lifecycle/build-identity.ts';
19
- import { verifyCodexSandboxControllerContextWithWarnings as verifySandboxControllerWithWarnings } from '../agent-clients/adapters/codex-lifecycle/sandbox-controller.ts';
20
- import {
21
- verifyCodexSandboxControllerContextWithWarnings as verifyControllerContextFileWithWarnings
22
- } from '../agent-clients/adapters/codex-lifecycle/controller-context.ts';
23
12
  import type { AgentClientId } from '../agent-clients/types.ts';
24
13
  import { resolveTaskRef } from './resolve-ref.ts';
25
14
  import {
@@ -29,32 +18,20 @@ import {
29
18
  OrchestrationStateError,
30
19
  pauseMatchingOrchestrationDelegation,
31
20
  prepareOrchestrationDelegation,
32
- routeOrchestration,
33
21
  reconcileMatchingOrchestrationDelegation,
34
22
  sealMatchingOrchestrationDelegationWithHostEvidence
35
23
  } from './orchestration.ts';
36
- import { randomUUID, createHash } from 'node:crypto';
37
24
  import type { OrchestrationOptions, OrchestrationResult } from './orchestration.ts';
38
- import {
39
- consumeLifecycleRecoveryAttestation,
40
- issueLifecycleRecoveryAttestation,
41
- validateLifecycleRecoveryAttestation,
42
- type LifecycleRecoveryAttestationV1
43
- } from './control-authority.ts';
44
25
 
45
26
  type LifecycleStore = ReturnType<typeof createCodexLifecycleStore>;
46
- type CapabilityStore = ReturnType<typeof createCodexCapabilityStore>;
47
27
  type CodexBridgeOptions = Readonly<{
48
28
  repoRoot?: string;
49
29
  store?: LifecycleStore;
50
30
  preflight?: typeof preflightCodexLifecycleEvidence;
51
31
  resolveThread?: typeof resolveCodexThread;
52
32
  resolveTerminal?: typeof resolveCodexTerminal;
53
- capabilityStore?: CapabilityStore;
54
33
  buildIdentity?: LifecycleBuildIdentity;
55
34
  orchestrationOptions?: OrchestrationOptions;
56
- controllerBinding?: Readonly<{ instanceDigest: string; controlGeneration: string }>;
57
- deferLifecycleRecoveryConsumption?: boolean;
58
35
  }>;
59
36
 
60
37
  type CodexSpawnIdentity = Readonly<{
@@ -68,35 +45,14 @@ type CodexSpawnIdentity = Readonly<{
68
45
  requestedReasoningEffort?: string;
69
46
  }>;
70
47
 
71
- function buildIdentityDigest(value: LifecycleBuildIdentity): string {
72
- return createHash('sha256').update(JSON.stringify(value), 'utf8').digest('hex');
73
- }
74
-
75
48
  function coreOptions(options: CodexBridgeOptions): OrchestrationOptions {
76
49
  return { ...options.orchestrationOptions, repoRoot: options.repoRoot ?? options.orchestrationOptions?.repoRoot };
77
50
  }
78
51
 
79
- function bridgeFailure(code: string, message: string, detail?: CodexCapabilityProvenanceDetail): OrchestrationResult {
52
+ function bridgeFailure(code: string, message: string): OrchestrationResult {
80
53
  return {
81
54
  status: 'failed', changed: false, taskId: null, run: null, next: null,
82
- error: { code, message, ...(detail ? { detail } : {}) }
83
- };
84
- }
85
-
86
- function capabilityFailure(error: unknown): NonNullable<OrchestrationResult['error']> {
87
- const detailValue = error instanceof Error
88
- ? (error as Error & { detail?: unknown }).detail
89
- : undefined;
90
- return {
91
- code: error instanceof Error && error.name.startsWith('CODEX_CAPABILITY_')
92
- ? error.name
93
- : 'ORCHESTRATION_CLIENT_PREFLIGHT_FAILED',
94
- message: error instanceof Error ? error.message : String(error),
95
- ...(error instanceof Error
96
- && error.name === 'CODEX_CAPABILITY_PROVENANCE_MISMATCH'
97
- && isCodexCapabilityProvenanceDetail(detailValue)
98
- ? { detail: detailValue }
99
- : {})
55
+ error: { code, message }
100
56
  };
101
57
  }
102
58
 
@@ -112,35 +68,12 @@ function requiredStore(options: CodexBridgeOptions): LifecycleStore {
112
68
  return options.store;
113
69
  }
114
70
 
115
- function brokerControllerBinding(): Readonly<{ instanceDigest: string; controlGeneration: string }> | null {
116
- const raw = process.env.AGENT_INFRA_CONTROL_CONTROLLER_BINDING;
117
- if (!raw) return null;
118
- let value: unknown;
119
- try {
120
- value = JSON.parse(raw);
121
- } catch {
122
- throw new Error('CODEX_SANDBOX_CONTROLLER_BINDING_INVALID');
123
- }
124
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
125
- throw new Error('CODEX_SANDBOX_CONTROLLER_BINDING_INVALID');
126
- }
127
- const binding = value as Record<string, unknown>;
128
- if (Object.keys(binding).sort().join(',') !== 'controlGeneration,instanceDigest'
129
- || typeof binding.instanceDigest !== 'string' || !/^[a-f0-9]{64}$/u.test(binding.instanceDigest)
130
- || typeof binding.controlGeneration !== 'string' || binding.controlGeneration.length === 0) {
131
- throw new Error('CODEX_SANDBOX_CONTROLLER_BINDING_INVALID');
132
- }
133
- return binding as { instanceDigest: string; controlGeneration: string };
134
- }
135
-
136
71
  async function prepareCodexOrchestrationDelegation(
137
72
  taskRef: string,
138
73
  input: Readonly<{
139
74
  client: AgentClientId;
140
75
  requestedModel?: string;
141
76
  requestedReasoningEffort?: string;
142
- capabilityRef?: string;
143
- lifecycleRecoveryAttestation?: LifecycleRecoveryAttestationV1 | null;
144
77
  }>,
145
78
  options: CodexBridgeOptions = {}
146
79
  ): Promise<OrchestrationResult> {
@@ -149,164 +82,11 @@ async function prepareCodexOrchestrationDelegation(
149
82
  const repoRoot = options.repoRoot ?? process.cwd();
150
83
  const resolved = resolveTaskRef(taskRef, { repoRoot });
151
84
  if (!resolved.ok) return bridgeFailure(resolved.code, resolved.message);
152
- const preflight = await (options.preflight ?? preflightCodexLifecycleEvidence)(repoRoot);
153
- const capabilityRef = input.capabilityRef;
154
- if (!capabilityRef) {
155
- return bridgeFailure(
156
- 'ORCHESTRATION_CODEX_CAPABILITY_REQUIRED',
157
- 'Codex prepare requires a current-session capability reference'
158
- );
159
- }
160
- const buildIdentity = options.buildIdentity ?? computeLifecycleBuildIdentity(repoRoot);
161
- const brokerController = options.controllerBinding ?? brokerControllerBinding();
162
- const contextPath = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
163
- const contextVerification = contextPath
164
- ? (brokerController
165
- ? verifyControllerContextFileWithWarnings(contextPath, {
166
- repoRoot,
167
- generation: process.env.AGENT_INFRA_CONTROL_GENERATION ?? brokerController.controlGeneration
168
- })
169
- : verifySandboxControllerWithWarnings(contextPath, { repoRoot }))
170
- : null;
171
- const identityWarnings: LifecycleIdentityWarning[] = [...(contextVerification?.warnings ?? [])];
172
- const localController = contextVerification?.context ?? null;
173
- if (localController && brokerController
174
- && (localController.controllerInstanceDigest !== brokerController.instanceDigest
175
- || localController.controlGeneration !== brokerController.controlGeneration)) {
176
- return bridgeFailure(
177
- 'CODEX_SANDBOX_CONTROLLER_BINDING_MISMATCH',
178
- 'broker and local controller bindings do not match'
179
- );
180
- }
181
- const controller = brokerController ?? (localController ? {
182
- instanceDigest: localController.controllerInstanceDigest,
183
- controlGeneration: localController.controlGeneration
184
- } : null);
185
- const capabilityStore = options.capabilityStore ?? createCodexCapabilityStore();
186
- const attested = capabilityStore.inspectReference(capabilityRef);
187
- const capabilityIdentity = verifyLifecycleBuildIdentity(attested.buildIdentity, buildIdentity);
188
- if (!capabilityIdentity.ok) {
189
- return bridgeFailure(capabilityIdentity.code!, capabilityIdentity.message!);
190
- }
191
- identityWarnings.push(...capabilityIdentity.warnings);
192
- const lifecycleProvenance = {
193
- ...attested.buildIdentity,
194
- hookDefinitionHash: preflight.hookDefinitionHash,
195
- ...preflight.hookProvenance,
196
- capabilitySessionId: attested.sessionId!,
197
- capabilityTurnId: attested.turnId!,
198
- capabilityToolUseId: attested.toolUseId!,
199
- controllerInstanceDigest: controller?.instanceDigest ?? null,
200
- controlGeneration: controller?.controlGeneration ?? null
201
- };
202
- const capabilityExpected = {
203
- taskId: resolved.taskId,
204
- hookDefinitionHash: preflight.hookDefinitionHash,
205
- buildIdentity,
206
- ...(controller ? { controller: {
207
- instanceDigest: controller.instanceDigest,
208
- controlGeneration: controller.controlGeneration
209
- } } : {})
210
- };
211
- if (input.lifecycleRecoveryAttestation) {
212
- try { validateLifecycleRecoveryAttestation(input.lifecycleRecoveryAttestation); }
213
- catch (error) {
214
- return bridgeFailure(
215
- 'LIFECYCLE_AUTHORITY_ATTESTATION_INVALID',
216
- error instanceof Error ? error.message : String(error)
217
- );
218
- }
219
- }
220
- let lifecycleRecoveryAttestation: LifecycleRecoveryAttestationV1 | null = input.lifecycleRecoveryAttestation ?? null;
221
- const routed = input.capabilityRef && !lifecycleRecoveryAttestation
222
- ? routeOrchestration(taskRef, coreOptions(options))
223
- : null;
224
- if (routed && !routed.next) return routed;
225
- if (routed?.next && ['analysis', 'plan', 'code'].includes(routed.next.stage)) {
226
- const recoveryRequest = {
227
- version: 1 as const,
228
- requestId: randomUUID(),
229
- operationId: randomUUID(),
230
- phase: 'orchestration.prepare' as const,
231
- taskId: resolved.taskId,
232
- family: routed.next.stage === 'analysis' ? 'analysis' as const
233
- : routed.next.stage === 'plan' ? 'plan' as const : 'code' as const,
234
- artifact: routed.next.artifact,
235
- round: routed.next.round,
236
- lifecycleRequestId: randomUUID(),
237
- authorityRef: capabilityRef,
238
- expectedControlGeneration: controller?.controlGeneration ?? '',
239
- expectedControllerInstanceDigest: controller?.instanceDigest ?? '0'.repeat(64),
240
- expectedBuildIdentityDigest: buildIdentityDigest(buildIdentity),
241
- expectedHookDefinitionHash: preflight.hookDefinitionHash
242
- };
243
- const authority = issueLifecycleRecoveryAttestation(recoveryRequest, {
244
- capabilityStore,
245
- ...(controller ? { controllerBinding: controller } : {}),
246
- buildIdentity
247
- });
248
- if (authority.status === 'rejected' || !authority.attestation) {
249
- return bridgeFailure(
250
- authority.error?.code ?? 'LIFECYCLE_AUTHORITY_REJECTED',
251
- authority.error?.message ?? 'lifecycle authority was rejected'
252
- );
253
- }
254
- lifecycleRecoveryAttestation = authority.attestation;
255
- }
256
- const prepared = prepareOrchestrationDelegation(taskRef, {
257
- ...input,
258
- lifecycleProvenance,
259
- lifecycleRecoveryAttestation
260
- }, {
261
- ...coreOptions(options),
262
- validateLifecycleCapability: () => {
263
- try {
264
- const validated = capabilityStore.validateReference(capabilityRef, capabilityExpected);
265
- if (validated.sessionId !== attested.sessionId
266
- || validated.turnId !== attested.turnId
267
- || validated.toolUseId !== attested.toolUseId) {
268
- return {
269
- code: 'CODEX_CAPABILITY_IDENTITY_CHANGED',
270
- message: 'capability identity changed during validation'
271
- };
272
- }
273
- return null;
274
- } catch (error) {
275
- return capabilityFailure(error);
276
- }
277
- },
278
- consumeLifecycleCapability: () => null
279
- });
280
- if (lifecycleRecoveryAttestation && !options.deferLifecycleRecoveryConsumption && prepared.status !== 'failed') {
281
- try {
282
- consumeLifecycleRecoveryAttestation(lifecycleRecoveryAttestation);
283
- } catch (error) {
284
- return bridgeFailure(
285
- error instanceof Error ? error.name : 'LIFECYCLE_AUTHORITY_CONSUME_FAILED',
286
- error instanceof Error ? error.message : String(error)
287
- );
288
- }
289
- }
290
- return identityWarnings.length > 0 && prepared.status !== 'failed'
291
- ? { ...prepared, warnings: Object.freeze(identityWarnings) }
292
- : prepared;
85
+ await (options.preflight ?? preflightCodexLifecycleEvidence)(repoRoot);
86
+ return prepareOrchestrationDelegation(taskRef, input, coreOptions(options));
293
87
  } catch (error) {
294
88
  if (error instanceof OrchestrationStateError) return bridgeFailure(error.code, error.message);
295
- const detailValue = error instanceof Error
296
- ? (error as Error & { detail?: unknown }).detail
297
- : undefined;
298
- const detail = error instanceof Error
299
- && error.name === 'CODEX_CAPABILITY_PROVENANCE_MISMATCH'
300
- && isCodexCapabilityProvenanceDetail(detailValue)
301
- ? detailValue
302
- : undefined;
303
- return bridgeFailure(
304
- error instanceof Error && error.name.startsWith('CODEX_CAPABILITY_')
305
- ? error.name
306
- : 'ORCHESTRATION_CLIENT_PREFLIGHT_FAILED',
307
- error instanceof Error ? error.message : String(error),
308
- detail
309
- );
89
+ return bridgeFailure('ORCHESTRATION_CLIENT_PREFLIGHT_FAILED', error instanceof Error ? error.message : String(error));
310
90
  }
311
91
  }
312
92
 
@@ -335,16 +115,6 @@ async function activateCodexOrchestrationDelegation(
335
115
  toolUseId: evidence.spawnToolUseId
336
116
  });
337
117
  const buildIdentity = options.buildIdentity ?? computeLifecycleBuildIdentity(repoRoot);
338
- const contextPath = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
339
- const contextVerification = contextPath
340
- ? verifySandboxControllerWithWarnings(contextPath, { repoRoot })
341
- : null;
342
- const controller = options.controllerBinding
343
- ?? brokerControllerBinding()
344
- ?? (contextVerification?.context ? {
345
- instanceDigest: contextVerification.context.controllerInstanceDigest,
346
- controlGeneration: contextVerification.context.controlGeneration
347
- } : null);
348
118
  const activated = activateMatchingOrchestrationDelegation('codex', {
349
119
  nativeAgent: evidence.nativeAgent,
350
120
  childId: evidence.childThreadId,
@@ -366,14 +136,11 @@ async function activateCodexOrchestrationDelegation(
366
136
  capabilityTurnId: evidence.parentTurnId,
367
137
  spawnToolUseId: evidence.spawnToolUseId,
368
138
  spawnObservedAt: record.spawnObservedAt ?? undefined,
369
- controllerInstanceDigest: controller?.instanceDigest ?? null,
370
- controlGeneration: controller?.controlGeneration ?? null
139
+ controllerInstanceDigest: null,
140
+ controlGeneration: null
371
141
  }
372
142
  }, coreOptions(options));
373
- const warnings = contextVerification?.warnings ?? [];
374
- return warnings.length > 0 && activated.status !== 'failed'
375
- ? { ...activated, warnings: Object.freeze(warnings) }
376
- : activated;
143
+ return activated;
377
144
  } catch (error) {
378
145
  if (error instanceof OrchestrationStateError) return bridgeFailure(error.code, error.message);
379
146
  return pauseBridge('ORCHESTRATION_CODEX_START_FAILED', error instanceof Error ? error.message : String(error), options);
@@ -32,8 +32,6 @@ type CommitOperationInput = Readonly<{
32
32
  agent?: string;
33
33
  mode?: CommitExecutionMode;
34
34
  round?: number;
35
- /** Permit one retry to rebase a prepared intent's expected tree while HEAD and intent identity remain unchanged. */
36
- recoverPreparedIntent?: boolean;
37
35
  delivery?: Readonly<{
38
36
  mode: 'local' | 'push';
39
37
  remote: string;
@@ -282,20 +280,6 @@ function checkpointTimestamp(): string {
282
280
  return new Date().toISOString();
283
281
  }
284
282
 
285
- function samePreparedCheckpointIdentity(
286
- pending: NonNullable<ReturnType<typeof readCheckpointIntent>>,
287
- identity: Parameters<typeof checkpointIntentDigest>[0]
288
- ): boolean {
289
- return pending.state === 'prepared'
290
- && pending.taskId === identity.taskId
291
- && pending.branch === identity.branch
292
- && pending.mode === identity.mode
293
- && pending.expectedHead === identity.expectedHead
294
- && pending.message === identity.message
295
- && pending.round === identity.round
296
- && JSON.stringify(pending.paths) === JSON.stringify(identity.paths);
297
- }
298
-
299
283
  function executeUnlocked(input: CommitOperationInput, task: BoundTask | null, mode: CommitExecutionMode): CommitOperationResult {
300
284
  const inspected = inspectGitWorkflow(input.cwd);
301
285
  if (!inspected.snapshot) return failure(input, mode, task?.taskId ?? null, 'GIT_INSPECT_FAILED', 'Unable to inspect Git repository');
@@ -330,15 +314,11 @@ function executeUnlocked(input: CommitOperationInput, task: BoundTask | null, mo
330
314
  };
331
315
  }
332
316
  if (pendingIntent && !sameCheckpointIntent(pendingIntent, identity)) {
333
- if (!input.recoverPreparedIntent || !samePreparedCheckpointIdentity(pendingIntent, identity)) return {
334
- status: 'failed' as const, changed: false, snapshot: inspected.snapshot, operations: [],
335
- error: { code: 'COMMIT_INTENT_CONFLICT', message: 'A different checkpoint intent is still pending for this task' }
336
- };
317
+ const timestamp = checkpointTimestamp();
337
318
  pendingIntent = {
338
- ...pendingIntent,
339
- expectedTree: identity.expectedTree,
319
+ version: 1, ...identity,
340
320
  digest: checkpointIntentDigest(identity),
341
- updatedAt: checkpointTimestamp()
321
+ state: 'prepared', committedHead: null, createdAt: timestamp, updatedAt: timestamp
342
322
  };
343
323
  try { writeCheckpointIntent(task!.repoRoot, pendingIntent); }
344
324
  catch (error) {
@@ -789,17 +789,11 @@ function orchestration(
789
789
  client: input.client as AgentClientId,
790
790
  requestedModel: input.requestedModel as string | undefined,
791
791
  requestedReasoningEffort: input.requestedReasoningEffort as string | undefined,
792
- ...(input.capabilityRef === undefined ? {} : { capabilityRef: input.capabilityRef as string }),
793
- ...(context.lifecycleRecoveryAttestation === undefined
794
- ? {}
795
- : { lifecycleRecoveryAttestation: context.lifecycleRecoveryAttestation })
796
792
  };
797
793
  if (prepareInput.client === 'codex') {
798
794
  return prepareCodexOrchestrationDelegation(operation.taskRef, prepareInput, {
799
795
  repoRoot: context.repoRoot,
800
796
  orchestrationOptions: options,
801
- deferLifecycleRecoveryConsumption: context.source === 'sandbox-executor',
802
- ...(context.controllerBinding ? { controllerBinding: context.controllerBinding } : {})
803
797
  });
804
798
  }
805
799
  return prepareOrchestrationDelegation(operation.taskRef, prepareInput, options);
@@ -912,7 +906,7 @@ const FINALIZATION_FLAGS = new Set(['--agent']);
912
906
  const ORCHESTRATION_FLAGS = new Set([
913
907
  '--agent', '--max-steps', '--executor-model', '--executor-reasoning-effort', '--reviewer-model',
914
908
  '--reviewer-reasoning-effort', '--client', '--requested-model', '--requested-reasoning-effort',
915
- '--capability-ref', '--parent-id', '--before-fingerprint', '--stage', '--round', '--artifact', '--role',
909
+ '--parent-id', '--before-fingerprint', '--stage', '--round', '--artifact', '--role',
916
910
  '--native-agent', '--child-id', '--spawn-mode', '--actual-model', '--actual-reasoning-effort',
917
911
  '--model-fallback-reason', '--reasoning-effort-fallback-reason', '--exit-code', '--after-fingerprint',
918
912
  '--changed-paths', '--code', '--message', '--recoverable', '--git-worktree-root'
@@ -1049,7 +1043,6 @@ export function parseTaskControlOperation(
1049
1043
  if (parsedIntent === 'prepare') {
1050
1044
  input.requestedModel = value(values, '--requested-model');
1051
1045
  input.requestedReasoningEffort = value(values, '--requested-reasoning-effort');
1052
- input.capabilityRef = value(values, '--capability-ref');
1053
1046
  }
1054
1047
  if (parsedIntent === 'await-activation') {
1055
1048
  required(values, ['--stage', '--round', '--artifact', '--role']);
@@ -108,13 +108,6 @@ function exactText(value: unknown): value is string {
108
108
  return typeof value === 'string' && value.length > 0 && value.trim() === value;
109
109
  }
110
110
 
111
- function validCodexBuildMetadata(value: Readonly<Record<string, unknown>>): boolean {
112
- return Number.isSafeInteger(value.protocolVersion) && (value.protocolVersion as number) > 0
113
- && exactText(value.packageVersion)
114
- && exactText(value.internalExecutableBuildHash)
115
- && exactText(value.lifecycleContractHash);
116
- }
117
-
118
111
  function nullableText(value: unknown): value is string | null {
119
112
  return value === null || exactText(value);
120
113
  }
@@ -183,52 +176,6 @@ function isDelegationHostEvidence(value: unknown): value is DelegationHostEviden
183
176
  && nullableText(value.controlGeneration);
184
177
  }
185
178
 
186
- function hasCurrentCodexEvidence(receipt: DelegationReceipt): boolean {
187
- const provenance = receipt.lifecycleProvenance;
188
- if (!provenance) return false;
189
- const activated = ['activated', 'stage-completed', 'sealed', 'consumed'].includes(receipt.status)
190
- || (receipt.status === 'aborted' && receipt.activatedAt !== null);
191
- if (!activated) return receipt.hostEvidence === null;
192
- const host = receipt.hostEvidence;
193
- if (
194
- host?.kind !== 'codex-lifecycle-v2'
195
- || host.protocolVersion !== provenance.protocolVersion
196
- || host.hookDefinitionHash !== provenance.hookDefinitionHash
197
- || host.hookSource !== provenance.hookSource
198
- || host.hookSourcePathDigest !== provenance.hookSourcePathDigest
199
- || host.hookSourceHash !== provenance.hookSourceHash
200
- || host.capabilitySessionId !== provenance.capabilitySessionId
201
- || host.capabilityTurnId !== provenance.capabilityTurnId
202
- || host.controllerInstanceDigest !== provenance.controllerInstanceDigest
203
- || host.controlGeneration !== provenance.controlGeneration
204
- || receipt.parentId !== provenance.capabilitySessionId
205
- || host.spawnToolUseId === provenance.capabilityToolUseId
206
- ) return false;
207
- const spawnObservedAt = Date.parse(host.spawnObservedAt ?? '');
208
- const spawnDispatchedAt = Date.parse(receipt.spawnDispatchedAt ?? '');
209
- const activationDeadlineAt = Date.parse(receipt.activationDeadlineAt ?? '');
210
- if (
211
- !Number.isFinite(spawnObservedAt)
212
- || !Number.isFinite(spawnDispatchedAt)
213
- || !Number.isFinite(activationDeadlineAt)
214
- || spawnObservedAt < spawnDispatchedAt
215
- || spawnObservedAt > activationDeadlineAt
216
- ) return false;
217
- if (['sealed', 'consumed'].includes(receipt.status)) {
218
- return Number.isSafeInteger(host.stopRevision)
219
- && (host.stopRevision as number) > host.startRevision
220
- && host.consumer === receipt.id
221
- && exactText(host.consumedAt);
222
- }
223
- if (receipt.status === 'aborted') {
224
- return Number.isSafeInteger(host.stopRevision)
225
- && (host.stopRevision as number) > host.startRevision
226
- && host.consumer === `lifecycle-recovery:${receipt.taskId}:${receipt.id}`
227
- && exactText(host.consumedAt);
228
- }
229
- return host.stopRevision === null && host.consumer === null && host.consumedAt === null;
230
- }
231
-
232
179
  const RECEIPT_KEYS = [
233
180
  'id', 'taskId', 'runId', 'role', 'stage', 'round', 'artifact', 'client',
234
181
  'requestedModel', 'requestedReasoningEffort', 'actualModel', 'actualReasoningEffort',
@@ -366,8 +313,15 @@ function isDelegationReceipt(value: unknown): value is DelegationReceipt {
366
313
  && nullableText(value.consumedAt);
367
314
  if (!structurallyValid) return false;
368
315
  const receipt = value as unknown as DelegationReceipt;
369
- return hasStatusBoundEvidence(receipt)
370
- && (receipt.client !== 'codex' || hasCurrentCodexEvidence(receipt));
316
+ if (!hasStatusBoundEvidence(receipt)) return false;
317
+ const host = receipt.hostEvidence;
318
+ if (receipt.client === 'codex' && receipt.activatedAt !== null) {
319
+ if (host?.kind !== 'codex-lifecycle-v2' || host.capabilitySessionId !== receipt.parentId) return false;
320
+ if (['sealed', 'consumed'].includes(receipt.status)) {
321
+ return Number.isSafeInteger(host.stopRevision) && host.stopRevision! > host.startRevision;
322
+ }
323
+ }
324
+ return true;
371
325
  }
372
326
 
373
327
  const MANAGED_AGENTS = {
@@ -550,30 +504,9 @@ function activateDelegation(
550
504
  || event.hostEvidence.startRevision < 1
551
505
  )
552
506
  ) return fail('DELEGATION_HOST_EVIDENCE_INVALID', 'Codex start evidence reference is invalid');
553
- if (event.hostEvidence?.kind === 'codex-lifecycle-v2') {
554
- const expected = receipt.lifecycleProvenance;
555
- const spawnObservedAt = Date.parse(event.hostEvidence.spawnObservedAt ?? '');
556
- const spawnDispatchedAt = Date.parse(receipt.spawnDispatchedAt);
557
- const activationDeadlineAt = Date.parse(receipt.activationDeadlineAt);
558
- if (
559
- !expected
560
- || event.hostEvidence.protocolVersion !== expected.protocolVersion
561
- || event.hostEvidence.hookDefinitionHash !== expected.hookDefinitionHash
562
- || event.hostEvidence.hookSource !== expected.hookSource
563
- || event.hostEvidence.hookSourcePathDigest !== expected.hookSourcePathDigest
564
- || event.hostEvidence.hookSourceHash !== expected.hookSourceHash
565
- || event.hostEvidence.capabilitySessionId !== expected.capabilitySessionId
566
- || event.hostEvidence.capabilityTurnId !== expected.capabilityTurnId
567
- || !event.hostEvidence.spawnToolUseId?.trim()
568
- || event.hostEvidence.spawnToolUseId === expected.capabilityToolUseId
569
- || !Number.isFinite(spawnObservedAt)
570
- || spawnObservedAt < spawnDispatchedAt
571
- || spawnObservedAt > activationDeadlineAt
572
- || event.parentId !== expected.capabilitySessionId
573
- || (event.hostEvidence.controllerInstanceDigest ?? null) !== expected.controllerInstanceDigest
574
- || (event.hostEvidence.controlGeneration ?? null) !== expected.controlGeneration
575
- || !validCodexBuildMetadata(event.hostEvidence)
576
- ) return fail('DELEGATION_HOST_EVIDENCE_INVALID', 'Codex lifecycle provenance does not match the prepared receipt');
507
+ if (event.hostEvidence?.kind === 'codex-lifecycle-v2'
508
+ && event.hostEvidence.capabilitySessionId !== event.parentId) {
509
+ return fail('DELEGATION_HOST_EVIDENCE_INVALID', 'Codex start evidence does not match the observed parent');
577
510
  }
578
511
  return { ok: true, receipt: Object.freeze({
579
512
  ...receipt,