diff --git a/ROADMAP.md b/ROADMAP.md index 01d85bd..1920622 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -245,7 +245,8 @@ ADR-147:Terminal正常实际提交“你”及wq前缀确认后的failure/INT/ - [ ] **2026-10-27 MVP 正式发布(目标 `1.0.0`,ADR-298)**:阶段 A 在 0.1.16/26 上演练 IT-22(`docs/tasks/T-ITER-22.md`)→ 修复入库 → 阶段 B 递增 1.0.0(build 27)并双机装同一包(同时闭环「更新器自更新」)→ 阶段 C 只在 1.0.0 上做正式 IT-22、IT-15 独立重建、IT-23 五工作日 → 阶段 D `tag v1.0.0` 打在验收候选提交 → Release → Pages。 - [x] 2026-10-28 **锁定候选 1.0.0 / build 29**(报告217):提交 `11abece3`、ZIP `aca4ed5c…`、宿主执行 `4ad949e6…`,air 已装同包。装机定向复验:2.1 多词拼接 PASS、9.1 编码播报 PASS、11.1 候选跟随(6 张截图:下方/镜像/底部翻上,无压字)PASS。**IT-22 限定范围通过**(必查 11 + 抽查 8 全 PASS,其余沿用报告216 基线)。 - [x] 2026-10-28 **IT-15 独立离线重建通过(报告218)**:用户在 air 上从候选自带源码包离线重建 1.0.0/build 29,身份链与逐架构网络导入 PASS、**默认数据 4/4 逐字节一致**、空闲 0 外联;可执行文件因本机 SDK 27.0 vs 发布 26.5 不同(ADR-033 边界)。顺带修掉 `run-repro.sh` 的缺陷:原来 `cmp` 可执行文件失败会中断,导致数据表比对根本没跑,且漏比 `variant-s2t.tsv`。 -- [ ] 2026-10-28 IT-23 五工作日试用(**1.0.0 / build 29**,air 与 pro 执行 SHA 均为 `4ad949e6…`):两台设备已装同一包(报告217 §8),pro 装前数据与备份已核对;从下一个工作日开始逐日记录,换包即作废。 +- [ ] 2026-10-29 IT-23 五工作日试用(**1.0.0 / build 30**,air 与 pro 执行 SHA 均为 `16ac739f…`):两台设备已装同一包(报告217 §8)。build 29 因「候选窗跟随鼠标」缺陷(报告219)被 30 取代,IT-23 尚未起算,故换包不影响基线。 +- [x] 2026-10-29 **候选窗跟着鼠标而不是插入点(报告219,build 30)**:`caretRect` 给解析器传了 `allowsEmptyCaret: false`,`length()==0` 时解析直接返回 nil → 落到鼠标兜底;改为 `true`,并把回退链收敛为「本轮 → 上次成功位置 → 鼠标」,新增 3 条断言。两台设备已装 build 30。 - [~] I3/IT-12/23:IT-12 性能/内存/久用已 PASS(报告191/192/199/207);**IT-23 五工作日试用尚未开始**(模板报告211)。 - [~] I4/IT-13…15:IT-13 附件绑定已在两次 Release 对账(报告194/208);**IT-14 最终候选锁定、IT-15 第三方核验待 0.1.15**。 diff --git a/docs/reviews/217-1.0.0-freeze.md b/docs/reviews/217-1.0.0-freeze.md index 714ca65..c663e34 100644 --- a/docs/reviews/217-1.0.0-freeze.md +++ b/docs/reviews/217-1.0.0-freeze.md @@ -123,15 +123,15 @@ platforms/macos/tests/run-repro.sh \ - **静态零外联**:`./scripts/verify-no-network.sh`(或 `make verify-no-network`)通过。 - **运行时零外联**:一边打字一边 `lsof -i -a -p "$(pgrep -x Lampyris)"`,预期**无输出**。 -## 8. IT-23 试用基线:两台设备装同一个包(2026-10-28) +## 8. IT-23 试用基线:两台设备装同一个包(2026-10-29 更新为 build 30) | 项 | air(本机,arm64 / macOS 27.0.1) | pro(x86_64 / macOS 13.7.8) | |---|---|---| -| 版本 / 构建 | **1.0.0 / 29** | **1.0.0 / 29** | -| 宿主执行 SHA-256 | `4ad949e6c3608c689c07e8a3f092a53babc788b290e424b4784bebc1d3aae31c` | **同值**(同一个二进制) | -| 更新程序构建号 | 29 | 29 | +| 版本 / 构建 | **1.0.0 / 30** | **1.0.0 / 30** | +| 宿主执行 SHA-256 | `16ac739f135ef1e9abfd750956a54411da3313e9cf675bdf7f50a165d246bddb` | **同值**(同一个二进制) | +| 更新程序构建号 | 30 | 30 | | 签名 / 公证 | Developer ID + `spctl` Notarized | 同(`codesign --strict`、`stapler validate` 均 PASS) | -| 用户数据 | config `cfc86cff…`、词库 800+ 行 | config `2bd3fde6…`、词库 **593 行**(装前装后一致) | +| 用户数据 | config `cfc86cff…`、词库 800+ 行 | config `cb8e7d05…`、词库 **685 行**(build 30 装前装后一致) | | 旧版本备份 | `updates/`、`uninstalled/` 历史项 | `uninstalled/bundle.aPZKev`(0.1.16) | | 输入源 | `cn.jokerhub.inputmethod.Lampyris.default` 已启用 | 已启用;当前停在 ABC,使用时按 ⌃Space 切 | @@ -140,3 +140,6 @@ pro 的安装记录:`ev-95-pro-stage.log`(ZIP 校验 → 解包 → 停宿 改为「停宿主 → 确认 `pgrep -x Lampyris` 为空 → 立即安装」后成功;这是安装器**正确的**保护行为,不是缺陷。 **IT-23 从下一个工作日开始**:两台设备都固定在 1.0.0/29,期间任何换包都会让当天记录作废。 + +> **为什么从 29 换到 30**:build 29 装机复验时发现「聚焦输入框 + 鼠标在远处 → 候选窗跟着鼠标」, +> 根因与修法见报告 219。IT-23 尚未开始记第 1 天,因此换包不影响试用基线;两台设备均已升级到 30。 diff --git a/docs/reviews/219-caret-follows-focus.md b/docs/reviews/219-caret-follows-focus.md index ecacc33..9dfc098 100644 --- a/docs/reviews/219-caret-follows-focus.md +++ b/docs/reviews/219-caret-follows-focus.md @@ -34,9 +34,9 @@ HUD 那条路径一直传的是 `allowsEmptyCaret: true`,所以同样的场景 | 单元 | `caret-placement.swift` 新增回退链三例:本轮结果优先 / 无本轮时用上次位置 / 两者都没有才用鼠标 | | 解析器 | 既有断言已覆盖「空文档 + `allowsEmptyCaret: true` 取到行框」,本次让候选窗走同一条 | | 回归 | `make verify`、`make macos-offline-tests`(56 文件 / 303 例)全绿 | -| 实机 | 待 build 30 装机复验:**聚焦输入框、把鼠标移到屏幕另一端、再打字**,候选窗应贴着插入点 | +| 实机 | 待用户复验(build 30 已装两台设备):**聚焦输入框、把鼠标移到屏幕另一端、再打字**,候选窗应贴着插入点 | ## 4. 影响 -- 版本仍 1.0.0,构建号 29 → **30**;锁定候选随之更新(报告 217 §8 的身份表在复验后补记)。 +- 版本仍 1.0.0,构建号 29 → **30**;锁定候选随之更新为 build 30(ZIP `9704f209…`、宿主执行 `16ac739f…`,报告 217 §8)。 - IT-23 尚未开始记第 1 天,因此**不影响**试用基线;两台设备都升级到 30 后再开始计时。 diff --git a/packaging/build-number b/packaging/build-number index 64bb6b7..e85087a 100644 --- a/packaging/build-number +++ b/packaging/build-number @@ -1 +1 @@ -30 +31 diff --git a/platforms/macos/Sources/InputController.swift b/platforms/macos/Sources/InputController.swift index 9eee0b5..ff7966c 100644 --- a/platforms/macos/Sources/InputController.swift +++ b/platforms/macos/Sources/InputController.swift @@ -272,11 +272,20 @@ final class LampyrisInputController: IMKInputController { // 只有会话仍在组合、候选窗会保留时才内联;宽度/模式/中英会 cancel 组合, // 这类切换必须走 HUD,否则候选窗随即关闭、用户什么都看不到。 if let window = candidateWindow, window.isVisible, session?.isComposing == true { + if Self.hudDiagEnabled { + Self.hudDiag("feedback msg=\(message) branch=chip visible=true composing=true") + } window.updateStatus(candidateStatus()) window.refreshLayout() return } - StateHUDController.shared.show(message, caret: hudCaretRect()) + let caret = hudCaretRect() + if Self.hudDiagEnabled { + Self.hudDiag("feedback msg=\(message) branch=hud visible=" + + "\(candidateWindow?.isVisible ?? false) composing=\(session?.isComposing ?? false) " + + "caret=\(caret.map(NSStringFromRect) ?? "nil")") + } + StateHUDController.shared.show(message, caret: caret) } /// HUD 用光标矩形:无客户端/取不到时返回 nil(不显示,不退鼠标)。 @@ -298,6 +307,11 @@ final class LampyrisInputController: IMKInputController { let length = max(0, client.length()) let selection = client.selectedRange() let bundle = client.bundleIdentifier() ?? "" + if Self.hudDiagEnabled { + Self.hudDiag("hud client=\(bundle) frontmost=" + + "\(NSWorkspace.shared.frontmostApplication?.bundleIdentifier ?? "nil") " + + "len=\(length) sel=\(selection.location)") + } let windowLevel = client.windowLevel() let diag = Self.hudDiagEnabled let startIndex = Self.caretLookupIndex( @@ -376,7 +390,10 @@ final class LampyrisInputController: IMKInputController { /// 诊断开关(默认关闭):`launchctl setenv LAMPYRIS_HUD_DIAG 1` 后重启宿主, /// 光标矩形解析过程写入 `$TMPDIR/lampyris-hud-diag.log`,用于真机定位 HUD 偏移。 static var hudDiagEnabled: Bool { - ProcessInfo.processInfo.environment["LAMPYRIS_HUD_DIAG"] != nil + if ProcessInfo.processInfo.environment["LAMPYRIS_HUD_DIAG"] != nil { return true } + // 文件开关:宿主由 launchd 拉起,`launchctl setenv` 不总能传进来(报告219/220)。 + let marker = ImePaths.supportDirectory()?.appendingPathComponent("hud-diag") + return marker.map { FileManager.default.fileExists(atPath: $0.path) } ?? false } static func hudDiag(_ message: String) {