Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions HANDOFF.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ make macos-offline-tests

## 9. 会话日志(最近)

- 2026-11-15 / Claude Code(air):**快速 UI 回路修复(报告 286)**。`make macos-ui-snapshots` 因
`CandidateWindow` 新增 `CaretPlacement`/`LearningHints` 依赖而编译失败;补全源码清单,新增
`test-ui-snapshots.py` 防清单漂移。离线回归 68 文件/337 例 PASS;快照可重新产出(候选 6 / 面板 14 / HUD 6)。
日常 UI/功能验收优先 `make macos-ui-snapshots` + `make macos-dev`,不必每次换包。
- 2026-11-15 / Claude Code(air):**PR #314、#315 已合入 main(`7014346`、`7b95ba6`)**。PR #314 = 86 专注 +
标准变体(240→241 条 root/key,98/新世纪仅留 profile);PR #315 = D2 字形别名(ADR-359,报告 285)。
当前 B0 3,000 `full` 2,614(87.1%)/ `partial` 232 / `unknown` 154;1,000 `full` 928。CI 全绿后均为 merge commit。
Expand Down
42 changes: 42 additions & 0 deletions docs/reviews/286-ui-snapshot-source-drift.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# 286 — UI 快照源码清单漂移修复

> 2026-11-15。`make macos-ui-snapshots` 在候选窗新增依赖后编译失败;修复并加回归。

## 1. 现象

```
platforms/macos/Sources/CandidateWindow.swift:1290: error: cannot find 'CaretPlacement' in scope
platforms/macos/Sources/CandidateWindow.swift:448: error: cannot find 'LearningHints' in scope
```

`scripts/ui-snapshots.sh` 为候选窗/面板各维护一份**硬编码源码清单**。`CandidateWindow.swift`
先后引入 `CaretPlacement`(ADR-301)与 `LearningHints`(ADR-311)后,清单没有同步;
主应用 `build.sh` 与 `dev-preview.sh` 用的是各自完整的清单,所以 `make verify`/CI 一直绿,
只有快速 UI 入口坏掉。

## 2. 修复

- `CANDIDATE_SOURCES` / `PANEL_SOURCES` 补 `CaretPlacement.swift`、`LearningHints.swift`;
- 新增 `platforms/macos/tests/test-ui-snapshots.py`:跑候选窗这一档(源码集合最小、命中缓存约 1 秒),
断言编译成功且产出非空 PNG。清单再漂移会直接红。

## 3. 结果

- `make macos-ui-snapshots` 重新可用:候选窗 6 张 + 面板 14 张 + 状态 HUD 6 张;
- 离线回归 **68 文件 / 337 例 PASS**;`make verify` PASS(542 产物零网络符号);
- 快照只离屏渲染,不显示窗口、不读真实配置、不碰已装包。

## 4. 快速本地验收回路(本轮确认)

| 目的 | 命令 | 代价 |
|---|---|---|
| 看候选窗/设置/关于/诊断/状态 HUD | `make macos-ui-snapshots` | 秒级;图片在 `platforms/macos/build/ui-snapshots/` |
| 点菜单/设置/学习区(隔离私有配置) | `make macos-dev` | 启动自有的隔离窗口,不装包、不碰真实数据 |
| 全量离线回归 | `make macos-offline-tests` | 约 50 秒 |
| 需要真实 IMK 行为 | 换包验收(签名+公证) | 需要手动移除/重新添加输入源 |

日常改 UI/功能优先用前两条,不必每次换包。

## 5. 关联

`scripts/ui-snapshots.sh`、`platforms/macos/tests/test-ui-snapshots.py`、ADR-301/311。
34 changes: 34 additions & 0 deletions platforms/macos/tests/test-ui-snapshots.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env python3
"""UI 离屏快照必须能编译并产出图片(防止 `scripts/ui-snapshots.sh` 的源码清单漂移)。

2026-11-15:候选窗新增 `CaretPlacement` / `LearningHints` 依赖后,快照脚本的硬编码
源码清单没有同步,`make macos-ui-snapshots` 直接编译失败。这里跑候选窗这一档(最少的
源码集合、命中缓存后约数秒),确保快速 UI 迭代入口始终可用。
"""
import os
from pathlib import Path
import subprocess
import tempfile
import unittest

ROOT = Path(__file__).resolve().parents[3]
SCRIPT = ROOT / 'scripts/ui-snapshots.sh'


class UISnapshotsTests(unittest.TestCase):
def test_candidate_snapshot_builds_and_renders(self):
with tempfile.TemporaryDirectory(prefix='lampyris-ui-shot-') as out:
env = dict(os.environ, UI='candidate', OUT=out)
result = subprocess.run(
[str(SCRIPT)], cwd=ROOT, env=env,
capture_output=True, text=True, timeout=300,
)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
pngs = sorted(Path(out).glob('*.png'))
self.assertTrue(pngs, '候选窗快照没有产出图片')
for png in pngs:
self.assertGreater(png.stat().st_size, 1024, f'{png.name}: 图片为空')


if __name__ == '__main__':
unittest.main()
4 changes: 4 additions & 0 deletions scripts/ui-snapshots.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@ cp assets/icons/yinghuo-official-app.icns "$TMP/icon.icns"
CANDIDATE_SOURCES=(
platforms/macos/Sources/ImeSession.swift
platforms/macos/Sources/Config.swift
platforms/macos/Sources/CaretPlacement.swift
platforms/macos/Sources/LearningHints.swift
platforms/macos/Sources/CandidateWindow.swift
)
PANEL_SOURCES=(
platforms/macos/Sources/ImeSession.swift
platforms/macos/Sources/Config.swift
platforms/macos/Sources/CaretPlacement.swift
platforms/macos/Sources/LearningHints.swift
platforms/macos/Sources/CandidateWindow.swift
platforms/macos/Sources/Settings.swift
platforms/macos/Sources/Feedback.swift
Expand Down
Loading