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任务 ID:design-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任务 ID:quality-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;