docs: 自主推进一批的登记(假开关 / 静默丢正文 / 分享自打断 全修完 + 一条口径冲突要主人拍板)

主人睡前说「按主线继续推,或者先按模块检查」,我把两件都做了:先做了一次只读自审
(假开关 / 死代码 / UI 规范 / 文档漂移,四张带「文件:行号」的清单),然后按清单修了一批。
本批全部是「界面上或文档上声称能做到、代码里其实没接线」这一类问题。

devdocs/05:新增「锚点补记三」,写清——
- 本批 5 条落地(W25 打断模式真接线 / W26 stream_chunk 不再静默丢正文、错误横幅可关闭、
  分享不再自相打断、两处死代码 / W27 删只被测试养的 API、公式去重、03 四处更正 /
  WsEvent KDoc 更正);
- 三个「假开关 / 静默」的真相与各自的修法;
- 两条查完发现不是 bug 的(「抽屉最后消息预览不刷新」与「session_interrupted 丢弃 N 条」),
  附证据,免得下次返工;
- 装机验证:错误行的关闭叉验通(x2/x3 截图),以及一条我刻意没验的(登录页 IME ——
  要清空 App 数据才能回到登录页,万一登不回去今晚所有装机验证能力一起没了,风险不对称);
- 本批没做的:连接所有权(共享 socket)只写设计要点与七条验收清单,不动手;
  DocumentDelivery 那组「正文转文件」API 不删也不接(口径冲突);
- W26 留下的一条边界(回退路径没有 message.start,freshTurnIfFinished 不触发)。

devdocs/02:追加客户端登记三条——
1. 请后端确认 stream_chunk 今天还会不会发、delta 是增量还是整段、会不会与结构化帧并存
   (我们按契约的「非流式回退路径」实现,但那条路可能已经名存实亡);
2. 告知我们开始发 interrupt{scope:"current"} 了(窄触发条件、默认档零变化、分享不打断、
   以及「两条道无强序」这个我们坦承的边界);
3. 登记「超限走文件」的口径冲突(05 的定案说做的是「用户打的字自动变附件」不做,
   主人后来点名要做 —— 两者多半不是一件事),不替主人合并,所以那组 API 原样留着。

本次提交只动文档,无代码改动。
This commit is contained in:
AskaEth committed 2026-10-04 22:40:43 +08:00
1 parent 85a922c01b
commit 219c50b7c2
2 files changed
+140 -1

No files matched your search

+58
View File
@@ -1391,3 +1391,61 @@ v0.61 让**扫描件/图片型 PDF** 落到 `status:"unreadable"`,而**原因
### 四、主人侧一句
主人这两天提的「分享到 App」那条路的**附件部分**已经走通(选文件 / 待发预览 / 上传 / 落库 / 气泡芯片 / 预览弹层),**IM 渠道那条路按你们 §三 的结论仍算不通**,我们在登记里保持「未验证」。
---
## 登记(客户端会话,2026-10-04 深夜续 · 一条请你们确认 + 一条告知 + 一条要主人拍板)
> 这一批是客户端做了一次**只读自审**(假开关 / 死代码 / UI 规范 / 文档漂移)之后清出来的问题,
> 绝大多数是**我方自己的**,不需要你们动作。下面只挑**与你们有关**的三条。
### 一、⚠️ 请你们确认:`stream_chunk` 今天还会不会发?
我们审计时发现:`WsEvent` 里解析了 `stream_chunk`,但**消费侧一个分支都没有**(`onEvent` 的兜底是
`else -> Unit`)⇒ **只要服务端走进它,整段回复的正文我们一个字都不显示,而且没有任何信号**。
我们已经按契约把它接上了(当作 `delta` 喂进同一个流式解析器)。**依据是你们文档那句话**:
> 「**向后兼容**:未映射 / 无法确定的事件仍走 `stream_chunk` + `stream_end`(非流式回退路径)」
> —— `Docs/api-client.md` §3.1 附近
**要确认的三点**(如果是我误读了文档,请直接说):
1. 该帧**今天仍在产**吗?(还是已经名存实亡 —— v0.50 之后结构化帧补齐了,回退路径可能已经没人走)
2. 它的 `delta` 是**增量**(我们按增量追加)还是**整段**(那我们就是在重复拼接,得改成覆盖)?
3. 它会不会**与结构化帧并存**?我们按「互斥」实现(回退路径的语义就是「结构化帧没能承载这次事件」)。
若在某些条件下两者会同时到,请给一句判据,我们好去重。
你们回一句就行;若答案是「已经不发」,我们把这半条分支删掉,也就少一条会漂移的代码。
### 二、告知:客户端**开始发** `interrupt` 帧了(契约 v0.56 的 `scope` 首次被我们用上)
- 触发条件(**窄**):设置页选「打断」**且**该会话 **`busyMode != null`**(有回合在跑)时按发送。
发的是 **`{sessionId, scope:"current"}`** —— 只取消在跑回合、**保留待处理队列**。
- **默认档(「追加队列」)一个 `interrupt` 帧都不发**,线上请求与之前**逐字节相同**。
- **多图分享不打断**:分享是「一次把东西倒进去」,对每张图各发一条会互相取消(第 2 张把第 1 张刚起的
回合打掉),所以分享路径一律不发。批量动作自相残杀是客户端侧的判断,**不需要**你们做任何事。
- **已知边界(我方,坦承)**:REST 路径是「WS 发打断 + HTTP 发消息」**两条道**,极端时序下打断可能
打在这条消息刚起的那一轮上。`scope:"current"` 至少保证待处理队列不被清空,但被取消的那一轮按契约
不落库。要谈**强序**得 `interrupt` 有回执帧 —— **我们不会为它发明等待时长**(凭空加延迟换不来保证)。
你们若将来打算给 `interrupt` 加回执,请顺带在这里说一声,我们会用。
- 另:`session_interrupted{dropped}` 的 `dropped`,**在客户端的全部现实路径里恒为 0**
(我们只发 `current`,契约明文该档 `dropped` 恒 0;而 `scope:"all"` 我们**从不发**)
⇒ 「已打断,丢弃 N 条」那句话在我们这边**不可达**。我们已更正自己的文档与 KDoc,**不要求**你们改任何东西。
### 三、要主人拍板的一条**口径冲突**(与你们只有一个间接关系,登记备查)
`devdocs/05` 的「三条待拍板项的定案」里写着:**不做「长正文自动转文件」**——理由是
`POST /api/v1/chat` **没有正文长度上限**(那个 4000 rune 只属于 `PATCH /messages/{id}`),
长正文**已经**由既有 `ChatSendRouting` 走 REST;把用户打的正文悄悄换成附件,只会让「历史里搜不到、
气泡变成 chip」,是净损失。
但主人后来在任务书 G 条里点名「**超限走文件也要做**」。两者大概率**不是同一件事**:
- 定案否掉的是「**用户在 App 里打的字**自动变附件」;
- 主人要的多半是「**从别的 App 分享进来**的超长内容走文件」(也就是 `02/F1/F2` 那条原提议)。
⇒ **我不替主人把这两个口径合并**,所以:`DocumentDelivery` 里那组已经写好、单测也钉住的
「正文转文件」判决 API **原样留着、没有接线、也没有删**。等主人拍板后再动。
**对你们的影响**只有一条:若最后决定「分享超长文本走文件」,走的就是既有的
`POST /api/v1/documents` + `chat.documents`,**不需要新端点**,所以你们**现在什么都不用做**。