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
10 changes: 6 additions & 4 deletions HANDOFF.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

## 0. 元信息

- 更新:2026-11-12 / Claude Code(**air 本机**,仅文档:ADR-324)。上次实质更新 2026-11-09 / pi。阶段:**1.2.0 已发布并上线**(tag `v1.2.0` → `31fdbcd`,站点 `v1.2.0 · 构建 39`,air 与 pro 同包 1.2.0/39)。
- 分支:`dev` = `main` = `31fdbcd`(1.2.0 候选提交);开放 PR **0 个**。
- 版本:`Cargo.toml` = **1.2.0**、`packaging/build-number` = **39**;最新 tag **`v1.2.0`**(Release 已发布)。
- 更新:2026-11-12 / Claude Code(**air 本机**)。阶段:**线上 1.2.1 / build 40**;`main` 已合入 P1-U 三批(ADR-324…336,PR #269/#270/#271),**尚未发版、版本号未升**。air 已装 `main` 候选 `3e428b7`(报告 264)。
- 分支:`main` = `3e428b7`;`dev` 在其上有复验工具与报告 264 的提交(见 §9 首条)。
- 版本:`Cargo.toml` = **1.2.1**、`packaging/build-number` = **40**;最新 tag **`v1.2.1`**。**`main` 上的候选与发布版同号不同内容,发版前必须升版本号。**
- 最近验证:`make verify` PASS(325 产物零网络符号)、`make macos-offline-tests` **62 文件 / 328 例 PASS**、`modules/keymap/tests/test-key-roots.py` **8 例 PASS**。
- 1.2.1 身份:提交 `168115e`、ZIP `102f4928…`、DMG `a6f4bdbd…`、更新程序 `b04049e3…`、appcast `40`、包内执行 `3eeeb0aa2ae4be0facd0120c854ea822ad1ba749dd3a22611f39a97db6fc32d9`(`docs/releases/1.2.1.md`)。
- 1.2.0 候选身份:提交 `31fdbcd`、ZIP `64eeb90f…`、源码 `3dc6f717…`、宿主执行 `ef25e92ba085ea3f556e12d477fb1b6a6cd08ebbc3b74897fdb7b2d9f6eead64`(`docs/releases/1.2.0.md`)。
Expand All @@ -13,7 +13,7 @@

| 设备 | 已装包与执行 SHA | 数据 / 输入源 | 恢复点 |
|---|---|---|---|
| **air**(arm64 / macOS 27.2 / Xcode 27,用户 `joker`;pi 跑在 Background 会话,驱动不了 GUI 点击) | **1.2.0 / build 39(候选 `31fdbcd`,2026-11-09 装机)**,宿主执行 `ef25e92b…`;输入源 `Lampyris.default` 已启用(覆盖安装后常需手动再选一次,见 `docs/故障恢复.md` §4.2/§4.3) | config 与词库沿用(练习进度 `practice.tsv` 新增) | `uninstalled/`、`updates/` 可回滚 |
| **air**(arm64 / macOS 27.2 / Xcode 27,用户 `joker`;Claude 桌面应用会话**没有辅助功能/事件投递权限**,键入类探针要在已授权的终端如 ghostty 里跑) | **`main` 候选 `3e428b7`(1.2.1 / build 40 同号,2026-11-12 装机,报告 264)**,ZIP `8e7aece7…`,宿主执行 `f38e4e1a238e38249de5f8b195454bc6e48e4da37272b879b58b6b57971ee82f`;输入源 `Lampyris.default` 已启用并选中 | 装机前后未变;键入复验后 config `52af2b90…`(取值同前,多两行显式默认值)、词库 1715 行、`practice.tsv` `90530ef7…` | 旧包(1.2.1 发布版 `3eeeb0aa…`)在 `updates/install-backup-20261112T060612Z/`;用户数据备份在 `platforms/macos/build/acceptance-air-p1u-3e428b7/userdata-before/` |
| **pro**(Intel / macOS 13.7.8,用户 `bot`,SSH 别名 `pro`) | **1.2.0 / build 39**,宿主执行 `ef25e92b…`(2026-11-09 经 `upgrade.py --apply` 升级,旧包 `updates/upgrade-20261109T121300-9c1061c4/backup/`) | config `b8c7a351…`、词库 962 行,升级前后未变(`show_wubi_learning=true` 是用户有意设置) | 升级前有 `uninstalled/bundle.*` |

## 2. 本轮完成
Expand Down Expand Up @@ -117,6 +117,8 @@ make macos-offline-tests

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

- 2026-11-12 / Claude Code(air):**P1-U 真机键入复验 22/22 PASS(报告 264 §3.1)**。用户为代理会话的责任进程(`~/Library/Application Support/Claude/claude-code/<版本>/…/claude.app`,不是 `/Applications/Claude.app`)授了辅助功能权限后复跑 `quality-samples.sh`:原 13 条 + ADR-325…336 的 9 条全过。跑后 `config.toml` 取值还原但多出两行显式默认值(SHA `88651507…`→`52af2b90…`);词库 1713→1715 行(含样本副作用 `pinyin zhuang 装 1`)。**未验证**:`;`/`12:30`、五笔码浮层、练习新题型、设置页新开关、DMG 完成页(需人工目视);内存门禁与延迟未复测。PR #272(报告与探针工具)待合并。
- 2026-11-12 / Claude Code(air):**P1-U 候选 `3e428b7` 装机 PASS、真机键入复验 BLOCKED(报告 264)**。PR #271 已合并;从 CI 验收包(run `43163118879`,ZIP `8e7aece7…`,Notarized)覆盖安装:切 ABC → 停宿主 → `install.sh`,装后执行 `f38e4e1a…` = 包内,config/词库/练习进度 SHA 不变,宿主跑新二进制。**键入复验一条都没跑成**:本会话进程 `AXIsProcessTrusted=false`,合成按键被系统丢弃。已给 `quality-samples.sh` 加 9 条 ADR-325…336 样本,并让 preflight 能识别「无事件投递权限」(`keytopid --check-access`)。**下一步:用户在已授权终端跑报告 264 §4 的一条命令,再按 §5 目视 5 类项**;通过后才谈升版本号与发版。
- 2026-11-12 / Claude Code(air):**P1-U 第三批(ADR-333…336)+ 前两档已合入 main**。PR [#269](https://github.com/EasyIndie/EasyInputMethod/pull/269)(第一档)与 [#270](https://github.com/EasyIndie/EasyInputMethod/pull/270)(第二档)均已用合并提交并入(`c882c06`、`2f8ee06`),**下面一条日志里「第二档未推送」已过时**。第三批:按应用记住中英状态(仅内存)、练习「词组」题型(随包码表前 800 词)、薄弱字清单(`practice.collect_weak_chars` 默认关,`weak-chars.tsv`)、小鹤双拼(`pinyin.scheme`,仅拼音模式;425 个音节 419 个可达)。Schema 27→30。四道检查全绿、评测 98.2%/86.4% 与基线一致。**三批改动全部未装机**,复验清单见 `docs/待办与积压.md` P1-U;P1-U 剩余 8 项都需用户先定口径或授权取数据(同处有表)。仓库已开启 auto-merge。
- 2026-11-12 / Claude Code(air):**P1-U 第二档可直接做的部分完成(ADR-330…332)**。U2-1 拼音分段选词(`Candidate.consumed`、`Session::preedit`、`IME_SELECT_PARTIAL`,整句学成用户拼音词);U2-4 混输下拼音上屏后提示五笔码(`candidate.hint_wubi_code`,Schema 26→27);U2-5 练习新增「字根」题型并排最前。第一档 PR [#269](https://github.com/EasyIndie/EasyInputMethod/pull/269) 已开(首跑 `macos` 红:预览冒烟写死设置项 23 → `7e37dba` 修)。**第二档提交只在本地 `dev`,未推送**——同一个 `dev → main` 只能有一个 PR,要等 #269 合并后再推并开第二档 PR。四道检查全绿(`make verify`、离线 62/328、预览冒烟、`build.sh --strict`),**均未装机**。教训:离线回归不含预览冒烟与宿主编译,改设置项数量或 `InputController.swift` 后必须另跑这两项。剩余 U2-2 五笔造词 / U2-3 扩展词库 / U2-5 分阶段与跟打都需用户先定口径。
- 2026-11-12 / Claude Code(air):**P1-U 第一档全部完成(ADR-326…329)**。U1-2 拼音没打完给补全(`nih`→你好,补全不拦五笔自动上屏,评测与基线一致 98.2%/86.4%);U1-3 `;`/`'` 选二三候选、`[`/`]` 以词定字(两个开关默认开,Schema 24→26);U1-5 练习按错题加权出题(文件格式不变);U1-4 安装完成页加上手提示(窗口高 300→340,**版式未目视确认**)。`dev` 领先 `main` 7 个提交(`df2019c`…),`make verify` PASS、离线 62 文件 / 328 例 PASS。**未推送、未开 PR、未换包;六项行为都待装机实键复验**(清单见 `docs/待办与积压.md` P1-U 末尾)。下一步:第二档 U2-1 → U2-4 → U2-2。
Expand Down
123 changes: 123 additions & 0 deletions docs/reviews/264-p1u-device-install-and-reverify.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# 264 · P1-U(ADR-324…336)装机与真机复验

- 日期:2026-11-12 / Claude Code(air 本机,Claude 桌面应用会话)
- 范围:把已合入 `main` 的 P1-U 三批改动(PR #269 / #270 / #271)装到 air,并做真机键入复验
- 结论:**装机 PASS;真机键入复验 22/22 PASS**(首轮因进程无「辅助功能 / 事件投递」权限 BLOCKED,用户授权后复跑通过,§3.1)。
探针覆盖不到、仍需人工目视的 5 类项见 §5——**这些尚未验证**。

## 1. 候选身份

| 项 | 值 |
|---|---|
| 源码提交 | `3e428b78f69c4da525d131c66603fdc307b187a3`(`main`,Merge PR #271) |
| CI 构建 | `macOS Acceptance Package` run `43163118879`(success) |
| ZIP | `Lampyris-1.2.1-universal.zip`,SHA-256 `8e7aece75dd65de169de5b1b3417a6238e61a1ae817a61822edfe29e413f704b`(与随包 `.sha256` 一致) |
| 包内执行 SHA | `f38e4e1a238e38249de5f8b195454bc6e48e4da37272b879b58b6b57971ee82f` |
| 版本 / 构建号 | 1.2.1 / 40(**与线上发布版同号,内容不同**;发版前须升版本号) |
| 签名 / 公证 | `codesign --verify --deep --strict` 通过;`spctl`:accepted,Notarized Developer ID(2N62934Y28) |

## 2. 装机(PASS)

| 步骤 | 结果 | 证据 |
|---|---|---|
| 装前记录 | 已装 1.2.1/40,执行 `3eeeb0aa…`(`168115e`);config `88651507…`;词库 1713 行 `bffc9d1a…`;`practice.tsv` `90530ef7…` | `00-pre.txt` |
| 用户数据备份 | config / 词库 / 练习进度复制到证据目录 | `userdata-before/` |
| 安装器预检 | `--dry-run`:签名与公证通过,但**拒绝在宿主运行时替换** | — |
| 停宿主并安装 | 切到 ABC → `pkill -x Lampyris` → `LAMPYRIS_RESTART_HOST=1 ./scripts/install.sh --app ./Lampyris.app`;旧包备份到 `updates/install-backup-20261112T060612Z/`;更新程序一并安装;尾部输出「已注册到输入源」 | `10-install.txt` |
| 装后回读 | 已装执行 SHA = 包内 `f38e4e1a…`;`SOURCE-COMMIT` = `3e428b7`;输入源已启用并选中;宿主 PID 23732,`lsof` 无 deleted inode(跑的是新二进制);**config / 词库 / 练习进度 SHA 与装前逐一相同** | `11-post-install.txt` |

## 3. 真机键入复验(首轮 BLOCKED → 授权后 PASS)

### 3.0 首轮:BLOCKED

- `tools/macos-probe/quality-samples.sh` 在第一步「归位到中文态」即停,**没有执行任何用例**(`20-quality.txt`)。
- 归因:单独做一次最小键入(新建 TextEdit 文档 → `keytopid … 'wq ' --hid`)显示「posted」,但文档为空、`axtext` 报 `NO_WINDOW`。
自检程序给出 `AXIsProcessTrusted() = false`、`CGPreflightPostEventAccess() = false`:**调用方进程未被系统信任**,
合成按键被静默丢弃、AX 也读不到窗口。此前的验收都是从已授权的终端发起的。
- 这是系统安全设置,代理不应也没有去改;未向任何应用送达按键(权限不足时系统丢弃事件),未改动用户配置与词库。
- 探针自开的 2 个空白 TextEdit 文档已关闭、TextEdit 已退出(`99-restore.txt`)。

**工具缺陷(已修)**:`acceptance-preflight.sh` 此前在这种环境下仍报 `ready:true`,随后的键入项只会表现成含义不明的 BLOCKED。
现在 `keytopid --check-access` 提供只读自检,preflight 新增 `event_access` 检查,无权限时直接给出「请在已授权的终端里运行」并以 78 退出。

### 3.1 授权后复跑:22/22 PASS

用户在「系统设置 → 隐私与安全性 → 辅助功能」里为本会话的责任进程授权
(`~/Library/Application Support/Claude/claude-code/<版本>/…/claude.app`——桌面版 Claude 通过 `disclaimer` 助手把 TCC 责任转给它,
给 `/Applications/Claude.app` 授权无效;路径带版本号,Claude Code 更新后需重新授权)。
`keytopid --check-access` 回读 `ax_trusted:true, post_event:true`,preflight `event_access: ok`。

| 样本 | 结果 | 实得 |
|---|---|---|
| 五笔四码自动上屏 / 一级简码 | PASS | 你 / 的 |
| 混输拼音兜底、全拼双字词、拼音长词 | PASS | 你好 / 中国 / 中华人民共和国 |
| 中文标点句号、逗号、成对引号 | PASS | 你好。 / 你好, / ‘’ |
| 翻页键不破坏输入、撤销回到空态、长文本不丢字 | PASS | — |
| **数字后句点保持半角**(ADR-325) | PASS | `3.14` |
| **数字后逗号仍是中文**(ADR-325) | PASS | `3,` |
| **拼音没打完给补全**(ADR-326) | PASS | 你好 |
| **以词定字取首字 / 末字**(ADR-327) | PASS | 你 / 好 |
| **分段选词后回车**(ADR-330) | PASS | 你好shijie |
| **双拼(小鹤)**(ADR-336) | PASS | 你好 |
| **薄弱字清单**(ADR-335) | PASS | 「装」已记入 `weak-chars.tsv` |
| **按应用记住英文状态**(ADR-333) | PASS | nihao |
| 切输入源不丢字、失焦再回来不丢字 | PASS | abc \| 你好 / 你好 |

证据:`21-quality.txt`、`21-quality.stderr`、`quality-2/`、`99-restore-2.txt`。

**跑完后的状态(如实记录,不是全都原样)**:

| 项 | 状态 |
|---|---|
| 输入源 / 宿主 / 已装执行 SHA | 萤火虫已选中;宿主 PID 未变;执行 `f38e4e1a…` |
| `config.toml` | **取值已还原**(`mode=mixed`、`pinyin.scheme=full`、`practice.collect_weak_chars=false`),但文件里**多了这两行显式写出的默认值**,SHA 由 `88651507…` 变为 `52af2b90…`。按铁律 3 没有用备份文件覆盖回去 |
| `weak-chars.tsv` | 用例产生的文件已删除(装前不存在) |
| 用户词库 | 1713 → 1715 行。样本造成的:`nihao 你好`、`zhongguo 中国`、`zhonghuarenmingongheguo 中华人民共和国`、`r 的`、`wq 你` 学习次数增加,**新增一行 `pinyin zhuang 装 1`**(薄弱字用例的副作用,未清理);其余变化是用户在此期间自己打字产生的 |
| `practice.tsv` | 未变 |
| TextEdit | 样本结束后仍在运行(无文档),已确认 0 个文档后退出 |

**样本自身的两个待改进点**:薄弱字用例会在用户词库留下一条学习记录;改配置后 `config.toml` 会多出显式默认值行。
两者都无功能影响,后续可让键入类样本统一跑在私有数据根(`LAMPYRIS_SUPPORT_DIR`,ADR-215)下根治。

## 4. 复跑方法

```sh
cd ~/Documents/EasyInputMethod
OUT="$PWD/platforms/macos/build/acceptance-air-p1u-3e428b7/quality" ./tools/macos-probe/quality-samples.sh
```

需在有辅助功能权限的进程里运行(已授权的终端,或已授权的代理会话)。约 4–5 分钟,期间会打开文本编辑并发送按键,请勿操作键盘。新增的 9 条样本(ADR-325…336):

| 样本 | 按键 | 期望 |
|---|---|---|
| 数字后句点保持半角 | `3.14` | `3.14` |
| 数字后逗号仍是中文 | `3,` | `3,` |
| 拼音没打完给补全 | `nih␣` | `你好` |
| 以词定字取首字 / 末字 | `nihao[` / `nihao]` | `你` / `好` |
| 分段选词后回车 | `nihaoshijie2⏎` | `你好shijie` |
| 双拼(小鹤) | 拼音模式 + `pinyin.scheme=xiaohe`,`nihc␣` | `你好` |
| 薄弱字清单 | 开 `practice.collect_weak_chars`,`zhuang␣` | 上屏的字出现在 `weak-chars.tsv` |
| 按应用记住英文状态 | Shift 切英文 → 新建文档 → `nihao` | `nihao` |

样本会临时改配置(经 `ime-cli :set`,即 `ime-config` 的写路径)并在结束时还原;薄弱字用例产生的文件会删除;
「分段选词」会给用户词库里「你好」的拼音学习次数加一。

## 5. 仍需人工目视的项(探针覆盖不到)

| 项 | 原因 |
|---|---|
| `;` 选第二候选、`12:30` | 探针按键串以分号分段,打不出字面的 `;` 与 `:`;仅单测覆盖 |
| 拼音上屏后的五笔码浮层(ADR-331) | 浮层不在 AX 树里,需目视 |
| 练习窗口「字根」「词组」题型与错题加权(ADR-328/332/334) | 需目视;词组题答后讲解区(两位键码的格子)尚无截图 |
| 设置页 7 个新开关 | 同源代码已由 `test-settings-presentation.py` 覆盖,实机未看 |
| 安装完成页的上手提示(ADR-329) | 在 DMG 图形安装器里;本次用的是 ZIP + `install.sh` |

## 6. 回滚

旧包在 `~/Library/Application Support/Lampyris/updates/install-backup-20261112T060612Z/Lampyris.app`(1.2.1 发布版,执行 `3eeeb0aa…`);
用户数据备份在证据目录 `userdata-before/`。

## 7. 证据

`platforms/macos/build/acceptance-air-p1u-3e428b7/`(不入库):`00-pre.txt`、`10-install.txt`、`11-post-install.txt`、
`20-quality.txt`、`20-quality.stderr`、`99-restore.txt`、`userdata-before/`、`artifact/`、`extracted/`。
1 change: 1 addition & 0 deletions docs/reviews/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
| 1.1.0 发布线 | 225–250 | 简码/排序、验收成本、延迟归因、1.1.0 发布与站点 |
| 1.2.0 候选与发布 | 251–262 | B1 门禁、B0 运行时、学习区、练习四题型与键位图、1.2.0 发布 |
| 1.2.1 清理 | 263 | 安装/无障碍补丁、死代码与文档审计 |
| P1-U 装机 | 264 | ADR-324…336 候选 `3e428b7` 装机 PASS;真机键入复验 22/22 PASS(首轮因无辅助功能权限 BLOCKED,授权后复跑);5 类目视项待人工 |

## 4. 常见查找

Expand Down
4 changes: 2 additions & 2 deletions docs/tasks/T-ITER-22-coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

| IT-22 条目 | 覆盖手段 | 怎么跑 |
|---|---|---|
| 1.1–1.3、1.7–1.12 上屏/标点/全角/简繁/模式/中英 | 热键探针 + 质量样本 | `make macos-auto-acceptance`(7 项)、`tools/macos-probe/quality-samples.sh`(13 项) |
| 1.1–1.3、1.7–1.12 上屏/标点/全角/简繁/模式/中英 | 热键探针 + 质量样本 | `make macos-auto-acceptance`(7 项)、`tools/macos-probe/quality-samples.sh`(22 项) |
| 1.4 翻页、1.5 方向键选择 | 组合导航单测 + 质量样本「翻页键不破坏输入」 | `make test`、`quality-samples.sh` |
| 2.1 长组合不丢字 | 质量样本「长文本不丢字」 | `quality-samples.sh` |
| 2.2–2.6 退格/Esc/Home/End/Delete/Tab | 核心与 FFI 单测(ADR-164) | `make test`(`ime-core`/`ime-ffi`) |
Expand Down Expand Up @@ -77,7 +77,7 @@ make macos-acceptance-full # ~5 分钟:preflight → 热键/上屏 →
## 4. 与旧清单的差异(为什么能砍掉 47 项)

0. **只依赖系统自带应用**(报告234):TextEdit / Safari / Terminal 之外的一律 optional(装了才测、没装 SKIP),由 `test-acceptance-portability.py` 强制。
1. **同一件事此前被写了三遍**:`quality-samples.sh`(16 项)、`acceptance-auto.sh`(8 项)、IT-22 手工表(12 项重叠)。报告 230 之后两份脚本**按行为分工**:`quality-samples.sh` 断言打字产物(13 项),`acceptance-auto.sh` 断言热键状态语义(7 项),重复项已删并由 `test-acceptance-map.py` 守住不再回流。
1. **同一件事此前被写了三遍**:`quality-samples.sh`(16 项)、`acceptance-auto.sh`(8 项)、IT-22 手工表(12 项重叠)。报告 230 之后两份脚本**按行为分工**:`quality-samples.sh` 断言打字产物(22 项;报告264 起含 ADR-325…336 的 9 条:数字后标点、拼音补全、以词定字、分段选词、双拼、薄弱字、按应用记住英文),`acceptance-auto.sh` 断言热键状态语义(7 项),重复项已删并由 `test-acceptance-map.py` 守住不再回流。
2. **离屏单测已经断言了 GUI 结构**:候选/设置/关于/学习的布局与文案由 `test-*-presentation.py` 断言,手工"看一眼分组是否连续"不再重复。
3. **几何/落点类**(多屏、边缘、翻页位置)已有 `CaretPlacement` 与离屏快照对比度自动判定(ADR-301、报告 197)。
4. **安装类**从"每次走查"降为"每版一次",因为它们只在换包时才有意义。
Expand Down
Loading
Loading