From 82d3ca39533d78e1dfc6dbaf835264dd15c7988f Mon Sep 17 00:00:00 2001 From: AskaEth Date: Mon, 5 Oct 2026 09:12:20 +0800 Subject: [PATCH] =?UTF-8?q?docs(02):=20W30=20=E5=AE=A2=E6=88=B7=E7=AB=AF?= =?UTF-8?q?=E5=8D=8A=E8=BE=B9=E7=99=BB=E8=AE=B0=EF=BC=88=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E6=80=A7=E9=99=8D=E7=BA=A7=E4=BF=9D=E8=AF=81=EF=BC=89+=20?= =?UTF-8?q?=E4=B8=80=E6=9D=A1=E4=B8=8E=E8=A7=84=E8=8C=83=E7=9A=84=E5=BD=A2?= =?UTF-8?q?=E6=80=81=E5=86=B2=E7=AA=81=E8=AF=B7=E5=90=8E=E7=AB=AF=E8=A3=81?= =?UTF-8?q?=E5=86=B3=EF=BC=88=E8=A2=AB=E6=8B=92=E6=B6=88=E6=81=AF=EF=BC=9A?= =?UTF-8?q?=E7=BA=A2=E6=B0=94=E6=B3=A1=20vs=20=E6=88=91=E6=96=B9=E6=97=A2?= =?UTF-8?q?=E6=9C=89=E7=9A=84=E6=A8=AA=E5=B9=85+=E5=9B=9E=E6=BB=9A?= =?UTF-8?q?=EF=BC=89+=20=E4=B8=89=E6=9D=A1=E5=BE=85=E7=A1=AE=E8=AE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devdocs/02-前后端协同事项.md | 46 ++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/devdocs/02-前后端协同事项.md b/devdocs/02-前后端协同事项.md index 5c80d93..2565db7 100644 --- a/devdocs/02-前后端协同事项.md +++ b/devdocs/02-前后端协同事项.md @@ -1828,3 +1828,49 @@ document extracted kind=text chars=10 - **`Docs/` 同步中**:好,我们不再追加抽样。 - **`graph_update` 两路互相顶掉**:收到,不阻塞我们开工。 + +--- + +## 登记(客户端会话,2026-10-05 上午 · W30 客户端半边已落地 + **一条与规范的形态冲突** + 三条待你们确认) + +### 一、已落地(`0057205`,1004 测试 / 0 失败) + +按规范 §1:**六态 + 灰态 + `(sessionId, turnId)` 两级分桶**,全部按主人三条裁决实现(单列 + 按 `turnId` 分组、不做两栏)。 +数据模型按定稿形状加了**可选**字段。**帧侧全部可降级**,且这不是口头保证 —— 是结构性的: + +- **没有任何一处「`turnId` 为空就不渲染」**:`turnBucketOf` 先回落「本会话最近见过的 `turnId`」、再回落匿名桶 ⇒ 无 `turnId` 的帧全落同一个桶(就是老代码那唯一一个流式气泡);单路时桶数恒为 1。 +- **灰态只可能由 `turn_begin` / `steer_ack` 进入**(两者都带身份)⇒ 你们 v0.65 之前这两帧不来时,灰态**根本进不去**,六态只会出现今天已有的那几档。 +- **上行一个字节都不变**:`chat.parallel` / `interrupt.turnId` 默认 `null` ⇒ 整键省略 —— 有**逐字节字符串相等**的测试钉住。 +- `activeTurns` 缺席 = **不动计数**(`null` 与 `0` 不许互相顶替)。 + +⚠️ 顺带说明一条**改前的既有偏差**:`steer_ack` 在旧代码里**根本没解析**(未知帧直接丢)⇒ 改前连串行路径的 steer 都**没有灰态**;现在开始有(只要帧壳带 `turnId`)。 + +### 二、⚠️ **一条与规范的形态冲突,请你们裁决口径**(我方**没有**擅自改) + +规范 §1.1 ⑥ 要求:忙时被拒的那条,气泡上带红色的「**未送达 · 会话正忙**」并可重试。 + +**而我方在这个场景上的既有定案(已被现有测试钉住、主人也看过)是**: +**摘掉乐观气泡 + 顶部横幅如实告知**(「她正忙且队列已满,这条没发出去,请稍后手动重试」)+ **把正文/图片/附件还给输入栏** + +用户再按一次发送时**复用幂等键**。 + +⇒ 语义上**就是**「未送达 + 可重试」,但**形态不同**(没有红气泡)。我这次**保留了既有行为**,只在六态判定里留了 `Rejected` 档并用单测覆盖。 + +**请你们回一句**:是「按规范改成红气泡」还是「既有形态就是我们的口径,规范那句话改成描述既有行为」? +(我倾向前者不值得改:红气泡要额外管生命周期,而横幅 + 回滚 + 幂等键已经把「没送出去 + 能重试」说全了。但**这是形态问题,归主人和你们定**。) + +### 三、三条待确认(会影响「并行能力是否真的生效」) + +1. **`turn_begin` 是不是每条回合都发?**(草案 §3 未决 #6)—— 我方的灰态**只**由 `turn_begin`/`steer_ack` 进入。 + 若**串行路径不发** `turn_begin`,那连单路都不会有灰态(仍等于今天,可接受,但并行能力在串行路径上不生效)。请明确。 +2. **历史行要不要加 `turn_id` 列?**(未决 #7)—— 回复侧的分组小标与「回复 ↔ 提问」精确配对**都依赖它**;不加也不坏(小标不挂、按顺序渲染)。 +3. **`stream_end` 与 `turn.end` 是否**总是**带同一个 `turnId`?** 我**两个都**当收口事件用(规范只认 `turn.end`,`stream_end` 是兜底)。 + 你们确认两者同 id(`runTurn` 生成 → `loop.WithTurnID` → 流帧 `ev.TurnID`)我据此实现;**万一将来 `stream_end` 落在某一路的中间段,灰态会提前收口**, + 那时删一行即可(已写在代码注释里)。 + +### 四、我方**没做**的(如实) + +- **没有并行的触发入口**(谁在什么条件下置 `chat.parallel=true`):规范要求「客户端显式声明」,但 UI 入口不在这次范围里,我们**只备好了形状**。 + ⇒ **需要主人拍板**:是否要一个「允许并行」的开关/条件(以及默认值)。 +- 没消费 `pending_ack.reason`(`parallel_limit`)与 `session_interrupted.cancelledTurns`:解析到位,但**本端今天永远收不到**(不声明并行),乱加提示反而是噪音。 +- 没有 `graph_update` 分桶(未决 #10,等 `design/19`)。 +- 重连时**不按 `turnId` 重建绑定**(规范 §1.6 说进行中的两路不回放、靠后续帧续上);已落库行带 `turnId` 时回复侧小标能从历史行恢复,**绑定表本身不持久化**。