MediaKind 穷尽性守卫 + 文档「第四态」计数纠正 #100

Closed
opened 2026-07-30 02:21:47 +00:00 by KumaAgent · 0 comments
Member

来源

2026-07-30 对「MediaKind.file 第四态是否该开实现票」做的一轮核实(4 个调查 agent + 2 个对抗性 skeptic)。结论是不开 file 的实现票(ADR-0028 有三处设计空白:声明粒度掉到 file format 而路由函数只吃 kind、file 内容块的线格式未定、第三级「host 前处理 port 的责任」既非 describe 也非 placeholder 且没说怎么通知 host;且本仓刚对同源条目「日期临近触发」给过「等 host、不是设计错了」的留痕判例)。

但核实过程中掉出两件不依赖任何未决设计、可以独立做掉的事,就是本票。

What to build

一、给 MediaKind 补穷尽性守卫(代码)

MediaKind 是本仓唯一没有 get_args 驱动穷尽性测试的 Literal——BreakerStateTriggerPathGateVerdict 都已经有(其中 GateVerdict/TriggerPath 的守卫正是 assert set(<表>) == set(get_args(<Literal>)) 这个形状,直接照抄即可)。

multimodal 模块里有两张MediaKind 键控的表(占位标签表 _PLACEHOLDER_LABEL、原生内容块构造器表 _NATIVE_BLOCK_BUILDERS)。它们是 dict[MediaKind, ...] 字面量,basedpyright 不对字典字面量做穷尽检查:往 MediaKind 里加一个取值而忘了给这两张表补 key,类型检查不报错、现有测试全绿,只在运行时 KeyError

守卫的价值不是"修一个正在发生的 bug"——今天没有任何取值缺 key。价值是让下一次加 kind 在测试期就红,而不是等到运行时。(延续本仓既有教训:机械枚举驱动的覆盖会静默消失,必须另配一条守卫。)

注意传输层别名表 _TRANSPORT_ALIASdict[str, str]、刻意不按 MediaKind 键控(它只装 sticker→image 这一条),不要把它纳入穷尽性断言。

二、纠正文档里「第四态 / 封闭四态」的措辞(文档)

MediaKind 在代码里的实际取值是 image/video/audio/sticker——第四态的位置早被 sticker(issue #70、ADR-0024)占了。而 ADR-0028、CONTEXT.md、design.md 三处仍写着"MediaRef.kind 扩展为封闭四态,新增 file"/"file第四态)"。这两套说法的名单不重叠:真要落地 file,实际是态,"第四态"这个序数和"封闭四态"这个计数都已被证伪。

这是一处真实的文档自相矛盾(不是滞后一步,是算错了个数),会误导任何按文档排期的人。

Acceptance criteria

  • 新增穷尽性守卫测试,断言两张按 MediaKind 键控的表(占位标签表、原生内容块构造器表)的 key 集合各自等于 set(get_args(MediaKind)),形状照抄本仓既有的 GateVerdict/TriggerPath 守卫
  • 用变异验证一次这条守卫真的有效:临时从其中一张表删掉一个 key,确认新测试变红撤销变异不要用 git checkout <file>,会连未提交的实现一起丢;用精确反向替换或先 cp 备份)
  • 不把 _TRANSPORT_ALIASdict[str, str],刻意只装 sticker→image)纳入穷尽性断言
  • 本票不新增任何 MediaKind 取值,不碰 multimodal 的路由逻辑,纯加测试
  • ADR-0028 的措辞纠正按本仓 ADR 纪律追加一个 ## 更新(2026-07-xx,issue #N)说明实际取值与"封闭四态/第四态"的偏差,绝不就地改写既有决策/更新节(既有原文与推翻它的理由都应能被读到)
  • CONTEXT.md 与 design.md 不适用「更新节」体例,就地修订即可,但改动要能被 git log 追溯到本票
  • 不改 docs/research/ 下的研究底稿——那是 2026-07-10 当时的证据记录,按本仓惯例不追溯改写历史底稿
  • 文档改动只在 docs 分支,按既定规则永不推送(同 issue #61 的先例:代码走 PR,文档留本地 commit)

Not in scope

  • MediaKind.file 本体的实现:ADR-0028 有三处设计空白(声明粒度、线格式、第三级 host 通知接口),按 #96 对实现类落差的既定路径需先 grill 再拆 PRD,不在本票。
  • file 决策打「尚未实现」留痕:独立事项。本票只纠正"第四态/封闭四态"这个算错了的计数,不对 file 的实现状态表态。
  • host 上报 kind="file" 时的 KeyError 加固:该路径当下不可达(core 从不构造 MediaRef,唯一入口是 host,而目前没有任何 host 接入过 arise)。要触发必须有一个违反类型契约的 host。不在本票,也不要顺手加一个"看起来合理"的理由把它写成活 bug。
## 来源 2026-07-30 对「`MediaKind.file` 第四态是否该开实现票」做的一轮核实(4 个调查 agent + 2 个对抗性 skeptic)。结论是**不开** file 的实现票(ADR-0028 有三处设计空白:声明粒度掉到 file format 而路由函数只吃 kind、file 内容块的线格式未定、第三级「host 前处理 port 的责任」既非 describe 也非 placeholder 且没说怎么通知 host;且本仓刚对同源条目「日期临近触发」给过「等 host、不是设计错了」的留痕判例)。 但核实过程中掉出**两件不依赖任何未决设计、可以独立做掉**的事,就是本票。 ## What to build **一、给 `MediaKind` 补穷尽性守卫(代码)** `MediaKind` 是本仓**唯一**没有 `get_args` 驱动穷尽性测试的 `Literal`——`BreakerState`、`TriggerPath`、`GateVerdict` 都已经有(其中 `GateVerdict`/`TriggerPath` 的守卫正是 `assert set(<表>) == set(get_args(<Literal>))` 这个形状,直接照抄即可)。 而 `multimodal` 模块里有两张**按 `MediaKind` 键控**的表(占位标签表 `_PLACEHOLDER_LABEL`、原生内容块构造器表 `_NATIVE_BLOCK_BUILDERS`)。它们是 `dict[MediaKind, ...]` 字面量,**basedpyright 不对字典字面量做穷尽检查**:往 `MediaKind` 里加一个取值而忘了给这两张表补 key,类型检查不报错、现有测试全绿,只在运行时 `KeyError`。 守卫的价值不是"修一个正在发生的 bug"——今天没有任何取值缺 key。价值是**让下一次加 kind 在测试期就红**,而不是等到运行时。(延续本仓既有教训:机械枚举驱动的覆盖会静默消失,必须另配一条守卫。) 注意传输层别名表 `_TRANSPORT_ALIAS` 是 `dict[str, str]`、刻意不按 `MediaKind` 键控(它只装 sticker→image 这一条),**不要**把它纳入穷尽性断言。 **二、纠正文档里「第四态 / 封闭四态」的措辞(文档)** `MediaKind` 在代码里的实际取值是 `image`/`video`/`audio`/**`sticker`**——第四态的位置早被 `sticker`(issue #70、ADR-0024)占了。而 ADR-0028、CONTEXT.md、design.md 三处仍写着"`MediaRef.kind` 扩展为**封闭四态**,新增 `file`"/"`file`(**第四态**)"。这两套说法的名单不重叠:真要落地 `file`,实际是**五**态,"第四态"这个序数和"封闭四态"这个计数都已被证伪。 这是一处真实的文档自相矛盾(不是滞后一步,是算错了个数),会误导任何按文档排期的人。 ## Acceptance criteria - [ ] 新增穷尽性守卫测试,断言两张按 `MediaKind` 键控的表(占位标签表、原生内容块构造器表)的 key 集合各自等于 `set(get_args(MediaKind))`,形状照抄本仓既有的 `GateVerdict`/`TriggerPath` 守卫 - [ ] 用变异验证一次这条守卫真的有效:临时从其中一张表删掉一个 key,确认新测试**变红**(**撤销变异不要用 `git checkout <file>`**,会连未提交的实现一起丢;用精确反向替换或先 `cp` 备份) - [ ] 不把 `_TRANSPORT_ALIAS`(`dict[str, str]`,刻意只装 sticker→image)纳入穷尽性断言 - [ ] 本票**不新增任何 `MediaKind` 取值**,不碰 `multimodal` 的路由逻辑,纯加测试 - [ ] ADR-0028 的措辞纠正按本仓 ADR 纪律**追加一个 `## 更新(2026-07-xx,issue #N)` 节**说明实际取值与"封闭四态/第四态"的偏差,**绝不就地改写既有决策/更新节**(既有原文与推翻它的理由都应能被读到) - [ ] CONTEXT.md 与 design.md 不适用「更新节」体例,就地修订即可,但改动要能被 `git log` 追溯到本票 - [ ] **不改 `docs/research/` 下的研究底稿**——那是 2026-07-10 当时的证据记录,按本仓惯例不追溯改写历史底稿 - [ ] 文档改动只在 `docs` 分支,按既定规则**永不推送**(同 issue #61 的先例:代码走 PR,文档留本地 commit) ## Not in scope - **`MediaKind.file` 本体的实现**:ADR-0028 有三处设计空白(声明粒度、线格式、第三级 host 通知接口),按 #96 对实现类落差的既定路径需**先 grill 再拆 PRD**,不在本票。 - **给 `file` 决策打「尚未实现」留痕**:独立事项。本票只纠正"第四态/封闭四态"这个**算错了的计数**,不对 file 的实现状态表态。 - **host 上报 `kind="file"` 时的 KeyError 加固**:该路径**当下不可达**(core 从不构造 `MediaRef`,唯一入口是 host,而目前没有任何 host 接入过 arise)。要触发必须有一个违反类型契约的 host。不在本票,也不要顺手加一个"看起来合理"的理由把它写成活 bug。
Yushu closed this issue 2026-08-11 01:16:09 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ProjectKuma/arise#100
No description provided.