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
2 changes: 2 additions & 0 deletions HANDOFF.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ make macos-offline-tests

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

- 2026-11-13 / Claude Code(air):**内存口径已定(ADR-338)**。`memory-gate.sh` 改以稳态存活堆 `heap_live_mb` 判定,门槛 24 MiB,不再按学习区分档;「私有已提交」与 footprint 只作参考;新增 `ANALYZE_ONLY=1` 复核旧快照。对报告 265 的 5 组快照(23 轮)重判全部 PASS(20.1–21.2 MiB)。取代 ADR-263/292/312 的口径与门槛。**发版阻塞里的内存一项已解除**;剩余:PR #274(ADR-337)未合并、其两项修复未实机确认,升版本号,DMG 完成页。本条与上一条文档提交都在本地 `dev`,等 #274 合并后再推。
- 2026-11-13 / Claude Code(air):**重启后内存重测(报告 265 §4.3):无回归,门禁口径失效**。swap 0、负载 1–4,新旧包各 5 轮:稳态「私有已提交」新 37.4 / 37.3、旧(1.2.1 发布版)37.5 / 37.3,两者都 5 轮全超 34 MiB;存活堆都是 20.1–20.2 MiB。该口径随内存压力反向变化(swap 满时 31–34,swap 空时 35–37.6),量的是系统状态。**待用户裁定**:把判定口径换成 `heap_live_mb`(需 ADR)。已装回新包 `3e428b7`。PR #274(ADR-337)CI 全绿(首跑 `macos` 是没分到运行机被取消,重跑通过),**未合并、等用户授权**;本条文档提交暂留本地,等 #274 合并后再推,免得重跑 CI。
- 2026-11-12 / Claude Code(air):**用户实机反馈两处缺陷 → ADR-337**。① `12:30` 得到 `12;30`:带 Shift 的标点到核心时是未加 Shift 的字符 → 宿主改用 `typedScalar`(按键码 + Shift 重算)。② 拼音上屏后五笔码提示不出现:探针复现属实(宿主无浮层变化、诊断日志无取光标记录),进程内重放逻辑通过,**根因未定位**;改为上屏前候选快照并给提示路径每个分支加诊断日志。用户确认练习「字根」「词组」题型正常。四道检查全绿,新增 3 条真机样本(共 26 条)。**两项修复都未在真机确认**:等本批 PR 合并出包后装机,先看 `lampyris-hud-diag.log` 里的 `hint skip=/show=`。内存门槛按用户决定:重启电脑后重测再定。DMG 完成页仍未验证。
- 2026-11-12 / Claude Code(air):**首键 +4.6 MiB 归因完成(报告 265 §4.2),不改产品代码**。读 `vmmap` 的 MALLOC ZONE 存活分配:首键时点只有两种状态——5.2 MiB(无会话存活,数据已随 `Weak` 缓存释放)或约 19 MiB(有会话存活);新包 8 轮里 3 轮撞上后者、旧包 5 轮 0 轮(偶然概率约 20%),无会话的轮次新旧完全相同。稳态存活堆新包 +0.5 MiB(21.0 vs 20.5)。`memory-gate.sh` 新增参考字段 `heap_live_mb` / `heap_allocations`。副产结论:冷首键 ~30 ms 很可能来自「最后一个会话释放后重新读盘解析」,与本批无关,是否常驻数据需 ADR。PR #273 待合并;已装仍是 `3e428b7`。
- 2026-11-12 / Claude Code(air):**内存新旧包 A/B(报告 265 §4.1)**。新→旧(1.2.1 发布版)→新,各经 `install.sh` 覆盖安装。稳态私有中位数:`six-words` 新 31.8 / 旧 33.0,`idle-8s` 新 31.6 / 旧 31.0 → **稳态无回归**;但学习区开启时两者都贴 34 MiB 门槛(旧包最高 33.7,新包 11 个样本 2 个超限,同包三次运行 FAIL/PASS/FAIL)。**新发现:首键时点新包 +4.6 MiB(27.8 vs 23.2),未归因。** 结束状态:已装新包 `f38e4e1a…`(`3e428b7`)、输入源萤火虫、config 未变;`updates/` 多出两份 A/B 产生的备份(`…T105406Z`、`…T110001Z`)未删。待用户裁定:门槛是否重测调整、首键内存是否发版前归因。
Expand Down
2 changes: 1 addition & 1 deletion docs/MVP产品验收标准.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ MVP是首个准备正式分发的macOS产品版本:核心输入功能齐全、
| 交互完整 | 首次安装可照说明完成;设置分组连续、名称清楚;词库错误保留输入、可纠错;反馈/复制结果明确;错误不反复打断 | 用户从安装到输入、修改设置、纠错、反馈、升级/卸载完整任务走查;不要求新增引导弹窗或助手 |
| 视觉良好 | 候选/设置/词库/版本窗口/菜单风格统一;选中、首选、悬停、错误状态可辨;布局无重叠/不可操作截断;亮暗与Retina/非Retina下文字清楚,图标实际显示合格 | 完整界面状态截图和人工评审;正文/次要文字实际合成背景对比度≥4.5:1,不能以全图极值证明;长词可读且提交完整文本 |
| 可访问性 | 核心操作可用键盘完成;VoiceOver能识别候选/选择/设置标签,辅助动作选词不夺走客户端焦点 | 原生AX及VoiceOver实机结果;安全测试环境中复验 |
| 性能与体积 | 按键→候选p95<16ms,正常输入稳态常驻内存≤30MB,安装包≤15MB;无可感知持续卡顿或异常空闲负载 | 真实IMK与FFI分别记录;明确计时边界/环境/预热/样本数;冷简繁与面板另报告,不用单点或不同内存单位混算 |
| 性能与体积 | 按键→候选p95<16ms,正常输入稳态常驻内存≤30MB(MVP 时的口径;自 ADR-338 起门禁改为稳态存活堆 ≤24 MiB,原口径随系统内存压力漂移,只作参考),安装包≤15MB;无可感知持续卡顿或异常空闲负载 | 真实IMK与FFI分别记录;明确计时边界/环境/预热/样本数;冷简繁与面板另报告,不用单点或不同内存单位混算 |
| macOS兼容 | 至少macOS13 Intel与设备B macOS27 arm64的目标覆盖;多屏/缩放/Spaces/全屏测试;支持范围和未验证版本明确 | 最终包commit/SHA/架构/签名/系统/应用版本矩阵;目标必测项不得SKIP冒充通过 |
| 隐私安全与数据 | 核心零网络/遥测、唯一配置、合规数据;测试与异常路径保护已有数据 | make verify零诊断、安全脚本正常/失败/中断证据,独立第三方离线重建及零外联核验 |
| 分发就绪 | 签名、公证、Gatekeeper、二进制/源码对应、附件摘要、安装/升级/卸载恢复及发布说明齐全 | 锁最终提交与候选;实机安装和第三方核验;同页长期源码交付;发布操作单独记录 |
Expand Down
30 changes: 29 additions & 1 deletion docs/reviews/265-p1u-followup-latency-memory.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

- 日期:2026-11-12 / Claude Code(air 本机)
- 范围:报告 264 之后的收尾——仓库状态核对、把探针测不了的项尽量补上、延迟与内存门禁复测
- 结论:**延迟 PASS(稳态 p95 7.33 ms,0 外联);内存门禁在学习区开启时不稳定——新旧包 A/B 显示稳态无回归,但两者都贴着 34 MiB 门槛**(§4.1)。
- 结论:**延迟 PASS(稳态 p95 7.33 ms,0 外联);内存无回归——重启后新旧包同条件各 5 轮完全一致(§4.3),但门禁口径本身失效:
已发布的 1.2.1 在干净系统上同样 5 轮全超 34 MiB,而存活堆只有约 20 MiB**。
新包「首键」时点高约 4.6 MiB 已归因(§4.2):**不是泄漏、也不是数据变多**,是采样时是否恰好有一个输入会话存活;稳态存活堆新包多约 0.5 MiB。

## 1. 仓库状态(核对时)
Expand Down Expand Up @@ -118,6 +119,33 @@ A/B 过程中的换包:旧包与新包各经 `install.sh` 覆盖安装一次
这很可能就是冷首键 30 ms 量级延迟(ADR-307)的主要来源,且与本批改动无关。是否改成「宿主存活期间常驻数据」是内存换延迟的取舍,
需单独立 ADR(会让无会话时的常驻内存从约 5 MiB 升到约 20 MiB)。

### 4.3 重启后重测(2026-11-12 夜,用户重启电脑后)

条件:开机后等 1 分钟负载降到 4 以下再开始;全程 **swap 用量 0**,负载 1.3–3.7。同一配置(学习区开,门槛 34 MiB),各 5 轮,新 → 旧 → 装回新。

| 包 | 时点 | 「私有已提交」逐轮 | 中位数 | 存活堆 | 判定 |
|---|---|---|---|---|---|
| 新 `f38e4e1a…` | six-words | 35.0 / 37.5 / 37.2 / 37.4 / 37.6 | **37.4** | 20.1–20.2 | FAIL |
| 新 | idle-8s | 34.9 / 37.3 / 37.0 / 37.3 / 37.5 | **37.3** | 20.1 | |
| 新 | first-key | 33.2 / 34.1 / 33.0 / 32.7 / 34.4 | 33.2 | 19.2 / 5.1 ×4 | |
| 旧 `3eeeb0aa…`(1.2.1 发布版) | six-words | 37.3 / 37.5 / 37.5 / 37.3 / 37.7 | **37.5** | 20.2 | FAIL |
| 旧 | idle-8s | 37.2 / 37.3 / 37.3 / 37.2 / 37.5 | **37.3** | 20.1 | |
| 旧 | first-key | 33.0 / 33.1 / 32.4 / 33.3 / 34.1 | 33.1 | 5.1 ×5 | |

结论:

1. **新旧包没有差别**:稳态中位数 37.4 对 37.5、37.3 对 37.3,存活堆都是 20.1–20.2 MiB,首键时点也一致。§4.1 里看到的差异全部是测量噪声。
本批改动(ADR-325…336)**没有内存回归**。§4.2 说的「稳态存活堆 +0.5 MiB」在干净状态下也不成立(那是用户词库与系统状态的差异)。
2. **已发布的 1.2.1 在干净系统上同样过不了这道门禁**(5 轮全超,约 37.3–37.7 对 34)。门槛失效与本批无关。
3. **「私有已提交」这个口径随系统内存压力反向变化**:swap 用满时 31–34 MiB,swap 为 0 时 35–37.6 MiB,而存活堆始终约 20 MiB。
差出来的 13–17 MiB 是分配器已释放但系统尚未回收的页——内存紧张时被回收(数字变低),内存宽裕时留着(数字变高)。
它量的主要是系统状态,不适合做有固定门槛的门禁。首键时点最能说明问题:存活堆只有 5.1 MiB,这个口径却报 33 MiB。

**已落地(ADR-338,2026-11-13)**:门禁判定口径改为 `heap_live_mb`,门槛 24 MiB,不再按学习区分档;「私有已提交」与 footprint 降为参考项。
用 `ANALYZE_ONLY=1` 对本报告的 5 组快照(共 23 轮)重新判定:全部 PASS,稳态存活堆 20.1–21.2 MiB。

结束状态:已装回新包 `f38e4e1a…`(`3e428b7`),宿主跑新二进制,输入源为萤火虫。证据:`50-mem-reboot-*.txt`、`51-mem-reboot-*.txt`、`memory-reboot-new/`、`memory-reboot-old/`。

## 5. 仍未验证

`12:30`、五笔码浮层是否可见、练习「字根」「词组」题型、设置页 7 个新开关、DMG 安装完成页——都需人工目视。
Expand Down
2 changes: 1 addition & 1 deletion docs/reviews/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 补充复验 | 265 | 分号选词真机 PASS;延迟稳态 p95 7.33 ms PASS;内存 A/B:稳态无回归但学习区开启时贴 34 MiB 门槛;首键 +4.6 MiB 归因为采样时会话是否存活(非泄漏),稳态存活堆 +0.5 MiB |
| P1-U 补充复验 | 265 | 分号选词真机 PASS;延迟稳态 p95 7.33 ms PASS;内存:重启后新旧包各 5 轮完全一致、无回归;门禁口径失效(1.2.1 发布版在干净系统上同样全超 34 MiB,存活堆约 20 MiB) |
| P1-U 装机 | 264 | ADR-324…336 候选 `3e428b7` 装机 PASS;真机键入复验 22/22 PASS(首轮因无辅助功能权限 BLOCKED,授权后复跑);5 类目视项待人工 |

## 4. 常见查找
Expand Down
28 changes: 28 additions & 0 deletions docs/决策记录.md
Original file line number Diff line number Diff line change
Expand Up @@ -3432,3 +3432,31 @@
`make verify`、离线回归、预览冒烟、`build.sh --strict` 全绿。**两项修复都待换包后实机确认。**
- **状态**:已采纳(2026-11-12)。
- **关联**:ADR-325、ADR-331、ADR-335、报告 264/265。

### ADR-338:常驻内存门禁改以「存活堆」判定,门槛 24 MiB

- **背景**:`memory-gate.sh` 此前以「私有已提交」(vmmap 的 Writable regions resident + swapped_out)判定,门槛 30 MiB、学习区开启时 34 MiB
(ADR-263/292/312)。报告 265 的三轮实测表明这个口径不可用:
- 同一份包,swap 用满时稳态 31–34 MiB,重启后 swap 为 0 时 35–37.6 MiB——**随系统内存压力反向变化**;
- 已发布的 1.2.1 在干净系统上 5 轮全部超过 34 MiB;
- 首键时点存活堆只有 5.1 MiB,该口径却报 33 MiB。多出的是分配器已释放、系统尚未回收的页。
- 而存活堆在全部条件下稳定:新旧包、重启前后共 23 轮,稳态 20.1–21.2 MiB。
- **决策**:
1. 判定口径改为**稳态时点的存活堆**:`vmmap -summary` 的 MALLOC ZONE 表里 `DefaultMallocZone` 的已分配字节(`heap_live_mb`)。
2. 门槛 **24 MiB**,**不再按学习区开关分档**(实测约 20–21 MiB,余量约 3 MiB / 15%)。`LIMIT_MB` 仍可由调用方覆盖。
3. 「私有已提交」与 physical footprint 继续采样、写入 JSON,但**只作参考**,不参与判定。
4. 读不到存活堆(vmmap 输出格式变化)按 **FAIL** 处理,不退回旧口径。
5. 新增 `ANALYZE_ONLY=1`:只对已有快照目录重新判定,不重启宿主、不发键——用于复核旧证据与验证脚本改动。
- **取代关系**:本条取代 ADR-263/292 的判定口径与 ADR-312 的两档门槛;那三条的测量方法与历史数字保留作背景,不改写。
对用户的承诺由「常驻内存 ≤30 MB」改述为「输入法自身持有的数据约 20 MiB,门禁 24 MiB」;
系统「活动监视器」里看到的数字含共享库与可回收页,会更高,且随系统状态变化。
- **理由**:门禁要回答的是「这次改动有没有让输入法多占内存」,只有不随系统状态漂移的量才能设固定门槛。
存活堆直接对应码表、拼音表、用户词库与候选对象的大小,新增数据或泄漏都会如实反映。
- **边界 / 已知限制**:
- 存活堆不含映射文件与代码段;若将来改用 mmap 加载词典,需要把映射的常驻页另算进门禁。
- 学习区**关闭**时的存活堆没有单独实测(用户配置为开启);预期不高于开启时,门槛同为 24 MiB。
- 只统计 `DefaultMallocZone`;宿主若出现大额的其它 zone 分配不会被计入(当前其它 zone 合计不足 1 MiB)。
- **验收**:用 `ANALYZE_ONLY=1` 对报告 265 的 5 组快照(新旧包 × 重启前后,共 23 轮)重新判定,全部 PASS,稳态存活堆 20.1–21.2 MiB;
`test-acceptance-tooling.py`、`test-probe-cleanup.py` 与离线回归全绿。
- **状态**:已采纳(2026-11-13,用户指示「先定内存口径」)。
- **关联**:ADR-263、ADR-292、ADR-312、报告 198/209/256/265。
3 changes: 3 additions & 0 deletions docs/待办与积压.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@
> 拼音上屏后的五笔码浮层、练习「字根」题型。**第二档剩余**:U2-2 五笔造词(要定启发式)、U2-3 扩展词库(要联网取数据并登记许可)、
> U2-5 分阶段解锁与跟打(要定口径与文本来源)——三项都需要你先拍板,不是能直接开工的活。

> **内存结论(报告 265 §4.3,重启后重测)**:新旧包同条件各 5 轮完全一致,**本批无内存回归**;但门禁口径失效——1.2.1 发布版在干净系统上同样全超 34 MiB,存活堆只有约 20 MiB。
> **已定(ADR-338)**:门禁改以存活堆 `heap_live_mb` 判定、门槛 24 MiB;用旧快照复核 23 轮全部 PASS(20.1–21.2 MiB)。此前关于「贴线」「首键 +4.6」「稳态 +0.5」的说法以本条为准。
>
> **实机反馈(2026-11-12,ADR-337)**:`12:30` → `12;30`(Shift 标点取字符有误,已修);拼音上屏后五笔码提示不出现(已加固并加诊断,**根因未定位、未确认修好**)。
> 用户已确认练习「字根」「词组」题型正常;内存门槛定为「重启电脑后重测再定」;DMG 完成页待出 DMG 后确认。
>
Expand Down
2 changes: 1 addition & 1 deletion scripts/acceptance-evidence.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"hotkeys": ("快捷键", "热键", "shift 切", "⌥p", "⌥f", "⌥t", "⌥m"),
"clients": ("客户端", "client matrix", "文本编辑/safari", "safari"),
"quality": ("质量样本", "quality-samples"),
"memory": ("内存门禁", "memory-gate", "adr-263", "adr-292"),
"memory": ("内存门禁", "memory-gate", "adr-263", "adr-292", "adr-338"),
"soak": ("久用", "soak"),
"network": ("零外联", "外联", "tcp/udp", "0 条"),
"voiceover": ("voiceover", "播报", "axannouncementrequested"),
Expand Down
Loading
Loading