#!/usr/bin/env node import { _electron as electron } from '@playwright/test'; import { execFile } from 'node:child_process'; import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'; import { createServer } from 'node:net'; import { tmpdir } from 'node:os'; import { dirname, join, resolve } from 'node:path'; import { pathToFileURL } from 'node:url'; import { performance } from 'node:perf_hooks'; import { promisify } from 'node:util'; import { defaultProductExecutable } from './lib/pi-product-artifact.mjs'; const execFileAsync = promisify(execFile); function parseArgs(argv, projectRoot = process.cwd()) { const options = { projectRoot: resolve(projectRoot), runtimeRoot: undefined, electronExecutable: undefined, reportPath: undefined, verifyCleanupFailure: true, }; for (let index = 0; index < argv.length; index += 1) { const argument = argv[index]; if (argument === '--') continue; const value = argv[index + 1]; if (!value || value.startsWith('--')) throw new Error(`${argument} requires a value`); if (argument === '--runtime-root') options.runtimeRoot = resolve(value); else if (argument === '--electron-executable') options.electronExecutable = resolve(value); else if (argument === '--report') options.reportPath = resolve(value); else throw new Error(`Unknown argument: ${argument}`); index += 1; } options.electronExecutable ??= defaultProductExecutable(options.projectRoot); return options; } async function allocatePort() { return await new Promise((resolvePort, reject) => { const server = createServer(); server.once('error', reject); server.listen(0, '127.0.0.1', () => { const address = server.address(); if (!address || typeof address === 'string') { server.close(() => reject(new Error('Failed to allocate PI proof Host API port'))); return; } server.close((error) => error ? reject(error) : resolvePort(address.port)); }); }); } function assertPackagedMain(result) { if (result?.packagedMain?.isPackaged !== true || result?.packagedMain?.appPathUsesAsar !== true) { throw new Error(`PI proof did not execute from packaged app.asar Main: ${JSON.stringify(result?.packagedMain)}`); } } function assertActivePressure(pressure) { const expected = { parentWorkers: 4, childWorkers: 4, parentProcesses: 1, childProcesses: 4, liveProcesses: 5, parentProviderRequests: 4, childProviderRequests: 4, processBudget: 4, childPermits: 4, dispatches: 4, writeLeases: 4, }; const actual = { parentWorkers: pressure?.parentWorkers, childWorkers: pressure?.childWorkers, parentProcesses: pressure?.parentProcessIds?.length, childProcesses: pressure?.childProcessIds?.length, liveProcesses: pressure?.liveProcessIds?.length, parentProviderRequests: pressure?.providerRequests?.parent, childProviderRequests: pressure?.providerRequests?.child, processBudget: pressure?.processBudget?.active, childPermits: pressure?.childPermits?.active, dispatches: pressure?.dispatches?.active, writeLeases: pressure?.writeLeases?.active, }; if (JSON.stringify(actual) !== JSON.stringify(expected)) { throw new Error(`PI pressure did not reach 4 parent threads + 4 child process state: ${JSON.stringify(actual)}`); } } function assertReleasedPressure(pressure) { const counts = [ pressure?.parentWorkers, pressure?.childWorkers, pressure?.parentProcessIds?.length, pressure?.childProcessIds?.length, pressure?.liveProcessIds?.length, pressure?.providerRequests?.parent, pressure?.providerRequests?.child, pressure?.processBudget?.active, pressure?.processBudget?.waiting, pressure?.childPermits?.active, pressure?.childPermits?.waiting, pressure?.dispatches?.active, pressure?.dispatches?.parents, pressure?.writeLeases?.active, pressure?.writeLeases?.waiting, ]; if (counts.some((value) => value !== 0)) { throw new Error(`PI pressure resources were not fully released: ${JSON.stringify(pressure)}`); } } function assertManagedTurns(extension) { const expectedMilestones = 'worker.queue_wait,resources.ready,worker.spawn,rpc.ready,session.open,prompt.accepted,agent.start,provider.first_event,agent.settled'; const expectedDelayMs = extension?.providerFirstEventDelayMs; if (!Number.isFinite(expectedDelayMs) || expectedDelayMs < 1) { throw new Error(`PI proof did not expose a controlled Provider first-event delay: ${expectedDelayMs}`); } for (const turn of extension?.managedTurns ?? []) { if (turn.milestones.map(({ milestone }) => milestone).join(',') !== expectedMilestones) { throw new Error(`PI managed turn timeline is incomplete: ${JSON.stringify(turn)}`); } const agentStart = turn.milestones.find(({ milestone }) => milestone === 'agent.start'); const providerFirstEvent = turn.milestones.find(({ milestone }) => milestone === 'provider.first_event'); if (agentStart?.source !== 'pi.agent_start' || providerFirstEvent?.source !== 'pi.assistant_message_start' || providerFirstEvent.at <= agentStart.at || providerFirstEvent.durationMs < Math.floor(expectedDelayMs * 0.75)) { throw new Error(`PI Provider first-event milestone is not Provider-response-backed: ${JSON.stringify(turn)}`); } } } function assertProxyStatus(status) { if (status?.currentHostTokenAvailable !== true || status?.realTurnVerified !== false || status?.activeProviderRequests?.child !== 1 || status?.providerRequests?.parent < 1 || status?.providerRequests?.child !== 1 || status?.processes?.supported !== true || status?.processes?.parent?.length !== 1 || status?.processes?.child?.length !== 1 || status?.providerCompatibility?.roleContract?.developerRejected !== true || status?.providerCompatibility?.roleContract?.systemAccepted !== true || status?.providerCompatibility?.developerRoleRequests !== 0 || status?.providerCompatibility?.systemRoleRequests < 2 || status?.providerCompatibility?.controlledDefiniteRejections !== 1 || Object.values(status?.tokenSafety ?? {}).some((safe) => safe !== true)) { throw new Error(`Packaged Main proxy status is incomplete: ${JSON.stringify(status)}`); } } function assertProxyProof(proof) { if (proof?.providerMode !== 'loopback-through-authenticated-host-proxy' || proof?.realTurnVerified !== false || proof?.firstConversation?.count !== 1 || proof?.firstConversation?.bindingEstablished !== true || proof?.firstConversation?.workerStatus !== 'ready' || proof?.firstConversation?.runStatus !== 'idle' || proof?.firstConversation?.userInputProjected !== true || proof?.firstConversation?.parentResponseProjected !== true || proof?.firstConversation?.definiteRejectionObserved !== true || proof?.firstConversation?.retryAccepted !== true || proof?.fork?.conversationCount !== 2 || proof?.fork?.sameAgent !== true || proof?.fork?.targetBindingEstablished !== true || proof?.fork?.distinctSessionBinding !== true || proof?.fork?.workerStatus !== 'ready' || proof?.fork?.runStatus !== 'idle' || proof?.fork?.sourceEntryRole !== 'user' || proof?.fork?.targetHydratedBeforeSourceEntry !== true || proof?.fork?.sourceUnchanged !== true || proof?.fork?.promptReplayObserved !== false || proof?.providerCompatibility?.developerRoleRequests !== 0 || proof?.providerCompatibility?.controlledDefiniteRejections !== 1 || proof?.currentHostTokenUsedBy?.join(',') !== 'parent,child' || proof?.released?.workers !== 0 || Object.values(proof?.tokenSafety ?? {}).some((safe) => safe !== true)) { throw new Error(`Packaged Main proxy proof failed: ${JSON.stringify(proof)}`); } } async function waitForProxyProof(electronApplication, predicate, message) { const deadline = Date.now() + 30_000; let latest; while (Date.now() < deadline) { latest = await evaluateProof(electronApplication, 'proxy.status'); if (predicate(latest?.proxy)) return latest; await new Promise((resolveWait) => setTimeout(resolveWait, 200)); } throw new Error(`${message}: ${JSON.stringify(latest?.proxy)}`); } async function waitForActiveProxyProof(electronApplication) { return await waitForProxyProof( electronApplication, (status) => status?.activeProviderRequests?.child === 1 && status?.processes?.parent?.length === 1 && status?.processes?.child?.length === 1, 'Packaged Main proxy child did not become active', ); } async function waitForResilienceProof(electronApplication, predicate, message) { const deadline = Date.now() + 30_000; let latest; while (Date.now() < deadline) { latest = await evaluateProof(electronApplication, 'resilience.status'); if (predicate(latest?.resilience)) return latest; await new Promise((resolveWait) => setTimeout(resolveWait, 100)); } throw new Error(`${message}: ${JSON.stringify(latest?.resilience)}`); } async function waitForResilienceIdleProof(electronApplication, predicate, message) { const deadline = Date.now() + 30_000; let latest; while (Date.now() < deadline) { latest = await evaluateProof(electronApplication, 'resilience.idle-status'); if (predicate(latest?.resilience)) return latest; await new Promise((resolveWait) => setTimeout(resolveWait, 100)); } throw new Error(`${message}: ${JSON.stringify(latest?.resilience)}`); } async function setMainWindowVisible(electronApplication, visible) { await electronApplication.evaluate(({ BrowserWindow }, shouldShow) => { const window = BrowserWindow.getAllWindows()[0]; if (!window) throw new Error('Packaged Main window is unavailable'); if (shouldShow) window.show(); else window.hide(); }, visible); } function assertResilienceTerminal( status, expectedRunStatus = 'error', expectedErrorCode = 'CODING_RUNTIME_START_FAILED', ) { if (status?.target?.workerStatus !== 'error' || status?.target?.runStatus !== expectedRunStatus || status?.target?.errorCode !== expectedErrorCode || status?.target?.recoverable !== true || status?.target?.bindingPreserved !== true || status?.other?.bindingPreserved !== true) { throw new Error(`Packaged resilience target did not converge: ${JSON.stringify(status)}`); } } async function recoverSelectedConversation(page, electronApplication) { await page.getByRole('button', { name: '恢复' }).first().click({ timeout: 10_000 }); const recovered = await waitForResilienceProof( electronApplication, (status) => status?.target?.workerStatus === 'ready' && status?.target?.runStatus === 'idle', 'Packaged resilience target did not recover', ); const composer = page.getByRole('textbox'); await composer.waitFor({ state: 'visible', timeout: 10_000 }); if (!await composer.isEnabled()) throw new Error('Recovered resilience composer is disabled'); return recovered; } async function evaluateProof(electronApplication, action) { return await electronApplication.evaluate(async (_electron, requestedAction) => { const proof = globalThis.__niancodeRunPiReleaseProofE2E; if (typeof proof !== 'function') throw new Error('Packaged Main has no PI release proof entry'); return await proof(requestedAction); }, action); } async function closeApplication(electronApplication) { await Promise.race([ electronApplication.close().catch(() => undefined), new Promise((resolveTimeout) => setTimeout(resolveTimeout, 5_000)), ]); } async function windowsDescendantProcessIds(rootPid) { if (process.platform !== 'win32') return []; const script = 'Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId | ConvertTo-Json -Compress'; const { stdout } = await execFileAsync( 'powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', script], { windowsHide: true, maxBuffer: 4 * 1024 * 1024 }, ); const parsed = stdout.trim() ? JSON.parse(stdout) : []; const processes = (Array.isArray(parsed) ? parsed : [parsed]).flatMap((entry) => { const pid = Number(entry?.ProcessId); const parentPid = Number(entry?.ParentProcessId); return Number.isSafeInteger(pid) && Number.isSafeInteger(parentPid) ? [{ pid, parentPid }] : []; }); const descendants = new Set(); const frontier = [rootPid]; while (frontier.length > 0) { const parentPid = frontier.shift(); for (const processEntry of processes) { if (processEntry.parentPid !== parentPid || descendants.has(processEntry.pid)) continue; descendants.add(processEntry.pid); frontier.push(processEntry.pid); } } return [...descendants]; } function processIsAlive(pid) { try { process.kill(pid, 0); return true; } catch { return false; } } export async function runPackagedProductProof(options) { const scratchRoot = await mkdtemp(join(tmpdir(), 'makelore-pi-final-product-proof-')); const homeDir = join(scratchRoot, 'home'); const userDataDir = join(scratchRoot, 'user-data'); await Promise.all([ mkdir(join(homeDir, '.config'), { recursive: true }), mkdir(join(homeDir, 'AppData', 'Local'), { recursive: true }), mkdir(join(homeDir, 'AppData', 'Roaming'), { recursive: true }), mkdir(userDataDir, { recursive: true }), ]); const hostApiPort = await allocatePort(); let electronApplication; let pressureActive = false; let proxyActive = false; let resilienceActive = false; try { electronApplication = await electron.launch({ executablePath: options.electronExecutable, env: { ...process.env, HOME: homeDir, USERPROFILE: homeDir, APPDATA: join(homeDir, 'AppData', 'Roaming'), LOCALAPPDATA: join(homeDir, 'AppData', 'Local'), XDG_CONFIG_HOME: join(homeDir, '.config'), NIANCODE_E2E: '1', NIANCODE_E2E_SKIP_SETUP: '1', NIANCODE_USER_DATA_DIR: userDataDir, NIANCODE_PORT_NIANCODE_HOST_API: String(hostApiPort), ...(process.platform === 'linux' ? { ELECTRON_DISABLE_SANDBOX: '1' } : {}), }, timeout: 90_000, }); const page = await electronApplication.firstWindow(); await page.waitForLoadState('domcontentloaded'); const extension = await evaluateProof(electronApplication, 'extension'); assertPackagedMain(extension); assertManagedTurns(extension.extension); if (extension.extension?.subagentStatus !== 'complete' || extension.extension?.childToolNames?.join(',') !== 'find,grep,ls,read' || !extension.extension?.parentToolNames?.includes('subagent') || extension.extension?.parentProcessIds?.length !== 1 || extension.extension?.childProcessIds?.length !== 1 || extension.extension?.providerRequests?.child !== 1 || extension.extension?.managedTurns?.length !== 2) { throw new Error(`Final ASAR extension/subagent proof failed: ${JSON.stringify(extension.extension)}`); } const pressureStart = await evaluateProof(electronApplication, 'pressure.start'); pressureActive = true; assertPackagedMain(pressureStart); assertActivePressure(pressureStart.pressure); const uiStartedAt = performance.now(); await page.getByTestId('ai-module-option-programming').click(); await page.getByTestId('main-layout').waitFor({ state: 'visible', timeout: 10_000 }); const uiInteractiveMs = Math.round(performance.now() - uiStartedAt); const pressureFinish = await evaluateProof(electronApplication, 'pressure.finish'); pressureActive = false; assertPackagedMain(pressureFinish); assertReleasedPressure(pressureFinish.pressure); let failureCleanup; if (options.verifyCleanupFailure === true) { const failureStart = await evaluateProof(electronApplication, 'pressure.start'); pressureActive = true; assertPackagedMain(failureStart); assertActivePressure(failureStart.pressure); let injectedFailure; try { await evaluateProof(electronApplication, 'pressure.finish.inject-failure'); } catch (error) { injectedFailure = error; } if (!injectedFailure || !String(injectedFailure).includes('PI release pressure cleanup failed: parents.settle')) { throw new Error(`PI pressure cleanup failure injection did not fail as expected: ${String(injectedFailure)}`); } const retryFinish = await evaluateProof(electronApplication, 'pressure.finish'); pressureActive = false; assertPackagedMain(retryFinish); assertReleasedPressure(retryFinish.pressure); failureCleanup = { injectedAt: 'parents.settle', firstFinish: 'failed-as-injected', retry: 'pass', released: retryFinish.pressure, }; } const proxyStart = await evaluateProof(electronApplication, 'proxy.start'); proxyActive = true; assertPackagedMain(proxyStart); if (proxyStart?.proxy?.providerMode !== 'works_square_ai_gateway_proxy' || proxyStart?.proxy?.currentHostTokenAvailable !== true || proxyStart?.proxy?.realTurnVerified !== false) { throw new Error(`Packaged Main proxy setup failed: ${JSON.stringify(proxyStart?.proxy)}`); } await page.reload(); await page.waitForLoadState('domcontentloaded'); const moduleSelection = page.getByTestId('ai-module-selection-page'); if (await moduleSelection.count()) { await page.getByTestId('ai-module-option-programming').click(); await page.getByTestId('main-layout').waitFor({ state: 'visible', timeout: 10_000 }); } await page.evaluate(() => { window.location.hash = '/chat'; }); const composer = page.getByRole('textbox'); await composer.waitFor({ state: 'visible', timeout: 30_000 }); const rejectedPrompt = 'Exercise the packaged Main proxy rejection'; const retryPrompt = 'Retry the packaged Main proxy Conversation'; await composer.fill(rejectedPrompt); if (!await composer.isEnabled()) throw new Error('Packaged proxy first Conversation composer is disabled'); const beforeSubmitText = await page.locator('body').innerText(); if (beforeSubmitText.includes('本地编程运行时暂时不可用') || beforeSubmitText.includes('正在重新连接本地 Agent')) { throw new Error(`Packaged proxy first Conversation exposed a runtime banner: ${beforeSubmitText}`); } await page.getByRole('button', { name: '发送' }).click({ timeout: 30_000 }); const rejectedProxy = await waitForProxyProof( electronApplication, (status) => status?.providerCompatibility?.controlledDefiniteRejections === 1, 'Packaged Main did not observe the controlled definite rejection', ); const draftDeadline = Date.now() + 10_000; while (Date.now() < draftDeadline && await composer.inputValue() !== rejectedPrompt) { await new Promise((resolveWait) => setTimeout(resolveWait, 100)); } const draftRestored = await composer.inputValue() === rejectedPrompt; const rejectionText = await page.locator('body').innerText(); const submissionErrorSafe = !rejectionText.includes('controlled definite model rejection') && !rejectionText.includes('developer role is unsupported') && !rejectionText.includes('X-Works-Square-AI-Token') && !rejectionText.includes('Authorization'); if (!draftRestored || !submissionErrorSafe) { throw new Error( `Packaged definite rejection did not restore a safe draft: ${JSON.stringify({ draftRestored, submissionErrorSafe })}`, ); } if (await page.getByRole('button', { name: '重试' }).count()) { throw new Error('Packaged definite submission rejection was exposed as a runtime recovery error'); } await composer.fill(retryPrompt); const sendButton = page.getByRole('button', { name: '发送' }); const retryDeadline = Date.now() + 10_000; while (Date.now() < retryDeadline && !await sendButton.isEnabled()) { await new Promise((resolveWait) => setTimeout(resolveWait, 100)); } const retryAfterEditEnabled = await sendButton.isEnabled(); if (!retryAfterEditEnabled) { const bodyText = await page.locator('body').innerText(); throw new Error(`Packaged proxy retry stayed disabled after editing: ${bodyText}`); } await sendButton.click({ timeout: 30_000 }); let proxyStatus; try { proxyStatus = await waitForActiveProxyProof(electronApplication); } catch (error) { const bodyText = await page.locator('body').innerText().catch(() => ''); throw new Error(`${error instanceof Error ? error.message : String(error)}; UI=${bodyText}`); } assertPackagedMain(proxyStatus); assertProxyStatus(proxyStatus.proxy); await evaluateProof(electronApplication, 'proxy.release-child'); await page.getByText('REAL_PARENT_COMPLETE').waitFor({ state: 'visible', timeout: 30_000 }); const afterTurnText = await page.locator('body').innerText(); if (afterTurnText.includes('本地编程运行时暂时不可用') || afterTurnText.includes('正在重新连接本地 Agent')) { throw new Error(`Packaged proxy Conversation did not leave recovery cleanly: ${afterTurnText}`); } if (!await composer.isEnabled()) throw new Error('Packaged proxy composer is not editable after the turn'); const settledProxy = await evaluateProof(electronApplication, 'proxy.status'); if (settledProxy?.proxy?.conversationCount !== 1 || settledProxy?.proxy?.activeProviderRequests?.parent !== 0 || settledProxy?.proxy?.activeProviderRequests?.child !== 0) { throw new Error(`Packaged proxy source did not settle before fork: ${JSON.stringify(settledProxy?.proxy)}`); } await page.reload(); await page.waitForLoadState('domcontentloaded'); if (await page.getByTestId('ai-module-selection-page').count()) { await page.getByTestId('ai-module-option-programming').click(); await page.getByTestId('main-layout').waitFor({ state: 'visible', timeout: 10_000 }); } await page.evaluate(() => { window.location.hash = '/chat'; }); await page.getByText('REAL_PARENT_COMPLETE').waitFor({ state: 'visible', timeout: 30_000 }); const timeline = page.getByTestId('coding-conversation-timeline'); const forkActions = timeline.getByRole('button', { name: '从这里创建新对话分支' }); await forkActions.waitFor({ state: 'visible', timeout: 30_000 }); if (await forkActions.count() !== 1) { throw new Error(`Packaged proxy timeline exposed ${await forkActions.count()} fork actions for one user and one assistant entry`); } const sourceHeader = await page.getByTestId('coding-conversation-header').innerText(); await forkActions.click({ timeout: 30_000 }); await page.waitForFunction((previous) => { const header = document.querySelector('[data-testid="coding-conversation-header"]'); return Boolean(header?.textContent?.includes('(fork)') && header.textContent !== previous); }, sourceHeader, { timeout: 30_000 }); const forkedHeader = await page.getByTestId('coding-conversation-header').innerText(); const forkedTitle = forkedHeader.split('\n', 1)[0]?.trim(); if (!forkedTitle?.includes('(fork)')) { throw new Error(`Packaged proxy fork target was not selected: ${forkedHeader}`); } const agentConversations = page.getByRole('group', { name: 'Packaged proxy proof agent 的对话' }); await agentConversations.getByRole('button', { name: forkedTitle, exact: true }) .waitFor({ state: 'visible', timeout: 30_000 }); const forkedBody = await page.locator('body').innerText(); if (forkedBody.includes('本地编程运行时暂时不可用') || forkedBody.includes('正在重新连接本地 Agent')) { throw new Error(`Packaged user-entry fork exposed a runtime banner: ${forkedBody}`); } if (await timeline.getByText(retryPrompt, { exact: true }).count() !== 0 || await timeline.getByText('REAL_PARENT_COMPLETE', { exact: true }).count() !== 0 || await timeline.getByRole('button', { name: '从这里创建新对话分支' }).count() !== 0) { throw new Error('Packaged fork target did not hydrate at the path before the selected user entry'); } const proxyFinish = await evaluateProof(electronApplication, 'proxy.finish'); proxyActive = false; assertPackagedMain(proxyFinish); assertProxyProof(proxyFinish.proxy); const resilienceStart = await evaluateProof(electronApplication, 'resilience.start'); resilienceActive = true; assertPackagedMain(resilienceStart); if (resilienceStart?.resilience?.bindingsEstablished !== true || resilienceStart?.resilience?.otherRunAccepted !== true || resilienceStart?.resilience?.realTurnVerified !== false) { throw new Error(`Packaged resilience setup failed: ${JSON.stringify(resilienceStart?.resilience)}`); } const promptDelay = await evaluateProof(electronApplication, 'resilience.arm-prompt-delay'); assertPackagedMain(promptDelay); if (!(promptDelay?.resilience?.delayMs > 10_000)) { throw new Error(`Packaged prompt proof did not exceed the former 10s threshold: ${JSON.stringify(promptDelay?.resilience)}`); } await page.reload(); await page.waitForLoadState('domcontentloaded'); if (await page.getByTestId('ai-module-selection-page').count()) { await page.getByTestId('ai-module-option-programming').click(); await page.getByTestId('main-layout').waitFor({ state: 'visible', timeout: 10_000 }); } await page.evaluate(() => { window.location.hash = '/chat'; }); const resilienceTarget = page.locator('aside').getByRole('button', { name: 'Resilience fault target', exact: true, }); await resilienceTarget.waitFor({ state: 'visible', timeout: 30_000 }); await resilienceTarget.click(); const resilienceComposer = page.getByRole('textbox'); await resilienceComposer.waitFor({ state: 'visible', timeout: 30_000 }); await resilienceComposer.fill('BACKGROUND_ACTIVE'); try { await page.getByRole('button', { name: '发送' }).click({ timeout: 30_000 }); } catch (error) { const [bodyText, status] = await Promise.all([ page.locator('body').innerText().catch(() => ''), evaluateProof(electronApplication, 'resilience.status').catch(() => null), ]); throw new Error( `${error instanceof Error ? error.message : String(error)}; ` + `UI=${bodyText}; resilience=${JSON.stringify(status?.resilience ?? status)}`, ); } const backgroundActive = await waitForResilienceProof( electronApplication, (status) => status?.target?.runStatus === 'running' && status?.target?.errorCode === 'CODING_REQUEST_UNCERTAIN' && status?.other?.runStatus === 'running' && status?.activeProviderRequests?.parent === 2 && status?.resources?.backgroundLeases?.active === 2 && status?.processes?.parent?.length === 2, 'Packaged background lease proof did not reach two active Main-owned runs', ); const uncertaintyMessage = page.getByText(/请求确认延迟,可能仍在执行/).last(); await uncertaintyMessage.waitFor({ state: 'visible', timeout: 15_000 }); const compactButton = page.getByRole('button', { name: '整理上下文' }); if (await compactButton.isEnabled()) { throw new Error('Packaged UI allowed compact to overlap a confirmation-uncertain prompt'); } if (await page.getByText(/本地编程运行时暂时不可用/).count()) { throw new Error('Confirmation uncertainty was presented as a local runtime outage'); } await setMainWindowVisible(electronApplication, false); await new Promise((resolveWait) => setTimeout(resolveWait, 600)); const backgroundHidden = await evaluateProof(electronApplication, 'resilience.status'); if (backgroundHidden?.resilience?.target?.runStatus !== 'running' || backgroundHidden?.resilience?.other?.runStatus !== 'running' || backgroundHidden?.resilience?.activeProviderRequests?.parent !== 2 || backgroundHidden?.resilience?.resources?.backgroundLeases?.active !== 2 || backgroundHidden?.resilience?.processes?.parent?.length !== 2) { throw new Error(`Hidden packaged Pi run was stopped despite active leases: ${JSON.stringify(backgroundHidden?.resilience)}`); } await evaluateProof(electronApplication, 'resilience.release-parents'); await setMainWindowVisible(electronApplication, true); await waitForResilienceProof( electronApplication, (status) => status?.target?.runStatus === 'idle' && status?.other?.runStatus === 'idle' && status?.resources?.backgroundLeases?.active === 0, 'Hidden packaged Pi runs did not settle and release their background leases', ); await page.getByText('RESILIENCE_ACTIVE').last().waitFor({ state: 'visible', timeout: 30_000 }); if (!await resilienceComposer.isEnabled()) { throw new Error('Packaged composer stayed disabled after the hidden run settled'); } await uncertaintyMessage.waitFor({ state: 'hidden', timeout: 10_000 }); const compactDelay = await evaluateProof(electronApplication, 'resilience.arm-compact-delay'); assertPackagedMain(compactDelay); if (!(compactDelay?.resilience?.delayMs > 10_000)) { throw new Error(`Packaged compact proof did not exceed the former 10s threshold: ${JSON.stringify(compactDelay?.resilience)}`); } await compactButton.click(); await uncertaintyMessage.waitFor({ state: 'visible', timeout: 15_000 }); const compactUncertain = await waitForResilienceProof( electronApplication, (status) => status?.target?.runStatus === 'compacting' && status?.target?.errorCode === 'CODING_REQUEST_UNCERTAIN' && status?.target?.contextCompaction === 'running' && status?.activeProviderRequests?.parent === 1 && status?.resources?.backgroundLeases?.active === 1, 'Packaged manual compact did not retain ownership after the 10s confirmation threshold', ); if (await compactButton.isEnabled()) { throw new Error('Packaged UI enabled another compact while the first compact was uncertain'); } if (await page.getByText(/本地编程运行时暂时不可用/).count()) { throw new Error('Packaged manual compact uncertainty was presented as a local runtime outage'); } const compactSettled = await waitForResilienceProof( electronApplication, (status) => status?.target?.runStatus === 'idle' && status?.target?.errorCode === null && status?.target?.contextCompaction === 'idle' && status?.target?.completedCompactions >= 1 && status?.activeProviderRequests?.parent === 0 && status?.resources?.backgroundLeases?.active === 0, 'Packaged manual compact did not settle and release its Main-owned lease', ); await uncertaintyMessage.waitFor({ state: 'hidden', timeout: 10_000 }); if (!await resilienceComposer.isEnabled()) { throw new Error('Packaged composer stayed disabled after manual compact settled'); } await setMainWindowVisible(electronApplication, false); const backgroundIdle = await waitForResilienceIdleProof( electronApplication, (status) => status?.workers?.length === 0 && status?.resources?.backgroundLeases?.active === 0 && status?.resources?.pool?.processBudget?.active === 0 && status?.processes?.parent?.length === 0 && status?.processes?.child?.length === 0 && status?.backgroundSleepReasoned === true, 'Settled hidden packaged Pi workers were not reasoned background-sleep evicted', ); await setMainWindowVisible(electronApplication, true); await page.reload(); await page.waitForLoadState('domcontentloaded'); if (await page.getByTestId('ai-module-selection-page').count()) { await page.getByTestId('ai-module-option-programming').click(); await page.getByTestId('main-layout').waitFor({ state: 'visible', timeout: 10_000 }); } await page.evaluate(() => { window.location.hash = '/chat'; }); await resilienceTarget.waitFor({ state: 'visible', timeout: 30_000 }); await resilienceTarget.click(); await resilienceComposer.waitFor({ state: 'visible', timeout: 30_000 }); const restartedOther = await evaluateProof(electronApplication, 'resilience.restart-other'); assertPackagedMain(restartedOther); if (restartedOther?.resilience?.other?.runStatus !== 'running' || restartedOther?.resilience?.resources?.backgroundLeases?.active !== 1) { throw new Error(`Packaged resilience sibling did not restart: ${JSON.stringify(restartedOther?.resilience)}`); } await resilienceComposer.fill('RESILIENCE_TARGET_ACTIVE'); await page.getByRole('button', { name: '发送' }).click({ timeout: 30_000 }); const intentionalActive = await waitForResilienceProof( electronApplication, (status) => status?.target?.runStatus === 'running' && status?.other?.runStatus === 'running' && status?.resources?.subagents?.activeChildPermits === 1 && status?.resources?.subagents?.activeDispatches === 1 && status?.resources?.extension?.registrations?.child === 1 && status?.resources?.extension?.writeLeases?.active === 1 && status?.resources?.backgroundLeases?.active === 2 && status?.processes?.parent?.length === 2 && status?.processes?.child?.length === 1, 'Packaged intentional-dispose parent/child state did not become active', ); const intentionalDispose = await evaluateProof(electronApplication, 'resilience.dispose-target'); assertPackagedMain(intentionalDispose); if (intentionalDispose?.resilience?.terminal?.observed !== true || intentionalDispose?.resilience?.terminal?.errorCode !== 'CODING_RUNTIME_START_FAILED' || intentionalDispose?.resilience?.terminal?.recoverable !== true || intentionalDispose?.resilience?.other?.runStatus !== 'running' || intentionalDispose?.resilience?.other?.bindingPreserved !== true || intentionalDispose?.resilience?.targetBindingPreserved !== true || intentionalDispose?.resilience?.providerRequestsUnchanged !== true || intentionalDispose?.resilience?.resources?.backgroundLeases?.active !== 1) { throw new Error(`Packaged intentional dispose did not converge safely: ${JSON.stringify(intentionalDispose?.resilience)}`); } await page.getByText('本地 Agent 已中断,原请求未自动重发。').waitFor({ state: 'visible', timeout: 10_000 }); if (!await resilienceComposer.isEnabled()) { throw new Error('Packaged composer stayed disabled after intentional dispose'); } const recoveredAfterDispose = await recoverSelectedConversation(page, electronApplication); if (JSON.stringify(recoveredAfterDispose.resilience.providerRequests) !== JSON.stringify(intentionalActive.resilience.providerRequests)) { throw new Error('Recover replayed the uncertain prompt after intentional dispose'); } await resilienceComposer.fill('RESILIENCE_RECOVERED_TURN'); await page.getByRole('button', { name: '发送' }).click({ timeout: 30_000 }); await page.getByText('RESILIENCE_RECOVERED_COMPLETE').waitFor({ state: 'visible', timeout: 30_000 }); await resilienceComposer.fill('RESILIENCE_TARGET_ACTIVE'); await page.getByRole('button', { name: '发送' }).click({ timeout: 30_000 }); const activeResilience = await waitForResilienceProof( electronApplication, (status) => status?.target?.runStatus === 'running' && status?.other?.runStatus === 'running' && status?.resources?.subagents?.activeChildPermits === 1 && status?.resources?.subagents?.activeDispatches === 1 && status?.resources?.extension?.registrations?.child === 1 && status?.resources?.extension?.writeLeases?.active === 1 && status?.resources?.backgroundLeases?.active === 2 && status?.processes?.parent?.length === 2 && status?.processes?.child?.length === 1, 'Packaged resilience parent/child/write-lease fault state did not become active', ); const requestsBeforeExit = activeResilience.resilience.providerRequests; const exitFailure = await evaluateProof(electronApplication, 'resilience.inject-exit'); assertPackagedMain(exitFailure); assertResilienceTerminal(exitFailure.resilience.status); if (exitFailure.resilience.terminalizationMs > 2_000) { throw new Error(`Packaged worker exit convergence exceeded 2s: ${exitFailure.resilience.terminalizationMs}`); } const releasedAfterExit = await waitForResilienceProof( electronApplication, (status) => status?.other?.runStatus === 'running' && status?.resources?.subagents?.activeChildPermits === 0 && status?.resources?.subagents?.activeDispatches === 0 && status?.resources?.extension?.registrations?.child === 0 && status?.resources?.extension?.writeLeases?.active === 0 && status?.processes?.child?.length === 0, 'Target crash did not release child and write-lease resources or preserve the other run', ); await page.getByText('本地 Agent 已中断,原请求未自动重发。').waitFor({ state: 'visible', timeout: 10_000 }); const composerAfterExit = await page.getByTestId('coding-message-composer').innerText(); if (composerAfterExit.includes('当前对话正在处理') || composerAfterExit.includes('生成中')) { throw new Error(`Packaged resilience UI remained busy after worker exit: ${composerAfterExit}`); } if (!await resilienceComposer.isEnabled()) { throw new Error('Packaged resilience composer stayed disabled after worker exit'); } const abortAfterExit = await evaluateProof(electronApplication, 'resilience.abort-after-exit'); assertPackagedMain(abortAfterExit); assertResilienceTerminal(abortAfterExit.resilience); const recoveredAfterExit = await recoverSelectedConversation(page, electronApplication); if (JSON.stringify(recoveredAfterExit.resilience.providerRequests) !== JSON.stringify(requestsBeforeExit)) { throw new Error('Recover replayed the uncertain accepted prompt after worker exit'); } await resilienceComposer.fill('RESILIENCE_RECOVERED_TURN'); await page.getByRole('button', { name: '发送' }).click({ timeout: 30_000 }); await page.getByText('RESILIENCE_RECOVERED_COMPLETE').waitFor({ state: 'visible', timeout: 30_000 }); await evaluateProof(electronApplication, 'resilience.release-parents'); await waitForResilienceProof( electronApplication, (status) => status?.other?.runStatus === 'idle' && status?.target?.runStatus === 'idle', 'Isolation control Conversation did not settle after release', ); await resilienceComposer.fill('RESILIENCE_PROTOCOL_ACTIVE'); await page.getByRole('button', { name: '发送' }).click({ timeout: 30_000 }); const protocolActive = await waitForResilienceProof( electronApplication, (status) => status?.target?.runStatus === 'running' && status?.activeProviderRequests?.parent === 1, 'Protocol invalidation target did not become active', ); const protocolFailure = await evaluateProof(electronApplication, 'resilience.inject-protocol'); assertPackagedMain(protocolFailure); assertResilienceTerminal( protocolFailure.resilience.status, 'error', 'CODING_RUNTIME_PROTOCOL_ERROR', ); if (protocolFailure.resilience.terminalizationMs > 2_000) { throw new Error(`Packaged protocol convergence exceeded 2s: ${protocolFailure.resilience.terminalizationMs}`); } await page.getByText('本地 Agent 通信异常,当前对话已停止。').waitFor({ state: 'visible', timeout: 10_000 }); const recoveredAfterProtocol = await recoverSelectedConversation(page, electronApplication); if (JSON.stringify(recoveredAfterProtocol.resilience.providerRequests) !== JSON.stringify(protocolFailure.resilience.status.providerRequests)) { throw new Error('Recover replayed the uncertain prompt after protocol invalidation'); } await resilienceComposer.fill('RESILIENCE_SETTLED_BEFORE_CLOSE'); await page.getByRole('button', { name: '发送' }).click({ timeout: 30_000 }); await page.getByText('RESILIENCE_SETTLED_COMPLETE').waitFor({ state: 'visible', timeout: 30_000 }); const settledBeforeClose = await waitForResilienceProof( electronApplication, (status) => status?.target?.runStatus === 'idle' && status?.target?.workerStatus === 'ready', 'Settled-before-close target did not reach its authoritative terminal event', ); const settledClose = await evaluateProof(electronApplication, 'resilience.inject-exit'); assertPackagedMain(settledClose); assertResilienceTerminal(settledClose.resilience.status, 'idle'); await recoverSelectedConversation(page, electronApplication); const resilienceFinish = await evaluateProof(electronApplication, 'resilience.finish'); resilienceActive = false; assertPackagedMain(resilienceFinish); if (resilienceFinish?.resilience?.released?.workers !== 0 || resilienceFinish?.resilience?.released?.processes !== 0 || Object.values(resilienceFinish?.resilience?.lifecycle ?? {}).some((value) => value !== true) || resilienceFinish?.resilience?.realTurnVerified !== false) { throw new Error(`Packaged resilience proof failed: ${JSON.stringify(resilienceFinish?.resilience)}`); } const mainProcessId = electronApplication.process().pid; const proofProcessIds = [ mainProcessId, ...await windowsDescendantProcessIds(mainProcessId), ]; await closeApplication(electronApplication); electronApplication = undefined; const exitDeadline = Date.now() + 5_000; let lingeringProcessIds = proofProcessIds.filter(processIsAlive); while (lingeringProcessIds.length > 0 && Date.now() < exitDeadline) { await new Promise((resolveWait) => setTimeout(resolveWait, 100)); lingeringProcessIds = proofProcessIds.filter(processIsAlive); } if (lingeringProcessIds.length > 0) { throw new Error(`Packaged proof left Electron/Pi processes alive: ${lingeringProcessIds.join(',')}`); } const report = { schemaVersion: 1, generatedAt: new Date().toISOString(), executable: options.electronExecutable, runtimeRoot: options.runtimeRoot ?? null, packagedMain: extension.packagedMain, extension: extension.extension, pressure: { processKind: 'final-product-executable-with-ELECTRON_RUN_AS_NODE', active: pressureStart.pressure, ui: { action: 'select Makelore Code and render main layout', interactive: true, durationMs: uiInteractiveMs, }, released: pressureFinish.pressure, ...(failureCleanup ? { failureCleanup } : {}), }, proxy: { setup: proxyStart.proxy, rejected: rejectedProxy.proxy, active: proxyStatus.proxy, completed: proxyFinish.proxy, ui: { firstConversationEditable: true, definiteRejectionObserved: true, draftRestored, submissionErrorSafe, retryAfterEditEnabled, retrySubmitted: true, assistantForkActionHidden: true, userForkActionAvailable: true, forkTargetSelected: true, sameAgentOwnership: true, sourceUnchanged: proxyFinish.proxy?.fork?.sourceUnchanged === true, uncertainPromptReplayed: proxyFinish.proxy?.fork?.promptReplayObserved === true, runtimeUnavailableBanner: false, permanentRecovering: false, }, realTurnVerified: false, }, resilience: { setup: resilienceStart.resilience, backgroundLifecycle: { configured: promptDelay.resilience, active: backgroundActive.resilience, hiddenPastGrace: backgroundHidden.resilience, idleEvicted: backgroundIdle.resilience, uiPromptSubmitted: true, hostConfirmationUncertain: true, answerVisibleAfterShow: true, composerUnlocked: true, }, delayedCompact: { configured: compactDelay.resilience, uncertain: compactUncertain.resilience, settled: compactSettled.resilience, overlappingMutationBlocked: true, runtimeUnavailableBanner: false, composerUnlocked: true, }, intentionalDispose: { active: intentionalActive.resilience, disposed: intentionalDispose.resilience, recovered: recoveredAfterDispose.resilience, siblingContinued: true, uncertainPromptReplayed: false, }, active: activeResilience.resilience, exit: exitFailure.resilience, abortAfterExit: abortAfterExit.resilience, releasedAfterExit: releasedAfterExit.resilience, protocol: { active: protocolActive.resilience, failure: protocolFailure.resilience, }, settledBeforeClose: { settled: settledBeforeClose.resilience, close: settledClose.resilience, }, completed: resilienceFinish.resilience, ui: { terminalErrorVisible: true, composerUnlocked: true, recoverAvailable: true, uncertainPromptReplayed: false, }, realTurnVerified: false, }, cleanExit: { trackedProcessIds: proofProcessIds, lingeringProcessIds, }, result: 'pass', }; if (options.reportPath) { await mkdir(dirname(options.reportPath), { recursive: true }); await writeFile(options.reportPath, `${JSON.stringify(report, null, 2)}\n`); } return report; } finally { if (electronApplication && pressureActive) { await evaluateProof(electronApplication, 'pressure.finish').catch(() => undefined); } if (electronApplication && proxyActive) { await evaluateProof(electronApplication, 'proxy.release-child').catch(() => undefined); await evaluateProof(electronApplication, 'proxy.finish').catch(() => undefined); } if (electronApplication && resilienceActive) { await evaluateProof(electronApplication, 'resilience.release-parents').catch(() => undefined); await evaluateProof(electronApplication, 'resilience.finish').catch(() => undefined); } if (electronApplication) await closeApplication(electronApplication); await rm(scratchRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 }); } } async function main() { const options = parseArgs(process.argv.slice(2)); const report = await runPackagedProductProof(options); process.stdout.write(`${JSON.stringify(report, null, 2)}\n`); } const isMain = process.argv[1] && pathToFileURL(resolve(process.argv[1])).href === import.meta.url; if (isMain) { main().catch((error) => { process.stderr.write(`${error.stack ?? error.message}\n`); process.exitCode = 1; }); }