feat: add DeepSeek Chat behavior evidence

This commit is contained in:
wuyang
2026-07-29 22:47:03 +08:00
parent b615224798
commit 96443d4dfc
18 changed files with 35709 additions and 34 deletions
@@ -0,0 +1,278 @@
import { createHash } from "node:crypto";
import { readFileSync, statSync, writeFileSync } from "node:fs";
import { resolve } from "node:path";
const root = resolve(import.meta.dirname, "..");
const formalPath = resolve(
root,
"src/data/deepseek-v2-lite-chat-behavior.json",
);
const reproPath = resolve(
root,
"src/data/deepseek-v2-lite-chat-behavior-repro-1pd.json",
);
const outputPath = resolve(
root,
"src/data/deepseek-v2-lite-chat-behavior-compact.json",
);
const sha256 = (path) => createHash("sha256")
.update(readFileSync(path))
.digest("hex");
const formal = JSON.parse(readFileSync(formalPath, "utf8"));
const repro = JSON.parse(readFileSync(reproPath, "utf8"));
const formalSha256 = sha256(formalPath);
const reproSha256 = sha256(reproPath);
const formalOutputByKey = new Map(
formal.sources.flatMap((source) => source.outputs.map((output) => [
`${source.id}\0${output.condition}`,
{ source, output },
])),
);
const reproduction = {
sources: repro.sources.length,
cells: 0,
promptHashExact: 0,
generatedTokenIdsExact: 0,
generatedTextExact: 0,
eosStateExact: 0,
};
for (const source of repro.sources) {
for (const output of source.outputs) {
const key = `${source.id}\0${output.condition}`;
const reference = formalOutputByKey.get(key);
if (!reference) throw new Error(`formal output missing: ${key}`);
reproduction.cells += 1;
reproduction.promptHashExact += (
reference.output.prompt_token_ids_sha256
=== output.prompt_token_ids_sha256
);
reproduction.generatedTokenIdsExact += (
JSON.stringify(reference.output.generated_token_ids)
=== JSON.stringify(output.generated_token_ids)
);
reproduction.generatedTextExact += (
reference.output.text === output.text
);
reproduction.eosStateExact += (
reference.output.hit_eos === output.hit_eos
);
}
}
if (
reproduction.cells !== 32
|| reproduction.promptHashExact !== reproduction.cells
|| reproduction.generatedTokenIdsExact !== reproduction.cells
|| reproduction.generatedTextExact !== reproduction.cells
|| reproduction.eosStateExact !== reproduction.cells
) {
throw new Error(
`Chat behavior reproduction mismatch: ${JSON.stringify(reproduction)}`,
);
}
const formalModelHashes = Object.fromEntries(
Object.entries(formal.model.files).map(([name, value]) => [
name,
value.sha256,
]),
);
const reproModelHashes = Object.fromEntries(
Object.entries(repro.model.files).map(([name, value]) => [
name,
value.sha256,
]),
);
if (JSON.stringify(formalModelHashes) !== JSON.stringify(reproModelHashes)) {
throw new Error("formal and reproduction model-file hashes differ");
}
const conditions = formal.generation_contract.conditions;
const edgeOrder = [
"system_eos",
"system_bos",
"system_x",
"system_period",
"bos_at_s0",
"bos_at_s1",
"x_at_s0",
"x_at_s1",
"period_at_s0",
"period_at_s1",
];
const edgeLabels = {
system_eos: "System on − off · EOS",
system_bos: "System on − off · BOS",
system_x: "System on − off · x",
system_period: "System on − off · 句点",
bos_at_s0: "BOS − EOS · system off",
bos_at_s1: "BOS − EOS · system on",
x_at_s0: "x − EOS · system off",
x_at_s1: "x − EOS · system on",
period_at_s0: "句点 − EOS · system off",
period_at_s1: "句点 − EOS · system on",
};
const compactOutput = (output) => ({
condition: output.condition,
factors: output.factors,
promptTokens: output.prompt_tokens,
leftPaddingTokens: output.left_padding_tokens,
promptTokenIdsSha256: output.prompt_token_ids_sha256,
generatedTokens: output.generated_tokens,
generatedTokenIdsSha256: output.generated_token_ids_sha256,
hitEos: output.hit_eos,
stoppedAtMaxNewTokens: output.stopped_at_max_new_tokens,
text: output.text,
textSha256: output.text_sha256,
taskScore: output.task_score,
});
const compact = {
schemaVersion: 1,
source: {
formalSha256,
reproSha256,
formalBytes: statSync(formalPath).size,
reproBytes: statSync(reproPath).size,
reproduction,
},
model: {
repo: formal.model.repo,
revision: formal.model.revision,
checkpointIdentity: formal.model.checkpoint_identity,
architecture: formal.model.architecture,
dtype: formal.model.dtype,
checkpointTensorBytes: formal.model.checkpoint_tensor_bytes,
shardFileBytesIncludingHeaders: (
formal.model.shard_file_bytes_including_headers
),
allFilesSameRevision: (
formal.model.download_revision_contract.all_files_same_revision
),
fileCount: Object.keys(formal.model.files).length,
fileHashes: formalModelHashes,
},
tokenizer: formal.tokenizer_contract,
sources: formal.sources.map((source) => ({
id: source.id,
domain: source.domain,
label: source.label,
withinDomainIndex: source.within_domain_index,
selectionRank: source.selection_rank,
sourceTextSha256: source.source_text_sha256,
sourceCharacters: source.source_characters,
sourceTokens: source.source_tokens,
promptTokensByCondition: source.prompt_tokens_by_condition,
batchPromptTokens: source.batch_prompt_tokens_after_left_padding,
batchPaddingSide: source.batch_padding_side,
outputs: source.outputs.map(compactOutput),
})),
contract: {
source: formal.source_contract,
conditions,
edgeOrder,
edgeLabels,
officialSerialization: (
formal.generation_contract.official_serialization
),
decode: formal.generation_contract.decode,
doSample: formal.generation_contract.do_sample,
maxNewTokens: formal.generation_contract.max_new_tokens,
useCache: formal.generation_contract.use_cache,
batchPadding: formal.generation_contract.batch_padding,
counterfactualBoundary: (
formal.generation_contract.counterfactual_boundary
),
officialGenerationConfigRecordedNotUsed: (
formal.generation_contract
.official_generation_config_recorded_not_used
),
},
execution: {
python: formal.execution.python,
torch: formal.execution.torch,
transformers: formal.execution.transformers,
accelerate: formal.execution.accelerate,
safetensors: formal.execution.safetensors,
gpu: formal.execution.gpu,
gpuMemoryLimit: formal.execution.gpu_memory_limit,
cpuMemoryLimit: formal.execution.cpu_memory_limit,
inputDevice: formal.execution.input_device,
deviceMap: formal.execution.device_map,
parameterBytesByRuntimeParameterDevice: (
formal.execution.parameter_bytes_by_runtime_parameter_device
),
parameterBytesByDtype: formal.execution.parameter_bytes_by_dtype,
offloadParameterDeviceNote: (
formal.execution.offload_parameter_device_note
),
loadSeconds: formal.execution.load_seconds,
generationSeconds: formal.sources.reduce(
(sum, source) => sum + source.generation_seconds,
0,
),
loadPeakCudaMemoryAllocatedBytes: (
formal.execution.load_peak_cuda_memory_allocated_bytes
),
peakCudaMemoryAllocatedBytes: (
formal.execution.peak_cuda_memory_allocated_bytes
),
processMaxRssKib: formal.execution.process_max_rss_kib,
officialSingleGpuBf16Requirement: (
formal.execution.official_single_gpu_bf16_requirement
),
localSingleGpuCapacityMib: (
formal.execution.local_single_gpu_capacity_mib
),
offloadRequiredByLocalCapacity: (
formal.execution.offload_required_by_local_capacity
),
},
summary: {
aggregates: Object.fromEntries(
edgeOrder.map((edge) => [
edge,
formal.summary.aggregates[edge],
]),
),
aggregatesByDomain: formal.summary.aggregates_by_domain,
outputByCondition: formal.summary.output_by_condition,
taskByCondition: formal.summary.task_by_condition,
pairwise: Object.fromEntries(
edgeOrder.map((edge) => [
edge,
formal.summary.pairwise[edge],
]),
),
completedOutputs: formal.sources.reduce(
(sum, source) => sum + source.outputs.filter(
(output) => output.hit_eos,
).length,
0,
),
truncatedOutputs: formal.sources.reduce(
(sum, source) => sum + source.outputs.filter(
(output) => output.stopped_at_max_new_tokens,
).length,
0,
),
},
claimBoundary: formal.claim_boundary,
};
writeFileSync(
outputPath,
`${JSON.stringify(compact, null, 2)}\n`,
"utf8",
);
process.stdout.write(
`${outputPath}\n`
+ `${formalSha256}\n`
+ `${statSync(formalPath).size} bytes formal → `
+ `${statSync(outputPath).size} bytes compact\n`
+ `${reproduction.generatedTokenIdsExact}`
+ ` / ${reproduction.cells} long-sequence cells exact\n`,
);
+101 -5
View File
@@ -76,6 +76,10 @@ const overview = await evaluate(`(() => ({
artifactTabs: document.querySelectorAll("[data-artifact-tab]").length,
artifactPanels: document.querySelectorAll("[data-artifact-panel]").length,
artifactLayers: document.querySelectorAll(".layer-evidence > span").length,
behaviorTabs: document.querySelectorAll("[data-behavior-tab]").length,
behaviorPanels: document.querySelectorAll("[data-behavior-panel]").length,
behaviorSources: document.querySelectorAll("[data-behavior-source] option").length,
behaviorEdges: document.querySelectorAll("[data-behavior-map-edge]").length,
branches: document.querySelectorAll(".branch-grid > a").length,
followups: document.querySelectorAll(".lineage-row.followup").length,
navLinks: document.querySelectorAll(".top-nav a").length,
@@ -803,6 +807,78 @@ await evaluate(`(() => {
await pause(180);
await screenshot("/tmp/llm-atlas-deepseek-artifact-desktop.png");
const behavior = await evaluate(`(() => {
const root = document.querySelector("[data-behavior-lab]");
const readPair = () => ({
panel: root.querySelector("[data-behavior-panel]:not([hidden])").dataset.behaviorPanel,
source: root.querySelector("[data-behavior-source-id]").textContent.trim(),
domain: root.querySelector("[data-behavior-domain]").textContent.trim(),
exact: root.querySelector("[data-behavior-exact]").textContent.trim(),
prefix: root.querySelector("[data-behavior-prefix]").textContent.trim(),
edit: root.querySelector("[data-behavior-edit]").textContent.trim(),
similarity: root.querySelector("[data-behavior-similarity]").textContent.trim(),
conditions: [...root.querySelectorAll("[data-output-condition]")].map((node) => node.textContent.trim()),
statuses: [...root.querySelectorAll("[data-output-status]")].map((node) => node.textContent.trim()),
outputCharacters: [...root.querySelectorAll("[data-output-text]")].map((node) => node.textContent.length),
});
const initial = readPair();
const source = root.querySelector("[data-behavior-source]");
const edge = root.querySelector("[data-behavior-edge]");
source.value = "gsm8k/test/1069";
source.dispatchEvent(new Event("change", { bubbles: true }));
edge.value = "x_at_s1";
edge.dispatchEvent(new Event("change", { bubbles: true }));
const switched = readPair();
root.querySelector('[data-behavior-tab="map"]').click();
const map = root.querySelector("[data-behavior-map-domain]");
map.value = "math";
map.dispatchEvent(new Event("change", { bubbles: true }));
const mathMap = {
panel: root.querySelector("[data-behavior-panel]:not([hidden])").dataset.behaviorPanel,
rows: root.querySelectorAll("[data-behavior-map-edge]").length,
note: root.querySelector("[data-behavior-map-note]").textContent.trim(),
firstExact: root.querySelector("[data-behavior-map-edge] [data-map-exact]").textContent.trim(),
firstSimilarity: root.querySelector("[data-behavior-map-edge] [data-map-similarity]").textContent.trim(),
};
root.querySelector('[data-behavior-tab="execution"]').click();
const execution = {
panel: root.querySelector("[data-behavior-panel]:not([hidden])").dataset.behaviorPanel,
layers: root.querySelectorAll(".layer-device-map > span").length,
gpu: root.querySelectorAll(".layer-device-map > span.gpu").length,
cpu: root.querySelectorAll(".layer-device-map > span.cpu").length,
runtimeCards: root.querySelectorAll(".runtime-grid > article").length,
};
root.querySelector('[data-behavior-tab="boundary"]').click();
const boundary = {
panel: root.querySelector("[data-behavior-panel]:not([hidden])").dataset.behaviorPanel,
ladder: root.querySelectorAll(".evidence-ladder > article").length,
tokenCards: root.querySelectorAll(".token-contract > article").length,
reproCards: root.querySelectorAll(".repro-grid > article").length,
links: root.querySelectorAll(".artifact-links > a").length,
forbidden: root.querySelector(".forbidden-claims").textContent.replaceAll(/\\s+/g, " ").trim(),
};
const first = root.querySelector('[data-behavior-tab="pair"]');
first.focus();
first.dispatchEvent(new KeyboardEvent("keydown", { key: "ArrowRight", bubbles: true }));
return {
initial,
switched,
mathMap,
execution,
boundary,
keyboardSelected: root.querySelector('[data-behavior-tab][aria-selected="true"]').dataset.behaviorTab,
keyboardVisible: root.querySelector("[data-behavior-panel]:not([hidden])").dataset.behaviorPanel,
};
})()`);
await evaluate(`(() => {
const root = document.querySelector("[data-behavior-lab]");
root.querySelector('[data-behavior-tab="pair"]').click();
root.scrollIntoView({ block: "start", behavior: "instant" });
window.scrollBy(0, -82);
})()`);
await pause(180);
await screenshot("/tmp/llm-atlas-deepseek-behavior-desktop.png");
await navigate("/");
const home = await evaluate(`(() => ({
releaseCards: document.querySelectorAll(".release-card").length,
@@ -835,6 +911,7 @@ await navigate("/deepseek/");
const mobile = await evaluate(`(() => {
const root = document.querySelector("[data-deepseek-lab]");
const artifact = document.querySelector("[data-dsv2-lab]");
const behavior = document.querySelector("[data-behavior-lab]");
root.scrollIntoView({ block: "start", behavior: "instant" });
const toggle = document.querySelector("#menu-toggle");
toggle?.click();
@@ -845,6 +922,10 @@ const mobile = await evaluate(`(() => {
mobileLinks: document.querySelectorAll("#mobile-nav a").length,
tabs: root.querySelectorAll("[data-ds-tab]").length,
artifactTabs: artifact.querySelectorAll("[data-artifact-tab]").length,
behaviorTabs: behavior.querySelectorAll("[data-behavior-tab]").length,
behaviorSources: behavior.querySelectorAll("[data-behavior-source] option").length,
behaviorEdges: behavior.querySelectorAll("[data-behavior-map-edge]").length,
behaviorDeviceCells: behavior.querySelectorAll(".layer-device-map > span").length,
artifactHeatCells: artifact.querySelectorAll("[data-route-heatmap] > span").length,
corpusCohorts: artifact.querySelectorAll("[data-corpus-cohort]").length,
lengthDeltaCards: artifact.querySelectorAll("[data-length-delta-grid] > article").length,
@@ -894,7 +975,7 @@ const mobile = await evaluate(`(() => {
roleBlockDomainCards: artifact.querySelectorAll("[data-role-block-domain-grid] > article").length,
roleBlockDepthCells: artifact.querySelectorAll("[data-role-block-depth-map] > div > span").length,
offenders: [...document.querySelectorAll("body *")]
.filter((node) => !node.closest(".paper-chain, .advantage-table, .precision-table, .mapping-table, [data-deepseek-lab], [data-dsv2-lab]"))
.filter((node) => !node.closest(".paper-chain, .advantage-table, .precision-table, .mapping-table, [data-deepseek-lab], [data-dsv2-lab], [data-behavior-lab]"))
.filter((node) => node.getBoundingClientRect().right > document.documentElement.clientWidth + 1)
.slice(0, 12)
.map((node) => ({
@@ -1018,19 +1099,28 @@ await evaluate(`(() => {
})()`);
await pause(120);
await screenshot("/tmp/llm-atlas-deepseek-role-block-results-mobile.png");
await evaluate(`(() => {
const behavior = document.querySelector("[data-behavior-lab]");
behavior.querySelector('[data-behavior-tab="pair"]').click();
behavior.scrollIntoView({ block: "start", behavior: "instant" });
window.scrollBy(0, -70);
})()`);
await pause(180);
await screenshot("/tmp/llm-atlas-deepseek-behavior-mobile.png");
const report = { overview, capacity, cache, codesign, rl, artifactRoute, artifactLoad, artifactCache, artifactAbsorb, artifactCorpus, artifactTemplate, artifactHistory, artifactDistance, artifactBoundary, artifactRole, artifactSpecial, artifactRoleBlock, artifactEvidence, home, papers, mobile, exceptions };
const report = { overview, capacity, cache, codesign, rl, artifactRoute, artifactLoad, artifactCache, artifactAbsorb, artifactCorpus, artifactTemplate, artifactHistory, artifactDistance, artifactBoundary, artifactRole, artifactSpecial, artifactRoleBlock, artifactEvidence, behavior, home, papers, mobile, exceptions };
console.log(JSON.stringify(report, null, 2));
const numeric = (text) => Number.parseFloat(text.replaceAll(",", ""));
const failures = [];
if (!overview.title.includes("为什么转向")) failures.push("专题标题异常");
if (overview.sections !== 26 || overview.tocLinks !== 26) failures.push("二十五个编号专题加阅读链的目录结构异常");
if (overview.sections !== 27 || overview.tocLinks !== 27) failures.push("二十六个编号专题加阅读链的目录结构异常");
if (overview.ledgers !== 24 || overview.waves !== 10) failures.push("二十四张问题账或十次转向结构异常");
if (overview.paperLinks !== 60 || overview.branches !== 5 || overview.followups !== 1) failures.push("论文链、旁支或公开后续标记异常");
if (overview.labTabs !== 4 || overview.labPanels !== 4) failures.push("四联实验结构异常");
if (overview.artifactTabs !== 13 || overview.artifactPanels !== 13 || overview.artifactLayers !== 27) failures.push("真实权重十三联实验结构异常");
if (overview.heroLabs !== "17 个可操作实验") failures.push("DeepSeek 实验总数账异常");
if (overview.behaviorTabs !== 4 || overview.behaviorPanels !== 4 || overview.behaviorSources !== 16 || overview.behaviorEdges !== 10) failures.push("Chat 行为实验结构异常");
if (overview.heroLabs !== "18 个可操作实验") failures.push("DeepSeek 实验总数账异常");
if (overview.navLinks !== 20 || home.navLinks !== 20 || mobile.mobileLinks !== 20 || overview.activeNav !== "DeepSeek") failures.push("全站导航未同步 DeepSeek");
if (overview.documentOverflow > 1 || mobile.documentOverflow > 1) failures.push("桌面或移动端存在文档级横向溢出");
if (capacity.initial.panel !== "capacity" || capacity.initial.total !== "32.1× FFN" || capacity.initial.active !== "1.13× FFN") failures.push("V3 稀疏容量初始账异常");
@@ -1117,9 +1207,15 @@ if (artifactRoleBlock.layer1Head.batchValues.join("|") !== "512 / 512|368 / 512|
if (artifactEvidence.panel !== "evidence" || artifactEvidence.layers !== 27 || artifactEvidence.executed !== 7 || artifactEvidence.split !== 1 || artifactEvidence.unloaded !== 19 || artifactEvidence.exact !== "31 / 31") failures.push("真实工件执行边界或复跑闸门异常");
if (!artifactEvidence.dependency.includes("Transformers 5.5") || !artifactEvidence.dependency.includes("4.41.2") || !artifactEvidence.boundary.includes("完整 27 层生成")) failures.push("依赖版本或未覆盖边界异常");
if (artifactEvidence.keyboardSelected !== "load" || artifactEvidence.keyboardVisible !== "load") failures.push("真实工件实验键盘 tab 导航异常");
if (behavior.initial.panel !== "pair" || behavior.initial.source !== "wikitext2/raw-validation/0443" || behavior.initial.conditions.join("|") !== "S0 · EOS|S1 · EOS" || behavior.initial.exact !== "DIVERGED" || behavior.initial.prefix !== "63" || behavior.initial.edit !== "33" || behavior.initial.similarity !== "74.2%") failures.push("Chat 行为逐格输出初值异常");
if (behavior.switched.domain !== "Grade-school math" || behavior.switched.conditions.join("|") !== "S1 · EOS|S1 · x" || behavior.switched.exact !== "DIVERGED" || behavior.switched.outputCharacters.some((value) => value < 100)) failures.push("Chat 行为 source / contrast 切换异常");
if (behavior.mathMap.panel !== "map" || behavior.mathMap.rows !== 10 || !behavior.mathMap.note.includes("GSM8K") || behavior.mathMap.firstExact !== "2 / 4" || behavior.mathMap.firstSimilarity !== "84.0%") failures.push("Chat 行为分域分叉地图异常");
if (behavior.execution.panel !== "execution" || behavior.execution.layers !== 29 || behavior.execution.gpu !== 25 || behavior.execution.cpu !== 4 || behavior.execution.runtimeCards !== 4) failures.push("Chat BF16 GPU / CPU offload 设备图异常");
if (behavior.boundary.panel !== "boundary" || behavior.boundary.ladder !== 3 || behavior.boundary.tokenCards !== 4 || behavior.boundary.reproCards !== 4 || behavior.boundary.links !== 3 || !behavior.boundary.forbidden.includes("route TV")) failures.push("Chat 行为证据阶梯或限制异常");
if (behavior.keyboardSelected !== "map" || behavior.keyboardVisible !== "map") failures.push("Chat 行为实验键盘 tab 导航异常");
if (home.releaseCards !== 17 || !home.firstRelease.includes("47 页不再压成摘要") || home.firstHref !== "/k3/" || home.paperCount !== "486") failures.push("首页 DeepSeek 首发入口或论文数异常");
if (papers.total !== 486 || !papers.hasFilter || papers.visible < 20 || !papers.hasCoder || !papers.hasEngram) failures.push("论文库 DeepSeek 聚光异常");
if (!mobile.menuVisible || mobile.menuOpen !== "true" || mobile.tabs !== 4 || mobile.artifactTabs !== 13 || mobile.artifactHeatCells !== 64 || mobile.corpusCohorts !== 3 || mobile.lengthDeltaCards !== 4 || mobile.templateLayers !== 6 || mobile.templateScopes !== 2 || mobile.templateModes !== 2 || mobile.templateDomainCards !== 4 || mobile.templateDepthCells !== 24 || mobile.historyLayers !== 6 || mobile.historyScopes !== 2 || mobile.historyModes !== 2 || mobile.historyEffects !== 3 || mobile.historyDomainCards !== 4 || mobile.historyDepthCells !== 24 || mobile.distanceLayers !== 6 || mobile.distanceScopes !== 2 || mobile.distanceModes !== 2 || mobile.distanceContrasts !== 2 || mobile.distanceDomainCards !== 4 || mobile.distanceDepthCells !== 24 || mobile.boundaryLayers !== 6 || mobile.boundaryScopes !== 2 || mobile.boundaryModes !== 2 || mobile.boundaryContrasts !== 3 || mobile.boundaryTokenCards !== 4 || mobile.boundaryDomainCards !== 4 || mobile.boundaryDepthCells !== 24 || mobile.roleLayers !== 6 || mobile.roleScopes !== 2 || mobile.roleModes !== 2 || mobile.roleContrasts !== 3 || mobile.roleLevelCards !== 4 || mobile.roleDomainCards !== 4 || mobile.roleDepthCells !== 24 || mobile.specialLayers !== 6 || mobile.specialScopes !== 2 || mobile.specialModes !== 2 || mobile.specialContrasts !== 4 || mobile.specialTokenCards !== 4 || mobile.specialDomainCards !== 4 || mobile.specialDepthCells !== 24 || mobile.roleBlockLayers !== 6 || mobile.roleBlockScopes !== 2 || mobile.roleBlockModes !== 2 || mobile.roleBlockEffects !== 3 || mobile.roleBlockMatrixCards !== 4 || mobile.roleBlockDomainCards !== 4 || mobile.roleBlockDepthCells !== 24) failures.push("移动端导航或实验异常");
if (!mobile.menuVisible || mobile.menuOpen !== "true" || mobile.tabs !== 4 || mobile.artifactTabs !== 13 || mobile.behaviorTabs !== 4 || mobile.behaviorSources !== 16 || mobile.behaviorEdges !== 10 || mobile.behaviorDeviceCells !== 29 || mobile.artifactHeatCells !== 64 || mobile.corpusCohorts !== 3 || mobile.lengthDeltaCards !== 4 || mobile.templateLayers !== 6 || mobile.templateScopes !== 2 || mobile.templateModes !== 2 || mobile.templateDomainCards !== 4 || mobile.templateDepthCells !== 24 || mobile.historyLayers !== 6 || mobile.historyScopes !== 2 || mobile.historyModes !== 2 || mobile.historyEffects !== 3 || mobile.historyDomainCards !== 4 || mobile.historyDepthCells !== 24 || mobile.distanceLayers !== 6 || mobile.distanceScopes !== 2 || mobile.distanceModes !== 2 || mobile.distanceContrasts !== 2 || mobile.distanceDomainCards !== 4 || mobile.distanceDepthCells !== 24 || mobile.boundaryLayers !== 6 || mobile.boundaryScopes !== 2 || mobile.boundaryModes !== 2 || mobile.boundaryContrasts !== 3 || mobile.boundaryTokenCards !== 4 || mobile.boundaryDomainCards !== 4 || mobile.boundaryDepthCells !== 24 || mobile.roleLayers !== 6 || mobile.roleScopes !== 2 || mobile.roleModes !== 2 || mobile.roleContrasts !== 3 || mobile.roleLevelCards !== 4 || mobile.roleDomainCards !== 4 || mobile.roleDepthCells !== 24 || mobile.specialLayers !== 6 || mobile.specialScopes !== 2 || mobile.specialModes !== 2 || mobile.specialContrasts !== 4 || mobile.specialTokenCards !== 4 || mobile.specialDomainCards !== 4 || mobile.specialDepthCells !== 24 || mobile.roleBlockLayers !== 6 || mobile.roleBlockScopes !== 2 || mobile.roleBlockModes !== 2 || mobile.roleBlockEffects !== 3 || mobile.roleBlockMatrixCards !== 4 || mobile.roleBlockDomainCards !== 4 || mobile.roleBlockDepthCells !== 24) failures.push("移动端导航或实验异常");
if (mobile.offenders.length) failures.push(`移动端越界元素:${JSON.stringify(mobile.offenders)}`);
if (exceptions.length) failures.push(`浏览器异常:${exceptions.join(" | ")}`);