@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.
- package/dist/lib/internal/cli-route-inventory.js +1 -1
- package/dist/lib/internal/manual-validation.js +6 -2
- package/dist/lib/internal/platform-comment.js +59 -0
- package/dist/lib/internal/sandbox-control.js +4 -131
- package/dist/lib/internal/task-artifact.js +1 -1
- package/dist/lib/internal/task-operation-registry.js +1 -0
- package/dist/lib/internal/task-review.js +5 -5
- package/dist/lib/internal/task-validate.js +0 -6
- package/dist/lib/platform/comment-safety.js +7 -1
- package/dist/lib/platform/github-provider.js +13 -3
- package/dist/lib/platform/issue-comments.js +120 -13
- package/dist/lib/platform/issues.js +3 -4
- package/dist/lib/platform/provider-contract.d.ts +2 -0
- package/dist/lib/platform/provider-validation.js +7 -2
- package/dist/lib/platform/verification-sync.js +161 -156
- package/dist/lib/sandbox/control/executor.js +0 -38
- package/dist/lib/sandbox/control/finalization-response.js +10 -2
- package/dist/lib/sandbox/control/task-view.js +3 -1
- package/dist/lib/sandbox/control/workflow-executor.js +32 -41
- package/dist/lib/task/artifact-command.js +6 -6
- package/dist/lib/task/artifact-lifecycle.js +15 -52
- package/dist/lib/task/artifact-operations.js +27 -1
- package/dist/lib/task/capabilities.js +0 -2
- package/dist/lib/task/codex-orchestration.js +10 -208
- package/dist/lib/task/commit-operation.js +3 -18
- package/dist/lib/task/control-authority.js +1 -8
- package/dist/lib/task/delegation-receipts.js +14 -76
- package/dist/lib/task/events.js +147 -278
- package/dist/lib/task/finalization-state.js +2 -1
- package/dist/lib/task/finalization.js +273 -49
- package/dist/lib/task/gate-policy.js +94 -0
- package/dist/lib/task/lifecycle-execution.js +2 -11
- package/dist/lib/task/local-artifact-finalization.js +31 -245
- package/dist/lib/task/orchestration.js +8 -24
- package/dist/lib/task/review-artifacts.js +12 -6
- package/dist/lib/task/review-command.js +0 -1
- package/dist/lib/task/review-finalization.js +47 -218
- package/dist/lib/task/verification-engine.js +28 -17
- package/dist/lib/task/verification.js +25 -9
- package/dist/lib/task/workflow-command.js +4 -1
- package/dist/lib/task/workflow-dispatch.js +55 -3
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/internal/cli-route-inventory.ts +1 -1
- package/lib/internal/manual-validation.ts +6 -2
- package/lib/internal/platform-comment.ts +38 -0
- package/lib/internal/sandbox-control.ts +3 -145
- package/lib/internal/task-artifact.ts +1 -1
- package/lib/internal/task-operation-registry.ts +1 -0
- package/lib/internal/task-review.ts +5 -5
- package/lib/internal/task-validate.ts +0 -5
- package/lib/platform/comment-safety.ts +8 -0
- package/lib/platform/github-provider.ts +11 -2
- package/lib/platform/issue-comments.ts +132 -13
- package/lib/platform/issues.ts +3 -4
- package/lib/platform/provider-contract.ts +2 -0
- package/lib/platform/provider-validation.ts +6 -2
- package/lib/platform/verification-sync.ts +178 -179
- package/lib/sandbox/control/executor.ts +0 -44
- package/lib/sandbox/control/finalization-response.ts +10 -2
- package/lib/sandbox/control/task-view.ts +3 -1
- package/lib/sandbox/control/workflow-executor.ts +31 -48
- package/lib/task/artifact-command.ts +6 -7
- package/lib/task/artifact-lifecycle.ts +12 -49
- package/lib/task/artifact-operations.ts +27 -1
- package/lib/task/capabilities.ts +0 -1
- package/lib/task/codex-orchestration.ts +8 -241
- package/lib/task/commit-operation.ts +3 -23
- package/lib/task/control-authority.ts +1 -8
- package/lib/task/delegation-receipts.ts +12 -79
- package/lib/task/events.ts +155 -287
- package/lib/task/finalization-state.ts +2 -1
- package/lib/task/finalization.ts +277 -57
- package/lib/task/gate-policy.ts +133 -0
- package/lib/task/lifecycle-execution.ts +10 -21
- package/lib/task/local-artifact-finalization.ts +29 -285
- package/lib/task/orchestration.ts +12 -41
- package/lib/task/review-artifacts.ts +8 -2
- package/lib/task/review-command.ts +0 -1
- package/lib/task/review-finalization.ts +46 -200
- package/lib/task/verification-engine.ts +24 -14
- package/lib/task/verification-types.ts +7 -0
- package/lib/task/verification.ts +25 -9
- package/lib/task/workflow-command.ts +4 -1
- package/lib/task/workflow-dispatch.ts +46 -3
- package/package.json +2 -2
- package/templates/.agents/rules/issue-sync.en.md +2 -0
- package/templates/.agents/rules/issue-sync.zh-CN.md +5 -8
- package/templates/.agents/rules/lifecycle-orchestration.en.md +7 -7
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +7 -7
- package/templates/.agents/rules/local-artifact-repair.en.md +14 -52
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +13 -52
- package/templates/.agents/skills/analyze-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -10
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/block-task/config/verify.json +1 -3
- package/templates/.agents/skills/cancel-task/config/verify.json +1 -4
- package/templates/.agents/skills/code-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/code-task/config/verify.en.json +1 -12
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -12
- package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
- package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/reference/report-template.en.md +11 -0
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +11 -0
- package/templates/.agents/skills/commit/config/verify.json +1 -5
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +6 -6
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +6 -6
- package/templates/.agents/skills/complete-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/complete-task/config/verify.en.json +3 -14
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +3 -14
- package/templates/.agents/skills/create-pr/config/verify.json +1 -10
- package/templates/.agents/skills/create-task/config/verify.json +1 -4
- package/templates/.agents/skills/import-issue/config/verify.json +1 -2
- package/templates/.agents/skills/plan-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/plan-task/config/verify.en.json +1 -10
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/review-analysis/SKILL.en.md +2 -2
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -10
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/review-code/SKILL.en.md +3 -3
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -10
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/review-code/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/review-plan/SKILL.en.md +2 -2
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -10
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/review-pr/config/verify.en.json +1 -8
- package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +1 -8
- package/templates/.agents/skills/run-manual-validation/config/verify.en.json +38 -13
- package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +38 -13
- package/templates/.agents/skills/run-task/SKILL.en.md +6 -6
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +6 -6
- package/templates/.agents/skills/run-task/reference/host-validation.en.md +2 -2
- package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +2 -2
|
@@ -1,39 +1,15 @@
|
|
|
1
1
|
import { preflightCodexLifecycleEvidence, resolveCodexSpawnedChild, resolveCodexTerminal, resolveCodexThread } from '../agent-clients/adapters/codex-lifecycle/app-server.js';
|
|
2
2
|
import { createCodexLifecycleStore } from '../agent-clients/adapters/codex-lifecycle/store.js';
|
|
3
|
-
import {
|
|
4
|
-
import { computeLifecycleBuildIdentity, verifyLifecycleBuildIdentity } from '../agent-clients/adapters/codex-lifecycle/build-identity.js';
|
|
5
|
-
import { verifyCodexSandboxControllerContextWithWarnings as verifySandboxControllerWithWarnings } from '../agent-clients/adapters/codex-lifecycle/sandbox-controller.js';
|
|
6
|
-
import { verifyCodexSandboxControllerContextWithWarnings as verifyControllerContextFileWithWarnings } from '../agent-clients/adapters/codex-lifecycle/controller-context.js';
|
|
3
|
+
import { computeLifecycleBuildIdentity, } from '../agent-clients/adapters/codex-lifecycle/build-identity.js';
|
|
7
4
|
import { resolveTaskRef } from './resolve-ref.js';
|
|
8
|
-
import { activateMatchingOrchestrationDelegation, hasActivatableOrchestrationDelegation, hasSealableOrchestrationDelegation, OrchestrationStateError, pauseMatchingOrchestrationDelegation, prepareOrchestrationDelegation,
|
|
9
|
-
import { randomUUID, createHash } from 'node:crypto';
|
|
10
|
-
import { consumeLifecycleRecoveryAttestation, issueLifecycleRecoveryAttestation, validateLifecycleRecoveryAttestation } from './control-authority.js';
|
|
11
|
-
function buildIdentityDigest(value) {
|
|
12
|
-
return createHash('sha256').update(JSON.stringify(value), 'utf8').digest('hex');
|
|
13
|
-
}
|
|
5
|
+
import { activateMatchingOrchestrationDelegation, hasActivatableOrchestrationDelegation, hasSealableOrchestrationDelegation, OrchestrationStateError, pauseMatchingOrchestrationDelegation, prepareOrchestrationDelegation, reconcileMatchingOrchestrationDelegation, sealMatchingOrchestrationDelegationWithHostEvidence } from './orchestration.js';
|
|
14
6
|
function coreOptions(options) {
|
|
15
7
|
return { ...options.orchestrationOptions, repoRoot: options.repoRoot ?? options.orchestrationOptions?.repoRoot };
|
|
16
8
|
}
|
|
17
|
-
function bridgeFailure(code, message
|
|
9
|
+
function bridgeFailure(code, message) {
|
|
18
10
|
return {
|
|
19
11
|
status: 'failed', changed: false, taskId: null, run: null, next: null,
|
|
20
|
-
error: { code, message
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
function capabilityFailure(error) {
|
|
24
|
-
const detailValue = error instanceof Error
|
|
25
|
-
? error.detail
|
|
26
|
-
: undefined;
|
|
27
|
-
return {
|
|
28
|
-
code: error instanceof Error && error.name.startsWith('CODEX_CAPABILITY_')
|
|
29
|
-
? error.name
|
|
30
|
-
: 'ORCHESTRATION_CLIENT_PREFLIGHT_FAILED',
|
|
31
|
-
message: error instanceof Error ? error.message : String(error),
|
|
32
|
-
...(error instanceof Error
|
|
33
|
-
&& error.name === 'CODEX_CAPABILITY_PROVENANCE_MISMATCH'
|
|
34
|
-
&& isCodexCapabilityProvenanceDetail(detailValue)
|
|
35
|
-
? { detail: detailValue }
|
|
36
|
-
: {})
|
|
12
|
+
error: { code, message }
|
|
37
13
|
};
|
|
38
14
|
}
|
|
39
15
|
function pauseBridge(code, message, options) {
|
|
@@ -47,28 +23,6 @@ function requiredStore(options) {
|
|
|
47
23
|
throw new Error('Codex lifecycle store is required for orchestration bridge events');
|
|
48
24
|
return options.store;
|
|
49
25
|
}
|
|
50
|
-
function brokerControllerBinding() {
|
|
51
|
-
const raw = process.env.AGENT_INFRA_CONTROL_CONTROLLER_BINDING;
|
|
52
|
-
if (!raw)
|
|
53
|
-
return null;
|
|
54
|
-
let value;
|
|
55
|
-
try {
|
|
56
|
-
value = JSON.parse(raw);
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
throw new Error('CODEX_SANDBOX_CONTROLLER_BINDING_INVALID');
|
|
60
|
-
}
|
|
61
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
62
|
-
throw new Error('CODEX_SANDBOX_CONTROLLER_BINDING_INVALID');
|
|
63
|
-
}
|
|
64
|
-
const binding = value;
|
|
65
|
-
if (Object.keys(binding).sort().join(',') !== 'controlGeneration,instanceDigest'
|
|
66
|
-
|| typeof binding.instanceDigest !== 'string' || !/^[a-f0-9]{64}$/u.test(binding.instanceDigest)
|
|
67
|
-
|| typeof binding.controlGeneration !== 'string' || binding.controlGeneration.length === 0) {
|
|
68
|
-
throw new Error('CODEX_SANDBOX_CONTROLLER_BINDING_INVALID');
|
|
69
|
-
}
|
|
70
|
-
return binding;
|
|
71
|
-
}
|
|
72
26
|
async function prepareCodexOrchestrationDelegation(taskRef, input, options = {}) {
|
|
73
27
|
if (input.client !== 'codex')
|
|
74
28
|
return prepareOrchestrationDelegation(taskRef, input, coreOptions(options));
|
|
@@ -77,152 +31,13 @@ async function prepareCodexOrchestrationDelegation(taskRef, input, options = {})
|
|
|
77
31
|
const resolved = resolveTaskRef(taskRef, { repoRoot });
|
|
78
32
|
if (!resolved.ok)
|
|
79
33
|
return bridgeFailure(resolved.code, resolved.message);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (!capabilityRef) {
|
|
83
|
-
return bridgeFailure('ORCHESTRATION_CODEX_CAPABILITY_REQUIRED', 'Codex prepare requires a current-session capability reference');
|
|
84
|
-
}
|
|
85
|
-
const buildIdentity = options.buildIdentity ?? computeLifecycleBuildIdentity(repoRoot);
|
|
86
|
-
const brokerController = options.controllerBinding ?? brokerControllerBinding();
|
|
87
|
-
const contextPath = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
|
|
88
|
-
const contextVerification = contextPath
|
|
89
|
-
? (brokerController
|
|
90
|
-
? verifyControllerContextFileWithWarnings(contextPath, {
|
|
91
|
-
repoRoot,
|
|
92
|
-
generation: process.env.AGENT_INFRA_CONTROL_GENERATION ?? brokerController.controlGeneration
|
|
93
|
-
})
|
|
94
|
-
: verifySandboxControllerWithWarnings(contextPath, { repoRoot }))
|
|
95
|
-
: null;
|
|
96
|
-
const identityWarnings = [...(contextVerification?.warnings ?? [])];
|
|
97
|
-
const localController = contextVerification?.context ?? null;
|
|
98
|
-
if (localController && brokerController
|
|
99
|
-
&& (localController.controllerInstanceDigest !== brokerController.instanceDigest
|
|
100
|
-
|| localController.controlGeneration !== brokerController.controlGeneration)) {
|
|
101
|
-
return bridgeFailure('CODEX_SANDBOX_CONTROLLER_BINDING_MISMATCH', 'broker and local controller bindings do not match');
|
|
102
|
-
}
|
|
103
|
-
const controller = brokerController ?? (localController ? {
|
|
104
|
-
instanceDigest: localController.controllerInstanceDigest,
|
|
105
|
-
controlGeneration: localController.controlGeneration
|
|
106
|
-
} : null);
|
|
107
|
-
const capabilityStore = options.capabilityStore ?? createCodexCapabilityStore();
|
|
108
|
-
const attested = capabilityStore.inspectReference(capabilityRef);
|
|
109
|
-
const capabilityIdentity = verifyLifecycleBuildIdentity(attested.buildIdentity, buildIdentity);
|
|
110
|
-
if (!capabilityIdentity.ok) {
|
|
111
|
-
return bridgeFailure(capabilityIdentity.code, capabilityIdentity.message);
|
|
112
|
-
}
|
|
113
|
-
identityWarnings.push(...capabilityIdentity.warnings);
|
|
114
|
-
const lifecycleProvenance = {
|
|
115
|
-
...attested.buildIdentity,
|
|
116
|
-
hookDefinitionHash: preflight.hookDefinitionHash,
|
|
117
|
-
...preflight.hookProvenance,
|
|
118
|
-
capabilitySessionId: attested.sessionId,
|
|
119
|
-
capabilityTurnId: attested.turnId,
|
|
120
|
-
capabilityToolUseId: attested.toolUseId,
|
|
121
|
-
controllerInstanceDigest: controller?.instanceDigest ?? null,
|
|
122
|
-
controlGeneration: controller?.controlGeneration ?? null
|
|
123
|
-
};
|
|
124
|
-
const capabilityExpected = {
|
|
125
|
-
taskId: resolved.taskId,
|
|
126
|
-
hookDefinitionHash: preflight.hookDefinitionHash,
|
|
127
|
-
buildIdentity,
|
|
128
|
-
...(controller ? { controller: {
|
|
129
|
-
instanceDigest: controller.instanceDigest,
|
|
130
|
-
controlGeneration: controller.controlGeneration
|
|
131
|
-
} } : {})
|
|
132
|
-
};
|
|
133
|
-
if (input.lifecycleRecoveryAttestation) {
|
|
134
|
-
try {
|
|
135
|
-
validateLifecycleRecoveryAttestation(input.lifecycleRecoveryAttestation);
|
|
136
|
-
}
|
|
137
|
-
catch (error) {
|
|
138
|
-
return bridgeFailure('LIFECYCLE_AUTHORITY_ATTESTATION_INVALID', error instanceof Error ? error.message : String(error));
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
let lifecycleRecoveryAttestation = input.lifecycleRecoveryAttestation ?? null;
|
|
142
|
-
const routed = input.capabilityRef && !lifecycleRecoveryAttestation
|
|
143
|
-
? routeOrchestration(taskRef, coreOptions(options))
|
|
144
|
-
: null;
|
|
145
|
-
if (routed && !routed.next)
|
|
146
|
-
return routed;
|
|
147
|
-
if (routed?.next && ['analysis', 'plan', 'code'].includes(routed.next.stage)) {
|
|
148
|
-
const recoveryRequest = {
|
|
149
|
-
version: 1,
|
|
150
|
-
requestId: randomUUID(),
|
|
151
|
-
operationId: randomUUID(),
|
|
152
|
-
phase: 'orchestration.prepare',
|
|
153
|
-
taskId: resolved.taskId,
|
|
154
|
-
family: routed.next.stage === 'analysis' ? 'analysis'
|
|
155
|
-
: routed.next.stage === 'plan' ? 'plan' : 'code',
|
|
156
|
-
artifact: routed.next.artifact,
|
|
157
|
-
round: routed.next.round,
|
|
158
|
-
lifecycleRequestId: randomUUID(),
|
|
159
|
-
authorityRef: capabilityRef,
|
|
160
|
-
expectedControlGeneration: controller?.controlGeneration ?? '',
|
|
161
|
-
expectedControllerInstanceDigest: controller?.instanceDigest ?? '0'.repeat(64),
|
|
162
|
-
expectedBuildIdentityDigest: buildIdentityDigest(buildIdentity),
|
|
163
|
-
expectedHookDefinitionHash: preflight.hookDefinitionHash
|
|
164
|
-
};
|
|
165
|
-
const authority = issueLifecycleRecoveryAttestation(recoveryRequest, {
|
|
166
|
-
capabilityStore,
|
|
167
|
-
...(controller ? { controllerBinding: controller } : {}),
|
|
168
|
-
buildIdentity
|
|
169
|
-
});
|
|
170
|
-
if (authority.status === 'rejected' || !authority.attestation) {
|
|
171
|
-
return bridgeFailure(authority.error?.code ?? 'LIFECYCLE_AUTHORITY_REJECTED', authority.error?.message ?? 'lifecycle authority was rejected');
|
|
172
|
-
}
|
|
173
|
-
lifecycleRecoveryAttestation = authority.attestation;
|
|
174
|
-
}
|
|
175
|
-
const prepared = prepareOrchestrationDelegation(taskRef, {
|
|
176
|
-
...input,
|
|
177
|
-
lifecycleProvenance,
|
|
178
|
-
lifecycleRecoveryAttestation
|
|
179
|
-
}, {
|
|
180
|
-
...coreOptions(options),
|
|
181
|
-
validateLifecycleCapability: () => {
|
|
182
|
-
try {
|
|
183
|
-
const validated = capabilityStore.validateReference(capabilityRef, capabilityExpected);
|
|
184
|
-
if (validated.sessionId !== attested.sessionId
|
|
185
|
-
|| validated.turnId !== attested.turnId
|
|
186
|
-
|| validated.toolUseId !== attested.toolUseId) {
|
|
187
|
-
return {
|
|
188
|
-
code: 'CODEX_CAPABILITY_IDENTITY_CHANGED',
|
|
189
|
-
message: 'capability identity changed during validation'
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
return null;
|
|
193
|
-
}
|
|
194
|
-
catch (error) {
|
|
195
|
-
return capabilityFailure(error);
|
|
196
|
-
}
|
|
197
|
-
},
|
|
198
|
-
consumeLifecycleCapability: () => null
|
|
199
|
-
});
|
|
200
|
-
if (lifecycleRecoveryAttestation && !options.deferLifecycleRecoveryConsumption && prepared.status !== 'failed') {
|
|
201
|
-
try {
|
|
202
|
-
consumeLifecycleRecoveryAttestation(lifecycleRecoveryAttestation);
|
|
203
|
-
}
|
|
204
|
-
catch (error) {
|
|
205
|
-
return bridgeFailure(error instanceof Error ? error.name : 'LIFECYCLE_AUTHORITY_CONSUME_FAILED', error instanceof Error ? error.message : String(error));
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
return identityWarnings.length > 0 && prepared.status !== 'failed'
|
|
209
|
-
? { ...prepared, warnings: Object.freeze(identityWarnings) }
|
|
210
|
-
: prepared;
|
|
34
|
+
await (options.preflight ?? preflightCodexLifecycleEvidence)(repoRoot);
|
|
35
|
+
return prepareOrchestrationDelegation(taskRef, input, coreOptions(options));
|
|
211
36
|
}
|
|
212
37
|
catch (error) {
|
|
213
38
|
if (error instanceof OrchestrationStateError)
|
|
214
39
|
return bridgeFailure(error.code, error.message);
|
|
215
|
-
|
|
216
|
-
? error.detail
|
|
217
|
-
: undefined;
|
|
218
|
-
const detail = error instanceof Error
|
|
219
|
-
&& error.name === 'CODEX_CAPABILITY_PROVENANCE_MISMATCH'
|
|
220
|
-
&& isCodexCapabilityProvenanceDetail(detailValue)
|
|
221
|
-
? detailValue
|
|
222
|
-
: undefined;
|
|
223
|
-
return bridgeFailure(error instanceof Error && error.name.startsWith('CODEX_CAPABILITY_')
|
|
224
|
-
? error.name
|
|
225
|
-
: 'ORCHESTRATION_CLIENT_PREFLIGHT_FAILED', error instanceof Error ? error.message : String(error), detail);
|
|
40
|
+
return bridgeFailure('ORCHESTRATION_CLIENT_PREFLIGHT_FAILED', error instanceof Error ? error.message : String(error));
|
|
226
41
|
}
|
|
227
42
|
}
|
|
228
43
|
async function activateCodexOrchestrationDelegation(childThreadId, options = {}) {
|
|
@@ -248,16 +63,6 @@ async function activateCodexOrchestrationDelegation(childThreadId, options = {})
|
|
|
248
63
|
toolUseId: evidence.spawnToolUseId
|
|
249
64
|
});
|
|
250
65
|
const buildIdentity = options.buildIdentity ?? computeLifecycleBuildIdentity(repoRoot);
|
|
251
|
-
const contextPath = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
|
|
252
|
-
const contextVerification = contextPath
|
|
253
|
-
? verifySandboxControllerWithWarnings(contextPath, { repoRoot })
|
|
254
|
-
: null;
|
|
255
|
-
const controller = options.controllerBinding
|
|
256
|
-
?? brokerControllerBinding()
|
|
257
|
-
?? (contextVerification?.context ? {
|
|
258
|
-
instanceDigest: contextVerification.context.controllerInstanceDigest,
|
|
259
|
-
controlGeneration: contextVerification.context.controlGeneration
|
|
260
|
-
} : null);
|
|
261
66
|
const activated = activateMatchingOrchestrationDelegation('codex', {
|
|
262
67
|
nativeAgent: evidence.nativeAgent,
|
|
263
68
|
childId: evidence.childThreadId,
|
|
@@ -279,14 +84,11 @@ async function activateCodexOrchestrationDelegation(childThreadId, options = {})
|
|
|
279
84
|
capabilityTurnId: evidence.parentTurnId,
|
|
280
85
|
spawnToolUseId: evidence.spawnToolUseId,
|
|
281
86
|
spawnObservedAt: record.spawnObservedAt ?? undefined,
|
|
282
|
-
controllerInstanceDigest:
|
|
283
|
-
controlGeneration:
|
|
87
|
+
controllerInstanceDigest: null,
|
|
88
|
+
controlGeneration: null
|
|
284
89
|
}
|
|
285
90
|
}, coreOptions(options));
|
|
286
|
-
|
|
287
|
-
return warnings.length > 0 && activated.status !== 'failed'
|
|
288
|
-
? { ...activated, warnings: Object.freeze(warnings) }
|
|
289
|
-
: activated;
|
|
91
|
+
return activated;
|
|
290
92
|
}
|
|
291
93
|
catch (error) {
|
|
292
94
|
if (error instanceof OrchestrationStateError)
|
|
@@ -181,16 +181,6 @@ function checkpointIdentity(input, task, delivery) {
|
|
|
181
181
|
function checkpointTimestamp() {
|
|
182
182
|
return new Date().toISOString();
|
|
183
183
|
}
|
|
184
|
-
function samePreparedCheckpointIdentity(pending, identity) {
|
|
185
|
-
return pending.state === 'prepared'
|
|
186
|
-
&& pending.taskId === identity.taskId
|
|
187
|
-
&& pending.branch === identity.branch
|
|
188
|
-
&& pending.mode === identity.mode
|
|
189
|
-
&& pending.expectedHead === identity.expectedHead
|
|
190
|
-
&& pending.message === identity.message
|
|
191
|
-
&& pending.round === identity.round
|
|
192
|
-
&& JSON.stringify(pending.paths) === JSON.stringify(identity.paths);
|
|
193
|
-
}
|
|
194
184
|
function executeUnlocked(input, task, mode) {
|
|
195
185
|
const inspected = inspectGitWorkflow(input.cwd);
|
|
196
186
|
if (!inspected.snapshot)
|
|
@@ -225,16 +215,11 @@ function executeUnlocked(input, task, mode) {
|
|
|
225
215
|
};
|
|
226
216
|
}
|
|
227
217
|
if (pendingIntent && !sameCheckpointIntent(pendingIntent, identity)) {
|
|
228
|
-
|
|
229
|
-
return {
|
|
230
|
-
status: 'failed', changed: false, snapshot: inspected.snapshot, operations: [],
|
|
231
|
-
error: { code: 'COMMIT_INTENT_CONFLICT', message: 'A different checkpoint intent is still pending for this task' }
|
|
232
|
-
};
|
|
218
|
+
const timestamp = checkpointTimestamp();
|
|
233
219
|
pendingIntent = {
|
|
234
|
-
...
|
|
235
|
-
expectedTree: identity.expectedTree,
|
|
220
|
+
version: 1, ...identity,
|
|
236
221
|
digest: checkpointIntentDigest(identity),
|
|
237
|
-
updatedAt:
|
|
222
|
+
state: 'prepared', committedHead: null, createdAt: timestamp, updatedAt: timestamp
|
|
238
223
|
};
|
|
239
224
|
try {
|
|
240
225
|
writeCheckpointIntent(task.repoRoot, pendingIntent);
|
|
@@ -535,17 +535,11 @@ function orchestration(context, operation) {
|
|
|
535
535
|
client: input.client,
|
|
536
536
|
requestedModel: input.requestedModel,
|
|
537
537
|
requestedReasoningEffort: input.requestedReasoningEffort,
|
|
538
|
-
...(input.capabilityRef === undefined ? {} : { capabilityRef: input.capabilityRef }),
|
|
539
|
-
...(context.lifecycleRecoveryAttestation === undefined
|
|
540
|
-
? {}
|
|
541
|
-
: { lifecycleRecoveryAttestation: context.lifecycleRecoveryAttestation })
|
|
542
538
|
};
|
|
543
539
|
if (prepareInput.client === 'codex') {
|
|
544
540
|
return prepareCodexOrchestrationDelegation(operation.taskRef, prepareInput, {
|
|
545
541
|
repoRoot: context.repoRoot,
|
|
546
542
|
orchestrationOptions: options,
|
|
547
|
-
deferLifecycleRecoveryConsumption: context.source === 'sandbox-executor',
|
|
548
|
-
...(context.controllerBinding ? { controllerBinding: context.controllerBinding } : {})
|
|
549
543
|
});
|
|
550
544
|
}
|
|
551
545
|
return prepareOrchestrationDelegation(operation.taskRef, prepareInput, options);
|
|
@@ -629,7 +623,7 @@ const FINALIZATION_FLAGS = new Set(['--agent']);
|
|
|
629
623
|
const ORCHESTRATION_FLAGS = new Set([
|
|
630
624
|
'--agent', '--max-steps', '--executor-model', '--executor-reasoning-effort', '--reviewer-model',
|
|
631
625
|
'--reviewer-reasoning-effort', '--client', '--requested-model', '--requested-reasoning-effort',
|
|
632
|
-
'--
|
|
626
|
+
'--parent-id', '--before-fingerprint', '--stage', '--round', '--artifact', '--role',
|
|
633
627
|
'--native-agent', '--child-id', '--spawn-mode', '--actual-model', '--actual-reasoning-effort',
|
|
634
628
|
'--model-fallback-reason', '--reasoning-effort-fallback-reason', '--exit-code', '--after-fingerprint',
|
|
635
629
|
'--changed-paths', '--code', '--message', '--recoverable', '--git-worktree-root'
|
|
@@ -769,7 +763,6 @@ export function parseTaskControlOperation(family, args) {
|
|
|
769
763
|
if (parsedIntent === 'prepare') {
|
|
770
764
|
input.requestedModel = value(values, '--requested-model');
|
|
771
765
|
input.requestedReasoningEffort = value(values, '--requested-reasoning-effort');
|
|
772
|
-
input.capabilityRef = value(values, '--capability-ref');
|
|
773
766
|
}
|
|
774
767
|
if (parsedIntent === 'await-activation') {
|
|
775
768
|
required(values, ['--stage', '--round', '--artifact', '--role']);
|
|
@@ -15,12 +15,6 @@ function hasExactKeys(value, required, optional = []) {
|
|
|
15
15
|
function exactText(value) {
|
|
16
16
|
return typeof value === 'string' && value.length > 0 && value.trim() === value;
|
|
17
17
|
}
|
|
18
|
-
function validCodexBuildMetadata(value) {
|
|
19
|
-
return Number.isSafeInteger(value.protocolVersion) && value.protocolVersion > 0
|
|
20
|
-
&& exactText(value.packageVersion)
|
|
21
|
-
&& exactText(value.internalExecutableBuildHash)
|
|
22
|
-
&& exactText(value.lifecycleContractHash);
|
|
23
|
-
}
|
|
24
18
|
function nullableText(value) {
|
|
25
19
|
return value === null || exactText(value);
|
|
26
20
|
}
|
|
@@ -88,51 +82,6 @@ function isDelegationHostEvidence(value) {
|
|
|
88
82
|
&& nullableText(value.controllerInstanceDigest)
|
|
89
83
|
&& nullableText(value.controlGeneration);
|
|
90
84
|
}
|
|
91
|
-
function hasCurrentCodexEvidence(receipt) {
|
|
92
|
-
const provenance = receipt.lifecycleProvenance;
|
|
93
|
-
if (!provenance)
|
|
94
|
-
return false;
|
|
95
|
-
const activated = ['activated', 'stage-completed', 'sealed', 'consumed'].includes(receipt.status)
|
|
96
|
-
|| (receipt.status === 'aborted' && receipt.activatedAt !== null);
|
|
97
|
-
if (!activated)
|
|
98
|
-
return receipt.hostEvidence === null;
|
|
99
|
-
const host = receipt.hostEvidence;
|
|
100
|
-
if (host?.kind !== 'codex-lifecycle-v2'
|
|
101
|
-
|| host.protocolVersion !== provenance.protocolVersion
|
|
102
|
-
|| host.hookDefinitionHash !== provenance.hookDefinitionHash
|
|
103
|
-
|| host.hookSource !== provenance.hookSource
|
|
104
|
-
|| host.hookSourcePathDigest !== provenance.hookSourcePathDigest
|
|
105
|
-
|| host.hookSourceHash !== provenance.hookSourceHash
|
|
106
|
-
|| host.capabilitySessionId !== provenance.capabilitySessionId
|
|
107
|
-
|| host.capabilityTurnId !== provenance.capabilityTurnId
|
|
108
|
-
|| host.controllerInstanceDigest !== provenance.controllerInstanceDigest
|
|
109
|
-
|| host.controlGeneration !== provenance.controlGeneration
|
|
110
|
-
|| receipt.parentId !== provenance.capabilitySessionId
|
|
111
|
-
|| host.spawnToolUseId === provenance.capabilityToolUseId)
|
|
112
|
-
return false;
|
|
113
|
-
const spawnObservedAt = Date.parse(host.spawnObservedAt ?? '');
|
|
114
|
-
const spawnDispatchedAt = Date.parse(receipt.spawnDispatchedAt ?? '');
|
|
115
|
-
const activationDeadlineAt = Date.parse(receipt.activationDeadlineAt ?? '');
|
|
116
|
-
if (!Number.isFinite(spawnObservedAt)
|
|
117
|
-
|| !Number.isFinite(spawnDispatchedAt)
|
|
118
|
-
|| !Number.isFinite(activationDeadlineAt)
|
|
119
|
-
|| spawnObservedAt < spawnDispatchedAt
|
|
120
|
-
|| spawnObservedAt > activationDeadlineAt)
|
|
121
|
-
return false;
|
|
122
|
-
if (['sealed', 'consumed'].includes(receipt.status)) {
|
|
123
|
-
return Number.isSafeInteger(host.stopRevision)
|
|
124
|
-
&& host.stopRevision > host.startRevision
|
|
125
|
-
&& host.consumer === receipt.id
|
|
126
|
-
&& exactText(host.consumedAt);
|
|
127
|
-
}
|
|
128
|
-
if (receipt.status === 'aborted') {
|
|
129
|
-
return Number.isSafeInteger(host.stopRevision)
|
|
130
|
-
&& host.stopRevision > host.startRevision
|
|
131
|
-
&& host.consumer === `lifecycle-recovery:${receipt.taskId}:${receipt.id}`
|
|
132
|
-
&& exactText(host.consumedAt);
|
|
133
|
-
}
|
|
134
|
-
return host.stopRevision === null && host.consumer === null && host.consumedAt === null;
|
|
135
|
-
}
|
|
136
85
|
const RECEIPT_KEYS = [
|
|
137
86
|
'id', 'taskId', 'runId', 'role', 'stage', 'round', 'artifact', 'client',
|
|
138
87
|
'requestedModel', 'requestedReasoningEffort', 'actualModel', 'actualReasoningEffort',
|
|
@@ -263,8 +212,17 @@ function isDelegationReceipt(value) {
|
|
|
263
212
|
if (!structurallyValid)
|
|
264
213
|
return false;
|
|
265
214
|
const receipt = value;
|
|
266
|
-
|
|
267
|
-
|
|
215
|
+
if (!hasStatusBoundEvidence(receipt))
|
|
216
|
+
return false;
|
|
217
|
+
const host = receipt.hostEvidence;
|
|
218
|
+
if (receipt.client === 'codex' && receipt.activatedAt !== null) {
|
|
219
|
+
if (host?.kind !== 'codex-lifecycle-v2' || host.capabilitySessionId !== receipt.parentId)
|
|
220
|
+
return false;
|
|
221
|
+
if (['sealed', 'consumed'].includes(receipt.status)) {
|
|
222
|
+
return Number.isSafeInteger(host.stopRevision) && host.stopRevision > host.startRevision;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return true;
|
|
268
226
|
}
|
|
269
227
|
const MANAGED_AGENTS = {
|
|
270
228
|
'agent-infra-lifecycle-executor': 'executor',
|
|
@@ -397,29 +355,9 @@ function activateDelegation(receipt, event, options = {}) {
|
|
|
397
355
|
|| !Number.isSafeInteger(event.hostEvidence.startRevision)
|
|
398
356
|
|| event.hostEvidence.startRevision < 1))
|
|
399
357
|
return fail('DELEGATION_HOST_EVIDENCE_INVALID', 'Codex start evidence reference is invalid');
|
|
400
|
-
if (event.hostEvidence?.kind === 'codex-lifecycle-v2'
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
const spawnDispatchedAt = Date.parse(receipt.spawnDispatchedAt);
|
|
404
|
-
const activationDeadlineAt = Date.parse(receipt.activationDeadlineAt);
|
|
405
|
-
if (!expected
|
|
406
|
-
|| event.hostEvidence.protocolVersion !== expected.protocolVersion
|
|
407
|
-
|| event.hostEvidence.hookDefinitionHash !== expected.hookDefinitionHash
|
|
408
|
-
|| event.hostEvidence.hookSource !== expected.hookSource
|
|
409
|
-
|| event.hostEvidence.hookSourcePathDigest !== expected.hookSourcePathDigest
|
|
410
|
-
|| event.hostEvidence.hookSourceHash !== expected.hookSourceHash
|
|
411
|
-
|| event.hostEvidence.capabilitySessionId !== expected.capabilitySessionId
|
|
412
|
-
|| event.hostEvidence.capabilityTurnId !== expected.capabilityTurnId
|
|
413
|
-
|| !event.hostEvidence.spawnToolUseId?.trim()
|
|
414
|
-
|| event.hostEvidence.spawnToolUseId === expected.capabilityToolUseId
|
|
415
|
-
|| !Number.isFinite(spawnObservedAt)
|
|
416
|
-
|| spawnObservedAt < spawnDispatchedAt
|
|
417
|
-
|| spawnObservedAt > activationDeadlineAt
|
|
418
|
-
|| event.parentId !== expected.capabilitySessionId
|
|
419
|
-
|| (event.hostEvidence.controllerInstanceDigest ?? null) !== expected.controllerInstanceDigest
|
|
420
|
-
|| (event.hostEvidence.controlGeneration ?? null) !== expected.controlGeneration
|
|
421
|
-
|| !validCodexBuildMetadata(event.hostEvidence))
|
|
422
|
-
return fail('DELEGATION_HOST_EVIDENCE_INVALID', 'Codex lifecycle provenance does not match the prepared receipt');
|
|
358
|
+
if (event.hostEvidence?.kind === 'codex-lifecycle-v2'
|
|
359
|
+
&& event.hostEvidence.capabilitySessionId !== event.parentId) {
|
|
360
|
+
return fail('DELEGATION_HOST_EVIDENCE_INVALID', 'Codex start evidence does not match the observed parent');
|
|
423
361
|
}
|
|
424
362
|
return { ok: true, receipt: Object.freeze({
|
|
425
363
|
...receipt,
|