From ef257c3167756ded40ab876e29b65edfe87a010d Mon Sep 17 00:00:00 2001 From: AskaEth Date: Mon, 5 Oct 2026 12:01:18 +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=B8=83=E2=80=94=E2=80=94=E5=B9=B6=E8=A1=8C=E4=B8=A4?= =?UTF-8?q?=E8=B7=AF=E5=AE=9E=E6=9C=BA=E9=AA=8C=E9=80=9A=EF=BC=88=E4=B8=89?= =?UTF-8?q?=E6=9D=A1=E5=88=A4=E6=8D=AE=EF=BC=89+=20leg=20=E8=AF=AF?= =?UTF-8?q?=E6=8A=A5=E5=B9=B6=E8=A1=8C=E5=B7=B2=E4=BF=AE=EF=BC=88W36?= =?UTF-8?q?=EF=BC=89+=20=E5=81=87=E5=90=8E=E7=AB=AF=E6=A8=AA=E5=B9=85?= =?UTF-8?q?=E4=B8=A4=E6=A1=A3=E9=AA=8C=E8=BF=87=20+=20=E6=A8=A1=E6=8B=9F?= =?UTF-8?q?=E5=99=A8=E8=B0=83=E5=8F=82=EF=BC=88iowait=20196%=E2=86=9214%?= =?UTF-8?q?=EF=BC=89+=20=E5=88=86=E4=BA=AB=E6=8E=A5=E5=85=A5=E5=85=B6?= =?UTF-8?q?=E5=AE=9E=E6=97=A9=E5=B7=B2=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 把「别用 leg 判并行、只看 turn_begin.kind」写成纪律,并记下 ANR 判据的正确做法(拉 trace 看主线程栈,别先怀疑代码)。 --- devdocs/05-开发进度与交接.md | 63 ++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/devdocs/05-开发进度与交接.md b/devdocs/05-开发进度与交接.md index ee0c451..ff0c8e1 100644 --- a/devdocs/05-开发进度与交接.md +++ b/devdocs/05-开发进度与交接.md @@ -682,3 +682,66 @@ curl -s -X PATCH "$BASE/api/v1/sessions/$SID" -H "Authorization: Bearer $TOK" \ > **本批已按此执行**(W34 合并后立刻清掉)。 > - **我又犯了一次「先怀疑代码、而不是先怀疑自己的测量」**(截图看不到横幅时)。这条已经写过两次了, > 是第三次 —— **下次第一反应必须是"我的验证条件对不对"**。 + +> ## ★★ 锚点补记七(2026-10-05 下午 · 并行两路**实机验通** + 一个误标 bug 已修 + 假后端横幅两档已验 + 模拟器调参) +> +> ### 状态 +> - `android` = `origin/android` = **`39a63f8`**,主树全量 `assembleDebug` + `testDebugUnitTest` 跑过: +> **1055 测试 / 0 失败 / 0 错误 / 0 跳过**。 +> - 本批代码两个都**已合并、已推送、worktree 已清**:**W35** `6e00697`(分享来源角标)、**W36** `39a63f8`(并行路角标改以 `kind` 为准)。 +> - ⚠️ **工作区有 `02` 的在途改动 —— 那是后端会话的追加(回执十八等),不是我们的,别提交它。** 处理手法见本文末。 +> +> ### ✅ ①「并行」两路:实机验通(这次是真证据,不是看角标猜的) +> 三条互相独立的判据: +> 1. **后端日志**(`%USERPROFILE%\cy.log`):`msg="parallel leg started" session=web turn=turn-4743035881e410af leg=2 active_turns=2` +> —— 这行**只在并行启动路径**打(`session_parallel.go:175`),`active_turns=2` 按定义就是「起第二路时第一路仍在飞」。 +> 2. **库内 `turnId`**(`GET /sessions/web/messages`):`write 2000 words about the ocean` = `turn-b618432ddb21ed42`(11:56:27.8), +> `para2` = `turn-4743035881e410af`(11:56:39.4)⇒ **两条 user 消息不同 turnId**;leg1 的 assistant 行 **11:56:41.8** 才落库 ⇒ 与 leg2 真重叠。 +> 3. **客户端画面**:底栏显示「正在思考… **并行 2 路**」(= `activeTurns=2`),两路回复各自成块、没互糊。 +> +> ⚠️ **差点被自己骗过去的坑(写死它)**:第一轮我把「角标显示并行路 2」当通过 —— **是假阳性**。 +> 后端 `leg` 来自 `st.legSeq++`(`session_parallel.go:202`,**每条新路都自增,串行回合也算**)⇒ `leg=2` 只说明「本会话第 2 条路」。 +> **判并行只能看 `turn_begin.kind` / `active_turns`,或后端那行 `parallel leg started` 日志。** +> +> ### 🐞 副产物 bug(已修 W36):`leg >= 2` 就挂「并行路 N」 +> 复现:会话里发**第二条普通消息**,气泡下就出现「并行路 2」。根因是客户端**把 `turn_begin.kind` 丢掉了**,角标只认 `leg`。 +> W36 把 `kind` 带进 `TurnBinding.parallel`,判据改成 `parallel && leg >= 2`;**`kind` 缺席(老服务端)⇒ 一枚都不挂**(宁可少挂,不说假话)。 +> +> ### ✅ ②「忙时被拒」横幅:假后端两档都验过 +> 手法(比改 App 服务器地址干净):**不动 App 配置**,把 `adb reverse` 的 10942 转到假后端端口 —— +> `adb reverse --remove-all; adb reverse tcp:10942 tcp:18099`,App 照旧访问 `http://127.0.0.1:10942`;验完还原 `adb reverse tcp:10942 tcp:10942`。 +> - 待发 **1** 条 ⇒ 横幅「**她正忙且队列已满,这条没发出去,请稍后手动重试**」+ 气泡摘掉、**正文退回输入栏**(`e2e-shots/fb3-banner.png`) +> - 待发 **≥2** 条 ⇒ 横幅「**她忙不过来,这条可能没发出去**」+ **一个气泡都不动**(`e2e-shots/fb5-unknown.png`) +> - 关键前置:**待发气泡必须 ≥1 条**(用 `--hold-replies` 挂住,别让它落库) +> +> ### 🔧 模拟器调参(今天那串 ANR 的真因不是代码) +> 宿主 Ryzen 5 5600G(6C/12T)/ 28G;AVD 原本 **4 vCPU + 6G**(`config.ini` 里 `hw.ramSize=2048`,靠 `-memory 6144` 顶)。 +> 客户机 `top` 显示 **iowait 196% + swap 已用 457MB** ⇒ 瓶颈是 **IO + 内存**,不是核数。 +> 已改 `C:\Users\Aska\.android\avd\Pixel_10_Pro_XL.avd\config.ini`:`hw.ramSize=8192` / `hw.cpu.ncore=6` / `vm.heapSize=512`。 +> 效果:**iowait 196% → 14%,swap 457MB → 0**。 +> 另外**别再每次 `-no-snapshot-save`** —— 冷启动那一遍 IO 最贵;现在让它存快照,下次热启动。 +> +> ### ⚠️ 新踩的两个坑 +> 1. **`settings put global hide_error_dialogs 1` 会让 ANR 直接杀掉 App**(日志 `reason=6 (ANR)` + `Killing … user request after error`)。 +> 它对自动化友好,但代价是丢状态 —— 配合「不在负载高峰驱动 UI」一起用。 +> 2. **别一边跑 Gradle 一边驱动模拟器 UI**(今天就这么把 App 饿到 ANR)。 +> 判断「是不是 App 的 bug」的正确做法:**拉 ANR trace 看主线程栈** —— 在 `/data/system/procexitstore/`,`adb root` 后可 pull。 +> 那次主线程是 `__epoll_pwait`(**空闲**),且 **launcher 同时段以同样理由 ANR** ⇒ **模拟器被饿死,不是 App 的问题**。 +> 3. `uiautomator dump` 失败会**留着上一次的快照**:每次用**唯一文件名**并检查输出行 `UI hierchary dumped to:`,否则会对着旧快照做判断(本批栽过一次)。 +> +> ### 📦 分享接入:**其实早就做完了** +> 子代理查实:Manifest 两个 intent-filter、`app/ShareIntake.kt`、`domain/share/{SharePayload,PendingShareHolder}.kt`、`ChatViewModel.sendShared` 全在, +> 且 `05-archive-历史批次.md:124-139` 有 2026-10-04 的装机验收(文本 / 单图 / 未登录暂存 / 登录后落地四条)。 +> 本次补的是**「可识别」那一半**(W35):分享进来的消息 `clientMsgId` 用 `share-` 前缀,渲染层挂 **`[用户分享]`** 角标,**正文零改动**(守 `02` 的 F4 红线)。 +> ⚠️ **一次观察(未结案)**:用 `am start -a SEND --es …TEXT` 投分享时,客户端出现「**发送失败,请重试**」并把正文退回输入栏,库里**没有**多出那条消息; +> 当时 WS 刚在附近重连过一次。**未定位**,先记着。 +> +> ### 待办(按优先级) +> 1. **分享路径剩下三条实机验证**(超长正文走文件 4000 rune / `SEND_MULTIPLE` 多图 / 冷启动)—— 命令见 README 与子代理报告。 +> 2. **W36 的真机目视**:单测钉住了,但「第二条普通消息不再冒角标」没在设备上目视过。 +> 3. 旧账:子会话流程(主人说搁置)、图片/工具卡实机验证(后端未配工具)。 +> +> ### 环境与纪律(更新) +> - 假后端**用完即关**(本次已关,18099 已释放);别长期占 18080/18081/18083/18099。 +> - worktree 纪律照旧(合并当场 `rm -rf` + `prune`);本批 W35/W36 都已执行,`git worktree list` 只剩主树。 +> - **动 `02` 之前先 `git status`**:本批 `02` 一直带着后端会话的在途追加,处理手法 = 先存他们的补丁 → `git checkout --` 还原 → 只提交我的 → 再把他们的贴回末尾。两边都没丢。