Files
Genarrative/apps/ai-game-creator-shell/scripts/agent-runtime-deterministic-playable-e2e.mjs
suzmii e34d797336
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / Frontend tests (pull_request) Successful in 2m59s
Project CI / Repository checks (pull_request) Failing after 21s
Project CI / Native shell tests (pull_request) Failing after 16m26s
修复 AGC 确定性 E2E 与 master 合并后的运行链路
合并 master 后 isolated AppData 配置改为私有副本,避免 Windows 安全校验拒绝硬链接。
只读 runner 状态命令显式配置 config dir,避免误读为 runner 未启用。
为 debug 构建增加仅 E2E 显式开启的确定性 Provider 路由开关,并补充回归测试。
兼容 Windows 对私有副本权限位的校验差异。
2026-09-03 15:59:19 +08:00

2031 lines
72 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { spawn } from 'node:child_process';
import { createHash, randomUUID } from 'node:crypto';
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import {
createDeterministicLaneDefenseRouter,
deterministicLaneDefenseCanonicalHtml,
deterministicLaneDefenseInitialHtml,
deterministicLaneDefenseModel,
deterministicManifestReadyAgentIds,
hiddenCanvasCss,
startDeterministicLaneDefenseProvider,
visibleCanvasCss,
} from './deterministic-lane-defense-provider.mjs';
import { withLoopbackNoProxy } from './llm-transient-fault-proxy.mjs';
const appRoot = path.resolve(fileURLToPath(new URL('..', import.meta.url)));
const repoRoot = path.resolve(appRoot, '../..');
const realE2eScript = path.join(appRoot, 'scripts/agent-runtime-real-e2e.mjs');
const suite = 'supervisor-autonomous-playable-lane-defense';
const wrapperSuite =
'supervisor-autonomous-playable-lane-defense-deterministic';
const configFileName = 'game-creator.config.json';
const configSentinelName = '.deterministic-provider-e2e.json';
const configSentinelSchema = 'genarrative-deterministic-provider-e2e-config.v1';
const platformSessionFixtureEnv = 'GENARRATIVE_AGC_PLATFORM_SESSION_FIXTURE';
const platformSessionFixtureName = '.deterministic-platform-session.json';
const platformSessionFixtureSchema =
'genarrative-agc-platform-session-fixture.v1';
const outputLimit = 32 * 1024 * 1024;
function hashValue(value) {
return createHash('sha256').update(value).digest('hex');
}
function assert(condition, code) {
if (condition) return;
const error = new Error(code);
error.code = code;
throw error;
}
function parseArguments(args) {
let keepProject = false;
let selfTest = false;
for (const arg of args) {
if (arg === '--keep-project') keepProject = true;
else if (arg === '--self-test') selfTest = true;
else throw new Error('unknown-argument');
}
assert(!(keepProject && selfTest), 'self-test-keep-project-conflict');
return { keepProject, selfTest };
}
function deterministicRuntimeConfig(apiKey, provider) {
return {
agentMode: 'provider',
editorApi: {
apiKey,
baseUrl: provider.editorBaseUrl,
},
llm: {
apiKey,
baseUrl: provider.baseUrl,
model: deterministicLaneDefenseModel,
apiKind: 'openai_chat',
reasoningEffort: 'max',
stream: false,
requestTimeoutMs: 30_000,
maxRetries: 0,
retryBackoffMs: 100,
},
agentLlm: {
'project-supervisor': {
reasoningEffort: 'max',
},
},
};
}
function deterministicPlatformSessionFixture(apiKey, provider) {
return {
schemaVersion: platformSessionFixtureSchema,
userId: 'deterministic-e2e-user',
accessToken: apiKey,
apiBaseUrl: provider.editorBaseUrl,
generation: 1,
};
}
function appendBounded(current, chunk) {
const combined = Buffer.concat([current, chunk]);
if (combined.length > outputLimit) throw new Error('child-output-too-large');
return combined;
}
function runChild(args, environment) {
return new Promise((resolve) => {
const child = spawn(process.execPath, args, {
cwd: appRoot,
env: environment,
stdio: ['ignore', 'pipe', 'pipe'],
});
let stdout = Buffer.alloc(0);
let stderr = Buffer.alloc(0);
let outputError = null;
child.stdout.on('data', (chunk) => {
try {
stdout = appendBounded(stdout, chunk);
} catch (error) {
outputError = error;
child.kill('SIGTERM');
}
});
child.stderr.on('data', (chunk) => {
try {
stderr = appendBounded(stderr, chunk);
} catch (error) {
outputError = error;
child.kill('SIGTERM');
}
});
child.once('error', (error) =>
resolve({ code: null, signal: null, error, stdout, stderr }),
);
child.once('close', (code, signal) =>
resolve({ code, signal, error: outputError, stdout, stderr }),
);
});
}
function safeChildDiagnostic(result) {
return {
exitCode: Number.isInteger(result.code) ? result.code : null,
signal: typeof result.signal === 'string' ? result.signal : null,
errorCode:
typeof result.error?.code === 'string' ? result.error.code : null,
stdoutBytes: result.stdout.length,
stdoutSha256: hashValue(result.stdout),
stderrBytes: result.stderr.length,
stderrSha256: hashValue(result.stderr),
};
}
function parseChildReport(result) {
try {
const report = JSON.parse(result.stdout.toString('utf8'));
assert(report && typeof report === 'object', 'child-report-root-invalid');
return report;
} catch (error) {
if (error?.code) throw error;
const wrapped = new Error('child-report-json-invalid');
wrapped.code = 'child-report-json-invalid';
throw wrapped;
}
}
function expectedProviderStats(stats) {
const manifestReadyTasks = manifestReadyTaskEvidence(stats);
const projectSupervisorRuntimePlanningCount =
Number.isInteger(stats.byAgent?.['project-supervisor']?.planning) &&
Number.isInteger(stats.interactionExecuteCount)
? stats.byAgent['project-supervisor'].planning -
stats.interactionExecuteCount
: null;
return (
Number.isInteger(stats.requestCount) &&
stats.requestCount >= 40 &&
stats.planningRequestCount +
stats.finalReplyRequestCount +
(stats.contextCompactionRequestCount ?? 0) +
(stats.imageInspectionRequestCount ?? 0) ===
stats.requestCount &&
stats.finalReplyRequestCount === 0 &&
stats.interactionExecuteCount === 1 &&
stats.goalContractCount === 1 &&
stats.actionHistoryCount === 1 &&
stats.acceptanceUpdateCount === 1 &&
stats.delegateActionCount === 0 &&
stats.runStatusCount >= 1 &&
stats.sourceWriteCount >= 7 &&
stats.staticSmokeCount >= 4 &&
stats.previewValidationCount >= 2 &&
manifestReadyTasks.exactlyOnce &&
stats.manifestReadyTaskFileWriteCount >= 7 &&
stats.manifestReadyTaskPreviewValidationCount >= 1 &&
stats.manifestReadyTaskCanvasGenerationCount >=
stats.canvasGenerationRequestCount &&
stats.manifestReadyTaskCanvasGenerationCount <=
stats.canvasGenerationRequestCount + 16 &&
stats.imageInspectionRequestCount === 1 &&
stats.canvasGenerationRequestCount === 3 &&
stats.canvasDownloadRequestCount === 3 &&
stats.canvasSliceDownloadRequestCount === 4 &&
stats.canvasGeneratedAspectRatios?.['16:9'] === 1 &&
stats.canvasGeneratedAspectRatios?.['1:1'] === 2 &&
stats.canonicalCodeRunCount === 1 &&
stats.canonicalCodeAssetListCount === 1 &&
stats.unexpectedRequestCount === 0 &&
Object.keys(stats.rejectionCodes ?? {}).length === 0 &&
projectSupervisorRuntimePlanningCount >= 5 &&
stats.byAgent?.['project-supervisor']?.finalReply === 0 &&
stats.byAgent?.['project-supervisor']?.projectMutation === 0 &&
stats.byAgent?.['code-prototype']?.planning >= 5 &&
stats.byAgent?.['code-prototype']?.finalReply === 0 &&
stats.byAgent?.['code-prototype']?.projectMutation === 1 &&
stats.byAgent?.['quality-review']?.finalReply === 0 &&
stats.byAgent?.['quality-review']?.projectMutation === 0
);
}
function manifestReadyTaskEvidence(stats) {
const rawCounts = stats?.readyTaskCountsByAgent;
const byAgent =
rawCounts && typeof rawCounts === 'object' && !Array.isArray(rawCounts)
? Object.fromEntries(
Object.entries(rawCounts)
.sort(([left], [right]) => left.localeCompare(right))
.map(([agentId, counts]) => [
agentId,
{
run: counts?.run ?? null,
completion: counts?.completion ?? null,
},
]),
)
: {};
const actualAgentIds = Object.keys(byAgent);
const expectedAgentIds = [...deterministicManifestReadyAgentIds].sort();
const exactAgentSet =
actualAgentIds.length === expectedAgentIds.length &&
actualAgentIds.every(
(agentId, index) => agentId === expectedAgentIds[index],
);
const runTotal = Object.values(byAgent).reduce(
(total, counts) => total + (Number.isInteger(counts.run) ? counts.run : 0),
0,
);
const completionTotal = Object.values(byAgent).reduce(
(total, counts) =>
total + (Number.isInteger(counts.completion) ? counts.completion : 0),
0,
);
const perAgentExactlyOnce =
exactAgentSet &&
expectedAgentIds.every(
(agentId) =>
byAgent[agentId]?.run === 1 && byAgent[agentId]?.completion === 1,
);
return {
expectedAgentIds,
byAgent,
runTotal,
completionTotal,
exactAgentSet,
perAgentExactlyOnce,
exactlyOnce:
perAgentExactlyOnce &&
runTotal === deterministicManifestReadyAgentIds.length &&
completionTotal === deterministicManifestReadyAgentIds.length &&
stats?.manifestReadyTaskRunCount ===
deterministicManifestReadyAgentIds.length &&
stats?.manifestReadyTaskCompletionCount ===
deterministicManifestReadyAgentIds.length,
};
}
const requiredZeroChildEvidenceFields = Object.freeze([
'activeRunnerKillCount',
'approveInputCount',
'answerInputCount',
'steerInputCount',
'turnReportWaitingForConfirmationCount',
'turnReportWaitingForUserInputCount',
'turnReportReconciliationAgentCount',
'providerLifecycleFailedCount',
'openProviderLifecycleCount',
'pendingActionCount',
'confirmationSidecarCount',
'userInputSidecarCount',
'providerActionBatchSidecarCount',
'providerRetrySidecarCount',
'providerHandoffSidecarCount',
'toolPlanHandoffSidecarCount',
'finalizationJournalCount',
'reconciliationResidueCount',
]);
function expectedChildReport(report, options, providerStats) {
const evidence = report?.evidence;
const providerRequestCount = providerStats?.requestCount;
const runtimeProviderRequestCount =
Number.isInteger(providerRequestCount) &&
Number.isInteger(providerStats?.interactionExecuteCount) &&
Number.isInteger(providerStats?.imageInspectionRequestCount)
? providerRequestCount -
providerStats.interactionExecuteCount -
providerStats.imageInspectionRequestCount
: null;
return (
report?.status === 'PASS' &&
report?.suite === suite &&
report?.errorCount === 0 &&
Array.isArray(report?.blocked) &&
report.blocked.length === 0 &&
report?.cleanup?.performed === !options.keepProject &&
report?.cleanup?.kept === options.keepProject &&
evidence?.evidenceCompleteness === 'complete' &&
evidence?.dedicatedZeroInterventionPath === true &&
evidence?.stdinTaskCount === 1 &&
evidence?.stdinEndedAfterTask === true &&
evidence?.turnReportOutcome === 'settled' &&
evidence?.parentTaskStatus === 'completed' &&
evidence?.parentRuntimeStatus === 'idle' &&
evidence?.parentRuntimePhase === 'completed' &&
evidence?.laneDefensePlaytestPassed === true &&
evidence?.laneDefenseAssertionCount === 37 &&
evidence?.laneDefensePassedAssertionCount === 37 &&
evidence?.browserValidationPassed === true &&
evidence?.staticSmokePassed === true &&
evidence?.gameIndexChanged === true &&
Number.isInteger(evidence?.projectRevisionDelta) &&
evidence.projectRevisionDelta > 0 &&
evidence?.finalSupervisorAssistantCount === 1 &&
evidence?.professionalAssistantCount >= 3 &&
evidence?.providerRequestIdentityCount === runtimeProviderRequestCount &&
evidence?.providerLifecycleStartedCount === runtimeProviderRequestCount &&
evidence?.providerLifecycleTerminalCount === runtimeProviderRequestCount &&
evidence?.providerLifecycleCompletedCount === runtimeProviderRequestCount &&
requiredZeroChildEvidenceFields.every((field) => evidence?.[field] === 0)
);
}
function syntheticPayload(agentId, runId, tools, extraContext = '') {
return {
model: deterministicLaneDefenseModel,
stream: false,
messages: [
{
role: 'user',
content: `- templateAgentId: ${agentId}\n- runId: ${runId}\n${extraContext}`,
},
],
tools: tools.map((name) => ({ type: 'function', function: { name } })),
};
}
function syntheticInteractionExecutePayload() {
return {
model: deterministicLaneDefenseModel,
stream: false,
reasoning_effort: 'max',
messages: [
{
role: 'system',
content: '你现在位于统一的 Agent interaction loop。',
},
{
role: 'user',
content: '用户这轮输入:\n制作一个三消经营游戏',
},
],
tools: ['runtime_execute', 'runtime_resume', 'project_location'].map(
(name) => ({ type: 'function', function: { name } }),
),
};
}
function syntheticUiPrototypeInspectionPayload() {
return {
model: deterministicLaneDefenseModel,
stream: false,
messages: [
{
role: 'system',
content: '你是游戏界面视觉检查 Agent。只分析画面。',
},
{
role: 'user',
content: [
{
type: 'text',
text: '请逐项检查 informationHud、gameplaySurface、objectiveEntities、primaryControls、failureRestartFlow、responsiveLayout、implementationClarity、originalTheme,并只返回严格 JSON。',
},
{
type: 'image_url',
image_url: { url: 'data:image/png;base64,AA==' },
},
],
},
],
};
}
function responseFunctionNames(response) {
return response.choices[0].message.tool_calls.map(
(call) => call.function.name,
);
}
function responseFunctionCalls(response) {
return response.choices[0].message.tool_calls.map((call) => ({
name: call.function.name,
arguments: JSON.parse(call.function.arguments),
}));
}
async function runSelfTest() {
const html = deterministicLaneDefenseInitialHtml();
assert([...html].length <= 8_000, 'self-test-html-source-budget-invalid');
assert(
html.includes(hiddenCanvasCss) &&
!html.includes(visibleCanvasCss) &&
html.includes('playable-web-game-state.v1') &&
html.includes('data-playtest-id="next-level"') &&
html.includes('Goal: defend the garden and win every wave.') &&
html.includes('requestAnimationFrame'),
'self-test-html-contract-invalid',
);
const canonicalHtml = deterministicLaneDefenseCanonicalHtml();
assert(
canonicalHtml.includes(visibleCanvasCss) &&
canonicalHtml.includes("atlasArt.src='../assets/art-spritesheet.png'") &&
[
'player.png',
'blocks-and-targets.png',
'obstacles-and-scene.png',
'feedback-effects.png',
].every((fileName) =>
canonicalHtml.includes(`../assets/art-spritesheet-slices/${fileName}`),
) &&
(canonicalHtml.match(/ctx\.drawImage\(/g) ?? []).length >= 5,
'self-test-canonical-visible-art-contract-invalid',
);
const apiKey = `deterministic-self-test-${randomUUID()}`;
const runtimeConfig = deterministicRuntimeConfig(apiKey, {
baseUrl: 'http://127.0.0.1:41001/v1',
editorBaseUrl: 'http://127.0.0.1:41002',
});
assert(
runtimeConfig.agentMode === 'provider' &&
runtimeConfig.llm.apiKind === 'openai_chat' &&
runtimeConfig.llm.reasoningEffort === 'max' &&
runtimeConfig.agentLlm?.['project-supervisor']?.reasoningEffort ===
'max' &&
runtimeConfig.llm.apiKey === apiKey &&
runtimeConfig.editorApi.apiKey === apiKey,
'self-test-provider-runtime-config-invalid',
);
const captureProviderErrorCode = (operation) => {
try {
operation();
return null;
} catch (error) {
return error?.code ?? null;
}
};
const allTools = [
'update_agent_plan',
'respond_to_user',
'runtime_tool_agent_action_history',
'runtime_tool_agent_acceptance_update',
'runtime_tool_agent_run_status',
'runtime_tool_command_run_limited',
'runtime_tool_file_patch',
'runtime_tool_file_write',
'runtime_tool_preview_validate',
'runtime_tool_task_list',
];
const manifestReadyTools = [
...allTools,
'runtime_tool_asset_list',
'runtime_tool_file_read',
];
const rootRunId = 'parent-run';
const contractFingerprint = 'a'.repeat(64);
const contractContext = `[Root Goal Contract]\n${JSON.stringify({ contractFingerprint })}`;
const observationContext = (observations) =>
`${contractContext}\n已有工具观察:\n${JSON.stringify(observations)}`;
const goalContractTools = ['runtime_tool_agent_goal_contract'];
const goalContractRouter = createDeterministicLaneDefenseRouter({ apiKey });
goalContractRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
'project-supervisor',
'goal-contract-order-run',
goalContractTools,
),
});
assert(
captureProviderErrorCode(() =>
goalContractRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
'project-supervisor',
'goal-contract-order-run',
goalContractTools,
),
}),
) === 'provider-goal-contract-out-of-order',
'self-test-goal-contract-duplicate-not-rejected',
);
const router = createDeterministicLaneDefenseRouter({ apiKey });
const route = (agentId, runId, tools = allTools, extraContext = '') =>
router.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(agentId, runId, tools, extraContext),
});
const interactionExecuteResponse = router.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticInteractionExecutePayload(),
});
const interactionExecuteCalls = responseFunctionCalls(
interactionExecuteResponse,
);
const interactionExecuteStats = router.getStats();
assert(
interactionExecuteCalls.length === 1 &&
interactionExecuteCalls[0]?.name === 'runtime_execute' &&
Object.keys(interactionExecuteCalls[0]?.arguments ?? {}).length === 0 &&
interactionExecuteStats.requestCount === 1 &&
interactionExecuteStats.planningRequestCount === 1 &&
interactionExecuteStats.interactionExecuteCount === 1 &&
interactionExecuteStats.manifestReadyTaskRunCount === 0 &&
interactionExecuteStats.manifestReadyTaskCompletionCount === 0 &&
Object.keys(interactionExecuteStats.readyTaskCountsByAgent).length === 0,
'self-test-interaction-max-execute-sequence-invalid',
);
const visualInspectionResponse = router.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticUiPrototypeInspectionPayload(),
});
const visualInspection = JSON.parse(
visualInspectionResponse.choices[0].message.content,
);
assert(
Object.keys(visualInspection?.checks ?? {}).join(',') ===
'informationHud,gameplaySurface,objectiveEntities,primaryControls,failureRestartFlow,responsiveLayout,implementationClarity,originalTheme' &&
Object.values(visualInspection.checks).every((value) => value === true) &&
Array.isArray(visualInspection.issues) &&
visualInspection.issues.length === 0 &&
router.getStats().imageInspectionRequestCount === 1 &&
router.getStats().unexpectedRequestCount === 0,
'self-test-ui-prototype-inspection-request-not-routed',
);
const goalContractResponse = route(
'project-supervisor',
rootRunId,
goalContractTools,
);
const goalContractCalls = responseFunctionCalls(goalContractResponse);
const acceptanceNodes =
goalContractCalls[0]?.arguments?.input?.acceptanceNodes ?? [];
assert(
goalContractCalls.length === 1 &&
goalContractCalls[0]?.name === 'runtime_tool_agent_goal_contract' &&
goalContractCalls[0]?.arguments?.input?.outcome?.includes(
'可完整游玩的原创植物塔防网页游戏',
) &&
acceptanceNodes.length === 2 &&
acceptanceNodes[0]?.criterionId === 'static-current-revision' &&
JSON.stringify(acceptanceNodes[0]?.requiredEvidence) ===
JSON.stringify(['tool:command.run_limited']) &&
acceptanceNodes[1]?.criterionId === 'playable-current-revision' &&
JSON.stringify(acceptanceNodes[1]?.requiredEvidence) ===
JSON.stringify(['tool:preview.validate']) &&
JSON.stringify(acceptanceNodes[1]?.dependsOn) ===
JSON.stringify(['static-current-revision']),
'self-test-goal-contract-invalid',
);
assert(
responseFunctionNames(
route(
'project-supervisor',
rootRunId,
['runtime_tool_task_list', 'runtime_tool_agent_run_status'],
`${contractContext}\n当前正式 manifest DAG 仍有专业 task 在运行`,
),
).join(',') === 'runtime_tool_task_list,runtime_tool_agent_run_status',
'self-test-manifest-wait-invalid',
);
const visualReadyAgentIds = new Set([
'art-director',
'design-foundation',
'art-asset-plan',
]);
const canvasCallsByAgent = new Map();
const callBatchesByAgent = new Map();
for (const agentId of deterministicManifestReadyAgentIds) {
const runId = `manifest-ready-${agentId}`;
const extraContext =
`处理 manifest ready 任务:${agentId}\n` + `任务 ID${agentId}`;
const readyTools = visualReadyAgentIds.has(agentId)
? [
...manifestReadyTools,
'runtime_tool_canvas_asset_generate',
'runtime_tool_image_inspect',
]
: manifestReadyTools;
let terminalCompletionCount = 0;
for (let attempt = 0; attempt < 8; attempt += 1) {
const attemptTools =
agentId === 'art-director' && attempt >= 2
? ['respond_to_user']
: readyTools;
const response = route(agentId, runId, attemptTools, extraContext);
const calls = responseFunctionCalls(response);
const batches = callBatchesByAgent.get(agentId) ?? [];
batches.push(calls.map((call) => call.name));
callBatchesByAgent.set(agentId, batches);
const canvasCall = calls.find(
(call) => call.name === 'runtime_tool_canvas_asset_generate',
);
if (canvasCall) {
assert(
!canvasCallsByAgent.has(agentId),
`self-test-canvas-generation-duplicate:${agentId}`,
);
canvasCallsByAgent.set(agentId, canvasCall);
}
if (calls.some((call) => call.name === 'respond_to_user')) {
terminalCompletionCount += 1;
break;
}
}
assert(
terminalCompletionCount === 1,
`self-test-manifest-ready-terminal-invalid:${agentId}`,
);
}
const artDirectorAssetCall = canvasCallsByAgent.get('art-director');
const designFoundationAssetCall = canvasCallsByAgent.get('design-foundation');
const artAssetPlanAssetCall = canvasCallsByAgent.get('art-asset-plan');
assert(
JSON.stringify(callBatchesByAgent.get('art-asset-plan')) ===
JSON.stringify([
['runtime_tool_asset_list'],
['runtime_tool_file_write'],
['runtime_tool_canvas_asset_generate'],
['runtime_tool_file_read', 'runtime_tool_asset_list'],
['update_agent_plan', 'respond_to_user'],
]),
'self-test-art-asset-plan-revision-stages-invalid',
);
assert(
JSON.stringify(callBatchesByAgent.get('code-prototype')) ===
JSON.stringify([
[
'runtime_tool_file_read',
'runtime_tool_file_read',
'runtime_tool_file_read',
],
[
'runtime_tool_file_read',
'runtime_tool_file_read',
'runtime_tool_file_read',
'runtime_tool_asset_list',
],
['runtime_tool_file_write'],
['runtime_tool_command_run_limited'],
['update_agent_plan', 'respond_to_user'],
]),
'self-test-code-prototype-asset-audit-sequence-invalid',
);
assert(
canvasCallsByAgent.size === 3 &&
artDirectorAssetCall?.arguments?.input?.outputPath ===
'assets/art-spec.png' &&
artDirectorAssetCall.arguments.input.aspectRatio === '1:1' &&
artDirectorAssetCall.arguments.input.assetKind === 'icon-spec' &&
designFoundationAssetCall?.arguments?.input?.outputPath ===
'assets/ui-prototype.png' &&
designFoundationAssetCall.arguments.input.aspectRatio === '16:9' &&
designFoundationAssetCall.arguments.input.assetKind === 'ui-prototype' &&
artAssetPlanAssetCall?.arguments?.input?.outputPath ===
'assets/art-spritesheet.png' &&
artAssetPlanAssetCall.arguments.input.aspectRatio === '1:1' &&
artAssetPlanAssetCall.arguments.input.assetKind === 'art-spritesheet',
'self-test-visual-assets-invalid',
);
const visualRecoveryRouter = createDeterministicLaneDefenseRouter({ apiKey });
const visualRecoveryRunId = 'visual-recovery-design-foundation';
const visualRecoveryTools = [
...manifestReadyTools,
'runtime_tool_canvas_asset_generate',
'runtime_tool_image_inspect',
];
const visualRecoveryRoute = (
tools = visualRecoveryTools,
extraContext = '',
) =>
visualRecoveryRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
'design-foundation',
visualRecoveryRunId,
tools,
`处理 manifest ready 任务:design-foundation\n任务 IDdesign-foundation${extraContext}`,
),
});
visualRecoveryRoute();
visualRecoveryRoute();
const visualRecoveryCanvasResponse = visualRecoveryRoute();
const visualRecoveryInitialInspectResponse = visualRecoveryRoute();
assert(
responseFunctionNames(visualRecoveryCanvasResponse).join(',') ===
'runtime_tool_canvas_asset_generate' &&
responseFunctionNames(visualRecoveryInitialInspectResponse).includes(
'runtime_tool_image_inspect',
),
'self-test-ui-prototype-initial-inspection-sequence-invalid',
);
const failedInspectObservation = {
tool: 'image.inspect',
status: 'failed',
summary: '视觉模型调用失败',
detail: 'upstream-422',
};
const prematureCompletionResponse = visualRecoveryRoute(
['update_agent_plan', 'respond_to_user'],
`\n已有工具观察:\n${JSON.stringify([failedInspectObservation])}`,
);
assert(
responseFunctionNames(prematureCompletionResponse).includes(
'respond_to_user',
),
'self-test-ui-prototype-premature-completion-fixture-invalid',
);
const visualBlockedObservation = {
tool: 'runtime.visual_asset',
status: 'blocked',
summary: 'UI 原型视觉检查尚未通过',
detail:
'expectedPath=assets/ui-prototype.png · requiredInspection=image.inspect',
};
const blockedRetryResponse = visualRecoveryRoute(
visualRecoveryTools,
`\n已有工具观察:\n${JSON.stringify([visualBlockedObservation])}`,
);
assert(
responseFunctionNames(blockedRetryResponse).join(',') ===
'runtime_tool_image_inspect',
'self-test-ui-prototype-visual-block-did-not-retry-inspection',
);
const failedRetryResponse = visualRecoveryRoute(
visualRecoveryTools,
`\n已有工具观察:\n${JSON.stringify([failedInspectObservation])}`,
);
assert(
responseFunctionNames(failedRetryResponse).join(',') ===
'runtime_tool_image_inspect',
'self-test-ui-prototype-failed-inspection-did-not-retry',
);
const successfulInspectObservation = {
tool: 'image.inspect',
status: 'ok',
summary: '视觉检查已完成,共分析 1 张图片',
detail: null,
};
const visualRecoveryFinalResponse = visualRecoveryRoute(
['update_agent_plan', 'respond_to_user'],
`\n已有工具观察:\n${JSON.stringify([successfulInspectObservation])}`,
);
const visualRecoveryStats = visualRecoveryRouter.getStats();
assert(
responseFunctionNames(visualRecoveryFinalResponse).includes(
'respond_to_user',
) &&
visualRecoveryStats.manifestReadyTaskRunCount === 1 &&
visualRecoveryStats.manifestReadyTaskCompletionCount === 1 &&
visualRecoveryStats.manifestReadyTaskCanvasGenerationCount === 1 &&
visualRecoveryStats.byAgent?.['design-foundation']?.projectMutation ===
3 &&
visualRecoveryStats.unexpectedRequestCount === 0,
'self-test-ui-prototype-visual-recovery-not-exactly-once',
);
const finalStaticResponse = route(
'project-supervisor',
rootRunId,
['runtime_tool_command_run_limited'],
`${contractContext}\n已有工具观察:\nseedTaskCounts: completed=16 running=0 pending=0 waiting=0 failed=0 total=16`,
);
assert(
responseFunctionNames(finalStaticResponse).join(',') ===
'runtime_tool_command_run_limited',
'self-test-final-static-not-exclusive',
);
const successfulFinalStaticObservation = {
tool: 'command.run_limited',
status: 'ok',
summary: 'game.static_smoke 已完成',
detail: null,
};
const finalPreviewResponse = route(
'project-supervisor',
rootRunId,
['runtime_tool_preview_validate'],
observationContext([successfulFinalStaticObservation]),
);
assert(
responseFunctionNames(finalPreviewResponse).join(',') ===
'runtime_tool_preview_validate',
'self-test-final-preview-not-exclusive',
);
const successfulFinalPreviewObservation = {
tool: 'preview.validate',
status: 'ok',
summary: '桌面与移动视口真实试玩已通过',
detail: null,
};
const finalHistoryResponse = route(
'project-supervisor',
rootRunId,
['runtime_tool_agent_action_history'],
observationContext([successfulFinalPreviewObservation]),
);
const finalHistoryCalls = responseFunctionCalls(finalHistoryResponse);
assert(
finalHistoryCalls.length === 1 &&
finalHistoryCalls[0]?.name === 'runtime_tool_agent_action_history' &&
JSON.stringify(finalHistoryCalls[0]?.arguments?.input) ===
JSON.stringify({
runId: null,
actionId: null,
tool: null,
status: 'ok',
limit: 10,
}),
'self-test-final-action-history-invalid',
);
const staticActionId = `action-${'1'.repeat(24)}`;
const previewActionId = `action-${'2'.repeat(24)}`;
const actionHistoryDetail = JSON.stringify({
runId: rootRunId,
count: 2,
truncated: false,
outputTruncated: false,
actions: [
{
agentId: 'project-supervisor',
runId: rootRunId,
actionId: staticActionId,
tool: 'command.run_limited',
status: 'ok',
},
{
agentId: 'project-supervisor',
runId: rootRunId,
actionId: previewActionId,
tool: 'preview.validate',
status: 'ok',
},
],
});
const finalAcceptanceResponse = route(
'project-supervisor',
rootRunId,
['runtime_tool_agent_acceptance_update'],
observationContext([
{
tool: 'agent.action_history',
status: 'ok',
summary: '已读取当前 Agent 的 2 条终态动作',
detail: actionHistoryDetail,
},
]),
);
const finalAcceptanceCalls = responseFunctionCalls(finalAcceptanceResponse);
const acceptanceInput = finalAcceptanceCalls[0]?.arguments?.input;
assert(
finalAcceptanceCalls.length === 1 &&
finalAcceptanceCalls[0]?.name ===
'runtime_tool_agent_acceptance_update' &&
acceptanceInput?.contractFingerprint === contractFingerprint &&
acceptanceInput?.evaluations?.length === 2 &&
acceptanceInput.evaluations[0]?.criterionId ===
'static-current-revision' &&
acceptanceInput.evaluations[0]?.evidence?.[0]?.actionId ===
staticActionId &&
acceptanceInput.evaluations[1]?.criterionId ===
'playable-current-revision' &&
acceptanceInput.evaluations[1]?.evidence?.[0]?.actionId ===
previewActionId,
'self-test-final-acceptance-update-invalid',
);
const finalRespondResponse = route(
'project-supervisor',
rootRunId,
['respond_to_user'],
observationContext([
{
tool: 'agent.acceptance_update',
status: 'ok',
summary: 'Acceptance Graph 已更新',
detail: null,
},
]),
);
assert(
responseFunctionNames(finalRespondResponse).join(',') === 'respond_to_user',
'self-test-final-respond-not-exclusive',
);
const planRejectionRouter = createDeterministicLaneDefenseRouter({ apiKey });
planRejectionRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
'project-supervisor',
'plan-rejection-run',
goalContractTools,
),
});
const planRejectionResponse = planRejectionRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
'project-supervisor',
'plan-rejection-run',
['respond_to_user', 'runtime_tool_file_patch', 'runtime_tool_file_write'],
'当前父 run 已进入只编排模式;本轮只允许收束或安全编排。',
),
});
const planRejectionWaitResponse = planRejectionRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
'project-supervisor',
'plan-rejection-run',
['runtime_tool_task_list', 'runtime_tool_agent_run_status'],
'当前正式 manifest DAG 仍有专业 task 在运行',
),
});
const planRejectionStats = planRejectionRouter.getStats();
assert(
responseFunctionNames(planRejectionResponse).join(',') ===
'respond_to_user' &&
responseFunctionNames(planRejectionWaitResponse).join(',') ===
'runtime_tool_task_list,runtime_tool_agent_run_status' &&
planRejectionStats.byAgent?.['project-supervisor']?.projectMutation ===
0 &&
planRejectionStats.delegateActionCount === 0 &&
planRejectionStats.runStatusCount === 1 &&
planRejectionStats.unexpectedRequestCount === 0,
'self-test-supervisor-plan-rejection-did-not-converge-read-only',
);
const earlyFinalReplyRouter = createDeterministicLaneDefenseRouter({
apiKey,
});
assert(
captureProviderErrorCode(() =>
earlyFinalReplyRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
'project-supervisor',
'early-final-reply-run',
[],
'给用户一个正常中文回复',
),
}),
) === 'provider-parent-final-reply-before-acceptance',
'self-test-parent-final-reply-bypassed-acceptance',
);
const acceptanceGuardRunId = 'acceptance-guard-run';
const acceptanceGuardRouter = createDeterministicLaneDefenseRouter({
apiKey,
});
const acceptanceGuardRoute = (tools, extraContext = '') =>
acceptanceGuardRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
'project-supervisor',
acceptanceGuardRunId,
tools,
extraContext,
),
});
acceptanceGuardRoute(goalContractTools);
acceptanceGuardRoute(
['runtime_tool_command_run_limited'],
`${contractContext}\n已有工具观察:\nseedTaskCounts: completed=16 running=0 pending=0 waiting=0 failed=0 total=16`,
);
acceptanceGuardRoute(
['runtime_tool_preview_validate'],
observationContext([successfulFinalStaticObservation]),
);
acceptanceGuardRoute(
['runtime_tool_agent_action_history'],
observationContext([successfulFinalPreviewObservation]),
);
const acceptanceGuardDetail = JSON.parse(actionHistoryDetail);
acceptanceGuardDetail.runId = acceptanceGuardRunId;
for (const action of acceptanceGuardDetail.actions) {
action.runId = acceptanceGuardRunId;
}
const actionHistoryObservationFor = (detail) => ({
tool: 'agent.action_history',
status: 'ok',
summary: '已读取当前 Agent 的 2 条终态动作',
detail: JSON.stringify(detail),
});
const ambiguousContractContext = `[Root Goal Contract]\n{"contractFingerprint":"${contractFingerprint}","nested":{"contractFingerprint":"${'b'.repeat(64)}"}}`;
assert(
captureProviderErrorCode(() =>
acceptanceGuardRoute(
['runtime_tool_agent_acceptance_update'],
`${ambiguousContractContext}\n已有工具观察:\n${JSON.stringify([
actionHistoryObservationFor(acceptanceGuardDetail),
])}`,
),
) === 'provider-goal-contract-fingerprint-missing',
'self-test-ambiguous-goal-contract-fingerprint-accepted',
);
const invalidActionHistoryDetail = structuredClone(acceptanceGuardDetail);
invalidActionHistoryDetail.actions[0].actionId = 'action-invalid';
assert(
captureProviderErrorCode(() =>
acceptanceGuardRoute(
['runtime_tool_agent_acceptance_update'],
`${contractContext}\n已有工具观察:\n${JSON.stringify([
actionHistoryObservationFor(invalidActionHistoryDetail),
])}`,
),
) === 'provider-final-acceptance-evidence-missing',
'self-test-invalid-action-history-id-accepted',
);
assert(
responseFunctionNames(
acceptanceGuardRoute(
['runtime_tool_agent_acceptance_update'],
`${contractContext}\n已有工具观察:\n${JSON.stringify([
actionHistoryObservationFor(acceptanceGuardDetail),
])}`,
),
).join(',') === 'runtime_tool_agent_acceptance_update',
'self-test-acceptance-stage-advanced-after-rejected-history',
);
const stats = router.getStats();
const manifestReadyTasks = manifestReadyTaskEvidence(stats);
assert(
manifestReadyTasks.exactlyOnce &&
stats.goalContractCount === 1 &&
stats.actionHistoryCount === 1 &&
stats.acceptanceUpdateCount === 1 &&
stats.interactionExecuteCount === 1 &&
stats.delegateActionCount === 0 &&
stats.imageInspectionRequestCount === 1 &&
stats.manifestReadyTaskCanvasGenerationCount === 3 &&
stats.byAgent?.['project-supervisor']?.projectMutation === 0 &&
stats.byAgent?.['code-prototype']?.projectMutation === 1 &&
stats.byAgent?.['quality-review']?.projectMutation === 0,
'self-test-manifest-ready-exactly-once-invalid',
);
const missingReadyTaskStats = structuredClone(stats);
const missingAgentId = deterministicManifestReadyAgentIds.at(-1);
delete missingReadyTaskStats.readyTaskCountsByAgent[missingAgentId];
missingReadyTaskStats.manifestReadyTaskRunCount -= 1;
missingReadyTaskStats.manifestReadyTaskCompletionCount -= 1;
assert(
!manifestReadyTaskEvidence(missingReadyTaskStats).exactlyOnce,
'self-test-manifest-ready-missing-accepted',
);
const duplicateReadyTaskStats = structuredClone(stats);
const duplicateAgentId = deterministicManifestReadyAgentIds[0];
duplicateReadyTaskStats.readyTaskCountsByAgent[duplicateAgentId].completion +=
1;
duplicateReadyTaskStats.manifestReadyTaskCompletionCount += 1;
assert(
!manifestReadyTaskEvidence(duplicateReadyTaskStats).exactlyOnce,
'self-test-manifest-ready-duplicate-accepted',
);
const retryObservationContext = (observations) =>
`\n已有工具观察:\n${JSON.stringify(observations)}`;
const staleObservation = {
tool: 'runtime.verification',
status: 'blocked',
summary: '最终回复生成期间项目 revision 已变化',
detail: 'responseRevision=1, currentRevision=2',
};
const successfulSmokeObservation = {
tool: 'command.run_limited',
status: 'ok',
summary: 'game.static_smoke 已完成',
detail: null,
};
const blockedSmokeObservation = {
tool: 'command.run_limited',
status: 'blocked',
summary: '仓库规范或启动上下文已漂移,旧动作未执行',
detail:
'repositoryContextDrift=true · 请在同一 run 下一轮 planning 重新确认适用规范',
};
const projectLockSmokeObservations = [
{
tool: 'command.run_limited',
status: 'failed',
summary: 'game.static_smoke 无法取得项目验证锁',
detail: '项目正在被其他写操作占用:$PROJECT_ROOT/.agent/project.lock',
},
{
tool: 'command.run_limited',
status: 'failed',
summary: 'game.static_smoke 无法取得项目验证锁',
detail: '项目正在被其他写操作占用:$PROJECT_ROOT\\.agent\\project.lock',
},
];
const projectRevisionDriftSmokeObservation = {
tool: 'command.run_limited',
status: 'blocked',
summary: '并行项目变更使旧动作过期,旧动作未执行',
detail:
'projectRevisionDrift=true · expectedRevision=4 · currentRevision=5 · replanRequired=true',
};
const projectRevisionDriftCanvasObservation = {
tool: 'canvas.asset_generate',
status: 'blocked',
summary: '并行项目变更使旧动作过期,旧动作未执行',
detail:
'projectRevisionDrift=true · expectedRevision=5 · currentRevision=6 · replanRequired=true',
};
const successfulProjectMutationObservation = {
tool: 'project.patchset',
status: 'ok',
summary: 'project.patchset 已原子应用 2 项变更',
detail: 'checkpointId=checkpoint-concurrent-ready-batch',
};
const missingArtAssetObservation = {
tool: 'runtime.visual_asset',
status: 'blocked',
summary: '首版美术素材图尚未按正式视觉流程生成并登记,不能完成任务',
detail: '[redacted sensitive context]',
};
const successfulCanvasMutationObservation = {
tool: 'canvas.asset_generate',
status: 'ok',
summary: '素材画布图片已生成并登记',
detail: null,
};
const artAssetRecoveryAgentId = 'art-asset-plan';
const artAssetRecoveryRunId = 'art-asset-visual-recovery-ready-run';
const artAssetRecoveryTools = [
...manifestReadyTools,
'runtime_tool_canvas_asset_generate',
];
const artAssetRecoveryRouter = createDeterministicLaneDefenseRouter({
apiKey,
});
const artAssetRecoveryRoute = (extraContext = '') =>
artAssetRecoveryRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
artAssetRecoveryAgentId,
artAssetRecoveryRunId,
artAssetRecoveryTools,
`处理 manifest ready 任务:${artAssetRecoveryAgentId}\n任务 ID${artAssetRecoveryAgentId}${extraContext}`,
),
});
for (let attempt = 0; attempt < 8; attempt += 1) {
if (
responseFunctionNames(artAssetRecoveryRoute()).includes('respond_to_user')
) {
break;
}
}
const artAssetRegenerationResponse = artAssetRecoveryRoute(
retryObservationContext([missingArtAssetObservation]),
);
const artAssetReverificationResponse = artAssetRecoveryRoute(
retryObservationContext([successfulCanvasMutationObservation]),
);
const artAssetRefinalizationResponse = artAssetRecoveryRoute(
retryObservationContext([successfulSmokeObservation]),
);
const artAssetRecoveryStats = artAssetRecoveryRouter.getStats();
assert(
responseFunctionNames(artAssetRegenerationResponse).join(',') ===
'runtime_tool_canvas_asset_generate' &&
responseFunctionNames(artAssetReverificationResponse).join(',') ===
'runtime_tool_command_run_limited' &&
responseFunctionNames(artAssetRefinalizationResponse).includes(
'respond_to_user',
) &&
artAssetRecoveryStats.readyTaskCountsByAgent[artAssetRecoveryAgentId]
?.completion === 1 &&
artAssetRecoveryStats.manifestReadyTaskCanvasGenerationCount === 2 &&
artAssetRecoveryStats.unexpectedRequestCount === 0,
'self-test-art-asset-visual-recovery-not-exactly-once',
);
const artAssetRevisionDriftRunId = 'art-asset-revision-drift-ready-run';
const artAssetRevisionDriftRouter = createDeterministicLaneDefenseRouter({
apiKey,
});
const artAssetRevisionDriftRoute = (extraContext = '') =>
artAssetRevisionDriftRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
artAssetRecoveryAgentId,
artAssetRevisionDriftRunId,
artAssetRecoveryTools,
`处理 manifest ready 任务:${artAssetRecoveryAgentId}\n任务 ID${artAssetRecoveryAgentId}${extraContext}`,
),
});
const artAssetInitialListResponse = artAssetRevisionDriftRoute();
const artAssetManifestWriteResponse = artAssetRevisionDriftRoute();
const artAssetInitialCanvasResponse = artAssetRevisionDriftRoute();
const artAssetRetryCanvasResponse = artAssetRevisionDriftRoute(
retryObservationContext([projectRevisionDriftCanvasObservation]),
);
const artAssetPostRetryReadResponse = artAssetRevisionDriftRoute(
retryObservationContext([successfulCanvasMutationObservation]),
);
const artAssetRevisionDriftFinalizationResponse =
artAssetRevisionDriftRoute();
const artAssetRevisionDriftStats = artAssetRevisionDriftRouter.getStats();
assert(
responseFunctionNames(artAssetInitialListResponse).join(',') ===
'runtime_tool_asset_list' &&
responseFunctionNames(artAssetManifestWriteResponse).join(',') ===
'runtime_tool_file_write' &&
responseFunctionNames(artAssetInitialCanvasResponse).join(',') ===
'runtime_tool_canvas_asset_generate' &&
responseFunctionNames(artAssetRetryCanvasResponse).join(',') ===
'runtime_tool_canvas_asset_generate' &&
responseFunctionNames(artAssetPostRetryReadResponse).join(',') ===
'runtime_tool_file_read,runtime_tool_asset_list' &&
responseFunctionNames(artAssetRevisionDriftFinalizationResponse).includes(
'respond_to_user',
) &&
artAssetRevisionDriftStats.readyTaskCountsByAgent[artAssetRecoveryAgentId]
?.run === 1 &&
artAssetRevisionDriftStats.readyTaskCountsByAgent[artAssetRecoveryAgentId]
?.completion === 1 &&
artAssetRevisionDriftStats.manifestReadyTaskCanvasGenerationCount === 2 &&
artAssetRevisionDriftStats.unexpectedRequestCount === 0,
'self-test-art-asset-revision-drift-recovery-not-exactly-once',
);
const artAssetRevisionDriftLimitRunId =
'art-asset-revision-drift-limit-ready-run';
const artAssetRevisionDriftLimitRouter = createDeterministicLaneDefenseRouter(
{ apiKey },
);
const artAssetRevisionDriftLimitRoute = (extraContext = '') =>
artAssetRevisionDriftLimitRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
artAssetRecoveryAgentId,
artAssetRevisionDriftLimitRunId,
artAssetRecoveryTools,
`处理 manifest ready 任务:${artAssetRecoveryAgentId}\n任务 ID${artAssetRecoveryAgentId}${extraContext}`,
),
});
artAssetRevisionDriftLimitRoute();
artAssetRevisionDriftLimitRoute();
artAssetRevisionDriftLimitRoute();
for (let retry = 0; retry < 16; retry += 1) {
assert(
responseFunctionNames(
artAssetRevisionDriftLimitRoute(
retryObservationContext([projectRevisionDriftCanvasObservation]),
),
).join(',') === 'runtime_tool_canvas_asset_generate',
`self-test-art-asset-revision-drift-retry-invalid:${retry}`,
);
}
const artAssetRevisionDriftLimitCode = captureProviderErrorCode(() =>
artAssetRevisionDriftLimitRoute(
retryObservationContext([projectRevisionDriftCanvasObservation]),
),
);
const artAssetRevisionDriftLimitStats =
artAssetRevisionDriftLimitRouter.getStats();
assert(
artAssetRevisionDriftLimitCode ===
'provider-ready-art-canvas-retry-exhausted' &&
artAssetRevisionDriftLimitStats.readyTaskCountsByAgent[
artAssetRecoveryAgentId
]?.run === 1 &&
artAssetRevisionDriftLimitStats.readyTaskCountsByAgent[
artAssetRecoveryAgentId
]?.completion === 0 &&
artAssetRevisionDriftLimitStats.manifestReadyTaskCanvasGenerationCount ===
17,
'self-test-art-asset-revision-drift-limit-invalid',
);
const readOnlyCommandRouter = createDeterministicLaneDefenseRouter({
apiKey,
});
const readOnlyCommandRunId = 'read-only-command-only-ready-run';
const readOnlyCommandRoute = (tools) =>
readOnlyCommandRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
'quality-review',
readOnlyCommandRunId,
tools,
'处理 manifest ready 任务:quality-review\n任务 IDquality-review',
),
});
readOnlyCommandRoute(manifestReadyTools);
readOnlyCommandRoute(manifestReadyTools);
const readOnlyCommandCode = captureProviderErrorCode(() =>
readOnlyCommandRoute(['runtime_tool_command_run_limited']),
);
const readOnlyCommandStats = readOnlyCommandRouter.getStats();
assert(
readOnlyCommandCode ===
'provider-ready-finalization-tools-invalid:quality-review:runtime_tool_command_run_limited' &&
readOnlyCommandStats.readyTaskCountsByAgent['quality-review']
?.completion === 0 &&
readOnlyCommandStats.manifestReadyTaskStaticSmokeCount === 0,
'self-test-read-only-command-only-not-rejected',
);
const preCompletionRouter = createDeterministicLaneDefenseRouter({ apiKey });
const preCompletionAgentId = 'preview-readiness';
const preCompletionRunId = 'pre-completion-transient-ready-run';
const preCompletionRoute = (tools, extraContext = '') =>
preCompletionRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
preCompletionAgentId,
preCompletionRunId,
tools,
`处理 manifest ready 任务:${preCompletionAgentId}\n任务 ID${preCompletionAgentId}${extraContext}`,
),
});
preCompletionRoute(manifestReadyTools);
for (let retry = 0; retry < 16; retry += 1) {
assert(
responseFunctionNames(
preCompletionRoute(
['runtime_tool_command_run_limited'],
retryObservationContext([blockedSmokeObservation]),
),
).join(',') === 'runtime_tool_command_run_limited',
`self-test-ready-precompletion-transient-invalid:${retry}`,
);
}
const preCompletionLimitCode = captureProviderErrorCode(() =>
preCompletionRoute(
['runtime_tool_command_run_limited'],
retryObservationContext([blockedSmokeObservation]),
),
);
const preCompletionStats = preCompletionRouter.getStats();
assert(
preCompletionLimitCode ===
`provider-ready-precompletion-verification-exhausted:${preCompletionAgentId}` &&
preCompletionStats.readyTaskCountsByAgent[preCompletionAgentId]
?.completion === 0 &&
preCompletionStats.manifestReadyTaskStaticSmokeCount === 17,
'self-test-ready-precompletion-limit-invalid',
);
const projectLockRouter = createDeterministicLaneDefenseRouter({ apiKey });
const projectLockRunId = 'project-lock-transient-ready-run';
const projectLockRoute = (tools, extraContext = '') =>
projectLockRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
preCompletionAgentId,
projectLockRunId,
tools,
`处理 manifest ready 任务:${preCompletionAgentId}\n任务 ID${preCompletionAgentId}${extraContext}`,
),
});
projectLockRoute(manifestReadyTools);
for (const observation of projectLockSmokeObservations) {
assert(
responseFunctionNames(
projectLockRoute(
['runtime_tool_command_run_limited'],
retryObservationContext([observation]),
),
).join(',') === 'runtime_tool_command_run_limited',
'self-test-ready-project-lock-path-separator-not-retried',
);
}
const duplicateRouter = createDeterministicLaneDefenseRouter({ apiKey });
const duplicateRoute = (runId, extraContext = '') =>
duplicateRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
duplicateAgentId,
runId,
manifestReadyTools,
`处理 manifest ready 任务:${duplicateAgentId}\n任务 ID${duplicateAgentId}${extraContext}`,
),
});
duplicateRoute('duplicate-ready-run');
duplicateRoute('duplicate-ready-run');
let duplicateTerminalCode = null;
try {
duplicateRoute('duplicate-ready-run');
} catch (error) {
duplicateTerminalCode = error?.code ?? null;
}
let duplicateRunCode = null;
try {
duplicateRoute('second-ready-run');
} catch (error) {
duplicateRunCode = error?.code ?? null;
}
assert(
duplicateTerminalCode ===
`provider-ready-run-terminal-duplicate:${duplicateAgentId}` &&
duplicateRunCode ===
`provider-ready-agent-run-duplicate:${duplicateAgentId}`,
'self-test-manifest-ready-provider-duplicate-not-rejected',
);
const retryAgentId = 'preview-readiness';
const retryRunId = 'retry-ready-run';
const retryRouter = createDeterministicLaneDefenseRouter({ apiKey });
const retryRoute = (extraContext = '') =>
retryRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
retryAgentId,
retryRunId,
manifestReadyTools,
`处理 manifest ready 任务:${retryAgentId}\n任务 ID${retryAgentId}${extraContext}`,
),
});
for (let attempt = 0; attempt < 8; attempt += 1) {
if (responseFunctionNames(retryRoute()).includes('respond_to_user')) break;
}
for (let retry = 0; retry < 16; retry += 1) {
assert(
responseFunctionNames(
retryRoute(retryObservationContext([staleObservation])),
).join(',') === 'runtime_tool_command_run_limited',
`self-test-ready-retry-verification-call-invalid:${retry}`,
);
if (retry === 0) {
let missingObservationCode = null;
try {
retryRoute();
} catch (error) {
missingObservationCode = error?.code ?? null;
}
assert(
missingObservationCode ===
`provider-ready-retry-verification-invalid:${retryAgentId}`,
'self-test-ready-retry-missing-observation-accepted',
);
}
assert(
responseFunctionNames(
retryRoute(retryObservationContext([successfulSmokeObservation])),
).includes('respond_to_user'),
`self-test-ready-retry-finalization-invalid:${retry}`,
);
}
let retryLimitCode = null;
try {
retryRoute(retryObservationContext([staleObservation]));
} catch (error) {
retryLimitCode = error?.code ?? null;
}
const retryStats = retryRouter.getStats();
assert(
retryLimitCode ===
`provider-ready-run-terminal-duplicate:${retryAgentId}` &&
retryStats.readyTaskCountsByAgent[retryAgentId]?.run === 1 &&
retryStats.readyTaskCountsByAgent[retryAgentId]?.completion === 1,
'self-test-ready-retry-limit-or-exactly-once-invalid',
);
const verifiedDeliveryRepairRouter = createDeterministicLaneDefenseRouter({
apiKey,
});
const verifiedDeliveryRepairRunId = 'verified-delivery-repair-ready-run';
const verifiedDeliveryRepairRoute = (tools, extraContext = '') =>
verifiedDeliveryRepairRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
retryAgentId,
verifiedDeliveryRepairRunId,
tools,
`处理 manifest ready 任务:${retryAgentId}\n任务 ID${retryAgentId}${extraContext}`,
),
});
for (let attempt = 0; attempt < 8; attempt += 1) {
if (
responseFunctionNames(
verifiedDeliveryRepairRoute(manifestReadyTools),
).includes('respond_to_user')
) {
break;
}
}
const rejectedVerificationPlan = verifiedDeliveryRepairRoute(
manifestReadyTools,
retryObservationContext([staleObservation]),
);
const verifiedDeliveryRepairResponse = verifiedDeliveryRepairRoute(
['respond_to_user'],
`${retryObservationContext([staleObservation])}\n上一条输出不符合工具计划协议:当前 revision 已通过验证。本次修复的原生工具目录只保留 respond_to_user;必须立即调用它交付专业合同结论。`,
);
const verifiedDeliveryRepairStats = verifiedDeliveryRepairRouter.getStats();
assert(
responseFunctionNames(rejectedVerificationPlan).join(',') ===
'runtime_tool_command_run_limited' &&
responseFunctionNames(verifiedDeliveryRepairResponse).join(',') ===
'respond_to_user' &&
verifiedDeliveryRepairStats.readyTaskCountsByAgent[retryAgentId]
?.completion === 1 &&
verifiedDeliveryRepairStats.unexpectedRequestCount === 0,
'self-test-ready-verified-delivery-repair-invalid',
);
const transientRetryRouter = createDeterministicLaneDefenseRouter({ apiKey });
const transientRetryRunId = 'transient-retry-ready-run';
const transientRetryRoute = (extraContext = '') =>
transientRetryRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
retryAgentId,
transientRetryRunId,
manifestReadyTools,
`处理 manifest ready 任务:${retryAgentId}\n任务 ID${retryAgentId}${extraContext}`,
),
});
for (let attempt = 0; attempt < 8; attempt += 1) {
if (
responseFunctionNames(transientRetryRoute()).includes('respond_to_user')
) {
break;
}
}
transientRetryRoute(retryObservationContext([staleObservation]));
assert(
responseFunctionNames(
transientRetryRoute(retryObservationContext([blockedSmokeObservation])),
).join(',') === 'runtime_tool_command_run_limited' &&
responseFunctionNames(
transientRetryRoute(
retryObservationContext([successfulSmokeObservation]),
),
).includes('respond_to_user') &&
transientRetryRouter.getStats().readyTaskCountsByAgent[retryAgentId]
?.completion === 1,
'self-test-ready-transient-verification-retry-invalid',
);
const standaloneRetryAgentId = 'design-foundation';
const standaloneRetryRunId = 'standalone-retry-ready-run';
const standaloneRetryRouter = createDeterministicLaneDefenseRouter({
apiKey,
});
const standaloneRetryRoute = (extraContext = '') =>
standaloneRetryRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
standaloneRetryAgentId,
standaloneRetryRunId,
manifestReadyTools,
`处理 manifest ready 任务:${standaloneRetryAgentId}\n任务 ID${standaloneRetryAgentId}${extraContext}`,
),
});
for (let attempt = 0; attempt < 8; attempt += 1) {
if (
responseFunctionNames(standaloneRetryRoute()).includes('respond_to_user')
) {
break;
}
}
const standaloneReplayResponse = standaloneRetryRoute(
retryObservationContext([successfulSmokeObservation]),
);
const standaloneReplayDuplicateCode = captureProviderErrorCode(() =>
standaloneRetryRoute(retryObservationContext([successfulSmokeObservation])),
);
assert(
responseFunctionNames(standaloneReplayResponse).includes(
'respond_to_user',
) &&
standaloneReplayDuplicateCode ===
`provider-ready-run-terminal-duplicate:${standaloneRetryAgentId}` &&
standaloneRetryRouter.getStats().readyTaskCountsByAgent[
standaloneRetryAgentId
]?.completion === 1,
'self-test-ready-standalone-verification-replay-invalid',
);
const concurrentMutationAgentId = 'design-foundation';
const concurrentMutationRunId = 'concurrent-mutation-ready-run';
const concurrentMutationRouter = createDeterministicLaneDefenseRouter({
apiKey,
});
const concurrentMutationRoute = (extraContext = '') =>
concurrentMutationRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
concurrentMutationAgentId,
concurrentMutationRunId,
manifestReadyTools,
`处理 manifest ready 任务:${concurrentMutationAgentId}\n任务 ID${concurrentMutationAgentId}${extraContext}`,
),
});
for (let attempt = 0; attempt < 8; attempt += 1) {
if (
responseFunctionNames(concurrentMutationRoute()).includes(
'respond_to_user',
)
) {
break;
}
}
assert(
responseFunctionNames(
concurrentMutationRoute(
retryObservationContext([successfulProjectMutationObservation]),
),
).join(',') === 'runtime_tool_command_run_limited' &&
responseFunctionNames(
concurrentMutationRoute(
retryObservationContext([successfulSmokeObservation]),
),
).includes('respond_to_user') &&
concurrentMutationRouter.getStats().readyTaskCountsByAgent[
concurrentMutationAgentId
]?.completion === 1,
'self-test-ready-concurrent-mutation-reverification-invalid',
);
const repairedWriterAgentId = 'balance-seed';
const repairedWriterRunId = 'repaired-writer-ready-run';
const repairedWriterRouter = createDeterministicLaneDefenseRouter({ apiKey });
const repairedWriterRoute = (tools = manifestReadyTools, extraContext = '') =>
repairedWriterRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
repairedWriterAgentId,
repairedWriterRunId,
tools,
`处理 manifest ready 任务:${repairedWriterAgentId}\n任务 ID${repairedWriterAgentId}${extraContext}`,
),
});
for (let attempt = 0; attempt < 8; attempt += 1) {
if (
responseFunctionNames(repairedWriterRoute()).includes('respond_to_user')
) {
break;
}
}
const repairedWriterMutation = repairedWriterRoute(
['runtime_tool_file_write'],
retryObservationContext([successfulSmokeObservation]),
);
const repairedWriterVerification = repairedWriterRoute(
manifestReadyTools,
retryObservationContext([successfulProjectMutationObservation]),
);
const repairedWriterFinalization = repairedWriterRoute(
manifestReadyTools,
retryObservationContext([successfulSmokeObservation]),
);
const repairedWriterDuplicateCode = captureProviderErrorCode(() =>
repairedWriterRoute(
manifestReadyTools,
retryObservationContext([successfulSmokeObservation]),
),
);
assert(
responseFunctionNames(repairedWriterMutation).join(',') ===
'runtime_tool_file_write' &&
responseFunctionNames(repairedWriterVerification).join(',') ===
'runtime_tool_command_run_limited' &&
responseFunctionNames(repairedWriterFinalization).includes(
'respond_to_user',
) &&
repairedWriterDuplicateCode ===
`provider-ready-run-terminal-duplicate:${repairedWriterAgentId}` &&
repairedWriterRouter.getStats().readyTaskCountsByAgent[
repairedWriterAgentId
]?.completion === 1,
'self-test-ready-repaired-writer-reverification-invalid',
);
const projectRevisionDriftAgentId = 'preview-readiness';
const projectRevisionDriftRunId = 'project-revision-drift-ready-run';
const projectRevisionDriftRouter = createDeterministicLaneDefenseRouter({
apiKey,
});
const projectRevisionDriftRoute = (extraContext = '') =>
projectRevisionDriftRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
projectRevisionDriftAgentId,
projectRevisionDriftRunId,
manifestReadyTools,
`处理 manifest ready 任务:${projectRevisionDriftAgentId}\n任务 ID${projectRevisionDriftAgentId}${extraContext}`,
),
});
for (let attempt = 0; attempt < 8; attempt += 1) {
if (
responseFunctionNames(projectRevisionDriftRoute()).includes(
'respond_to_user',
)
) {
break;
}
}
assert(
responseFunctionNames(
projectRevisionDriftRoute(
retryObservationContext([projectRevisionDriftSmokeObservation]),
),
).join(',') === 'runtime_tool_command_run_limited' &&
responseFunctionNames(
projectRevisionDriftRoute(
retryObservationContext([successfulSmokeObservation]),
),
).includes('respond_to_user') &&
projectRevisionDriftRouter.getStats().readyTaskCountsByAgent[
projectRevisionDriftAgentId
]?.completion === 1,
'self-test-ready-project-revision-drift-retry-invalid',
);
const readOnlyRetryAgentId = 'quality-review';
const readOnlyRetryRunId = 'read-only-retry-ready-run';
const readOnlyRetryRouter = createDeterministicLaneDefenseRouter({ apiKey });
const readOnlyRetryRoute = (extraContext = '') =>
readOnlyRetryRouter.route({
authorization: `Bearer ${apiKey}`,
payload: syntheticPayload(
readOnlyRetryAgentId,
readOnlyRetryRunId,
manifestReadyTools,
`处理 manifest ready 任务:${readOnlyRetryAgentId}\n任务 ID${readOnlyRetryAgentId}${extraContext}`,
),
});
for (let attempt = 0; attempt < 8; attempt += 1) {
if (
responseFunctionNames(readOnlyRetryRoute()).includes('respond_to_user')
) {
break;
}
}
assert(
responseFunctionNames(
readOnlyRetryRoute(retryObservationContext([staleObservation])),
).includes('respond_to_user') &&
readOnlyRetryRouter.getStats().manifestReadyTaskStaticSmokeCount === 0,
'self-test-read-only-retry-used-forbidden-verification',
);
assert(
stats.goalContractCount === 1 &&
stats.actionHistoryCount === 1 &&
stats.acceptanceUpdateCount === 1 &&
stats.delegateActionCount === 0 &&
stats.manifestReadyTaskCanvasGenerationCount === 3 &&
stats.byAgent?.['project-supervisor']?.projectMutation === 0 &&
stats.byAgent?.['code-prototype']?.projectMutation === 1 &&
stats.byAgent?.['quality-review']?.projectMutation === 0 &&
stats.unexpectedRequestCount === 0,
'self-test-provider-core-stats-invalid',
);
const syntheticRuntimeProviderRequestCount =
stats.requestCount -
stats.interactionExecuteCount -
stats.imageInspectionRequestCount;
const syntheticChildReport = {
status: 'PASS',
suite,
errorCount: 0,
blocked: [],
cleanup: { performed: true, kept: false },
evidence: {
...Object.fromEntries(
requiredZeroChildEvidenceFields.map((field) => [field, 0]),
),
evidenceCompleteness: 'complete',
dedicatedZeroInterventionPath: true,
stdinTaskCount: 1,
stdinEndedAfterTask: true,
turnReportOutcome: 'settled',
parentTaskStatus: 'completed',
parentRuntimeStatus: 'idle',
parentRuntimePhase: 'completed',
laneDefensePlaytestPassed: true,
laneDefenseAssertionCount: 37,
laneDefensePassedAssertionCount: 37,
browserValidationPassed: true,
staticSmokePassed: true,
gameIndexChanged: true,
projectRevisionDelta: 2,
finalSupervisorAssistantCount: 1,
professionalAssistantCount: 3,
providerRequestIdentityCount: syntheticRuntimeProviderRequestCount,
providerLifecycleStartedCount: syntheticRuntimeProviderRequestCount,
providerLifecycleTerminalCount: syntheticRuntimeProviderRequestCount,
providerLifecycleCompletedCount: syntheticRuntimeProviderRequestCount,
},
};
const incompletePlaytestReport = structuredClone(syntheticChildReport);
incompletePlaytestReport.evidence.laneDefensePassedAssertionCount = 36;
const manualInputReport = structuredClone(syntheticChildReport);
manualInputReport.evidence.approveInputCount = 1;
const residualSidecarReport = structuredClone(syntheticChildReport);
residualSidecarReport.evidence.providerHandoffSidecarCount = 1;
assert(
expectedChildReport(syntheticChildReport, { keepProject: false }, stats) &&
!expectedChildReport(
incompletePlaytestReport,
{ keepProject: false },
stats,
) &&
!expectedChildReport(manualInputReport, { keepProject: false }, stats) &&
!expectedChildReport(
residualSidecarReport,
{ keepProject: false },
stats,
),
'self-test-child-hard-gates-invalid',
);
const rootPackage = JSON.parse(
await fs.readFile(path.join(repoRoot, 'package.json'), 'utf8'),
);
const shellPackage = JSON.parse(
await fs.readFile(path.join(appRoot, 'package.json'), 'utf8'),
);
assert(
shellPackage.scripts?.[
'agent-runtime:supervisor-autonomous-playable-lane-defense-deterministic-e2e'
] === 'node scripts/agent-runtime-deterministic-playable-e2e.mjs' &&
rootPackage.scripts?.[
'ai-game-creator-shell:agent-runtime:supervisor-autonomous-playable-lane-defense-deterministic-e2e'
] ===
'npm --prefix apps/ai-game-creator-shell run agent-runtime:supervisor-autonomous-playable-lane-defense-deterministic-e2e --',
'self-test-package-command-invalid',
);
return {
status: 'PASS',
suite: `${wrapperSuite}-self-test`,
providerUsed: false,
htmlChars: [...html].length,
providerStats: stats,
manifestReadyTasks,
manifestReadyFailureSamplesValidated: ['missing', 'duplicate'],
manifestReadyProviderDuplicateRejections: {
terminal: duplicateTerminalCode,
run: duplicateRunCode,
},
terminalRetryContractsValidated: {
readOnlyCommandOnlyRejected: true,
preCompletionTransientRetryLimit: 16,
projectLockPathSeparatorsRetried: ['/', '\\'],
},
providerRuntimeModeValidated: true,
interactionExecutionValidated: {
reasoningEffort: 'max',
requestCount: stats.interactionExecuteCount,
responseTools: interactionExecuteCalls.map((call) => call.name),
readyTaskRunCountBeforeRuntime:
interactionExecuteStats.manifestReadyTaskRunCount,
readyTaskCompletionCountBeforeRuntime:
interactionExecuteStats.manifestReadyTaskCompletionCount,
},
goalContractValidated: true,
finalizationSequenceValidated: [
'command.run_limited',
'preview.validate',
'agent.action_history',
'agent.acceptance_update',
'respond_to_user',
],
canvasArtifactsValidated: [
'assets/art-spec.png',
'assets/ui-prototype.png',
'assets/art-spritesheet.png',
],
uiPrototypeInspectionValidated: true,
uiPrototypeVisualRecoveryExactlyOnceValidated: true,
artAssetVisualRecoveryExactlyOnceValidated: true,
artAssetRevisionDriftRecoveryExactlyOnceValidated: true,
artAssetRevisionDriftRetryLimitValidated: 16,
supervisorPlanRejectionMode: 'respond-only-then-read-only-wait',
childHardGatesValidated: true,
packageCommandsRegistered: true,
};
}
async function runE2e(options) {
const token = randomUUID();
const apiKey = `deterministic-runtime-${randomUUID()}`;
const configDir = await fs.mkdtemp(
path.join(os.tmpdir(), 'genarrative-deterministic-provider-config-'),
);
let provider = null;
let childResult = null;
let childReport = null;
let configRemoved = false;
let providerStats = null;
let failureCode = null;
try {
if (process.platform !== 'win32') await fs.chmod(configDir, 0o700);
await fs.writeFile(
path.join(configDir, configSentinelName),
`${JSON.stringify({ schemaVersion: configSentinelSchema, token })}\n`,
{ flag: 'wx', mode: 0o600 },
);
provider = await startDeterministicLaneDefenseProvider({ apiKey });
const config = deterministicRuntimeConfig(apiKey, provider);
const fixturePath = path.join(configDir, platformSessionFixtureName);
await fs.writeFile(
fixturePath,
`${JSON.stringify(deterministicPlatformSessionFixture(apiKey, provider))}\n`,
{ flag: 'wx', mode: 0o600 },
);
await fs.writeFile(
path.join(configDir, configFileName),
`${JSON.stringify(config)}\n`,
{ flag: 'wx', mode: 0o600 },
);
const childArgs = [
realE2eScript,
'--suite',
suite,
'--config-dir',
configDir,
];
if (options.keepProject) childArgs.push('--keep-project');
childResult = await runChild(
childArgs,
withLoopbackNoProxy({
...process.env,
NO_COLOR: '1',
[platformSessionFixtureEnv]: fixturePath,
GENARRATIVE_AGC_DEBUG_PROVIDER_E2E: '1',
}),
);
childReport = parseChildReport(childResult);
} catch (error) {
failureCode = error?.code ?? 'deterministic-e2e-unexpected-error';
} finally {
if (provider) {
try {
await provider.stop();
providerStats = provider.getStats();
} catch {
failureCode ??= 'deterministic-provider-stop-failed';
}
}
try {
const sentinel = JSON.parse(
await fs.readFile(path.join(configDir, configSentinelName), 'utf8'),
);
assert(
sentinel.schemaVersion === configSentinelSchema &&
sentinel.token === token,
'deterministic-config-sentinel-invalid',
);
await fs.rm(configDir, { recursive: true, force: false });
configRemoved = true;
} catch (error) {
failureCode ??= error?.code ?? 'deterministic-config-cleanup-failed';
}
}
const childPassed =
childResult?.code === 0 &&
childResult?.signal === null &&
!childResult?.error &&
expectedChildReport(childReport, options, providerStats);
const providerPassed =
providerStats?.stopped === true && expectedProviderStats(providerStats);
const manifestReadyTasks = manifestReadyTaskEvidence(providerStats);
const status =
!failureCode && childPassed && providerPassed && configRemoved
? 'PASS'
: 'FAIL';
if (status !== 'PASS' && !failureCode) {
failureCode = !childPassed
? 'deterministic-child-e2e-failed'
: !providerPassed
? 'deterministic-provider-contract-failed'
: 'deterministic-config-not-cleaned';
}
return {
status,
suite: wrapperSuite,
providerMode: 'deterministic-loopback-openai-chat',
delegatedSuite: suite,
child: childReport,
provider: providerStats,
manifestReadyTasks,
finalizationContract: {
goalContractCount: providerStats?.goalContractCount ?? null,
actionHistoryCount: providerStats?.actionHistoryCount ?? null,
acceptanceUpdateCount: providerStats?.acceptanceUpdateCount ?? null,
delegateActionCount: providerStats?.delegateActionCount ?? null,
supervisorProjectMutationCount:
providerStats?.byAgent?.['project-supervisor']?.projectMutation ?? null,
},
cleanup: {
providerStopped: providerStats?.stopped === true,
configRemoved,
projectKept: options.keepProject,
},
childDiagnostic: childResult ? safeChildDiagnostic(childResult) : null,
failureCode,
};
}
const options = parseArguments(process.argv.slice(2));
const report = options.selfTest ? await runSelfTest() : await runE2e(options);
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
process.exitCode = report.status === 'PASS' ? 0 : 1;