Files
llm-atlas/scripts/check-k3-attnres-local-path-browser.mjs
T
2026-07-30 14:35:48 +08:00

293 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { writeFileSync } from "node:fs";
const cdpPort = process.env.CDP_PORT ?? "9230";
const baseUrl = process.env.SITE_URL ?? "http://127.0.0.1:4329";
const pages = await fetch(`http://127.0.0.1:${cdpPort}/json/list`).then((response) => response.json());
const page = pages.find((entry) => entry.type === "page");
if (!page) throw new Error(`CDP ${cdpPort} 没有可用页面`);
const socket = new WebSocket(page.webSocketDebuggerUrl);
await new Promise((resolve, reject) => {
socket.addEventListener("open", resolve, { once: true });
socket.addEventListener("error", reject, { once: true });
});
let nextId = 0;
const pending = new Map();
const exceptions = [];
socket.addEventListener("message", (event) => {
const message = JSON.parse(event.data);
if (message.id && pending.has(message.id)) {
const { resolve, reject } = pending.get(message.id);
pending.delete(message.id);
if (message.error) reject(new Error(message.error.message));
else resolve(message.result);
}
if (message.method === "Runtime.exceptionThrown") {
exceptions.push(message.params.exceptionDetails.exception?.description ?? message.params.exceptionDetails.text);
}
});
const command = (method, params = {}) => new Promise((resolve, reject) => {
const id = ++nextId;
pending.set(id, { resolve, reject });
socket.send(JSON.stringify({ id, method, params }));
});
const pause = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
const evaluate = async (expression) => {
const result = await command("Runtime.evaluate", { expression, returnByValue: true, awaitPromise: true });
if (result.exceptionDetails) throw new Error(result.exceptionDetails.exception?.description ?? result.exceptionDetails.text);
return result.result.value;
};
const navigate = async (path) => {
await command("Page.navigate", { url: `${baseUrl}${path}` });
for (let attempt = 0; attempt < 100; attempt += 1) {
await pause(100);
if (await evaluate("document.readyState === 'complete'")) return;
}
throw new Error(`${path} 加载超时`);
};
const screenshot = async (path) => {
const result = await command("Page.captureScreenshot", { format: "png", captureBeyondViewport: false });
writeFileSync(path, Buffer.from(result.data, "base64"));
};
await command("Page.enable");
await command("Runtime.enable");
await command("Emulation.setDeviceMetricsOverride", {
width: 1440,
height: 1100,
deviceScaleFactor: 1,
mobile: false,
});
await navigate("/k3/");
const desktop = await evaluate(`(() => {
const root = document.querySelector("[data-local-path-lab]");
root.scrollIntoView({ block: "start", behavior: "instant" });
window.scrollBy(0, -78);
const text = (selector) => root.querySelector(selector)?.textContent.trim();
const panel = () => root.querySelector("[data-local-panel]:not([hidden])")?.dataset.localPanel;
const setSelect = (selector, value) => {
const node = root.querySelector(selector);
node.value = value;
node.dispatchEvent(new Event("change", { bubbles: true }));
};
const findMatrix = (needle) => [...root.querySelectorAll(".matrix-bars article")]
.find((node) => node.textContent.includes(needle))?.textContent.replace(/\\s+/g, " ").trim();
const initial = {
panel: panel(),
tabs: root.querySelectorAll("[data-local-tab]").length,
panels: root.querySelectorAll("[data-local-panel]").length,
ledger: root.querySelectorAll(".local-ledger article").length,
groups: root.querySelectorAll(".group-map article.target").length,
spikeLayers: root.querySelectorAll(".group-map i.spike").length,
boundary: root.textContent.includes("LOCALIZATION NOT ESTABLISHED") &&
root.textContent.includes("不是贡献率") &&
root.textContent.includes("不是 K3 checkpoint"),
};
root.querySelector('[data-local-tab="matrix"]').click();
const matrixInitial = {
panel: panel(),
rows: root.querySelectorAll(".matrix-bars article").length,
state: text("[data-local-matrix-state]"),
group67: findMatrix("仅 Groups 6+7 uniform"),
restoration67: findMatrix("恢复 Groups 6+7"),
};
setSelect("[data-local-matrix-seed]", "2026073002");
root.querySelector('[data-local-matrix-metric="peak_normalized"]').click();
const matrixChanged = {
rows: root.querySelectorAll(".matrix-bars article").length,
state: text("[data-local-matrix-state]"),
group67: findMatrix("仅 Groups 6+7 uniform"),
restoration67: findMatrix("恢复 Groups 6+7"),
};
root.querySelector('[data-local-tab="dual"]').click();
const dual = {
panel: panel(),
rows: root.querySelectorAll(".dual-table tbody tr").length,
good: root.querySelectorAll(".dual-table td.good").length,
bad: root.querySelectorAll(".dual-table td.bad").length,
verdict: text(".verdict-banner"),
mean: root.querySelector(".dual-table tr.mean")?.textContent.replace(/\\s+/g, " ").trim(),
};
root.querySelector('[data-local-tab="branch"]').click();
const branchInitial = {
panel: panel(),
state: text("[data-local-branch-state]"),
values: [...root.querySelectorAll("[data-local-branch-value]")].map((node) => node.textContent.trim()),
passed: root.dataset.branchPassed,
};
root.querySelector('[data-local-branch-group="7"]').click();
const branchChanged = {
state: text("[data-local-branch-state]"),
values: [...root.querySelectorAll("[data-local-branch-value]")].map((node) => node.textContent.trim()),
labels: [...root.querySelectorAll("[data-local-branch-label]")].map((node) => node.textContent.trim()),
passed: root.dataset.branchPassed,
};
root.querySelector('[data-local-tab="spectrum"]').click();
const spectrumInitial = {
panel: panel(),
points: root.querySelectorAll("[data-local-spectrum-points] circle").length,
line: root.querySelector("[data-local-spectrum-line]").getAttribute("points"),
state: text("[data-local-spectrum-state]"),
count: text("[data-local-spectrum-count]"),
contrast: text("[data-local-spectrum-contrast]"),
peak: text("[data-local-spectrum-peak]"),
layer: text("[data-local-spectrum-layer]"),
};
setSelect("[data-local-spectrum-seed]", "2026073002");
setSelect("[data-local-spectrum-mode]", "uniform_groups_6_7_only");
const spectrumGroup67 = {
points: root.querySelectorAll("[data-local-spectrum-points] circle").length,
line: root.querySelector("[data-local-spectrum-line]").getAttribute("points"),
state: text("[data-local-spectrum-state]"),
count: text("[data-local-spectrum-count]"),
contrast: text("[data-local-spectrum-contrast]"),
peak: text("[data-local-spectrum-peak]"),
layer: text("[data-local-spectrum-layer]"),
selectedPeakRadius: root.querySelector('[data-local-spectrum-points] circle[data-layer="25"]')?.getAttribute("r"),
};
setSelect("[data-local-spectrum-seed]", "2026073003");
setSelect("[data-local-spectrum-mode]", "uniform_all");
const spectrumAll = {
points: root.querySelectorAll("[data-local-spectrum-points] circle").length,
state: text("[data-local-spectrum-state]"),
count: text("[data-local-spectrum-count]"),
layer: text("[data-local-spectrum-layer]"),
selectedPeakRadius: root.querySelector('[data-local-spectrum-points] circle[data-layer="2"]')?.getAttribute("r"),
};
const first = root.querySelector('[data-local-tab="scope"]');
first.focus();
first.dispatchEvent(new KeyboardEvent("keydown", { key: "ArrowRight", bubbles: true }));
const keyboard = {
selected: root.querySelector('[data-local-tab][aria-selected="true"]').dataset.localTab,
panel: panel(),
};
return {
initial, matrixInitial, matrixChanged, dual, branchInitial, branchChanged,
spectrumInitial, spectrumGroup67, spectrumAll, keyboard,
documentOverflow: document.documentElement.scrollWidth - document.documentElement.clientWidth,
rootOverflow: root.scrollWidth - root.clientWidth,
};
})()`);
await pause(180);
await screenshot("/tmp/llm-atlas-k3-attnres-local-path-desktop.png");
await command("Emulation.setDeviceMetricsOverride", {
width: 390,
height: 844,
deviceScaleFactor: 1,
mobile: true,
});
await navigate("/k3/");
const mobile = await evaluate(`(() => {
const root = document.querySelector("[data-local-path-lab]");
root.scrollIntoView({ block: "start", behavior: "instant" });
window.scrollBy(0, -64);
root.querySelector('[data-local-tab="dual"]').click();
const dual = {
panel: root.querySelector("[data-local-panel]:not([hidden])")?.dataset.localPanel,
rows: root.querySelectorAll(".dual-table tbody tr").length,
wrapperOverflow: root.querySelector(".dual-table-wrap").scrollWidth -
root.querySelector(".dual-table-wrap").clientWidth,
};
root.querySelector('[data-local-tab="spectrum"]').click();
return {
tabs: root.querySelectorAll("[data-local-tab]").length,
ledger: root.querySelectorAll(".local-ledger article").length,
visiblePanel: root.querySelector("[data-local-panel]:not([hidden])")?.dataset.localPanel,
points: root.querySelectorAll("[data-local-spectrum-points] circle").length,
dual,
documentOverflow: document.documentElement.scrollWidth - document.documentElement.clientWidth,
rootOverflow: root.scrollWidth - root.clientWidth,
};
})()`);
await pause(180);
await screenshot("/tmp/llm-atlas-k3-attnres-local-path-mobile.png");
const report = { desktop, mobile, exceptions };
console.log(JSON.stringify(report, null, 2));
const numeric = (value) => Number.parseFloat(value.replace("−", "-").replace("×", ""));
const failures = [];
if (desktop.initial.panel !== "scope" || desktop.initial.tabs !== 5 || desktop.initial.panels !== 5 ||
desktop.initial.ledger !== 6 || desktop.initial.groups !== 2 || desktop.initial.spikeLayers !== 5) {
failures.push("五视图、六项账本或预注册路径地图结构异常");
}
if (!desktop.initial.boundary) failures.push("localization / contribution / reduced-model claim boundary 缺失");
if (desktop.matrixInitial.panel !== "matrix" || desktop.matrixInitial.rows !== 14 ||
!desktop.matrixInitial.state.includes("3-SEED MEAN") ||
!desktop.matrixInitial.group67.includes("+0.677") ||
!desktop.matrixInitial.restoration67.includes("+0.650")) {
failures.push("14-mask mean contrast 矩阵异常");
}
if (desktop.matrixChanged.rows !== 14 || !desktop.matrixChanged.state.includes("2026073002") ||
!desktop.matrixChanged.state.includes("PEAK / MEAN") ||
!desktop.matrixChanged.group67.includes("+1.783") ||
!desktop.matrixChanged.restoration67.includes("+0.355")) {
failures.push("matrix seed / metric 切换异常");
}
if (desktop.dual.panel !== "dual" || desktop.dual.rows !== 4 || desktop.dual.good !== 9 ||
desktop.dual.bad !== 6 || !desktop.dual.verdict.includes("LOCALIZATION NOT ESTABLISHED") ||
!desktop.dual.mean.includes("0.677") || !desktop.dual.mean.includes("0.380") ||
!desktop.dual.mean.includes("3 / 6")) {
failures.push("双向主门表格或冻结判定异常");
}
if (desktop.branchInitial.panel !== "branch" || desktop.branchInitial.passed !== "false" ||
!desktop.branchInitial.state.includes("5 / 6") ||
desktop.branchChanged.passed !== "true" || !desktop.branchChanged.state.includes("6 / 6 PASS") ||
desktop.branchChanged.labels.some((value) => value !== "GROUP 7") ||
Math.abs(numeric(desktop.branchChanged.values[0]) - .015) > .001 ||
Math.abs(numeric(desktop.branchChanged.values[1]) - .026) > .001 ||
Math.abs(numeric(desktop.branchChanged.values[2]) - .426) > .001 ||
Math.abs(numeric(desktop.branchChanged.values[3]) - .823) > .001) {
failures.push("group 6 / 7 branch gate 切换异常");
}
if (desktop.spectrumInitial.panel !== "spectrum" || desktop.spectrumInitial.points !== 32 ||
desktop.spectrumInitial.count !== "0 / 65" || numeric(desktop.spectrumInitial.contrast) !== 3.093 ||
numeric(desktop.spectrumInitial.peak) !== 3.241 || desktop.spectrumInitial.layer !== "21") {
failures.push("reference 32 层谱异常");
}
if (desktop.spectrumGroup67.points !== 32 || desktop.spectrumGroup67.line === desktop.spectrumInitial.line ||
!desktop.spectrumGroup67.state.includes("2026073002") ||
desktop.spectrumGroup67.count !== "16 / 65" ||
numeric(desktop.spectrumGroup67.contrast) !== 1.263 ||
numeric(desktop.spectrumGroup67.peak) !== 1.326 ||
desktop.spectrumGroup67.layer !== "25" || desktop.spectrumGroup67.selectedPeakRadius !== "4.5") {
failures.push("groups 6+7 spectrum seed / mode / peak 切换异常");
}
if (desktop.spectrumAll.points !== 32 || desktop.spectrumAll.count !== "65 / 65" ||
desktop.spectrumAll.layer !== "2" || desktop.spectrumAll.selectedPeakRadius !== "4.5") {
failures.push("all-uniform spectrum selector census 或 peak 异常");
}
if (desktop.keyboard.selected !== "matrix" || desktop.keyboard.panel !== "matrix") {
failures.push("键盘 tab 导航异常");
}
if (desktop.documentOverflow > 1 || desktop.rootOverflow > 1 ||
mobile.documentOverflow > 1 || mobile.rootOverflow > 1) {
failures.push("桌面或移动端出现文档级横向溢出");
}
if (mobile.tabs !== 5 || mobile.ledger !== 6 || mobile.visiblePanel !== "spectrum" ||
mobile.points !== 32 || mobile.dual.panel !== "dual" || mobile.dual.rows !== 4 ||
mobile.dual.wrapperOverflow <= 0) {
failures.push("移动端交互结构或局部可滚动表格异常");
}
if (exceptions.length) failures.push(`浏览器异常:${exceptions.join(" | ")}`);
if (failures.length) {
console.error(`\nFAIL\n- ${failures.join("\n- ")}`);
process.exitCode = 1;
} else {
console.log("\nPASS K3 AttnRes local-path browser regression");
}
socket.close();