第一章:综述与版本边界
Open Claude UI 分析手册(Claude Desktop 4.29.0 → 4.4212.0)「第一章:综述与版本边界」:每条结论附代码证据与复现命令。
1.1 版本边界声明
1.1.1 应用版本
从 /Applications/Claude.app/Contents/Resources/app.asar 内解出的 package.json 原文:
{
"name": "@ant/desktop",
"version": "3.6556.2",
"productName": "Claude"
}证据链:
- 文件位置:ASAR 根目录
package.json,size = 1835(REA 6.8.0 生成的取证包记录) - ASAR Header 结构:偏移
0..16为长度头,uint32LE@12给出 JSON 头长度;JSON 头从偏移 16 开始;文件数据区起始 =16 + headerSize - 交叉验证:
/Applications/Claude.app/Contents/Info.plist的CFBundleShortVersionString = 3.6556.2,CFBundleVersion = 3.6556.2
1.1.2 ASAR 根摘要
sha256 = b2dfbbb40325d978dcb7561ad12a6f9bc199f8f46b7d3d2897af74ce8965d68aREA 取证包 artifacts[0].digest.sha256 与 shasum -a 256 直接计算结果一致,同一次取证可复现。
REA 取证包标识:
evidence_id = ev_77dc39e02692fc4337a916c2321df1f1cfef85c3f30a034593655fa2eea55303
operation = analyze_javascript_application
authority = shipped-artifact
confidence = derived1.1.3 ASAR 内部规模
{
"relevant_files": 572,
"parsed_javascript_files": 546,
"skipped_javascript_files": 7,
"parse_failures": 0,
"invalid_utf8_files": 0,
"text_bytes_read": 42966700,
"visited_ast_nodes": 6621556,
"findings": 10872,
"modules": 72,
"nested_asar_containers": 0
}证据:records[0].normalized_result.statistics
独立复核:直接用 Node 解析 ASAR header,条目总数 629(含非 JS 文件如 CSS/HTML/JSON/node)。572 是 REA 判定为「相关」的子集。
1.1.4 进程与窗口拓扑(实测)
7 个 renderer 入口(ASAR 内 .vite/renderer/ 下的目录):
about_window
buddy_window
file_viewer
find_in_page
local_exec_consent
main_window
quick_window证据:Object.keys(asarHeader.files[".vite"].files.renderer.files) → 上述 7 项。
但 REA summary.browser_windows = 5。两者不矛盾:
5统计的是「代码里new BrowserWindow创建的不同窗口」7是「磁盘上的 renderer HTML 入口数」
差的 2 个(file_viewer、local_exec_consent)由其他机制打开,不走 new BrowserWindow。
⚠️ 本节的可信度限制:主进程文件 .vite/build/index.pre.js 在 REA 取证中 parse_status = "partial" 且 static_analysis 字段缺失(见 1.2),因此「5 个 BrowserWindow」来自 REA 对可解析部分的汇总,不是对主进程完整代码的直接计数。详见 第二章 2.3。
1.2 取证覆盖度与不可解项
REA 取证包 records[0].normalized_result.limitations 共 1064 条。按原因归并:
| 原因 | 条数 | 原文(节选) |
|---|---|---|
| 语义分析未启动 | 512 | The parent reserved its remaining result capacity for static observations; semantic analysis of <file> was not started |
| 语义图超预算 | 10 | Semantic graph for <file> exceeds the parent's remaining result budget; static and module facts were retained |
| 工作进程资源约束 | 7 | Owned JavaScript worker … resource constraint |
| 完整性冲突 | 8 | Artifact integrity metadata contradicts observed bytes at <path> |
| 其他(内联脚本、别名上限等) | 527 | 逐条不同 |
去重后的受约束文件数:532([...new Set(limitations.filter(l=>l.includes("Resource constraint")).map(l=>l.split(":")[0]))].length)。
1.2.1 被截断的核心文件
.vite/build/mainView.js
.vite/build/mainWindow.js
.vite/build/quickWindow.js
.vite/build/aboutWindow.js
.vite/build/heavy-work-worker/dist-CI9lzb1v.js
.vite/build/heavy-work-worker/heavyWorkWorker.js这直接导致本文的一个重要结论:REA 主报告中的 ipc.main_handlers = 0 不能直接采信,必须绕过 REA 直接读字节验证。第二章完成了这项验证,结论是该零值成立,但原因与 REA 的推断不同。
1.2.2 六个结构性零值
{
"ipc.main_handlers": 0,
"ipc.paired_renderer_transmissions": 0,
"ipc.ambiguous_renderer_transmissions": 0,
"preload_entrypoints": 0,
"resolved_utility_entrypoints": 0,
"native_addon_bindings": 0,
"resolved_native_addon_bindings": 0
}证据:records[0].normalized_result.summary。
本文对其中三个做了字节级复核(第二章):
| 零值 | 复核结论 | 复核方法 |
|---|---|---|
ipc.main_handlers = 0 | ✅ 成立 | 主进程仅 6 个 ipcMain.on(t.createKey(...)),全部属于 Sentry SDK 命名空间 |
preload_entrypoints = 0 | ✅ 成立 | 全 ASAR 无 preload 命名文件;preload 路径由 registerPreloadScript 运行时拼接 |
native_addon_bindings = 0 | ⚠️ 部分成立 | 磁盘有 5 个 native-addon 节点,但其中 8 处完整性冲突,REA 拒绝建立可信绑定 |
其余三个零值本文不复核、不推断,标注为 unknown。
1.2.3 语义图的族级覆盖度
records[0].normalized_result.semantic_graph.coverage.families 全部 12 个族状态均为 partial:
| family | retained_relations | unknown_ids 数量 |
|---|---|---|
| data-flow | 51995 | 24800 |
| object-flow | 5461 | 21917 |
| closure | 16153 | 531 |
| call-flow | 11047 | 8157 |
| promise-ownership | 295 | 715 |
| event | 121 | 626 |
| boundary | 54 | 537 |
| request | 48 | 543 |
| timer | 15 | 544 |
| configuration | 1 | 531 |
| child-process | 0 | 531 |
| resource-lifecycle | 0 | 531 |
全局 unknown 节点 59963 个。
含义:本文凡是涉及「数据流」「对象流」「资源生命周期」的推断都必须显式标注为不可靠。本文因此只采信可直接从字节读出的静态事实(token 值、keyframes 定义、选择器结构、字面量字符串)。
1.3 v2 → v3 迁移影响面
本节给出可直接执行的迁移判定,每条附证据。
1.3.1 必须修改的令牌值
| 令牌 | open-claude-ui 现值 | 3.6556.2 实测值 | 判定 |
|---|---|---|---|
--cds-clay-emphasized | var(--cds-clay-hover)(light #cc5a36 / dark #e08264) | #c6613f(2 处定义::root 与 .cds-root,值相同,无暗色覆盖) | ❌ 必须改 |
证据:
grep -c "\--cds-clay-emphasized:" MainWindowPage-BjVtjJFx.css # → 2(:root 与 .cds-root,值均为 #c6613f)
grep -c "\--cds-clay-emphasized:" MainWindowPage.css | grep dark # 反模式,见下
# 无暗色覆盖的验证方式:
grep -o "data-mode=dark[^{]*{[^}]*--cds-clay-emphasized" MainWindowPage-BjVtjJFx.css | wc -l # → 0
grep -o "\--cds-clay-emphasized:[^;}]*" MainWindowPage-BjVtjJFx.css # → --cds-clay-emphasized:#c6613f原 CSS 中的完整上下文(相邻令牌,用于确认这不是断章取义):
…--cds-oncolor-200:#f8f8f7bf;--cds-oncolor-300:#f8f8f780;--cds-clay:#d97757;--cds-clay-emphasized:#c6613f;--cds-heather:#cbcadb;--cds-plum:#827db…注意三份来源给出三个不同值:
| 来源 | 值 |
|---|---|
| v2 文档(v2.37337.1) | #cc5a36(双模同值) |
| open-claude-ui 分支实现 | var(--cds-clay-hover) → light #cc5a36 / dark #e08264 |
| 3.6556.2 实测 | #c6613f |
1.3.2 无需修改的令牌(已验证一致)
35 阶 gray 与 35 阶 orange 全部对齐,仅 1 处写法差异(值等价):
| 令牌 | ours | 3.6556.2 | 判定 |
|---|---|---|---|
--cds-gray-870 | #111111 | #111 | ✅ 值等价,仅书写长度不同 |
证据:
# gray: ours=35 cli=35 diff=1 (唯一差异 gray-870: #111111 vs #111)
# orange: ours=35 cli=35 diff=0完整 35 阶表见 4.3。
1.3.3 缺失的动效与结构
| 类别 | ours | 3.6556.2 | 交集 | 缺失 | 我方独有 |
|---|---|---|---|---|---|
@keyframes cds-* | 32 | 55 | 11 | 44 | 21 |
data-cds 命名空间 | 22 | 45 | 18 | 27 | 4 |
@property --cds-* | 19 | 24 | 17 | 7 | 2 |
证据:
# keyframes
comm -12 / -13 / -23 对 ours(32) 与 client(55) 做集合运算 → 11 / 44 / 21
32 = 11 + 21 ✓ 55 = 11 + 44 ✓
# data-cds
comm 对 ours(22) 与 client(45) → 18 / 27 / 4
22 = 18 + 4 ✓ 45 = 18 + 27 ✓
# @property
comm 对 ours(19) 与 client(24) → 17 / 7 / 2
19 = 17 + 2 ✓ 24 = 17 + 7 ✓具体清单见 第五章。
1.3.4 结构性变更(需要改代码,不只是改值)
| 变更 | 影响 |
|---|---|
骨架屏从 .skeleton-shimmer::after 改为 双层 data-cds 组件 + .cds-skel-sweep-band 子元素 | 组件标记需重写 |
新增 data-hold 三态揭示时序 | 需新增可选的揭示延迟控制 |
暗色从 .dark class 改为 [data-mode=dark|light|system] | 暗色切换逻辑需重写 |
RTL 从简单 255° 翻转改为 :lang(...) 精确语言列表 + animation-direction:reverse | RTL 选择器需重写 |
详细证据见 第三章。
本章证据索引
| 断言 | 证据来源 |
|---|---|
版本 3.6556.2 | ASAR 内 package.json;Info.plist |
| ASAR 根摘要 | shasum -a 256 与 REA artifacts[0].digest.sha256 双向一致 |
| 572/546/7/0/6621556 | REA records[0].normalized_result.statistics |
| 629 个 ASAR 条目 | 直接解析 ASAR header 计数 |
| 7 个 renderer 入口 | ASAR .vite/renderer/ 目录列表 |
| 532 文件截断 / 1064 条 limitation | REA records[0].normalized_result.limitations |
| 12 个语义族全 partial | REA semantic_graph.coverage.families |
clay-emphasized = #c6613f | grep 主样式表:2 处定义(:root / .cds-root),值一致,0 处暗色覆盖 |
| gray/orange 35 阶对齐 | 逐阶对比 ours vs cli |
| 55/45/24 vs 32/23/19 | 三方 sort -u | wc -l |