第七章:总结与后续工作
Open Claude UI 分析手册(Claude Desktop 4.29.0 → 4.4212.0)「第七章:总结与后续工作」:每条结论附代码证据与复现命令。
7.1 本次取证的确定性边界
7.1.1 确定性等级划分
本文所有结论按证据强度分为三级:
| 等级 | 定义 | 本文中的例子 |
|---|---|---|
| A 级:字节确证 | 直接从 ASAR 内文件读出,可逐字复现 | 55 个 keyframes、45 个 data-cds、24 个 @property、clay-emphasized = #c6613f、6 个 ipcMain.on 通道名、12 个 exposeInMainWorld 字面量 |
| B 级:结构性推断 | 由多条 A 级证据交叉推出,逻辑闭环 | 「主进程无业务 IPC handler」「preload 路径静态不可解」「wave 用 breathe 不用 sweep」 |
| C 级:未知 | 已明示无法确定,不填 | 「7 个 renderer 入口中 2 个如何打开」「--cds-skel-elapsed 运行时由谁写入」「44 个缺失 keyframes 是否在其它 CSS 文件」 |
7.1.2 本文未使用的推断方式
为避免虚构,本文刻意回避了以下三种常见但不可靠的做法:
- 不基于 naming 推断行为:例如
cds-pill-roll-out的命名暗示「滚出」,但本文只记录关键帧数值,不描述其触发条件与视觉轨迹 - 不基于 v2 文档补全 v3:v2 的基线已失效(见 第一章),其结论不能直接继承
- 不基于「合理推测」填零值:例如
utility_processes = 1与本文实测的「0 个 fork 调用点」冲突时,本文标注为unknown而非二选一
7.2 已完成的结论清单
7.2.1 版本与取证基础
| 结论 | 等级 | 位置 |
|---|---|---|
Claude Desktop 版本为 3.6556.2 | A | 1.1.1 |
ASAR 根摘要 b2dfbbb4…d68a | A | 1.1.2 |
v2 引用的 MainWindowPage-BD9CWQ83.css 与 index.chunk-BWk6pVUt.js 已不存在 | A | README |
| 532 个文件语义分析被截断 | A | 1.2 |
7.2.2 Electron 架构
| 结论 | 等级 | 位置 |
|---|---|---|
主进程 0 个 ipcMain.handle,仅 6 个 ipcMain.on | A | 2.1.1 |
这 6 个通道属于 Sentry SDK(start/scope/envelope/structured-log/metric/status) | B | 2.1.1 |
主进程 0 个 new BrowserWindow | A | 2.1.2 |
utilityProcess 3 处均为 Proxy 包装,无 fork 调用点 | B | 2.1.3 |
preload 入口 0 个,路径由 registerPreloadScript 运行时拼接 | B | 2.1.4 |
12 个字面量 exposeInMainWorld API 名 | A | 2.2.2 |
| 7 个 renderer HTML 入口 | A | 2.3 |
| 8 处 ASAR 完整性冲突 | A | 2.4 |
7.2.3 设计系统底座
| 结论 | 等级 | 位置 |
|---|---|---|
55 个 @keyframes | A | 4.1 |
45 个 data-cds 命名空间 | A | 4.2 |
24 个 @property | A | 4.5 |
| 35 阶 gray / 35 阶 orange 全表 | A | 4.3 |
--cds-clay-emphasized: #c6613f(2 处同值,0 处暗色覆盖) | A | 4.3.3 |
骨架屏暗色 base/sheen 均为 hsl(from neutral-900 / 7.5%) | A | 4.4.4 |
data-mode 三态(dark 86 / system 43 / light 29 处) | A | 4.4 |
| 5 阶时间 token(60ms / 120ms / 200ms / 300ms / 450ms) | A | 4.6.1 |
| 4 个 ease 曲线值(out×2 + overshoot + snap) | A | 4.6.2 |
7.2.4 骨架屏机制(issue #25 的核心)
| 结论 | 等级 | 位置 |
|---|---|---|
扫光参数 2s / linear / 105deg 成立 | A | 5.1.3 |
双层结构 SkeletonGroup + Skeleton | A | 3.1.1 |
扫光带是 .cds-skel-sweep-band 真实元素,非 ::after | A | 3.1.1 |
data-hold 三态机制 | A | 3.2 |
wave 用 cds-skeleton-breathe,不是 sweep | A | 3.3.1 |
RTL 需 animation-direction: reverse | A | 3.4 |
减少动效双轨(@media + [data-reduce-motion]) | A | 3.5 |
揭示完成后动画压至 .01ms 并 display:none 扫光带 | A | 3.2.4 |
7.2.5 open-claude-ui 差异
| 结论 | 等级 | 位置 |
|---|---|---|
gray 35 阶 diff=1(#111111 vs #111,值等价) | A | 5.1.1 |
| orange 35 阶 diff=0 | A | 5.1.1 |
| keyframes:交集 11 / 缺失 44 / 独有 21 | A | 4.1.2 |
| data-cds:交集 18 / 缺失 27 / 独有 4 | A | 5.3.2 |
| @property:交集 17 / 缺失 7 / 独有 2 | A | 5.3.3 |
| CI 门禁未剥离注释,存在漏报 | A | 5.4 |
| ASAR 顶层含 compile-cache / bundled-skills / github-mcp / office365-mcp | A | 6.10.1 |
| 内置 6 个 Agent Skills(含 frontend-design) | A | 6.10.3 |
官方 skill 原文确认 #D97757 为 "Anthropic's own Claude-interaction accent" | A | 6.10.4 |
基线增量:客户端已跳版至 4.29.0;CSS 结构清单逐项复验一致(2 处实质更新:Heatmap→CellChartContainer 更名、失焦去色覆盖扩展),我们的修复清单逐项成立无需改动 | A | 6.11 |
基线增量:4.4212.0 复核——token / data-cds / @property / JS 拓扑零变化,仅新增 cds-progress-sweep(进度扫光,已移植)与字体 role 链(已补 token) | A | 6.12 |
4.29.0 新增 2 个桥接 API(desktopNoFlushBytecode、desktopHomePath),桥接总数 12→14 | A | 6.11.3 |
| Cowork 体系内置 Linux micro-VM(smol-bin 24MB) | A | 6.10.5 |
| 内置 4 个 MCP server(github / office365 / computer-use / chrome) | A | 6.10.6 |
@starting-style + view-transition-name: match-element 用于附件重排 | A | 6.10.8 |
7.3 明确的未知项
以下各项本文无法确定,列出原因与可用的进一步手段。
7.3.1 已全部解决
原列的两项「需运行时观测」已通过 Claude 自带的 Enable Main Process Debugger 取得运行时事实(见 6.7)。
7.3.1.1 已在第六章解决
以下项原本列在未知清单中,第六章完成后已给出确定答案:
| 原未知项 | 结论 | 证据位置 |
|---|---|---|
| 44 个缺失 keyframes 是否在其它 CSS 文件 | 不在。全部 44 项仅存在于主样式表;其余 16 个文件只多出 4 个非 cds-* 关键帧 | 6.2 |
--cds-* 与官方 token 的关系 | --cds-X ≡ 官方 --X,131 个同名 | 6.5 |
--cds-radius-composer 官方值 | 14px(calc(.875rem * scale)),我们的 20px 是 v1 遗留;切换条件为 [data-density=comfortable] | 6.6.2 |
--cds-h-control-nested 官方值 | 22px(calc(1.375rem * scale)),v2 文档正确,我们错 | 6.8.1 |
--cds-gap-xl 官方值 | 40px(calc(2.5rem * scale)) | 6.8.2 |
--cds-skel-elapsed / skel-settled 由谁写入 | 没有代码写入。551 个 JS 文件中 SkeletonGroup 零出现,恒为 0s;reveal-end 恒为 0.65s | 6.6 |
| 「7 停非线性 mask」是否存在 | 不存在。全文 6 停以上 gradient 为 0 | 6.6.3 |
--cds-rem-scale 的实际取值 | 从未被赋值,306 处引用全部走 fallback 1 | 6.6.1 |
registerPreloadScript 的 filePath 实际值 | .vite/build/mainWindow.js(主窗口)与 .vite/build/mainView.js(about:blank)。preload 就是窗口脚本本身 | 6.7.2 |
utilityProcess.fork 的实际调用点 | 运行时钩子零命中。实测 3 个 Utility 全为 Chromium 内置(Network / Audio / VideoCapture),应用层未 fork 任何 utility process | 6.7.4 |
| preload 注册的实际 API | session 级 registerPreloadScript,但 getPreloadScripts() 返回 [];实际走 webPreferences.preload | 6.7.3 |
7.3.2 需要历史版本
| 未知项 | 原因 |
|---|---|
| v2.37337.1 的 CSS 实际内容 | 本机无该版本备份,无法比对「#cc5a36 从何而来」 |
v2 的 40 个 data-cds 具体名单 | v2 文档只写总数,04 章是占位符 [40 大标准化组件清单] |
| 「7 停非线性 mask」是否真实存在过 | 3.6556.2 主表中未找到;无法确认是重构还是 v2 文档的推断 |
7.3.2.1 第六章 6.10 新增的待验证项
| 未知项 | 原因 | 可行手段 |
|---|---|---|
| Cowork surface 的 UI 载体是本地 CSS 还是 claude.ai Web | 45 个 data-cds 中无 Cowork 专属组件 | 运行时打开 Cowork 界面后用 CDP 检查 DOM |
heavy-work-worker / pty-host / file-index-worker 是 worker_threads 还是 utilityProcess | 本会话未触发 | 运行时触发后看进程树 |
clawdQuestEngine(游戏化)的数据来源与 UI 触发点 | 仅静态扫描 | 同上 |
smol-bin VM 的最小规格(内存/CPU 配置) | 代码中有 vmCpuCount/memory GB 逻辑但未运行 | Cowork 启动 VM 时观测 |
7.3.3 需要组件源码
| 未知项 | 原因 |
|---|---|
open-claude-ui 独有的 21 个 keyframes 来源 | 需确认是 v1/v2 分析残留,还是自行命名 |
open-claude-ui 独有的 4 个 data-cds(CodeBlock/ConfirmationDialog/ContextMenu/Toast) | 同上 |
7.4 建议的后续工作
7.4.1 对 open-claude-ui 仓库
第一优先(P0,4 项)
- 修复
.cds-skeleton-sweep独立类把元素移出视口 - 修正
--cds-clay-emphasized为#c6613f - 修正骨架屏暗色 base/sheen 为
hsl(from var(--cds-neutral-900) h s l / 7.5%) - 修正 CI 门禁在判断消费前剥离注释
第二优先(P1,3 项)
- 补 RTL 的
animation-direction: reverse - 实现
data-hold三态揭示时序 - 修正 wave 模式用
cds-skeleton-breathe而非 sweep
第三优先(P2,3 项)
- 补
cds-placeholder-reveal关键帧 - 补 9 个
cds-pill-*关键帧 - 用
:where()降低.cds-skeleton的border-radius特异性
详见 5.5 修复优先级总表。
7.4.2 文档层面
v2 文档处理
建议在 docs/v2/ 各文件的 frontmatter 增加:
status: historical
superseded_by: "docs/v4.29.0-4.4212.0/"
verified_against: "2026-10-15"不要在 v2 里补充 3.6556.2 的数字——基线已不同,混写会产生新的错误。
v1 文档
docs/v1/ 同样引用了 2.37337.1(共 16 个文件 36 处),需做同样处理。
7.4.3 对 REA 工具
本次取证暴露 REA 6.8.0 的三个问题:
问题 1:--source-path 在 inventory 部分失效时不可用
rea analyze-javascript-application app.asar --source-path ".vite/build/index.pre.js"
→ invalid_value: "Select an exact relevant file path from the artifact inventory"但从 REA 自己的 asar-entry 节点取出的路径就是 .vite/build/index.pre.js。
原因(源码 src/artifacts/javascript/JavaScriptArtifactFiles.ts:104):
const issues = (sourcePaths ?? []).flatMap((path, index) =>
expected.has(path) || inventory.unavailableFiles.has(path) ? [] : [...]
);expected 来自本次运行的 inventory。当 inventory 因预算截断而不完整时,选中的路径恰好落在失效部分,导致定向补全这条恢复路径被完全切断。
问题 2:utility_processes 与 resolved_utility_entrypoints 语义冲突
summary.utility_processes = 1
summary.resolved_utility_entrypoints = 0实测代码中 utilityProcess 仅 3 处,全部是对 fork 的 Proxy 包装,无实际调用点。两个字段并列时读者会误以为「有 1 个 utility process 但入口未知」,而实际可能是「Proxy 包装被计数了」。
问题 3:context_bridge_apis 的口径不明确
同一份取证中:
| 位置 | 数值 |
|---|---|
summary.context_bridge_apis | 37 |
graph context-bridge-api 节点数 | 20 |
| graph 唯一 label 数 | 7 |
本文字节扫描的 exposeInMainWorld 字面量 | 12 |
四个数字都对,但口径不同且未在文档中说明。
7.4.4 下一步技术验证
若要继续深入,建议按以下顺序:
| 步骤 | 目标 | 手段 |
|---|---|---|
| 1 | 确认 44 个缺失 keyframes 是否在其它 CSS | 扫全部 17 个 CSS 文件 |
| 2 | 确认 data-mode 的完整覆盖范围 | 扫 4 个 window-*.css |
| 3 | 确认运行时注入的 --cds-skel-* | Electron + CDP |
| 4 | 确认 preload 实际路径 | Electron 主进程 --inspect |
| 5 | 重跑被截断的 532 个文件 | 待 REA 修复 --source-path,或分批分析 |
7.5 本文的可复现性声明
本文所有 A 级结论都可通过以下三条命令的任意组合复现:
# 1. 确认版本与摘要
shasum -a 256 "/Applications/Claude.app/Contents/Resources/app.asar"
# 2. 抽取主样式表(ASAR header: uint32LE@12 = JSON 长度,JSON 从偏移 16 开始)
node -e '
const fs=require("fs");
const p="/Applications/Claude.app/Contents/Resources/app.asar";
const fd=fs.openSync(p,"r");
const h=Buffer.alloc(16); fs.readSync(fd,h,0,16,0);
const hs=h.readUInt32LE(12);
const jb=Buffer.alloc(hs); fs.readSync(fd,jb,0,hs,16);
const J=JSON.parse(jb.toString("utf8"));
const n=J.files[".vite"].files.renderer.files.main_window.files.assets.files["MainWindowPage-BjVtjJFx.css"];
const b=Buffer.alloc(n.size); fs.readSync(fd,b,0,n.size,16+hs+Number(n.offset));
fs.writeFileSync("/tmp/MainWindowPage.css", b);
'
# 3. 验证任意一条清单
grep -o "@keyframes [a-zA-Z0-9_-]*" /tmp/MainWindowPage.css | sort -u | wc -l # 55
grep -o "\[data-cds=[A-Za-z-]*\]" /tmp/MainWindowPage.css | sort -u | wc -l # 45
grep -o "@property --cds-[a-zA-Z0-9_-]*" /tmp/MainWindowPage.css | sort -u | wc -l # 24
grep -c "\--cds-clay-emphasized:" /tmp/MainWindowPage.css # 1若 Claude Desktop 升级,MainWindowPage-*.css 的文件名 hash 会变化,上述路径需按 ASAR 目录树重新定位。ASAR 根摘要也会变化,本文所有结论需重新验证。
本章证据索引
本文为总结章,不引入新事实。所有断言均指向前述章节,前述章节各自带有代码证据。