From 0e6f1bedce658aedf345329ed4778407416217b0 Mon Sep 17 00:00:00 2001 From: wangzhizhou <824219521@qq.com> Date: Sun, 15 Nov 2026 01:54:37 +0800 Subject: [PATCH] fix(ui-snapshots): sync source list with CandidateWindow dependencies - add CaretPlacement.swift and LearningHints.swift to snapshot source lists - add test-ui-snapshots.py so drift fails offline regression - make macos-ui-snapshots renders candidate/panels/HUD again (report 286) Signed-off-by: wangzhizhou <824219521@qq.com> --- HANDOFF.md | 4 ++ docs/reviews/286-ui-snapshot-source-drift.md | 42 ++++++++++++++++++++ platforms/macos/tests/test-ui-snapshots.py | 34 ++++++++++++++++ scripts/ui-snapshots.sh | 4 ++ 4 files changed, 84 insertions(+) create mode 100644 docs/reviews/286-ui-snapshot-source-drift.md create mode 100644 platforms/macos/tests/test-ui-snapshots.py diff --git a/HANDOFF.md b/HANDOFF.md index 5240cba6..1cee2650 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -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。 diff --git a/docs/reviews/286-ui-snapshot-source-drift.md b/docs/reviews/286-ui-snapshot-source-drift.md new file mode 100644 index 00000000..296065ca --- /dev/null +++ b/docs/reviews/286-ui-snapshot-source-drift.md @@ -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。 diff --git a/platforms/macos/tests/test-ui-snapshots.py b/platforms/macos/tests/test-ui-snapshots.py new file mode 100644 index 00000000..30462900 --- /dev/null +++ b/platforms/macos/tests/test-ui-snapshots.py @@ -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() diff --git a/scripts/ui-snapshots.sh b/scripts/ui-snapshots.sh index 4e801708..e47e452e 100755 --- a/scripts/ui-snapshots.sh +++ b/scripts/ui-snapshots.sh @@ -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