// Isolated production YCode verification for N01, N03 and N07. // No remote model request, notification fetch, or system integration is performed. const fs = require('node:fs/promises') const path = require('node:path') const assert = require('node:assert/strict') if (!process.versions.electron) { ;(async () => { const directory = await fs.mkdtemp(path.resolve('.tmp/seven-ui-fixes-')) const data = path.join(directory, 'data') const home = path.join(directory, 'home') const workspace = path.join(directory, 'workspace') await Promise.all([ fs.mkdir(data, { recursive: true }), fs.mkdir(home, { recursive: true }), fs.mkdir(workspace, { recursive: true }) ]) const now = Date.now() const modelId = 'seven-ui-model' const workspaceId = 'seven-ui-workspace' const sessionId = 'seven-ui-session' await fs.writeFile(path.join(data, 'models.json'), JSON.stringify({ version: 1, selectedModelId: modelId, models: [{ id: modelId, name: 'UI Fixture Model', providerId: 'custom', model: 'fixture-model', baseUrl: 'http://127.0.0.1:1/v1', authMode: 'none', supportsToolCall: false }] })) await fs.writeFile(path.join(data, 'workspaces.json'), JSON.stringify({ selectedWorkspaceId: workspaceId, workspaces: [{ id: workspaceId, name: 'Seven UI Fixture', root: workspace, createdAt: now }] })) await fs.writeFile(path.join(data, 'sessions.json'), JSON.stringify({ sessions: [{ id: sessionId, title: '七项 UI 修复验收', cwd: workspace, workspaceId, modelId, createdAt: now, updatedAt: now, messages: [ { id: 'seven-ui-user', role: 'user', content: '只做本地 UI 验收', createdAt: now - 1, status: 'done' }, { id: 'seven-ui-assistant', role: 'assistant', content: '已准备本地 UI 验证。', createdAt: now, status: 'done', parts: [], tools: [] } ] }] })) const env = { ...process.env, YCODE_QA_DIRECTORY: directory, YCODE_USER_DATA_DIR: data, YCODE_DISABLE_GPU: '1', YCODE_QA_OFFSCREEN: '1', YCODE_DISABLE_SYSTEM_INTEGRATION: '1' } delete env.ELECTRON_RUN_AS_NODE delete env.ELECTRON_RENDERER_URL const child = require('node:child_process').spawn( require('electron'), ['--no-sandbox', '--disable-gpu-sandbox', __filename], { env, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] } ) let log = '' child.stdout.on('data', (bytes) => { log += bytes if (bytes.toString().includes('SEVEN_UI_FIXES_')) process.stdout.write(bytes) }) child.stderr.on('data', (bytes) => { log += bytes }) const timer = setTimeout(() => child.kill(), 180_000) child.once('exit', async (code) => { clearTimeout(timer) await fs.writeFile(path.join(directory, 'process.log'), log) console.log(JSON.stringify({ directory, exitCode: code })) if (code) console.error(log.slice(-12_000)) process.exitCode = code ?? 1 }) })().catch((error) => { console.error(error) process.exitCode = 1 }) } else { const { app, BrowserWindow } = require('electron') const { pathToFileURL } = require('node:url') const directory = process.env.YCODE_QA_DIRECTORY const data = process.env.YCODE_USER_DATA_DIR assert.ok(directory) assert.ok(data) const relative = path.relative(path.resolve('.tmp'), directory) assert.ok(relative.startsWith('seven-ui-fixes-') && !relative.includes(path.sep)) app.setPath('userData', data) app.setPath('sessionData', data) app.setPath('home', path.join(directory, 'home')) let main let phase = 'boot' const checks = [] const geometry = {} const snapshots = {} const screenshots = [] const rendererErrors = [] const pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) async function read(source) { let timer try { return await Promise.race([ main.webContents.executeJavaScript(source), new Promise((_, reject) => { timer = setTimeout(() => reject(new Error(`Renderer timeout: ${source.slice(0, 140)}`)), 20_000) }) ]) } finally { clearTimeout(timer) } } async function wait(source, label) { for (let index = 0; index < 400; index += 1) { const result = await read(source) if (result) return result await pause(40) } throw new Error(`Timeout: ${label}`) } async function step(label) { phase = label await fs.writeFile(path.join(directory, 'phase.txt'), label) } function check(id, label, actual, expected) { const pass = typeof expected === 'function' ? Boolean(expected(actual)) : JSON.stringify(actual) === JSON.stringify(expected) checks.push({ id, label, pass, actual, expected: typeof expected === 'function' ? expected.toString() : expected }) } function opaqueColor(value) { if (!value || value === 'transparent') return false const match = /^rgba?\((.+)\)$/i.exec(value) if (!match) return true const parts = match[1].split(',').map((part) => part.trim()) return parts.length < 4 || Number(parts[3]) >= 0.999 } function insideViewport(box, viewport) { return box[0] >= -0.5 && box[1] >= -0.5 && box[0] + box[2] <= viewport.width + 0.5 && box[1] + box[3] <= viewport.height + 0.5 } async function capture(name) { await pause(160) const image = (await main.webContents.capturePage()).toPNG() const filename = `${name}.png` await fs.writeFile(path.join(directory, filename), image) screenshots.push(filename) } async function setTheme(theme) { await read(`(() => { localStorage.setItem('ycode:theme', ${JSON.stringify(theme)}) window.dispatchEvent(new StorageEvent('storage', { key: 'ycode:theme', newValue: ${JSON.stringify(theme)} })) return true })()`) await wait( `document.documentElement.dataset.theme === ${JSON.stringify(theme)}`, `${theme} theme` ) await pause(180) } async function pressEscape() { await read(`(() => { document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', code: 'Escape', bubbles: true, cancelable: true })) return true })()`) } async function verifyProjectMenu(theme) { await setTheme(theme) await step(`N01-project-menu-${theme}`) const trigger = await read(`(() => { const node = document.querySelector('.conversation-list-tab-button-more') if (!node) return null node.click() return true })()`) assert.ok(trigger, 'project menu trigger') await wait(`!!document.querySelector('.yc-project-more')`, 'project menu') const snapshot = await read(`(() => { const menu = document.querySelector('.yc-project-more') const style = getComputedStyle(menu) const rect = menu.getBoundingClientRect() return { box: [rect.x, rect.y, rect.width, rect.height], background: style.backgroundColor, opacity: style.opacity, parentIsBody: menu.parentElement === document.body, viewport: { width: innerWidth, height: innerHeight }, text: menu.textContent } })()`) snapshots[`projectMenu-${theme}`] = snapshot geometry[`projectMenu-${theme}`] = snapshot check(`n01-${theme}-background`, 'project menu uses an opaque theme surface', opaqueColor(snapshot.background), true) check(`n01-${theme}-viewport`, 'project menu stays inside the viewport', insideViewport(snapshot.box, snapshot.viewport), true) check(`n01-${theme}-portal`, 'project menu is portaled to body', snapshot.parentIsBody, true) check(`n01-${theme}-visible`, 'project menu is fully visible', snapshot.opacity, '1') await capture(`n01-project-menu-${theme}`) await pressEscape() await wait(`!document.querySelector('.yc-project-more')`, 'project menu closes') } async function verifyNotifications(theme, closeWithEscape) { await setTheme(theme) await step(`N03-notifications-${theme}`) await read(`document.querySelector('.user-menu-trigger-msg-center').click()`) await wait( `!!document.querySelector('.notif-panel[data-positioned="true"]')`, 'notification panel' ) const snapshot = await read(`(() => { const panel = document.querySelector('.notif-panel') const bell = document.querySelector('.user-menu-trigger-msg-center') const style = getComputedStyle(panel) const rect = panel.getBoundingClientRect() const points = [ [rect.left + rect.width * 0.25, rect.top + rect.height * 0.25], [rect.left + rect.width * 0.75, rect.top + rect.height * 0.25], [rect.left + rect.width * 0.5, rect.top + rect.height * 0.5], [rect.left + rect.width * 0.5, rect.top + rect.height * 0.75] ] return { box: [rect.x, rect.y, rect.width, rect.height], background: style.backgroundColor, opacity: style.opacity, parentIsBody: panel.parentElement === document.body, viewport: { width: innerWidth, height: innerHeight }, bellExpanded: bell.getAttribute('aria-expanded'), bellControls: bell.getAttribute('aria-controls'), unobstructed: points.every(([x, y]) => { const hit = document.elementFromPoint(x, y) return !!hit && panel.contains(hit) }) } })()`) snapshots[`notifications-${theme}`] = snapshot geometry[`notifications-${theme}`] = snapshot check(`n03-${theme}-background`, 'notification panel uses an opaque theme surface', opaqueColor(snapshot.background), true) check(`n03-${theme}-viewport`, 'notification panel stays inside the viewport', insideViewport(snapshot.box, snapshot.viewport), true) check(`n03-${theme}-portal`, 'notification panel is portaled to body', snapshot.parentIsBody, true) check(`n03-${theme}-unobstructed`, 'notification content is not covered', snapshot.unobstructed, true) check(`n03-${theme}-aria`, 'bell exposes the open dialog state', snapshot.bellExpanded, 'true') check(`n03-${theme}-controls`, 'bell controls the notification dialog', snapshot.bellControls, 'ycode-notifications-panel') await capture(`n03-notifications-${theme}`) if (closeWithEscape) await pressEscape() else await read(`document.querySelector('.notif-panel__close').click()`) await wait(`!document.querySelector('.notif-panel')`, 'notification panel closes') await pause(80) check( `n03-${theme}-focus`, 'closing the notification restores bell focus', await read(`document.activeElement?.classList.contains('user-menu-trigger-msg-center')`), true ) check( `n03-${theme}-closed`, 'bell reports the closed state', await read(`document.querySelector('.user-menu-trigger-msg-center').getAttribute('aria-expanded')`), 'false' ) } async function openPermissionPanel() { const opened = await read(`(() => { const trigger = [...document.querySelectorAll('.cr-permission-setting')] .find((node) => node.offsetParent !== null) if (!trigger) return false trigger.click() return true })()`) assert.ok(opened, 'visible permission trigger') await wait(`!!document.querySelector('.cr-permission-setting-popover .cr-permission-panel')`, 'permission panel') } async function verifyPermissionPanel(theme) { await setTheme(theme) await step(`N07-permission-panel-${theme}`) await openPermissionPanel() const snapshot = await read(`(() => { const popover = document.querySelector('.cr-permission-setting-popover') const panel = popover.querySelector('.cr-permission-panel') const description = panel.querySelector('.cr-permission-panel__desc') const rect = panel.getBoundingClientRect() const style = getComputedStyle(panel) const trigger = [...document.querySelectorAll('.cr-permission-setting')] .find((node) => node.offsetParent !== null) return { box: [rect.x, rect.y, rect.width, rect.height], popoverWidth: popover.getBoundingClientRect().width, triggerLeft: trigger.getBoundingClientRect().left, viewport: { width: innerWidth, height: innerHeight }, background: style.backgroundColor, opacity: style.opacity, outsideComposer: !document.querySelector('.conversation-input')?.contains(popover) && !document.querySelector('.chat-pane')?.contains(popover), role: panel.getAttribute('role'), switchCount: panel.querySelectorAll('[role="switch"]').length, rowCount: panel.querySelectorAll('.cr-permission-panel__row').length, description: description?.textContent ?? '', triggerLabel: trigger?.querySelector('.cr-input-footer-item__label')?.textContent ?? '' } })()`) snapshots[`permissionPanel-${theme}`] = snapshot geometry[`permissionPanel-${theme}`] = snapshot check(`n07-${theme}-width`, 'permission panel keeps the recovered 200px width', Math.round(snapshot.box[2]), 200) check(`n07-${theme}-outer-width`, 'permission popover adds no second padded surface', Math.round(snapshot.popoverWidth), 200) check(`n07-${theme}-alignment`, 'permission panel starts at the trigger edge', Math.abs(snapshot.box[0] - snapshot.triggerLeft) < 1, true) check(`n07-${theme}-background`, 'permission panel uses an opaque theme surface', opaqueColor(snapshot.background), true) check(`n07-${theme}-viewport`, 'permission panel stays inside the viewport', insideViewport(snapshot.box, snapshot.viewport), true) check(`n07-${theme}-portal`, 'permission panel is outside the composer portal ancestor', snapshot.outsideComposer, true) check(`n07-${theme}-switch-count`, 'permission panel has one full-access switch', snapshot.switchCount, 1) check(`n07-${theme}-row-count`, 'permission panel has one permission row', snapshot.rowCount, 1) check( `n07-${theme}-description`, 'permission panel describes local default permissions without promising an OS sandbox', snapshot.description, '当前为默认权限,所有操作都会在默认权限约束内进行,超出范围会请求你的允许。' ) check(`n07-${theme}-default-label`, 'permission trigger defaults to 默认权限', snapshot.triggerLabel, '默认权限') await capture(`n07-permission-panel-${theme}`) await pressEscape() await wait(`!document.querySelector('.cr-permission-setting-popover')`, 'permission panel closes') } async function openPermissionConfirmation() { if (!(await read(`(() => { const panel = document.querySelector('.cr-permission-setting-popover .cr-permission-panel') return !!panel && panel.getClientRects().length > 0 })()`))) { await openPermissionPanel() } await read(`document.querySelector('.cr-permission-setting-popover .wb-switch__input').click()`) await wait(`!!document.querySelector('.permission-confirm-dialog')`, 'permission confirmation') } async function verifyPermissionConfirmation(theme) { await setTheme(theme) await step(`N07-permission-confirm-${theme}`) await openPermissionConfirmation() const snapshot = await read(`(() => { const dialog = document.querySelector('.permission-confirm-dialog') const style = getComputedStyle(dialog) const overlay = dialog.closest('.wb-modal__overlay') const popover = document.querySelector('.cr-permission-setting-popover') const panel = popover?.querySelector('.cr-permission-panel') const overlayZIndex = overlay ? Number(getComputedStyle(overlay).zIndex) : Number.NaN const panelZIndex = popover ? Number(getComputedStyle(popover).zIndex) : Number.NaN const rect = dialog.getBoundingClientRect() const buttons = [...dialog.querySelectorAll('button')] const confirm = buttons.find((button) => button.textContent.trim() === '允许完全访问') const cancel = buttons.find((button) => button.textContent.trim() === '取消') return { box: [rect.x, rect.y, rect.width, rect.height], viewport: { width: innerWidth, height: innerHeight }, background: style.backgroundColor, overlayZIndex, panelZIndex, modalAbovePanel: Number.isFinite(overlayZIndex) && Number.isFinite(panelZIndex) && overlayZIndex > panelZIndex, description: dialog.querySelector('.cr-permission-confirm__desc')?.textContent ?? '', acknowledgement: dialog.querySelector('.permission-confirm-acknowledgement')?.checked ?? null, confirmDisabled: confirm?.disabled ?? null, confirmDanger: confirm?.classList.contains('wb-composer__danger-button') ?? false, hasCancel: !!cancel, panelOpen: !!panel && panel.getClientRects().length > 0, outsideComposer: !document.querySelector('.conversation-input')?.contains(dialog) && !document.querySelector('.chat-pane')?.contains(dialog), triggerLabel: [...document.querySelectorAll('.cr-permission-setting')] .find((node) => node.offsetParent !== null) ?.querySelector('.cr-input-footer-item__label')?.textContent ?? '' } })()`) snapshots[`permissionConfirm-${theme}`] = snapshot geometry[`permissionConfirm-${theme}`] = snapshot check(`n07-${theme}-confirm-width`, 'permission confirmation keeps the recovered 480px width', Math.round(snapshot.box[2]), 480) check(`n07-${theme}-confirm-viewport`, 'permission confirmation stays inside the viewport', insideViewport(snapshot.box, snapshot.viewport), true) check(`n07-${theme}-confirm-background`, 'permission confirmation uses an opaque surface', opaqueColor(snapshot.background), true) check(`n07-${theme}-confirm-portal`, 'permission confirmation is outside the composer portal ancestor', snapshot.outsideComposer, true) check(`n07-${theme}-confirm-layer`, 'permission confirmation uses the recovered body portal layer', snapshot.overlayZIndex, 100001) check(`n07-${theme}-confirm-above-panel`, 'permission confirmation stays above the open panel', snapshot.modalAbovePanel, true) check(`n07-${theme}-panel-remains-open`, 'permission panel remains open behind confirmation', snapshot.panelOpen, true) check(`n07-${theme}-confirm-description`, 'permission confirmation states the implemented task scope', snapshot.description, '开启完全访问后,当前发送的任务将减少确认步骤并直接操作您的电脑,请谨慎操作。包括以下内容:') check(`n07-${theme}-ack-empty`, 'risk acknowledgement starts unchecked', snapshot.acknowledgement, false) check(`n07-${theme}-danger-disabled`, 'full-access confirmation is disabled before acknowledgement', snapshot.confirmDisabled, true) check(`n07-${theme}-danger-button`, 'full-access confirmation uses the dangerous action button', snapshot.confirmDanger, true) check(`n07-${theme}-cancel`, 'permission confirmation exposes cancel', snapshot.hasCancel, true) await capture(`n07-permission-confirm-${theme}`) await read(`(() => { const dialog = document.querySelector('.permission-confirm-dialog') const cancel = [...dialog.querySelectorAll('button')] .find((button) => button.textContent.trim() === '取消') cancel.click() return true })()`) await wait(`!document.querySelector('.permission-confirm-dialog')`, 'permission confirmation closes') check(`n07-${theme}-cancel-keeps-default`, 'cancelling confirmation keeps default permission', await read(`(() => { const trigger = [...document.querySelectorAll('.cr-permission-setting')] .find((node) => node.offsetParent !== null) return { label: trigger.querySelector('.cr-input-footer-item__label').textContent, danger: trigger.classList.contains('cr-permission-setting--danger') } })()`), { label: '默认权限', danger: false }) const panelAfterCancel = await read(`(() => { const panel = document.querySelector('.cr-permission-setting-popover .cr-permission-panel') return !!panel && panel.getClientRects().length > 0 })()`) check(`n07-${theme}-cancel-panel-open`, 'cancelling confirmation keeps the permission panel open', panelAfterCancel, true) check(`n07-${theme}-cancel-label`, 'default label remains after cancellation', snapshot.triggerLabel, '默认权限') await read(`document.querySelector('.cr-permission-setting-popover .wb-switch__input').click()`) await wait(`!!document.querySelector('.permission-confirm-dialog')`, 'permission confirmation reopens from the same panel') const reopened = await read(`(() => { const dialog = document.querySelector('.permission-confirm-dialog') const acknowledgement = dialog.querySelector('.permission-confirm-acknowledgement') const confirm = [...dialog.querySelectorAll('button')] .find((button) => button.textContent.trim() === '允许完全访问') const panel = document.querySelector('.cr-permission-setting-popover .cr-permission-panel') return { panelOpen: !!panel && panel.getClientRects().length > 0, acknowledgement: acknowledgement?.checked ?? null, confirmDisabled: confirm?.disabled ?? null } })()`) snapshots[`permissionConfirmReopened-${theme}`] = reopened check(`n07-${theme}-cancel-direct-reopen`, 'the switch can reopen confirmation without reopening the trigger', reopened.panelOpen, true) check(`n07-${theme}-reopen-ack-empty`, 'reopened confirmation still requires risk acknowledgement', reopened.acknowledgement, false) check(`n07-${theme}-reopen-disabled`, 'reopened confirmation stays disabled until risk acknowledgement', reopened.confirmDisabled, true) await read(`(() => { const dialog = document.querySelector('.permission-confirm-dialog') const cancel = [...dialog.querySelectorAll('button')] .find((button) => button.textContent.trim() === '取消') cancel.click() return true })()`) await wait(`!document.querySelector('.permission-confirm-dialog')`, 'permission confirmation closes after direct reopen') await pressEscape() await wait(`!document.querySelector('.cr-permission-setting-popover')`, 'permission panel closes after cancellation checks') } async function verifyFullAccessRoundTrip() { await setTheme('light') await step('N07-full-access-confirm') await openPermissionConfirmation() const confirmation = await read(`(() => { const dialog = document.querySelector('.permission-confirm-dialog') const acknowledgement = dialog.querySelector('.permission-confirm-acknowledgement') acknowledgement.click() const confirm = [...dialog.querySelectorAll('button')] .find((button) => button.textContent.trim() === '允许完全访问') return { acknowledgement: acknowledgement.checked, enabled: !confirm.disabled } })()`) snapshots.fullAccessConfirmation = confirmation check('n07-full-ack-checked', 'acknowledging the risk checks the source checkbox', confirmation.acknowledgement, true) check('n07-full-confirm-enabled', 'acknowledgement enables full-access confirmation', confirmation.enabled, true) await capture('n07-full-access-acknowledged') await read(`(() => { const dialog = document.querySelector('.permission-confirm-dialog') const confirm = [...dialog.querySelectorAll('button')] .find((button) => button.textContent.trim() === '允许完全访问') confirm.click() return true })()`) await wait(`(() => { const trigger = [...document.querySelectorAll('.cr-permission-setting')] .find((node) => node.offsetParent !== null) return trigger?.classList.contains('cr-permission-setting--danger') && trigger.querySelector('.cr-input-footer-item__label')?.textContent === '允许完全访问' })()`, 'full-access mode') check('n07-full-dialog-closed', 'confirming full access closes the dialog', await read(`!document.querySelector('.permission-confirm-dialog')`), true) check('n07-full-panel-closed', 'confirming full access closes the permission panel', await read(`!document.querySelector('.cr-permission-setting-popover')`), true) snapshots.fullAccess = await read(`(() => { const trigger = [...document.querySelectorAll('.cr-permission-setting')] .find((node) => node.offsetParent !== null) return { label: trigger.querySelector('.cr-input-footer-item__label')?.textContent, danger: trigger.classList.contains('cr-permission-setting--danger') } })()`) check('n07-full-label', 'full access updates the visible trigger', snapshots.fullAccess, { label: '允许完全访问', danger: true }) await capture('n07-full-access') await step('N07-restore-default') await openPermissionPanel() const reopened = await read(`(() => ({ switchCount: document.querySelectorAll('.cr-permission-setting-popover [role="switch"]').length, checked: document.querySelector('.cr-permission-setting-popover .wb-switch__input').checked }))()`) snapshots.fullAccessReopened = reopened check('n07-full-reopen-switch', 'reopened permission panel shows one enabled full-access switch', reopened, { switchCount: 1, checked: true }) await read(`document.querySelector('.cr-permission-setting-popover .wb-switch__input').click()`) await wait(`!document.querySelector('.cr-permission-setting-popover')`, 'permission panel closes after restoring default') await wait(`(() => { const trigger = [...document.querySelectorAll('.cr-permission-setting')] .find((node) => node.offsetParent !== null) return trigger.querySelector('.cr-input-footer-item__label')?.textContent === '默认权限' && !trigger.classList.contains('cr-permission-setting--danger') })()`, 'default permission restored') snapshots.restoredDefault = await read(`(() => { const trigger = [...document.querySelectorAll('.cr-permission-setting')] .find((node) => node.offsetParent !== null) return { label: trigger.querySelector('.cr-input-footer-item__label')?.textContent, danger: trigger.classList.contains('cr-permission-setting--danger') } })()`) check('n07-default-restored', 'turning the reopened switch off restores default permission', snapshots.restoredDefault, { label: '默认权限', danger: false }) await capture('n07-default-restored') } ;(async () => { await import(pathToFileURL(path.resolve('out/main/index.mjs')).href) await app.whenReady() for (let index = 0; index < 300; index += 1) { main = BrowserWindow.getAllWindows().find((window) => window.getTitle() === 'YCode') if (main && !main.webContents.isLoading()) break await pause(40) } assert.ok(main, 'YCode main window') main.setSize(1336, 902) main.showInactive() main.webContents.on('console-message', (...args) => { const event = args[0] const level = typeof event === 'object' ? event.level : args[1] const message = typeof event === 'object' ? event.message : args[2] if (level === 'error' || Number(level) >= 3) rendererErrors.push(message) }) await wait( `!!window.ycode && !!document.querySelector('.sidebar') && !!document.querySelector('.chat-pane')`, 'isolated production renderer' ) await read(`document.querySelector('[data-session-id="seven-ui-session"]')?.click()`) await wait( `(() => { const trigger = [...document.querySelectorAll('.cr-permission-setting')] .find((node) => node.offsetParent !== null) return !!trigger })()`, 'visible permission setting' ) await verifyProjectMenu('light') await verifyNotifications('light', false) await verifyPermissionPanel('light') await verifyPermissionConfirmation('light') await verifyProjectMenu('dark') await verifyNotifications('dark', true) await verifyPermissionPanel('dark') await verifyPermissionConfirmation('dark') await verifyFullAccessRoundTrip() check('console-errors', 'renderer has no console errors', rendererErrors, []) const report = { result: checks.every((item) => item.pass) ? 'PASS' : 'FAIL', scope: 'Isolated production YCode renderer/preload/IPC with local model, workspace and session fixtures. No remote model, notification, connector, or system requests are issued.', fixture: { directory, modelId: 'seven-ui-model', workspaceId: 'seven-ui-workspace', sessionId: 'seven-ui-session', viewport: await read(`({ width: innerWidth, height: innerHeight, theme: document.documentElement.dataset.theme })`) }, sourceEvidence: [ 'ev_d1a438b97437b2f6a98f5dddcc5c3385184e24a439c5a351365fbbefc39e457d', 'ev_f5e9d71a676c453daab40928acfb33aeabae68ba57ffda342380cead7f1a1fe2', 'ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94', 'ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb' ], checks, snapshots, geometry, screenshots, rendererErrors, limitations: [ 'The local model fixture is deliberately unreachable and no model request is made.', 'Notification content remains mock data; this verifier checks the shell, portal, geometry, and close behavior.', 'Project menu still contains only the currently implemented Project entry.' ] } await fs.writeFile(path.join(directory, 'report.json'), JSON.stringify(report, null, 2)) console.log(`SEVEN_UI_FIXES_${report.result} ${directory}`) for (const failure of checks.filter((item) => !item.pass)) { console.log(`SEVEN_UI_FIXES_FAILURE ${JSON.stringify(failure)}`) } app.exit(report.result === 'PASS' ? 0 : 1) })().catch(async (error) => { if (main && !main.isDestroyed()) { await fs.writeFile( path.join(directory, 'failure.png'), (await main.webContents.capturePage()).toPNG() ).catch(() => undefined) } await fs.writeFile(path.join(directory, 'failure.json'), JSON.stringify({ phase, error: String(error?.stack || error), checks, snapshots, geometry, rendererErrors }, null, 2)).catch(() => undefined) console.error(error) app.exit(1) }) }