From 755e206489e00302f863049d23ab394956b27fd5 Mon Sep 17 00:00:00 2001 From: wangzhizhou <824219521@qq.com> Date: Thu, 12 Nov 2026 13:36:59 +0800 Subject: [PATCH 1/3] test: add device samples for the post-1.2.1 input behaviours MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit quality-samples.sh now types the ADR-325…336 behaviours on an installed package: ASCII punctuation after digits, unfinished-pinyin completion, pick-a-character, segmented selection, Xiaohe double pinyin, the weak-character list and per-app English state. Config changes go through ime-cli :set and are restored. Signed-off-by: wangzhizhou <824219521@qq.com> --- tools/macos-probe/quality-samples.sh | 62 ++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tools/macos-probe/quality-samples.sh b/tools/macos-probe/quality-samples.sh index beea234f..3297ad38 100755 --- a/tools/macos-probe/quality-samples.sh +++ b/tools/macos-probe/quality-samples.sh @@ -114,6 +114,68 @@ run "翻页键不破坏输入" 'nihao ,,,' ' run "撤销回到空态" 'wqiy;cmd+z' 'empty:' run "长文本不丢字" 'nihao nihao nihao nihao wqiy ' 'contains:你好你好' +# —— 1.2.1 之后的输入体验(ADR-325…336) —— +# 限制:按键串用分号分段,探针打不出字面的 `;` 与 `:`,所以「; 选第二候选」「12:30」只有单测覆盖。 +ensure_cn >/dev/null 2>&1 +run "数字后句点保持半角" '3.14' 'exact:3.14' +run "数字后逗号仍是中文" '3,' 'exact:3,' +run "拼音没打完给补全" 'nih ' 'exact:你好' +run "以词定字取首字" 'nihao[' 'exact:你' +run "以词定字取末字" 'nihao]' 'exact:好' +# 选走前半段(第二候选「你好」只覆盖 nihao)后回车:已选文字 + 余码原文一起上屏。 +run "分段选词后回车" 'nihaoshijie2;return' 'exact:你好shijie' + +# 改配置只走 ime-config 的写路径(ime-cli :set),用完还原;缺 ime-cli 就记 BLOCKED,不手改 config.toml。 +ROOT="$(cd "$PROBE/../.." && pwd)" +IME_CLI="$ROOT/target/release/ime-cli" +CONFIG_FILE="$HOME/Library/Application Support/Lampyris/config.toml" +cfg_set() { printf ':set %s %s\n:quit\n' "$1" "$2" | "$IME_CLI" --config "$CONFIG_FILE" >/dev/null 2>&1; sleep 1.2; } + +case_double_pinyin() { + TOTAL=$((TOTAL + 1)) + [ -x "$IME_CLI" ] || { blocked "双拼(小鹤)" "缺 target/release/ime-cli(先 cargo build --release -p ime-cli)"; return; } + cfg_set mode '"pinyin"'; cfg_set pinyin.scheme '"xiaohe"' + got=$(type_read 'nihc ') + cfg_set pinyin.scheme '"full"'; cfg_set mode '"mixed"' + if check 'exact:你好' "$got"; then printf '%-26s PASS %s\n' "双拼(小鹤)" "$got" + else printf '%-26s FAIL 期望 你好,实得 %s\n' "双拼(小鹤)" "$got"; FAILED=$((FAILED + 1)); fi +} + +case_weak_chars() { + TOTAL=$((TOTAL + 1)) + [ -x "$IME_CLI" ] || { blocked "薄弱字清单" "缺 target/release/ime-cli"; return; } + weak="$HOME/Library/Application Support/Lampyris/weak-chars.tsv" + existed=0; [ -f "$weak" ] && { existed=1; cp "$weak" "$OUT/weak-chars.before.tsv"; } + cfg_set practice.collect_weak_chars true + # zhuang 超过 4 码,五笔不参与;首选是拼音单字。 + got=$(type_read 'zhuang ') + sleep 0.5 + recorded=0 + [ -n "$got" ] && [ -f "$weak" ] && grep -q "^${got} " "$weak" && recorded=1 + cfg_set practice.collect_weak_chars false + # 还原:本用例造出来的文件删掉;原来就有的恢复原样。 + if [ "$existed" -eq 1 ]; then cp "$OUT/weak-chars.before.tsv" "$weak"; else rm -f "$weak"; fi + if [ "$recorded" -eq 1 ]; then printf '%-26s PASS %s 已记入\n' "薄弱字清单" "$got" + else printf '%-26s FAIL 上屏 %s,未见于 weak-chars.tsv\n' "薄弱字清单" "$got"; FAILED=$((FAILED + 1)); fi +} + +case_remember_english() { + TOTAL=$((TOTAL + 1)) + ensure_cn >/dev/null 2>&1 + pid=$(front_pid); "$BIN/keytopid" "$pid" 'shiftc' 200 600 --hid >/dev/null 2>&1 + # 同一应用里新建文档(新的输入上下文):应仍是英文,字母原样上屏。 + new_doc + got=$(type_read 'nihao') + ensure_cn >/dev/null 2>&1 + if check 'exact:nihao' "$got"; then printf '%-26s PASS %s\n' "按应用记住英文状态" "$got" + else printf '%-26s FAIL 期望 nihao,实得 %s\n' "按应用记住英文状态" "$got"; FAILED=$((FAILED + 1)); fi +} + +case_double_pinyin +case_weak_chars +case_remember_english +ensure_cn >/dev/null 2>&1 + # —— 切换与焦点(MVP「日常可用」条目) —— # 注意:用 TIS 切回输入源后,已开文档的输入上下文不会立即跟随;新建文档才会取到当前源。 From dda98e01df571ea0e7b737456494fc024a6ab650 Mon Sep 17 00:00:00 2001 From: wangzhizhou <824219521@qq.com> Date: Thu, 12 Nov 2026 14:14:52 +0800 Subject: [PATCH 2/3] =?UTF-8?q?docs:=20report=20264=20=E2=80=94=20P1-U=20c?= =?UTF-8?q?andidate=20installed=20on=20air,=20typed=20re-verification=20bl?= =?UTF-8?q?ocked?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The main candidate 3e428b7 installs cleanly and leaves user data untouched, but the agent session lacks Accessibility/event-post access, so no typed sample ran. Preflight now detects that case (keytopid --check-access) instead of reporting ready, and the coverage map counts the nine new samples. Signed-off-by: wangzhizhou <824219521@qq.com> --- HANDOFF.md | 9 +- .../264-p1u-device-install-and-reverify.md | 82 +++++++++++++++++++ docs/reviews/README.md | 1 + docs/tasks/T-ITER-22-coverage.md | 4 +- ...36\344\270\216\347\247\257\345\216\213.md" | 5 +- tools/macos-probe/acceptance-preflight.sh | 7 ++ tools/macos-probe/keytopid.swift | 8 ++ 7 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 docs/reviews/264-p1u-device-install-and-reverify.md diff --git a/HANDOFF.md b/HANDOFF.md index 52b23bd6..b9c5ac82 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -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`)。 @@ -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 `88651507…`、词库 1713 行 `bffc9d1a…`、`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. 本轮完成 @@ -117,6 +117,7 @@ make macos-offline-tests ## 9. 会话日志(最近) +- 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。 diff --git a/docs/reviews/264-p1u-device-install-and-reverify.md b/docs/reviews/264-p1u-device-install-and-reverify.md new file mode 100644 index 00000000..737bdc17 --- /dev/null +++ b/docs/reviews/264-p1u-device-install-and-reverify.md @@ -0,0 +1,82 @@ +# 264 · P1-U(ADR-324…336)装机与真机复验 + +- 日期:2026-11-12 / Claude Code(air 本机,Claude 桌面应用会话) +- 范围:把已合入 `main` 的 P1-U 三批改动(PR #269 / #270 / #271)装到 air,并做真机键入复验 +- 结论:**装机 PASS;真机键入复验 BLOCKED**——本会话的进程没有「辅助功能 / 事件投递」权限,按键被系统静默丢弃, + **12 项行为在真机上一项都还没验证**。需要在已授权的终端(如 ghostty)里跑一条命令补做(§4)。 + +## 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) + +- `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 退出。 + +## 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/`。 diff --git a/docs/reviews/README.md b/docs/reviews/README.md index 89e65108..0526c7d4 100644 --- a/docs/reviews/README.md +++ b/docs/reviews/README.md @@ -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;真机键入复验因进程无辅助功能权限 BLOCKED | ## 4. 常见查找 diff --git a/docs/tasks/T-ITER-22-coverage.md b/docs/tasks/T-ITER-22-coverage.md index 7656868b..b9fe4db2 100644 --- a/docs/tasks/T-ITER-22-coverage.md +++ b/docs/tasks/T-ITER-22-coverage.md @@ -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`) | @@ -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. **安装类**从"每次走查"降为"每版一次",因为它们只在换包时才有意义。 diff --git "a/docs/\345\276\205\345\212\236\344\270\216\347\247\257\345\216\213.md" "b/docs/\345\276\205\345\212\236\344\270\216\347\247\257\345\216\213.md" index bab39a7e..ae202e31 100644 --- "a/docs/\345\276\205\345\212\236\344\270\216\347\247\257\345\216\213.md" +++ "b/docs/\345\276\205\345\212\236\344\270\216\347\247\257\345\216\213.md" @@ -76,7 +76,10 @@ > 拼音上屏后的五笔码浮层、练习「字根」题型。**第二档剩余**:U2-2 五笔造词(要定启发式)、U2-3 扩展词库(要联网取数据并登记许可)、 > U2-5 分阶段解锁与跟打(要定口径与文本来源)——三项都需要你先拍板,不是能直接开工的活。 -> **第三批状态(2026-11-12)**:ADR-333…336 已完成(按应用记住中英、词组题型、薄弱字清单、小鹤双拼),四道检查全绿、评测与基线一致,**均未装机**。 +> **第三批状态(2026-11-12)**:ADR-333…336 已完成(按应用记住中英、词组题型、薄弱字清单、小鹤双拼),四道检查全绿、评测与基线一致。 +> +> **装机状态(报告 264)**:三批已合入 `main`,候选 `3e428b7` 已装 air(装机 PASS);**真机键入复验 BLOCKED**(代理会话无辅助功能权限), +> 待在已授权终端跑 `quality-samples.sh`(新增 9 条样本)并目视 5 类项。**在此之前,12 项行为都只有自动化测试证据。** > > **P1-U 里剩下的,全部卡在「先要你定一件事」或「先要数据」上**: > diff --git a/tools/macos-probe/acceptance-preflight.sh b/tools/macos-probe/acceptance-preflight.sh index 4157f84a..a2a2d6c0 100755 --- a/tools/macos-probe/acceptance-preflight.sh +++ b/tools/macos-probe/acceptance-preflight.sh @@ -34,6 +34,13 @@ done front=$(osascript -e 'tell application "System Events" to name of first application process whose frontmost is true' 2>/dev/null) [ -n "$front" ] && check gui_session ok "" || check gui_session fail "无图形会话(无法取前台应用)" [ -x "$BIN/imetype" ] && check probe_built ok "" || check probe_built fail "探针未构建" +# 报告264:调用方进程没有「辅助功能/事件投递」权限时,按键被系统静默丢弃、AX 也读不到窗口, +# 所有键入项会连环 BLOCKED 却看不出原因。退出码 4 = 无权限;其它(旧二进制不认识该参数)不判。 +if [ -x "$BIN/keytopid" ]; then + "$BIN/keytopid" --check-access >/dev/null 2>&1 + [ "$?" -eq 4 ] && check event_access fail "当前进程没有辅助功能/事件投递权限:请在已授权的终端里运行" \ + || check event_access ok "" +fi if [ -x "$BIN/imetype" ] && [ ! -x "$BIN/axfocus" ]; then check ax_probe fail "缺少 axfocus"; fi # 报告199:只在目录缺失时重建会留下旧二进制(改完 imetype 后仍跑旧的),所以二进制更新时也重建。 STALE=0 diff --git a/tools/macos-probe/keytopid.swift b/tools/macos-probe/keytopid.swift index f9d64396..447def88 100644 --- a/tools/macos-probe/keytopid.swift +++ b/tools/macos-probe/keytopid.swift @@ -11,6 +11,14 @@ let keys: [Character: CGKeyCode] = [ ] let args = CommandLine.arguments +// 报告264:发键与 AX 回读都要求「调用方进程」被系统信任(辅助功能 / 事件投递)。 +// 没有权限时事件会被静默丢弃,表现成「按键发了、文档是空的」;这里提供一个只读自检给 preflight。 +if args.contains("--check-access") { + let trusted = AXIsProcessTrusted() + let post = CGPreflightPostEventAccess() + print("{\"ax_trusted\":\(trusted),\"post_event\":\(post)}") + exit(trusted && post ? 0 : 4) +} guard args.count >= 3, let pid = pid_t(args[1]) else { print("usage: keytopid ") exit(2) From 254804453aa92530195396e6c228095c7630655d Mon Sep 17 00:00:00 2001 From: wangzhizhou <824219521@qq.com> Date: Thu, 12 Nov 2026 14:26:47 +0800 Subject: [PATCH 3/3] =?UTF-8?q?docs:=20report=20264=20=E2=80=94=20typed=20?= =?UTF-8?q?re-verification=20passes=2022/22=20after=20access=20was=20grant?= =?UTF-8?q?ed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Records the rerun on the installed main candidate, the exact post-run state of the user's config and dictionary, and the five item groups that still need a human look. Signed-off-by: wangzhizhou <824219521@qq.com> --- HANDOFF.md | 3 +- .../264-p1u-device-install-and-reverify.md | 51 +++++++++++++++++-- docs/reviews/README.md | 2 +- ...36\344\270\216\347\247\257\345\216\213.md" | 5 +- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/HANDOFF.md b/HANDOFF.md index b9c5ac82..9dedd5fa 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -13,7 +13,7 @@ | 设备 | 已装包与执行 SHA | 数据 / 输入源 | 恢复点 | |---|---|---|---| -| **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 `88651507…`、词库 1713 行 `bffc9d1a…`、`practice.tsv` `90530ef7…`,装机前后未变 | 旧包(1.2.1 发布版 `3eeeb0aa…`)在 `updates/install-backup-20261112T060612Z/`;用户数据备份在 `platforms/macos/build/acceptance-air-p1u-3e428b7/userdata-before/` | +| **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. 本轮完成 @@ -117,6 +117,7 @@ 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 分阶段与跟打都需用户先定口径。 diff --git a/docs/reviews/264-p1u-device-install-and-reverify.md b/docs/reviews/264-p1u-device-install-and-reverify.md index 737bdc17..54c75e84 100644 --- a/docs/reviews/264-p1u-device-install-and-reverify.md +++ b/docs/reviews/264-p1u-device-install-and-reverify.md @@ -2,8 +2,8 @@ - 日期:2026-11-12 / Claude Code(air 本机,Claude 桌面应用会话) - 范围:把已合入 `main` 的 P1-U 三批改动(PR #269 / #270 / #271)装到 air,并做真机键入复验 -- 结论:**装机 PASS;真机键入复验 BLOCKED**——本会话的进程没有「辅助功能 / 事件投递」权限,按键被系统静默丢弃, - **12 项行为在真机上一项都还没验证**。需要在已授权的终端(如 ghostty)里跑一条命令补做(§4)。 +- 结论:**装机 PASS;真机键入复验 22/22 PASS**(首轮因进程无「辅助功能 / 事件投递」权限 BLOCKED,用户授权后复跑通过,§3.1)。 + 探针覆盖不到、仍需人工目视的 5 类项见 §5——**这些尚未验证**。 ## 1. 候选身份 @@ -26,7 +26,9 @@ | 停宿主并安装 | 切到 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) +## 3. 真机键入复验(首轮 BLOCKED → 授权后 PASS) + +### 3.0 首轮:BLOCKED - `tools/macos-probe/quality-samples.sh` 在第一步「归位到中文态」即停,**没有执行任何用例**(`20-quality.txt`)。 - 归因:单独做一次最小键入(新建 TextEdit 文档 → `keytopid … 'wq ' --hid`)显示「posted」,但文档为空、`axtext` 报 `NO_WINDOW`。 @@ -38,14 +40,53 @@ **工具缺陷(已修)**:`acceptance-preflight.sh` 此前在这种环境下仍报 `ready:true`,随后的键入项只会表现成含义不明的 BLOCKED。 现在 `keytopid --check-access` 提供只读自检,preflight 新增 `event_access` 检查,无权限时直接给出「请在已授权的终端里运行」并以 78 退出。 -## 4. 补做方法(需用户在已授权的终端里执行) +### 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): +需在有辅助功能权限的进程里运行(已授权的终端,或已授权的代理会话)。约 4–5 分钟,期间会打开文本编辑并发送按键,请勿操作键盘。新增的 9 条样本(ADR-325…336): | 样本 | 按键 | 期望 | |---|---|---| diff --git a/docs/reviews/README.md b/docs/reviews/README.md index 0526c7d4..a34d34d1 100644 --- a/docs/reviews/README.md +++ b/docs/reviews/README.md @@ -39,7 +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;真机键入复验因进程无辅助功能权限 BLOCKED | +| P1-U 装机 | 264 | ADR-324…336 候选 `3e428b7` 装机 PASS;真机键入复验 22/22 PASS(首轮因无辅助功能权限 BLOCKED,授权后复跑);5 类目视项待人工 | ## 4. 常见查找 diff --git "a/docs/\345\276\205\345\212\236\344\270\216\347\247\257\345\216\213.md" "b/docs/\345\276\205\345\212\236\344\270\216\347\247\257\345\216\213.md" index ae202e31..e4c9d1da 100644 --- "a/docs/\345\276\205\345\212\236\344\270\216\347\247\257\345\216\213.md" +++ "b/docs/\345\276\205\345\212\236\344\270\216\347\247\257\345\216\213.md" @@ -78,8 +78,9 @@ > **第三批状态(2026-11-12)**:ADR-333…336 已完成(按应用记住中英、词组题型、薄弱字清单、小鹤双拼),四道检查全绿、评测与基线一致。 > -> **装机状态(报告 264)**:三批已合入 `main`,候选 `3e428b7` 已装 air(装机 PASS);**真机键入复验 BLOCKED**(代理会话无辅助功能权限), -> 待在已授权终端跑 `quality-samples.sh`(新增 9 条样本)并目视 5 类项。**在此之前,12 项行为都只有自动化测试证据。** +> **装机状态(报告 264)**:三批已合入 `main`,候选 `3e428b7` 已装 air;**真机键入复验 22/22 PASS**(含 ADR-325/326/327/330/333/335/336 的 9 条新样本)。 +> **仍待人工目视的 5 类**:`;` 选第二候选与 `12:30`、五笔码提示浮层、练习「字根」「词组」题型、设置页 7 个新开关、DMG 安装完成页。 +> 发版前还需:升版本号(候选与线上同为 1.2.1/40)、IT-22 A 档人工走查、内存门禁与延迟复测(本轮未跑)。 > > **P1-U 里剩下的,全部卡在「先要你定一件事」或「先要数据」上**: >