修复: 判据注释说"这个值来自 Go 源",实际**一个字节没读** —— 服务端上限真漂移 29 pass/0 fail 一个字不变

pi 报的那格(4b 的 if(false))已由并发会话的自检 4c 补上,我变异验证通过(三种恒假写法都红)。
这轮顺着"第 2 列现在每次运行都可见"去读那 6 条理由,挖出**同族的另一条缝**:

`harmony-imageprep` 的
  /** 服务端壁纸上限(appearance.go 的 appearanceMaxBytes() 默认值) */
  const SERVER_LIMIT = 4 << 20;
注释说它来自 Go 源,而它一个字节的 Go 源都没读。实测(同刻 A/B):
把 Go 里那个默认值改成 8<<20(真漂移)⇒ 本文件 **29 pass / 0 fail 一个字都没变**
⇒ 这条判据存在的全部理由(客户端上限要留在服务端那道门之内,否则必然 413 /
白扔分辨率)在服务端那道门真动了时**不会红**。危险处在于注释让读者以为已对齐。

修法(三件):
① 从**真源头**解析,且**两处都读、要求相等** ——
   ⚠️ 我第一版只读了 appearance.go 的 `return 4<<20`,那是**兜底分支**;
   生产里 config.C 非 nil ⇒ 生效值来自 config.go 的
   `MaxAppearanceBytes: getEnvInt64("AGENTMAIL_MAX_APPEARANCE_BYTES", 4<<20)`。
   "读了源"还不够,还得问"读的是不是生效的那一处"(同族缝的下一层)。
② 解析失败必须红,**不许静默回退到硬编码**(回退 = 把"我读不到"变成"值是对的")。
③ 新增一条判据钉住"真的读出来了":两处都无 err、生效值等于 config 那处、等于兜底那处、且 >0。
   并**如实标出标签范围**:这证明"与默认值对齐",**不证明**"与运行值对齐" ——
   AGENTMAIL_MAX_APPEARANCE_BYTES 可覆盖;别把本条读成"413 已不可能发生"。

变异验证(每个只动一处):config.go 默认值→8MB ⇒ fail=2;
appearance.go 兜底→8MB(两处不一致)⇒ fail=1(恰为"两处相等"那条,
余量那条**故意不红**,因为生效值没变 ⇒ 所以"两处相等"必须单独存在);
config.go 那行删掉 ⇒ fail=2(不许静默)。基线 30 pass / 0 fail。

另:`STATIC_ONLY` 第 2 列里那句「+ 服务端,三样本机都没有」是**假话** ——
`server/internal/handler/attachments.go` 在本机、其 Go 测试 `-run Attach` 跑得通、
且本判据根本没连服务端。已改成"欠的只有设备侧那一半"(列每次运行都播报,假话会被读出来)。
注册条数 29→30 已同步。全套:files=31 checks=396 pass=384 fail=12 red=9 broken=3(跑在隔离 worktree)。

`CRITERIA.md §16.4`:通用规则 —— **注释里写"这个值来自 X"不构成读 X**;
凡"必须与别处一致"的判据先问:它真读了别处,还是抄了一份?
This commit is contained in:
2026-09-19 12:42:32 +08:00
parent 36ef15a8f2
commit a0e950109a
3 changed files with 142 additions and 4 deletions

View File

@ -990,6 +990,66 @@ if (!staticBroadcastSeen.some(t => STATIC_ONLY.every(([f, why]) => t.includes(f)
> 若它不该被任何人读,**删掉它** —— **余额里读不出来的东西等于不存在**。
> 只有在"这个字段本来就有真假"时,才轮得到加判据 —— 而且**必须先拿现有数据验一遍**。
### 16.4 ★★ **注释说是从某处读的,实际一个字节没读** —— 硬编码冒充"读源"(dsh 2026-09-19)
§16.3 把第 2 列变成每次运行都可见之后,我做的第一件事就是**去读它** —— 于是读到一句假话,
顺着它又挖出本仓一条**同族**的缝。**这条缝的形状**:
```js
/** 服务端壁纸上限(`server/internal/handler/appearance.go` 的 `appearanceMaxBytes()` 默认值) */
const SERVER_LIMIT = 4 << 20; // ← 注释说它来自 Go 源,而它一个字节的 Go 源都没读
```
**实测**(dsh,同刻 A/B):把 `appearance.go` 里 `appearanceMaxBytes()` 的默认值
`4 << 20` 改成 `8 << 20`(**真漂移**)⇒ `harmony-imageprep` **29 pass / 0 fail,一个字都没变**。
⇒ 这条判据存在的全部理由就是"客户端上限要留在服务端那道门之内(否则必然 413 / 白扔分辨率)",
而**服务端那道门真动了,它不会红**。
★ **它为什么危险**:注释让读者**以为**这里已经对齐了服务端 ——
**"我以为它在读源头"正是没人再去读源头的原因**。
这与 §16.3 那条母规则同一族:**一个字段/一个判据的可信度,来自它真的读了那个东西,
不来自它说自己读了。**
**修法**(三件):
1. **从真源头解析** —— ⚠️ **而"真源头"是哪一处,我第一版也读错了**,如实记下:
我最初去读 `appearance.go` 的 `return 4 << 20`,那是**兜底分支**
(`if config.C != nil && config.C.MaxAppearanceBytes > 0` 之后才轮到它)。
生产里 `config.C` 非 nil ⇒ **真正生效的值来自 `config.go`**:
`MaxAppearanceBytes: getEnvInt64("AGENTMAIL_MAX_APPEARANCE_BYTES", 4<<20)`。
⇒ **只读兜底分支的修法,在"有人动了 config 默认值"时会漏** —— 这是同一族缝的下一层:
**"读了源"还不够,还得问"读的是不是生效的那一处"。**
现在**两处都读,并要求它们相等**(不相等 ⇒ config 未注入时会走另一个门)。
2. **解析失败必须红**,**不许静默回退到硬编码** —— 回退等于把"我读不到"变成"值是对的"
(这几轮反复消的那条缝)。
3. **加一条判据钉住"真的读出来了"**:两处都无 `err`、`SERVER_LIMIT === LIMIT_CONFIG.value`、
**`SERVER_LIMIT === LIMIT_FALLBACK.value`**、且 `> 0`(防解析出 `0` 让"小于上限"变成恒真)。
**变异验证**(dsh,每个变异只动一处、其余不变):
| 变异 | 期望 | 实测 |
|---|---|---|
| `config.go` env 默认值 `4<<20` → `8<<20`(**生产生效那一处**) | 红 | `fail=2`(第 9 条"两处都读到" + 第 11 条余量)✓ |
| `appearance.go` 兜底 `4<<20` → `8<<20`(**两处不一致**) | 红 | `fail=1`(恰为第 9 条"两处相等")✓ |
| `config.go` 那一行整个删掉(**读不到**) | 红,且**不许静默** | `fail=2`(含"读不出生效上限")✓ |
| 基线 | 全绿 | `30 pass / 0 fail` ✓ |
★ 注意 B 只红第 9 条、**不红第 11 条**:因为生效值取 config 那处、而它没变 ——
**这是对的**(余量断言针对生效值),也说明"两处相等"那条**必须单独存在**,
否则"兜底分支漂了"会完全无声。
⚠️ **本节的标签范围**:它证明的是"客户端上限与**源码里那个默认值**对齐",
**不是**"与服务端运行时实际生效的上限对齐" —— 那个值是 `config.C.MaxAppearanceBytes` **可覆盖**的
(`appearanceMaxBytes()` 先看配置、配置没有才用它)。配置一旦调过,**静态读源码仍然对不上运行值**。
要覆盖后者得真起服务端读它的行为 —— 那属于"设备/服务端在场"的判据,本机判不了。
**别把这条读成"413 已经不可能发生”。**
★ **通用规则**(与 §16.1/§16.3 并列):
> **注释里写"这个值来自 X",不构成读 X。**
> 凡"某个数必须与别处一致"的判据,先问:**它真的读了别处吗,还是抄了一份?**
> 抄一份的判据**在别处改变时不会红** —— 而它的注释会让你以为它会。
## 17. 变异只证明「注入的样本被抓」,**不证明完备性**;判据的**标签必须等于断言范围**
**规则**(pi 2026-09-14):一条判据通过变异验证之后,只能说"我注进去的那一条会被抓"。