docs(05): 锚点补记十七——W45 阶梯设备验证通过(route=Rest、代理见 200、落库 1 条),附我连续三次误判的共同点与三条设备验证纪律,以及工具卡缺口的根因与登记位置
This commit is contained in:
1 parent
16699c4958
commit
798c6ee907
1 file changed
+43
@@ -1165,3 +1165,46 @@ curl -s -X PATCH "$BASE/api/v1/sessions/$SID" -H "Authorization: Bearer $TOK" \
|
||||
> 2. `devtools/fake-backend` 里的 `GET /api/v1/health` 路由与 README 的说法现在是死的(无害夹具,未清)。
|
||||
> 3. 待主人过目:静默持续到某次补发成功 vs 每轮结束恢复告知(改一行)。
|
||||
> 4. 待办:子会话流程跑一遍出清单;W42 多选器真机观感。
|
||||
|
||||
> ## ★★ 锚点补记十七(2026-10-06 · **W45 那条阶梯验通了**,以及我连续三次的误判)
|
||||
>
|
||||
> ### 状态
|
||||
> `android` = `origin/android` = **`16699c4`**(W46 合并提交;分支提交 `d546f31`);主树 **1155 测试 / 0 失败 / 0 错误**。W46 worktree 已清。`02` 里另有一笔**已推**的登记(`b8399b5`,工具卡缺数据面,见下)。
|
||||
>
|
||||
> ### ✅ 设备验证:**通过**(判据三条独立)
|
||||
> 场景:`ws_block_proxy.py` 只掐 `GET /ws/chat`(回 503)+ `adb reverse tcp:10942 tcp:18098`;新包(含 W46 的 `CyreneRoute` 日志);输入栏发一条纯文本。
|
||||
> ```
|
||||
> CyreneRoute: wsDispatched=false socket=Reconnecting mirror=Reconnecting wsObject=absent route=Rest reason=ConnectionNotReady outcome=Queued fromQueue=false
|
||||
> 代理日志: PASS POST /api/v1/chat -> 200
|
||||
> 库里: 恰好 1 条
|
||||
> ```
|
||||
> ⇒ **`route=Rest` ⇒ 直接试 REST ⇒ 请求真的发出去(代理看到 200)⇒ 消息落库。** W45「把探测换成直接尝试」**成立**。
|
||||
> 顺带把 W41 那个「探测不可用」的缺口**绕过去并消掉了**(那套机制已被删除)。
|
||||
>
|
||||
> ### ⚠️ 我在这一串里连着错了三次(必须记下来)
|
||||
> 1. 「App 从来没探过 `/health`」——**推不出来**(W44 证明:`Unreachable` 生在连接之前,三种成因在对端同形)。
|
||||
> 2. 「零请求 + 进队列 ⇒ 只能是 `Offline` 那一档」——**错**。这次日志给出的真实答案是 `route=Rest`,**REST 确实发出去了**。
|
||||
> 3. 前几轮「发送没发生」的结论——**错**,有两次是我点在了 `com.android.settings` 上(前台不是我们的 App),有一次消息其实**进了队列**(我当时只查了网络侧、没看界面)。
|
||||
>
|
||||
> **共同点:我拿「对端日志缺席」当「客户端没做」的证据,而中间还隔着几层我看不见的东西。**
|
||||
> **纪律(写死)**:① 设备验证**第一步永远是 `dumpsys window | grep mCurrentFocus`** 确认前台是自己的 App;② 要判「客户端做了什么」,**优先看客户端自己的输出**(`CyreneRoute` / `logcat -s OkHttp`),**不要**从代理/后端日志反推;③ 一次只改一个变量。
|
||||
>
|
||||
> ### 一条仍未解释的旧现象(如实留着)
|
||||
> W45 那次(同一场景)气泡停在「排队中 · 还没连上」、代理没有 POST、库里没有那条。**与本次唯一可见的差别是时机**:那次我在 App 启动后 ~55 秒就发了(正撞上启动期的请求洪峰),这次 App 已稳定运行一分多钟。
|
||||
> **最可能的解释**:`route=Rest` 但那次 REST 死在**整通上限 10 秒**(被启动期拥挤的连接/续期吃掉)⇒ `Unsent` ⇒ 进队列。**未经证实**,W46 的日志下一次复现时可以直接读到(看 `route` 与 `reason`,再看 OkHttp 有没有 `--> POST`)。
|
||||
>
|
||||
> ### W46 留下的可观测性(以后常备)
|
||||
> `ChatViewModel.sendThroughLadder` 一进入就一行 **`Log.d("CyreneRoute", …)`(仅 DEBUG)**:
|
||||
> `wsDispatched=<bool> socket=<WsState> mirror=<WsState> wsObject=<present|absent> route=<SendRoute> reason=<SendRouteReason> outcome=<WsSendOutcome> fromQueue=<bool>`
|
||||
> - `socket` 是**权威值**(`ChatSocket.state.value`),`mirror` 是**顶栏读的那个镜像** —— 一行就能分辨「镜像滞后」。
|
||||
> - `reason` 三档:`FrameDispatched`(走 WS)/ `ConnectionOffline`(进队列,一个请求都不发)/ `ConnectionNotReady`(直接试 REST)。
|
||||
> - 这是全仓**唯一**一处 `android.util.Log`,引入理由:必须是稳定可 grep 的固定 tag,而 OkHttp 的 BASIC 日志只照得到 REST 侧、照不到这条判据。
|
||||
> - `SendFallbackTest` 有「结果 + 原因」的全表测试。
|
||||
> - 复核结论:`WsState.Offline` 的写点**只有两处**(`ChatSocket.kt:233` ConfigMissing、`:284` 鉴权失败),**503 到不了 Offline** —— 所以「零请求 + 进队列」在纯函数层面**只有** `ConnectionOffline` 一条,本次实测也确认了不是它。
|
||||
>
|
||||
> ### 另外:主人报的「工具调用记录回合结束后消失」——根因已定,**已登记给后端**
|
||||
> **数据面缺失**:工具卡的数据只活在**流式路的本地状态**里;助手行落库时客户端把整条路丢掉,而**落库消息 DTO 里没有工具字段**可渲染。
|
||||
> **证据是同一段代码里的对比**:思维链有「打捞 + 滞留 10 分钟」的补救(因为 DTO 里有 `thinking`),**工具一个字段都没有**。
|
||||
> **不是我方本地状态的 bug**(我方与 `devdocs/03:141`「thinking / tool_call:仅 WS 实时有」逐字一致)。后端**其实已经把工具调用落进 `flow_graphs`**,缺的是「取出来给聊天端」。
|
||||
> 已登记进 `02`(`b8399b5`):要可选字段(`omitempty`,缺席=老行为逐字不变)、覆盖面对齐 `turnId`、**归属要明确**、允许开独立端点。
|
||||
> 我方接线点:目前 `ToolCard` 在「已落库消息」那条渲染路径上是**不可达代码**(渲染器签名里没有 tools 参数)——字段一到即可接。
|
||||
Reference in new issue
Block a user