@fitlab-ai/agent-infra 0.9.9 → 0.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/internal-cli.js +5 -0
- package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +17 -10
- package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-context.js +11 -31
- package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +15 -33
- package/dist/lib/agent-clients/adapters/codex-sandbox.js +72 -11
- package/dist/lib/agent-clients/adapters/index.js +3 -1
- package/dist/lib/agent-clients/adapters/traecli.js +66 -0
- package/dist/lib/agent-clients/tokens.js +2 -2
- package/dist/lib/agent-clients/types.js +2 -1
- package/dist/lib/defaults.json +5 -0
- package/dist/lib/internal/codex-lifecycle.js +2 -2
- package/dist/lib/internal/codex-sandbox-controller.js +4 -3
- package/dist/lib/internal/sandbox-control.js +2 -2
- package/dist/lib/{task/commands/validate.js → internal/task-validate.js} +75 -42
- package/dist/lib/run/tui.js +5 -2
- package/dist/lib/sandbox/control/controller-registration.js +4 -2
- package/dist/lib/sandbox/control/executor.js +4 -1
- package/dist/lib/task/codex-orchestration.js +31 -34
- package/dist/lib/task/delegation-receipts.js +8 -7
- package/dist/lib/task/finalization.js +72 -46
- package/dist/lib/task/index.js +0 -9
- package/dist/lib/task/orchestration.js +1 -1
- package/dist/lib/task/verification-engine.js +0 -3
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +25 -10
- package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +16 -33
- package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +16 -35
- package/lib/agent-clients/adapters/codex-sandbox.ts +89 -14
- package/lib/agent-clients/adapters/index.ts +3 -1
- package/lib/agent-clients/adapters/traecli.ts +67 -0
- package/lib/agent-clients/tokens.ts +2 -2
- package/lib/agent-clients/types.ts +2 -1
- package/lib/defaults.json +5 -0
- package/lib/internal/codex-lifecycle.ts +2 -2
- package/lib/internal/codex-sandbox-controller.ts +4 -3
- package/lib/internal/sandbox-control.ts +2 -2
- package/lib/{task/commands/validate.ts → internal/task-validate.ts} +75 -40
- package/lib/run/tui.ts +5 -3
- package/lib/sandbox/control/controller-registration.ts +8 -3
- package/lib/sandbox/control/executor.ts +8 -2
- package/lib/task/codex-orchestration.ts +38 -44
- package/lib/task/delegation-receipts.ts +8 -6
- package/lib/task/finalization.ts +84 -42
- package/lib/task/index.ts +0 -8
- package/lib/task/orchestration.ts +2 -1
- package/lib/task/verification-engine.ts +0 -3
- package/package.json +1 -1
- package/templates/.agents/QUICKSTART.en.md +2 -3
- package/templates/.agents/QUICKSTART.zh-CN.md +2 -3
- package/templates/.agents/rules/README.en.md +1 -0
- package/templates/.agents/rules/README.zh-CN.md +1 -0
- package/templates/.agents/rules/compatibility-policy.en.md +39 -0
- package/templates/.agents/rules/compatibility-policy.zh-CN.md +39 -0
- package/templates/.agents/rules/lifecycle-orchestration.en.md +4 -4
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +4 -4
- package/templates/.agents/rules/pr-sync.en.md +1 -1
- package/templates/.agents/rules/pr-sync.github.en.md +2 -1
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +2 -0
- package/templates/.agents/rules/pr-sync.zh-CN.md +1 -0
- package/templates/.agents/rules/review-method.en.md +1 -0
- package/templates/.agents/rules/review-method.zh-CN.md +1 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +1 -0
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/code-task/SKILL.en.md +1 -0
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +2 -0
- package/templates/.agents/skills/create-pr/SKILL.en.md +12 -6
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +12 -6
- package/templates/.agents/skills/create-pr/reference/change-report.en.md +41 -0
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +41 -0
- package/templates/.agents/skills/plan-task/SKILL.en.md +2 -1
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -1
- package/templates/.agents/skills/review-code/reference/migration-risks.en.md +8 -6
- package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +8 -6
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +3 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +1 -1
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +1 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -2
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -2
- package/templates/.agents/skills/run-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +2 -2
- 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
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +24 -0
- package/templates/.trae/skills/update-agent-infra.en.md +8 -0
- package/templates/.trae/skills/update-agent-infra.zh-CN.md +8 -0
|
@@ -3,19 +3,19 @@ import fs from 'node:fs';
|
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { randomUUID } from 'node:crypto';
|
|
6
|
-
import { loadConfig } from '
|
|
7
|
-
import { detectEngine } from '
|
|
8
|
-
import { runEngine } from '
|
|
9
|
-
import { sandboxBranchLabel, sandboxLabel } from '
|
|
10
|
-
import { fetchSandboxRows, selectSandboxContainer } from '
|
|
11
|
-
import { containerNameCandidates } from '
|
|
12
|
-
import { resolveSandboxTarget } from '
|
|
13
|
-
import { sandboxControlPaths } from '
|
|
14
|
-
import { appendSandboxControlAudit, readActiveLease, readSandboxControlStatus } from '
|
|
15
|
-
import { SANDBOX_CONTROL_FUTURE_SKEW_MS, SANDBOX_CONTROL_STATUS_STALE_MS } from '
|
|
16
|
-
import { getProcessStartTime } from '
|
|
17
|
-
import { assertGitWorktreeBinding } from '
|
|
18
|
-
const USAGE = `Usage:
|
|
6
|
+
import { loadConfig } from '../sandbox/config.js';
|
|
7
|
+
import { detectEngine } from '../sandbox/engine.js';
|
|
8
|
+
import { runEngine } from '../sandbox/shell.js';
|
|
9
|
+
import { sandboxBranchLabel, sandboxLabel } from '../sandbox/constants.js';
|
|
10
|
+
import { fetchSandboxRows, selectSandboxContainer } from '../sandbox/commands/list-running.js';
|
|
11
|
+
import { containerNameCandidates } from '../sandbox/constants.js';
|
|
12
|
+
import { resolveSandboxTarget } from '../sandbox/workspace-identity.js';
|
|
13
|
+
import { sandboxControlPaths } from '../sandbox/workspace-view.js';
|
|
14
|
+
import { appendSandboxControlAudit, readActiveLease, readSandboxControlStatus } from '../sandbox/control/state.js';
|
|
15
|
+
import { SANDBOX_CONTROL_FUTURE_SKEW_MS, SANDBOX_CONTROL_STATUS_STALE_MS } from '../sandbox/control/protocol.js';
|
|
16
|
+
import { getProcessStartTime } from '../server/process-state.js';
|
|
17
|
+
import { assertGitWorktreeBinding } from '../git/worktree-identity.js';
|
|
18
|
+
const USAGE = `Usage: agent-infra-internal task-validate <branch | TASK-id | N> [--scope snapshot|inplace] [--timeout <ms>] [--format text|json] -- <command> [args...]`;
|
|
19
19
|
const MAX_TIMEOUT_MS = 60 * 60 * 1000;
|
|
20
20
|
const RECOVERY_GRACE_MS = 30_000;
|
|
21
21
|
export function parseValidateArgs(args) {
|
|
@@ -254,36 +254,69 @@ function inplaceValidation(config, target, options) {
|
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
|
-
|
|
258
|
-
const
|
|
257
|
+
function errorCode(message) {
|
|
258
|
+
const match = message.match(/^([A-Z][A-Z0-9_]*)/);
|
|
259
|
+
return match && match[1].length >= 3 ? match[1] : 'TASK_VALIDATE_FAILED';
|
|
260
|
+
}
|
|
261
|
+
function fail(format, code, message) {
|
|
262
|
+
if (format === 'json') {
|
|
263
|
+
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code, message } })}\n`);
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
process.stderr.write(`${message}\n`);
|
|
267
|
+
}
|
|
268
|
+
process.exitCode = 1;
|
|
269
|
+
}
|
|
270
|
+
function sniffFormat(args) {
|
|
271
|
+
const index = args.indexOf('--format');
|
|
272
|
+
return index >= 0 && args[index + 1] === 'json' ? 'json' : 'text';
|
|
273
|
+
}
|
|
274
|
+
function taskValidate(args) {
|
|
275
|
+
let options;
|
|
276
|
+
try {
|
|
277
|
+
options = parseValidateArgs(args);
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
fail(sniffFormat(args), 'TASK_VALIDATE_ARGS_INVALID', error instanceof Error ? error.message : String(error));
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
259
283
|
if (options.help) {
|
|
260
284
|
process.stdout.write(`${USAGE}\n`);
|
|
261
|
-
return
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
try {
|
|
288
|
+
const config = loadConfig();
|
|
289
|
+
const target = resolveSandboxTarget(options.target, config.repoRoot);
|
|
290
|
+
const commit = git(config.repoRoot, ['rev-parse', target.branch]);
|
|
291
|
+
const startedAt = new Date().toISOString();
|
|
292
|
+
const result = options.scope === 'snapshot'
|
|
293
|
+
? snapshotValidation(config.repoRoot, commit, options)
|
|
294
|
+
: inplaceValidation(config, target, options);
|
|
295
|
+
const evidence = {
|
|
296
|
+
version: 1,
|
|
297
|
+
taskId: target.workspace.mode === 'task-bound' ? target.workspace.taskId : null,
|
|
298
|
+
branch: target.branch,
|
|
299
|
+
scope: options.scope,
|
|
300
|
+
commit,
|
|
301
|
+
command: path.basename(options.command[0]),
|
|
302
|
+
startedAt,
|
|
303
|
+
completedAt: new Date().toISOString(),
|
|
304
|
+
exitCode: result.exitCode,
|
|
305
|
+
signal: result.signal,
|
|
306
|
+
cleanup: result.cleanup()
|
|
307
|
+
};
|
|
308
|
+
if (options.format === 'json') {
|
|
309
|
+
process.stdout.write(`${JSON.stringify({ status: 'applied', changed: false, evidence, error: null })}\n`);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
process.stdout.write(`Validation ${result.exitCode === 0 ? 'passed' : 'failed'} (${options.scope}, ${evidence.command}, cleanup=${evidence.cleanup}).\n`);
|
|
313
|
+
}
|
|
314
|
+
process.exitCode = result.exitCode;
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
318
|
+
fail(options.format, errorCode(message), message);
|
|
262
319
|
}
|
|
263
|
-
const config = loadConfig();
|
|
264
|
-
const target = resolveSandboxTarget(options.target, config.repoRoot);
|
|
265
|
-
const commit = git(config.repoRoot, ['rev-parse', target.branch]);
|
|
266
|
-
const startedAt = new Date().toISOString();
|
|
267
|
-
const result = options.scope === 'snapshot'
|
|
268
|
-
? snapshotValidation(config.repoRoot, commit, options)
|
|
269
|
-
: inplaceValidation(config, target, options);
|
|
270
|
-
const evidence = {
|
|
271
|
-
version: 1,
|
|
272
|
-
taskId: target.workspace.mode === 'task-bound' ? target.workspace.taskId : null,
|
|
273
|
-
branch: target.branch,
|
|
274
|
-
scope: options.scope,
|
|
275
|
-
commit,
|
|
276
|
-
command: path.basename(options.command[0]),
|
|
277
|
-
startedAt,
|
|
278
|
-
completedAt: new Date().toISOString(),
|
|
279
|
-
exitCode: result.exitCode,
|
|
280
|
-
signal: result.signal,
|
|
281
|
-
cleanup: result.cleanup()
|
|
282
|
-
};
|
|
283
|
-
if (options.format === 'json')
|
|
284
|
-
process.stdout.write(`${JSON.stringify(evidence)}\n`);
|
|
285
|
-
else
|
|
286
|
-
process.stdout.write(`Validation ${result.exitCode === 0 ? 'passed' : 'failed'} (${options.scope}, ${evidence.command}, cleanup=${evidence.cleanup}).\n`);
|
|
287
|
-
return result.exitCode;
|
|
288
320
|
}
|
|
289
|
-
|
|
321
|
+
export { taskValidate };
|
|
322
|
+
//# sourceMappingURL=task-validate.js.map
|
package/dist/lib/run/tui.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { renderAgentClientInvocation } from '../agent-clients/invocation.js';
|
|
2
2
|
import { getAgentClientAdapter } from '../agent-clients/registry.js';
|
|
3
|
-
const TUI_NAMES = new Set(['claude', 'codex', 'antigravity', 'opencode']);
|
|
3
|
+
const TUI_NAMES = new Set(['claude', 'codex', 'antigravity', 'opencode', 'traecli']);
|
|
4
4
|
const TUI_AGENT_CLIENT_IDS = Object.freeze({
|
|
5
5
|
claude: 'claude-code',
|
|
6
6
|
codex: 'codex',
|
|
7
7
|
antigravity: 'antigravity-cli',
|
|
8
|
-
opencode: 'opencode'
|
|
8
|
+
opencode: 'opencode',
|
|
9
|
+
traecli: 'traecli'
|
|
9
10
|
});
|
|
10
11
|
function isTuiName(value) {
|
|
11
12
|
return typeof value === 'string' && TUI_NAMES.has(value);
|
|
@@ -33,6 +34,8 @@ export function buildTuiCommand(tui, prompt) {
|
|
|
33
34
|
return ['agy', ['--dangerously-skip-permissions', '--print', prompt]];
|
|
34
35
|
if (tui === 'opencode')
|
|
35
36
|
return ['opencode', ['run', '--dangerously-skip-permissions', prompt]];
|
|
37
|
+
if (tui === 'traecli')
|
|
38
|
+
return ['traecli', ['exec', '--dangerously-bypass-approvals-and-sandbox', prompt]];
|
|
36
39
|
return ['codex', ['exec', '--dangerously-bypass-approvals-and-sandbox', prompt]];
|
|
37
40
|
}
|
|
38
41
|
//# sourceMappingURL=tui.js.map
|
|
@@ -126,10 +126,12 @@ function defaultProbe(manifest, identity) {
|
|
|
126
126
|
function assertRegistrationBinding(registration, manifest, buildIdentity) {
|
|
127
127
|
if (registration.taskId !== manifest.taskId
|
|
128
128
|
|| registration.controlGeneration !== manifest.generation
|
|
129
|
-
|| registration.containerId !== manifest.containerIdentity.id
|
|
130
|
-
|| JSON.stringify(registration.buildIdentity) !== JSON.stringify(buildIdentity)) {
|
|
129
|
+
|| registration.containerId !== manifest.containerIdentity.id) {
|
|
131
130
|
fail('CODEX_SANDBOX_CONTROLLER_REGISTRATION_INVALID', 'controller registration binding is invalid');
|
|
132
131
|
}
|
|
132
|
+
if (registration.buildIdentity.protocolVersion !== buildIdentity.protocolVersion) {
|
|
133
|
+
fail('CODEX_LIFECYCLE_PROTOCOL_MISMATCH', 'Codex lifecycle protocol version does not match');
|
|
134
|
+
}
|
|
133
135
|
}
|
|
134
136
|
function atomicWrite(file, value) {
|
|
135
137
|
const temporary = path.join(path.dirname(file), `.${path.basename(file)}.${process.pid}.${crypto.randomUUID()}.tmp`);
|
|
@@ -117,12 +117,15 @@ function controllerFailure(error) {
|
|
|
117
117
|
? error.code
|
|
118
118
|
: /^([A-Z][A-Z0-9_]+)/u.exec(error instanceof Error ? error.message : String(error))?.[1]
|
|
119
119
|
?? 'CODEX_SANDBOX_CONTROLLER_FAILED';
|
|
120
|
+
const message = error instanceof CodexControllerRegistrationError
|
|
121
|
+
? error.message
|
|
122
|
+
: `${code}: controller operation failed; inspect the sandbox controller and rebuild the sandbox if needed`;
|
|
120
123
|
const payload = {
|
|
121
124
|
version: 1,
|
|
122
125
|
status: 'failed',
|
|
123
126
|
changed: false,
|
|
124
127
|
lease: null,
|
|
125
|
-
error: { code, message
|
|
128
|
+
error: { code, message, retryable: false }
|
|
126
129
|
};
|
|
127
130
|
return { exitCode: 1, stdout: `${JSON.stringify(payload)}\n`, stderr: '' };
|
|
128
131
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
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
3
|
import { createCodexCapabilityStore, isCodexCapabilityProvenanceDetail } from '../agent-clients/adapters/codex-lifecycle/capability-store.js';
|
|
4
|
-
import { computeLifecycleBuildIdentity } from '../agent-clients/adapters/codex-lifecycle/build-identity.js';
|
|
5
|
-
import {
|
|
6
|
-
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';
|
|
7
7
|
import { resolveTaskRef } from './resolve-ref.js';
|
|
8
8
|
import { activateMatchingOrchestrationDelegation, hasActivatableOrchestrationDelegation, hasSealableOrchestrationDelegation, OrchestrationStateError, pauseMatchingOrchestrationDelegation, prepareOrchestrationDelegation, reconcileMatchingOrchestrationDelegation, sealMatchingOrchestrationDelegationWithHostEvidence } from './orchestration.js';
|
|
9
9
|
function coreOptions(options) {
|
|
@@ -42,29 +42,6 @@ function requiredStore(options) {
|
|
|
42
42
|
throw new Error('Codex lifecycle store is required for orchestration bridge events');
|
|
43
43
|
return options.store;
|
|
44
44
|
}
|
|
45
|
-
function controllerContext(repoRoot, brokerController) {
|
|
46
|
-
const contextPath = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
|
|
47
|
-
if (!contextPath)
|
|
48
|
-
return null;
|
|
49
|
-
if (brokerController) {
|
|
50
|
-
return verifyControllerContextFile(contextPath, {
|
|
51
|
-
repoRoot,
|
|
52
|
-
generation: process.env.AGENT_INFRA_CONTROL_GENERATION ?? brokerController.controlGeneration
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
return verifyCodexSandboxControllerContext(contextPath, { repoRoot });
|
|
56
|
-
}
|
|
57
|
-
function brokerBindingConflictsWithContext(repoRoot, brokerController) {
|
|
58
|
-
const contextPath = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
|
|
59
|
-
if (!contextPath || !brokerController)
|
|
60
|
-
return false;
|
|
61
|
-
const context = verifyControllerContextFile(contextPath, {
|
|
62
|
-
repoRoot,
|
|
63
|
-
generation: process.env.AGENT_INFRA_CONTROL_GENERATION ?? brokerController.controlGeneration
|
|
64
|
-
});
|
|
65
|
-
return context.controllerInstanceDigest !== brokerController.instanceDigest
|
|
66
|
-
|| context.controlGeneration !== brokerController.controlGeneration;
|
|
67
|
-
}
|
|
68
45
|
function brokerControllerBinding() {
|
|
69
46
|
const raw = process.env.AGENT_INFRA_CONTROL_CONTROLLER_BINDING;
|
|
70
47
|
if (!raw)
|
|
@@ -101,10 +78,17 @@ async function prepareCodexOrchestrationDelegation(taskRef, input, options = {})
|
|
|
101
78
|
}
|
|
102
79
|
const buildIdentity = options.buildIdentity ?? computeLifecycleBuildIdentity(repoRoot);
|
|
103
80
|
const brokerController = brokerControllerBinding();
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
81
|
+
const contextPath = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
|
|
82
|
+
const contextVerification = contextPath
|
|
83
|
+
? (brokerController
|
|
84
|
+
? verifyControllerContextFileWithWarnings(contextPath, {
|
|
85
|
+
repoRoot,
|
|
86
|
+
generation: process.env.AGENT_INFRA_CONTROL_GENERATION ?? brokerController.controlGeneration
|
|
87
|
+
})
|
|
88
|
+
: verifySandboxControllerWithWarnings(contextPath, { repoRoot }))
|
|
89
|
+
: null;
|
|
90
|
+
const identityWarnings = [...(contextVerification?.warnings ?? [])];
|
|
91
|
+
const localController = contextVerification?.context ?? null;
|
|
108
92
|
if (localController && brokerController
|
|
109
93
|
&& (localController.controllerInstanceDigest !== brokerController.instanceDigest
|
|
110
94
|
|| localController.controlGeneration !== brokerController.controlGeneration)) {
|
|
@@ -116,6 +100,11 @@ async function prepareCodexOrchestrationDelegation(taskRef, input, options = {})
|
|
|
116
100
|
} : null);
|
|
117
101
|
const capabilityStore = options.capabilityStore ?? createCodexCapabilityStore();
|
|
118
102
|
const attested = capabilityStore.inspect(input.capabilityToken);
|
|
103
|
+
const capabilityIdentity = verifyLifecycleBuildIdentity(attested.buildIdentity, buildIdentity);
|
|
104
|
+
if (!capabilityIdentity.ok) {
|
|
105
|
+
return bridgeFailure(capabilityIdentity.code, capabilityIdentity.message);
|
|
106
|
+
}
|
|
107
|
+
identityWarnings.push(...capabilityIdentity.warnings);
|
|
119
108
|
const lifecycleProvenance = {
|
|
120
109
|
...attested.buildIdentity,
|
|
121
110
|
hookDefinitionHash: preflight.hookDefinitionHash,
|
|
@@ -135,7 +124,7 @@ async function prepareCodexOrchestrationDelegation(taskRef, input, options = {})
|
|
|
135
124
|
controlGeneration: controller.controlGeneration
|
|
136
125
|
} } : {})
|
|
137
126
|
};
|
|
138
|
-
|
|
127
|
+
const prepared = prepareOrchestrationDelegation(taskRef, {
|
|
139
128
|
...input,
|
|
140
129
|
lifecycleProvenance
|
|
141
130
|
}, {
|
|
@@ -175,6 +164,9 @@ async function prepareCodexOrchestrationDelegation(taskRef, input, options = {})
|
|
|
175
164
|
}
|
|
176
165
|
}
|
|
177
166
|
});
|
|
167
|
+
return identityWarnings.length > 0 && prepared.status !== 'failed'
|
|
168
|
+
? { ...prepared, warnings: Object.freeze(identityWarnings) }
|
|
169
|
+
: prepared;
|
|
178
170
|
}
|
|
179
171
|
catch (error) {
|
|
180
172
|
if (error instanceof OrchestrationStateError)
|
|
@@ -216,10 +208,11 @@ async function activateCodexOrchestrationDelegation(childThreadId, options = {})
|
|
|
216
208
|
});
|
|
217
209
|
const buildIdentity = options.buildIdentity ?? computeLifecycleBuildIdentity(repoRoot);
|
|
218
210
|
const contextPath = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
|
|
219
|
-
const
|
|
220
|
-
?
|
|
211
|
+
const contextVerification = contextPath
|
|
212
|
+
? verifySandboxControllerWithWarnings(contextPath, { repoRoot })
|
|
221
213
|
: null;
|
|
222
|
-
|
|
214
|
+
const controller = contextVerification?.context ?? null;
|
|
215
|
+
const activated = activateMatchingOrchestrationDelegation('codex', {
|
|
223
216
|
nativeAgent: evidence.nativeAgent,
|
|
224
217
|
childId: evidence.childThreadId,
|
|
225
218
|
parentId: evidence.parentThreadId,
|
|
@@ -244,6 +237,10 @@ async function activateCodexOrchestrationDelegation(childThreadId, options = {})
|
|
|
244
237
|
controlGeneration: controller?.controlGeneration ?? null
|
|
245
238
|
}
|
|
246
239
|
}, coreOptions(options));
|
|
240
|
+
const warnings = contextVerification?.warnings ?? [];
|
|
241
|
+
return warnings.length > 0 && activated.status !== 'failed'
|
|
242
|
+
? { ...activated, warnings: Object.freeze(warnings) }
|
|
243
|
+
: activated;
|
|
247
244
|
}
|
|
248
245
|
catch (error) {
|
|
249
246
|
if (error instanceof OrchestrationStateError)
|
|
@@ -15,6 +15,12 @@ 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
|
+
}
|
|
18
24
|
function nullableText(value) {
|
|
19
25
|
return value === null || exactText(value);
|
|
20
26
|
}
|
|
@@ -92,9 +98,6 @@ function hasCurrentCodexEvidence(receipt) {
|
|
|
92
98
|
const host = receipt.hostEvidence;
|
|
93
99
|
if (host?.kind !== 'codex-lifecycle-v2'
|
|
94
100
|
|| host.protocolVersion !== provenance.protocolVersion
|
|
95
|
-
|| host.packageVersion !== provenance.packageVersion
|
|
96
|
-
|| host.internalExecutableBuildHash !== provenance.internalExecutableBuildHash
|
|
97
|
-
|| host.lifecycleContractHash !== provenance.lifecycleContractHash
|
|
98
101
|
|| host.hookDefinitionHash !== provenance.hookDefinitionHash
|
|
99
102
|
|| host.hookSource !== provenance.hookSource
|
|
100
103
|
|| host.hookSourcePathDigest !== provenance.hookSourcePathDigest
|
|
@@ -379,9 +382,6 @@ function activateDelegation(receipt, event, options = {}) {
|
|
|
379
382
|
const activationDeadlineAt = Date.parse(receipt.activationDeadlineAt);
|
|
380
383
|
if (!expected
|
|
381
384
|
|| event.hostEvidence.protocolVersion !== expected.protocolVersion
|
|
382
|
-
|| event.hostEvidence.packageVersion !== expected.packageVersion
|
|
383
|
-
|| event.hostEvidence.internalExecutableBuildHash !== expected.internalExecutableBuildHash
|
|
384
|
-
|| event.hostEvidence.lifecycleContractHash !== expected.lifecycleContractHash
|
|
385
385
|
|| event.hostEvidence.hookDefinitionHash !== expected.hookDefinitionHash
|
|
386
386
|
|| event.hostEvidence.hookSource !== expected.hookSource
|
|
387
387
|
|| event.hostEvidence.hookSourcePathDigest !== expected.hookSourcePathDigest
|
|
@@ -395,7 +395,8 @@ function activateDelegation(receipt, event, options = {}) {
|
|
|
395
395
|
|| spawnObservedAt > activationDeadlineAt
|
|
396
396
|
|| event.parentId !== expected.capabilitySessionId
|
|
397
397
|
|| (event.hostEvidence.controllerInstanceDigest ?? null) !== expected.controllerInstanceDigest
|
|
398
|
-
|| (event.hostEvidence.controlGeneration ?? null) !== expected.controlGeneration
|
|
398
|
+
|| (event.hostEvidence.controlGeneration ?? null) !== expected.controlGeneration
|
|
399
|
+
|| !validCodexBuildMetadata(event.hostEvidence))
|
|
399
400
|
return fail('DELEGATION_HOST_EVIDENCE_INVALID', 'Codex lifecycle provenance does not match the prepared receipt');
|
|
400
401
|
}
|
|
401
402
|
return { ok: true, receipt: Object.freeze({
|
|
@@ -269,11 +269,18 @@ function mutationPatch(current, mutation) {
|
|
|
269
269
|
}
|
|
270
270
|
if (mutation.scope === 'verification') {
|
|
271
271
|
if (mutation.operation === 'succeeded') {
|
|
272
|
+
const resolvedTaskWarning = current.warnings.some((warning) => warning.step === 'verification' && warning.status === 'open');
|
|
272
273
|
const warnings = resolveStepWarnings(current, 'verification');
|
|
273
|
-
return {
|
|
274
|
+
return {
|
|
275
|
+
verification: 'done',
|
|
276
|
+
taskComment: resolvedTaskWarning ? 'pending' : current.taskComment,
|
|
277
|
+
warningProjection: warnings.length > 0 ? 'pending' : 'done',
|
|
278
|
+
warnings,
|
|
279
|
+
lastError: null
|
|
280
|
+
};
|
|
274
281
|
}
|
|
275
282
|
const warnings = replaceWarning(current, warningFromError('verification', mutation.error), 'open');
|
|
276
|
-
return { verification: 'pending', warningProjection: 'pending', warnings, lastError: mutation.error };
|
|
283
|
+
return { verification: 'pending', taskComment: 'pending', warningProjection: 'pending', warnings, lastError: mutation.error };
|
|
277
284
|
}
|
|
278
285
|
return mutation.operation === 'succeeded'
|
|
279
286
|
? { warningProjection: 'done', lastError: null }
|
|
@@ -339,6 +346,50 @@ function reconcileWarningProjection(repoRoot, taskId, receipt, consumed) {
|
|
|
339
346
|
return receipt;
|
|
340
347
|
}
|
|
341
348
|
}
|
|
349
|
+
function syncPendingTaskComment(input) {
|
|
350
|
+
const { repoRoot, taskId, agent, commentSync, consumedCapabilities } = input;
|
|
351
|
+
let receipt = input.receipt;
|
|
352
|
+
if (receipt.taskComment !== 'pending') {
|
|
353
|
+
return {
|
|
354
|
+
receipt,
|
|
355
|
+
step: { status: receipt.taskComment === 'skipped' ? 'skipped' : 'no-op', changed: false, error: null },
|
|
356
|
+
changed: false,
|
|
357
|
+
error: null
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
try {
|
|
361
|
+
const result = commentSync(taskId, { kind: 'task', agent, cwd: repoRoot });
|
|
362
|
+
const step = commentStep(result);
|
|
363
|
+
if (result.status === 'applied' || result.status === 'no-op') {
|
|
364
|
+
const skipped = result.error?.code === 'ISSUE_NOT_LINKED';
|
|
365
|
+
const capability = issueCapability(receipt, 'task-comment');
|
|
366
|
+
receipt = applyFinalizationReceiptMutationUnderLock(repoRoot, receipt, capability, {
|
|
367
|
+
scope: 'task-comment', operation: 'succeeded', state: skipped ? 'skipped' : 'done'
|
|
368
|
+
}, consumedCapabilities);
|
|
369
|
+
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
370
|
+
return { receipt, step: skipped ? { ...step, status: 'skipped' } : step, changed: result.changed, error: null };
|
|
371
|
+
}
|
|
372
|
+
const detail = step.error ?? { code: 'COMMENT_SYNC_FAILED', message: 'task comment synchronization failed', retryable: true };
|
|
373
|
+
const capability = issueCapability(receipt, 'task-comment');
|
|
374
|
+
receipt = applyFinalizationReceiptMutationUnderLock(repoRoot, receipt, capability, {
|
|
375
|
+
scope: 'task-comment', operation: 'failed', error: detail
|
|
376
|
+
}, consumedCapabilities);
|
|
377
|
+
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
378
|
+
return { receipt, step, changed: result.changed, error: detail };
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
const detail = errorOf(error, 'COMMENT_SYNC_FAILED', true);
|
|
382
|
+
try {
|
|
383
|
+
const capability = issueCapability(receipt, 'task-comment');
|
|
384
|
+
receipt = applyFinalizationReceiptMutationUnderLock(repoRoot, receipt, capability, {
|
|
385
|
+
scope: 'task-comment', operation: 'failed', error: detail
|
|
386
|
+
}, consumedCapabilities);
|
|
387
|
+
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
388
|
+
}
|
|
389
|
+
catch { /* preserve the primary error */ }
|
|
390
|
+
return { receipt, step: { status: 'blocked', changed: false, error: detail }, changed: false, error: detail };
|
|
391
|
+
}
|
|
392
|
+
}
|
|
342
393
|
function terminalResult(taskId, receipt, steps, changed, error = null) {
|
|
343
394
|
const pending = pendingSteps(receipt);
|
|
344
395
|
const blocked = [steps.lifecycle, steps.taskComment, steps.verification].some((step) => step?.status === 'blocked');
|
|
@@ -458,50 +509,15 @@ function applyUnderLock(request, taskId, options) {
|
|
|
458
509
|
return failed(taskId, detail, { lifecycle: lifecycleResult });
|
|
459
510
|
}
|
|
460
511
|
let taskComment = null;
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
}
|
|
470
|
-
else {
|
|
471
|
-
const result = commentSync(taskId, { kind: 'task', agent: request.agent, cwd: repoRoot });
|
|
472
|
-
taskComment = commentStep(result);
|
|
473
|
-
if (result.status === 'applied' || result.status === 'no-op') {
|
|
474
|
-
const skipped = result.error?.code === 'ISSUE_NOT_LINKED';
|
|
475
|
-
const capability = issueCapability(receipt, 'task-comment');
|
|
476
|
-
receipt = applyFinalizationReceiptMutationUnderLock(repoRoot, receipt, capability, {
|
|
477
|
-
scope: 'task-comment', operation: 'succeeded', state: skipped ? 'skipped' : 'done'
|
|
478
|
-
}, consumedCapabilities);
|
|
479
|
-
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
480
|
-
taskComment = skipped ? { ...taskComment, status: 'skipped' } : taskComment;
|
|
481
|
-
changed = changed || result.changed;
|
|
482
|
-
}
|
|
483
|
-
else {
|
|
484
|
-
const detail = taskComment.error ?? { code: 'COMMENT_SYNC_FAILED', message: 'task comment synchronization failed', retryable: true };
|
|
485
|
-
const capability = issueCapability(receipt, 'task-comment');
|
|
486
|
-
receipt = applyFinalizationReceiptMutationUnderLock(repoRoot, receipt, capability, {
|
|
487
|
-
scope: 'task-comment', operation: 'failed', error: detail
|
|
488
|
-
}, consumedCapabilities);
|
|
489
|
-
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
490
|
-
return terminalResult(taskId, receipt, { lifecycle: lifecycleResult, taskComment, verification: null }, changed, taskComment.error);
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
catch (error) {
|
|
495
|
-
const detail = errorOf(error, 'COMMENT_SYNC_FAILED', true);
|
|
496
|
-
try {
|
|
497
|
-
const capability = issueCapability(receipt, 'task-comment');
|
|
498
|
-
receipt = applyFinalizationReceiptMutationUnderLock(repoRoot, receipt, capability, {
|
|
499
|
-
scope: 'task-comment', operation: 'failed', error: detail
|
|
500
|
-
}, consumedCapabilities);
|
|
501
|
-
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
502
|
-
}
|
|
503
|
-
catch { /* preserve the primary error */ }
|
|
504
|
-
return terminalResult(taskId, receipt, { lifecycle: lifecycleResult, taskComment: { status: 'blocked', changed: false, error: detail }, verification: null }, changed, detail);
|
|
512
|
+
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
513
|
+
const initialComment = syncPendingTaskComment({
|
|
514
|
+
repoRoot, taskId, agent: request.agent, receipt, commentSync, consumedCapabilities
|
|
515
|
+
});
|
|
516
|
+
receipt = initialComment.receipt;
|
|
517
|
+
taskComment = initialComment.step;
|
|
518
|
+
changed = changed || initialComment.changed;
|
|
519
|
+
if (initialComment.error) {
|
|
520
|
+
return terminalResult(taskId, receipt, { lifecycle: lifecycleResult, taskComment, verification: null }, changed, initialComment.error);
|
|
505
521
|
}
|
|
506
522
|
let verification = null;
|
|
507
523
|
try {
|
|
@@ -518,6 +534,16 @@ function applyUnderLock(request, taskId, options) {
|
|
|
518
534
|
scope: 'verification', operation: 'succeeded'
|
|
519
535
|
}, consumedCapabilities);
|
|
520
536
|
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
537
|
+
const finalComment = syncPendingTaskComment({
|
|
538
|
+
repoRoot, taskId, agent: request.agent, receipt, commentSync, consumedCapabilities
|
|
539
|
+
});
|
|
540
|
+
receipt = finalComment.receipt;
|
|
541
|
+
if (finalComment.step.status !== 'no-op')
|
|
542
|
+
taskComment = finalComment.step;
|
|
543
|
+
changed = changed || finalComment.changed;
|
|
544
|
+
if (finalComment.error) {
|
|
545
|
+
return terminalResult(taskId, receipt, { lifecycle: lifecycleResult, taskComment, verification }, changed, finalComment.error);
|
|
546
|
+
}
|
|
521
547
|
}
|
|
522
548
|
else {
|
|
523
549
|
const detail = verification.error ?? { code: 'VERIFY_FAILED', message: 'verification failed', retryable: true };
|
package/dist/lib/task/index.js
CHANGED
|
@@ -10,7 +10,6 @@ Commands:
|
|
|
10
10
|
ls [--all | --blocked | --completed] List tasks (default: active)
|
|
11
11
|
show [--task <ref>] Print a task.md
|
|
12
12
|
status [--task <ref>] Aggregated status view (metadata / artifacts / git / platform)
|
|
13
|
-
validate <ref> [options] -- <command> Run host validation in snapshot or inplace scope
|
|
14
13
|
|
|
15
14
|
Examples:
|
|
16
15
|
ai task cat 11 analysis
|
|
@@ -30,7 +29,6 @@ Examples:
|
|
|
30
29
|
ai task show 11
|
|
31
30
|
ai task show TASK-20260612-162737
|
|
32
31
|
ai task status 11
|
|
33
|
-
ai task validate 11 -- npm test
|
|
34
32
|
|
|
35
33
|
Run 'ai task <command> --help' for details.`;
|
|
36
34
|
export async function runTask(args) {
|
|
@@ -91,13 +89,6 @@ export async function runTask(args) {
|
|
|
91
89
|
status(rest);
|
|
92
90
|
break;
|
|
93
91
|
}
|
|
94
|
-
case 'validate': {
|
|
95
|
-
const { validate } = await import('./commands/validate.js');
|
|
96
|
-
const exitCode = await validate(rest);
|
|
97
|
-
if (exitCode !== 0)
|
|
98
|
-
process.exitCode = exitCode;
|
|
99
|
-
break;
|
|
100
|
-
}
|
|
101
92
|
default:
|
|
102
93
|
process.stderr.write(`Unknown task command: ${subcommand}\n\n`);
|
|
103
94
|
process.stdout.write(`${USAGE}\n`);
|
|
@@ -25,7 +25,7 @@ function supportsLifecycleDelegation(client) {
|
|
|
25
25
|
function orchestrationPath(taskDir) {
|
|
26
26
|
return path.join(taskDir, 'orchestration.json');
|
|
27
27
|
}
|
|
28
|
-
const ORCHESTRATION_STATE_INVALID_MESSAGE = 'orchestration.json does not match the current runtime structure;
|
|
28
|
+
const ORCHESTRATION_STATE_INVALID_MESSAGE = 'orchestration.json does not match the current runtime structure; the file was left unchanged; rebuild the sandbox or manually repair the state before retrying';
|
|
29
29
|
class OrchestrationStateError extends Error {
|
|
30
30
|
code = 'ORCHESTRATION_STATE_INVALID';
|
|
31
31
|
taskId;
|
|
@@ -308,9 +308,6 @@ function checkOrchestrationEvidence({ taskDir }) {
|
|
|
308
308
|
if (!provenance
|
|
309
309
|
|| (activatedCodex && (host?.kind !== 'codex-lifecycle-v2'
|
|
310
310
|
|| host.protocolVersion !== provenance.protocolVersion
|
|
311
|
-
|| host.packageVersion !== provenance.packageVersion
|
|
312
|
-
|| host.internalExecutableBuildHash !== provenance.internalExecutableBuildHash
|
|
313
|
-
|| host.lifecycleContractHash !== provenance.lifecycleContractHash
|
|
314
311
|
|| host.hookDefinitionHash !== provenance.hookDefinitionHash
|
|
315
312
|
|| host.hookSource !== provenance.hookSource
|
|
316
313
|
|| host.hookSourcePathDigest !== provenance.hookSourcePathDigest
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"protocolVersion": 3,
|
|
3
|
-
"packageVersion": "0.9.
|
|
4
|
-
"sourceInputHash": "
|
|
5
|
-
"internalExecutableBuildHash": "
|
|
3
|
+
"packageVersion": "0.9.10",
|
|
4
|
+
"sourceInputHash": "fae928c7a46686dd39f9f57424e3caff8aed3ce5de5700475b4a3a8f2954b3a3",
|
|
5
|
+
"internalExecutableBuildHash": "a5e143239a8fdd93c4696125aab04b28d7baf59c2a65488705fe930d4965f354"
|
|
6
6
|
}
|
|
@@ -28,6 +28,13 @@ type IdentityVerification = Readonly<{
|
|
|
28
28
|
ok: boolean;
|
|
29
29
|
code: string | null;
|
|
30
30
|
message: string | null;
|
|
31
|
+
warnings: readonly LifecycleIdentityWarning[];
|
|
32
|
+
}>;
|
|
33
|
+
|
|
34
|
+
type LifecycleIdentityWarning = Readonly<{
|
|
35
|
+
code: 'CODEX_LIFECYCLE_BUILD_MISMATCH' | 'CODEX_LIFECYCLE_CONTRACT_MISMATCH';
|
|
36
|
+
message: string;
|
|
37
|
+
action: 'rebuild-sandbox';
|
|
31
38
|
}>;
|
|
32
39
|
|
|
33
40
|
function exactText(value: unknown): value is string {
|
|
@@ -201,25 +208,32 @@ function verifyLifecycleBuildIdentity(
|
|
|
201
208
|
return {
|
|
202
209
|
ok: false,
|
|
203
210
|
code: 'CODEX_LIFECYCLE_PROTOCOL_MISMATCH',
|
|
204
|
-
message: 'Codex lifecycle protocol version does not match'
|
|
211
|
+
message: 'Codex lifecycle protocol version does not match',
|
|
212
|
+
warnings: []
|
|
205
213
|
};
|
|
206
214
|
}
|
|
215
|
+
const warnings: LifecycleIdentityWarning[] = [];
|
|
207
216
|
if (actual.packageVersion !== expected.packageVersion
|
|
208
217
|
|| actual.internalExecutableBuildHash !== expected.internalExecutableBuildHash) {
|
|
209
|
-
|
|
210
|
-
ok: false,
|
|
218
|
+
warnings.push({
|
|
211
219
|
code: 'CODEX_LIFECYCLE_BUILD_MISMATCH',
|
|
212
|
-
message: 'Codex lifecycle executable build identity
|
|
213
|
-
|
|
220
|
+
message: 'Codex lifecycle executable build identity differs; rebuild the sandbox if the runtime is stale',
|
|
221
|
+
action: 'rebuild-sandbox'
|
|
222
|
+
});
|
|
214
223
|
}
|
|
215
224
|
if (actual.lifecycleContractHash !== expected.lifecycleContractHash) {
|
|
216
|
-
|
|
217
|
-
ok: false,
|
|
225
|
+
warnings.push({
|
|
218
226
|
code: 'CODEX_LIFECYCLE_CONTRACT_MISMATCH',
|
|
219
|
-
message: 'Codex lifecycle contract identity
|
|
220
|
-
|
|
227
|
+
message: 'Codex lifecycle contract identity differs; rebuild the sandbox if the runtime is stale',
|
|
228
|
+
action: 'rebuild-sandbox'
|
|
229
|
+
});
|
|
221
230
|
}
|
|
222
|
-
return {
|
|
231
|
+
return {
|
|
232
|
+
ok: true,
|
|
233
|
+
code: null,
|
|
234
|
+
message: null,
|
|
235
|
+
warnings: Object.freeze(warnings)
|
|
236
|
+
};
|
|
223
237
|
}
|
|
224
238
|
|
|
225
239
|
export {
|
|
@@ -233,6 +247,7 @@ export {
|
|
|
233
247
|
};
|
|
234
248
|
export type {
|
|
235
249
|
IdentityVerification,
|
|
250
|
+
LifecycleIdentityWarning,
|
|
236
251
|
LifecycleBuildIdentity,
|
|
237
252
|
LifecycleManifestFiles,
|
|
238
253
|
LifecycleBuildIdentityOptions
|