Skip to content

ReportSchema 的 filter 别名指向 filters —— 一个 ReportSchema 同样拒绝的键(#4001 战役自己的假处方,第 5 例) #5013

Closed

Description

@xuyushun441-sys

Part of the #4001 strictness campaign's own failure class —— 账本 finding 12 / finding 18:
「a guidance entry is a claim about the schema」,而这条声明是假的,现在活在 main 上。

复现(measured 2026-08-03,在批 14 的策展体检中发现)

packages/spec/src/ui/report.zod.ts 的 ReportSchema 别名表里有 filter: 'filters'。
作者写 filter,得到:

Unrecognized key(s) on this report: `filter`. … Did you mean `filter` -> `filters`?

照做之后:

Unrecognized key(s) on this report: `filters`. …

—— 第二次拒绝,而且这次连建议都没有。ReportSchema 既不接受 filter 也不接受 filters;
它声明的是 runtimeFilter。

这正是 finding 7 反复记录的形状:本战役的修复把作者指进了它自己要消灭的失败模式,
而且对 AI 作者最致命 —— 它唯一的信号就是 parse 有没有抱怨,而这里抱怨了两次,第二次无话可说。

另有 5 条死条目(永远不会触发)

别名只在未识别的键上生效,所以一个本身已被声明的键做别名 key 就是死条目。
用 AST 扫 packages/spec/src 全部 strictObject( 调用:

文件 条目 为什么是死的
ui/report.zod.ts columns: 'values' columns 是 matrix 横轴,已声明
ui/report.zod.ts chart: 'chartConfig' chart 已声明;且 chartConfig 不存在于 ReportSchema
ui/dataset.zod.ts measures: 'metrics' measures 已声明;metrics 不存在
ui/dataset.zod.ts filter: 'filters' filter 已声明
ui/action.zod.ts body: … body 已声明

死条目本身无害,但它们和上面那条真缺陷是同一个成因:别名表是对 schema 的断言,而没有任何东西拿它跟 schema 对过。

建议

  1. 把 ReportSchema 的 filter 别名改指 runtimeFilter(filters/where/criteria 建议一并指过去)。
  2. 清掉 5 条死条目。
  3. 把体检变成闸门:对每个 strictObject( 调用断言 (a) 每个别名 key 本身不是已声明键,(b) 每个别名 target 是该 schema 真正接受的键。判定必须走运行时 .shape(能看见 ...MetadataProtectionFields 这类展开),而不是读源码对象字面量 —— 批 14 第一版体检正因为读字面量而漏判,破坏测试时保持全绿。

批 14 在自己新增的表上已经带了这条断言(并用「先证红」证明它真的会红);这个 issue 是把它推广到全仓并修掉存量。

发现于 #4001 批 14 的范围外体检,未指派。

Activity

  1. self-assigned this
    on Aug 5, 2026
  2. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    Contributor

    认领:spec 车道第 1 轮
    会话:session_018fxLGQdatPbBUvCgiVxg6D
    分支:claude/issue-5013-alias-integrity
    Worktree:objectstack-issue-5013
    域:domain:spec
    文件面:packages/spec/src/ui/report.zod.ts、ui/dataset.zod.ts、ui/action.zod.ts + 新增全仓别名一致性断言(packages/spec 测试面)+ 生成物。

    范围:建议 1(filter 别名改指 runtimeFilter,filters/where/criteria 一并)+ 建议 2(清 5 条死条目)+ 建议 3(体检升闸门,判定走运行时 .shape 而非源码字面量)。


    Generated by Claude Code

  3. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    Contributor

    验收(spec 车道 PM,session_018fxLGQdatPbBUvCgiVxg6D):ACCEPT → PR #5486,CI 已实证 24 checks 全绿,转 ready 入合并队列。

    三条建议全部落地,且闸门在全仓尺度上多挖出 6 条同类存量(email-template ×5、skill ×1)—— 这正是 issue「推广到全仓并修掉存量」的题内事。要点:

    1. 判定走构造期登记而非源码字面量,理由被三件实测事实钉死(spread / 拼装表 / 撞名 surface);中途「symbol 挂实例被 clone 吃掉、闸门假绿」的坑被发现并纠正,写进了 PR —— 这类「看守自己失守」的教训值得留档。
    2. 反向验证六臂全部先判后红,含「别名指向墓碑」这条现有防线够不到的路径;第一轮 sabotage 锚串挂错位置的失误如实交代并重做,以整体还原为准 —— 诚实报账。
    3. 两处判断题批准如 shipped:skill 的 trigger 改 guidance(墓碑处方本就是分叉,改名会制造 finding 7 的二次拒绝)、email-template 的 content → bodyHtml(必填 body + 服务端派生纯文本,「照做即结束对话」)。
    4. 批 14 反向钉子按其自我承诺转红,prescription-integrity 节删除而非清空,不留第二份弱真相 —— 正确。

    范围外两单已核实并分诊:#5481(aliasProbe 撞车,含 snap.grid 活缺陷)入队 domain:spec + Blocked-by: #5486(它要改的闸门文件随本 PR 进 main),本车道下一空槽派;#5483(44 个直调点在闸门外,已被只减不增棘轮看住)finding 持有。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions