From d9b7c22ecb9c758192d67b764cefd8e44cc10ce7 Mon Sep 17 00:00:00 2001 From: AskaEth Date: Tue, 6 Oct 2026 07:38:29 +0800 Subject: [PATCH] =?UTF-8?q?docs(05):=20=E9=94=9A=E7=82=B9=E8=A1=A5?= =?UTF-8?q?=E8=AE=B0=E4=BA=8C=E5=8D=81=E5=85=AD=E2=80=94=E2=80=94=E7=BB=AD?= =?UTF-8?q?=E6=8E=A5=E9=94=9A=E7=82=B9=EF=BC=88=E7=8E=B0=E7=8A=B6/?= =?UTF-8?q?=E7=8E=AF=E5=A2=83/=E8=AE=BE=E5=A4=87=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=E5=8D=8F=E8=AE=AE/W50=20=E5=9C=A8=E9=A3=9E=E4=B8=8E=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E6=A3=80=E6=9F=A5=E6=B8=85=E5=8D=95/W38~W49=20?= =?UTF-8?q?=E7=B4=A2=E5=BC=95/=E5=BE=85=E5=8A=9E=E6=8E=92=E5=BA=8F/?= =?UTF-8?q?=E4=B8=8E=E5=90=8E=E7=AB=AF=E7=8A=B6=E6=80=81/=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E8=AE=BA=E6=95=99=E8=AE=AD=EF=BC=89=EF=BC=8C=E4=BE=9B?= =?UTF-8?q?=E4=B8=8B=E4=B8=80=E4=BC=9A=E8=AF=9D=E7=9B=B4=E6=8E=A5=E6=8E=A5?= =?UTF-8?q?=E6=89=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devdocs/05-开发进度与交接.md | 62 ++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/devdocs/05-开发进度与交接.md b/devdocs/05-开发进度与交接.md index 188933d..8ec262a 100644 --- a/devdocs/05-开发进度与交接.md +++ b/devdocs/05-开发进度与交接.md @@ -1399,3 +1399,65 @@ curl -s -X PATCH "$BASE/api/v1/sessions/$SID" -H "Authorization: Bearer $TOK" \ > > ### 顺带要改的旧引用(我) > `devdocs/05` 里那条「建议把 `ws_block_proxy.py` 挪进 `devtools/`」的建议**已执行**(`devtools/ws-block-proxy/`);文中提到旧路径(`app/build/e2e-shots/ws_block_proxy.py`)的地方**现在过时**,下次一并更正。 + +> ## ★★★ 锚点补记二十六(2026-10-06 深夜 · **续接锚点:从这里开始**) +> +> ### 0. 一句话现状 +> 客户端 **W38~W49 已全部落地并推送**;**W50(接上主动消息消费)正在跑**;主树 **1177 测试 / 0 失败 / 0 错误**;**worktree 只剩主树**。 +> +> ### 1. 仓库与环境 +> - 仓库 `D:\Project\Code\Uni\Cyrene-For-Android`,分支 **`android`**。 +> - **主仓只有一笔脏改动:`devdocs/02-前后端协同事项.md`** —— 那是**后端会话的在途追加**,**不是我们的**。**永远别 `git checkout --` 它、也别把它提交进来。** +> - **动 `02` 的纪律(今天写死的)**:① `git status`;② **再 `git diff` 看它最新那几十行**(「脏」≠「还是那批内容」——我今天差点因此给后端写信时漏掉他们的回执);③ 提交走「另存他们的补丁 → `git checkout --` → 只提交我这一节 → 再把他们那份贴回末尾」,两边都不丢。 +> - 模拟器 AVD `Pixel_10_Pro_XL`:**1080×2340 @440dpi / 5 vCPU / 8G**(**删掉 `skin.*` 三行**才让 `hw.lcd.*` 生效);`adb reverse tcp:10942 tcp:10942`;软键盘默认禁用(布局不因 IME 位移)。 +> - ⚠️ **环境坑**:屏幕会自己黑屏(`svc power stayon true` 也挡不住)⇒ 开测前 `input keyevent 224` + `82`;**`adb root` 会冲掉 `adb reverse`**;模拟器 `system_server` 会崩(`Can't find service: window`、`am` 报 `Broken pipe`)⇒ 只能重启模拟器。 +> +> ### 2. ⭐ 设备驱动协议(今天用四次栽跟头换来的,**务必照做**) +> 1. `dumpsys window | grep mCurrentFocus` **确认前台是我们的 App**(我今天两次点在 `com.android.settings` 上,白跑两轮); +> 2. 打字后 **dump 并读那段文字的 `bounds`**:x 落在输入框范围、y 被软键盘顶高(约 1293~1435)⇒ **在输入框里**;y 在列表区(<2000)⇒ **已成气泡**。这就是「发送到底触发没触发」的判据; +> 3. **绝不复用发送键坐标**(软键盘把输入栏顶高约 820px)⇒ **从 dump 取 `bounds` 再点**; +> 4. 要判「客户端做了什么」⇒ **优先看客户端自己的输出**(`logcat -s CyreneRoute`、`-s OkHttp`),**不要**从代理/后端日志反推 —— **对端看不到「没发出去的请求」**,我因此误判三次。 +> +> ### 3. 在飞:**W50**(`feat/W50-proactive-consume`,基线 `d5d2fee`) +> **缺口(真实产品缺口)**:她主动说的话**实时到不了安卓**。原因两条:① `proactive_message` 帧**零消费**(`ChatViewModel.onEvent` 无该分支,全仓 `app/src/main` 无消费点);② 我们**只解了错的 id**(只解 `messageId`,而落库行是另一个 `id`;`ignoreUnknownKeys` 把新 `id` 静默丢弃)。 +> **任务书硬要求(合并前逐条核对)**: +> ① 按**已落库的 assistant 行**经 `mergeMessages` 并入(**不造 UI 气泡**)⇒ 实时可见 + 刷新后仍在 + **按 id 不会重复**; +> ② **必须自己钉死主会话**(帧壳**不带 `sessionId`**,`isForSession` 会放行给**每一个**会话 ⇒ 不钉就在**每个次级会话**里冒一条); +> ③ **无 `id` 时退化为本地气泡**(后端落库失败那一档),**不许静默丢弃**; +> ④ 可选项:顺带触发一次 W49 的节流静默重拉(因为后端**不为这条路补 `message_persisted`** ⇒ 主会话红点不会自己亮); +> ⑤ 红线:不动 `mergeMessages` 语义、不动 W49 节流判据、不动 W48 的 VM key、**不许**把这条帧接成「收到就整表重拉」。 +> **合并后要做**:把「她主动说的话现在能实时到达安卓」写进文档 + **做一次设备验收**(用上面的协议 —— 这是**新的实时路径**)。 +> +> ### 4. 今天已落地(W38~W49;细节看各自锚点) +> | 批次 | 内容 | 锚点 | +> |---|---|---| +> | W38 | 分享落地**等连接就绪**(超时不再等于发送失败、内容不丢、连上自动补发) | 补记九(+ 真机回归通过) | +> | W39 | 三处措辞不诚实(告知不再两句叠加 / 未连接与发失败分开 / `Offline` 不再承诺自动发出) | 补记十 | +> | W40 | 普通发送**未连接进队列**(+ 真机回归通过) | 补记十一/十二 | +> | W41→**W45** | 先探 `/health` **改成直接试 REST**(**探测整套已删除**)⇒ 已真机验证 `route=Rest` + 落库 | 补记十三/十六/十七 | +> | W42 | 图片入口**改多选**(N 张 = N 条消息)+ 设备验收通过 | 补记十四/二十 | +> | W43 | 超限告知**入口中性** + 重试**静默**(阈值 3) | 补记十五 | +> | W46 | 一行 **`CyreneRoute`** 诊断日志(DEBUG)+ 判据带原因 | 补记十七 | +> | W47 | 静默改为**按事故复位**(队列排空即清零) | 补记十八 | +> | W48 | **账号指纹进 VM key**(修 S1 换环境串味)+ 5 处错注释 + 代理挪进 `devtools/` | 补记二十五 | +> | W49 | 非激活会话**节流静默重拉**(修 S6 红点滞后,3 秒窗口 + 结构性 trailing) | 补记二十五 | +> +> ### 5. 待办(按优先级) +> 1. **W50 合并 + 设备验收**(在飞) +> 2. ⚠️ **`d5d2fee` 之后还没跑过全量**?—— 不,`d5d2fee` 是纯文档提交;**代码最后一次全量是合并 W48/W49 后的 1177 绿**。**W50 合并后必须再跑一次。** +> 3. **W48/W49 的设备验收**(换账号后屏幕是否干净 / 红点是否自己亮):**都只有单测**。 +> 4. **老现象 ③**:**已结案**(机制正常、那次异常未复现)——见补记二十二,**别再花时间重跑**。 +> 5. **S1 的第二步(回收旧 VM)与 S5(切会话不打断 / 一个能看见能停的入口)**:**都属要主人拍板的设计取舍**。 +> 6. **S2/S3/S7/S9**(次级会话的窄窗口问题):清单在补记十九,按需。 +> 7. **等后端**:`toolCalls[]` **回看面**(他们说**比未读更重要**,且要**带输出/摘要**)、`unreadCount` 增量(都已认领,**契约先行**)。 +> 8. **等主人**:移除键位置那处**观感**、相册多选分享**真机**、**推送**(等自建)。 +> 9. **文档陈旧**:`05` 里提到 `ws_block_proxy.py` **旧路径**的地方已过时(工具已进 `devtools/ws-block-proxy/`)——**下次一并更正**。 +> +> ### 6. 与后端的状态(不用重新问) +> - 他们 `回执二十三`:**未读增量接**(`message_persisted.data.unreadCount`,**绝对未读 + 主人单一已读游标 ⇒ 多端共享**;`GET /sessions` 列表项也带)、**工具记录认且说比未读更重要**、**我们六条依赖逐条「保持现状 + 改前必登记」**、`/health` 保留不删、**采纳了我们那条取证约定**(不从对端日志反推)。 +> - 我们已答(`766843f`):P1 的真实含义是「**接上消费**」不是「去重」、`tool_execution` 选 **(a)** 并要 `toolCalls[]` **带输出**、纠正「每屏一条 WS」这个**过时前提**(W28 早已收成进程级唯一连接)、**推送暂不接**且告知「应用内提示」在我们这边**零实现**。 +> - **我们没在等他们的答复**;**在等**两个已认领的面落地。 +> +> ### 7. 一条方法论(今天最大的教训,写给下一个我) +> 我今天**四次**栽在自己的测量上(黑屏、前台不是本 App、复用坐标、不确认文字落点),**三次**拿「对端日志缺席」当「客户端没做」的证据。 +> ⇒ **先怀疑自己的测量,再怀疑代码**;**要判客户端行为,只看客户端自己的输出**;**一次只改一个变量**。