Skip to content

[finding] check-widening-tells 的 T1 把函数参数标注 ctx: z.RefinementCtx, 读成「Zod object 上的新键」—— 每个新增对象级 refinement check 的 PR 都白得一条假 T1 与一个 C5/exit 4,而最省事的补法恰是错的那个 #18721

Description

@os-bill

⏱️ 本卡所有读数取自同一动作:2026-09-17T16:51Z。逐条本席第一手实测,真阳性对照与假阳性并列。

一句话

scripts/pm/check-widening-tells.mjsT1 匹配器把函数参数的类型标注读成了「Zod object schema 上的新键」。本仓库每一个导出的对象级 refinement check 都带同一个 ctx: z.RefinementCtx, 参数 ⇒ 任何新增一个这种 check 的 PR 都会白得一条 T1,并因此在 check-clause2-carriers --pair 上白得一个 C5 / exit 4

实测:假阳性与它的真阳性对照并排

⛔ 假阳性(本轮 PR #18720 的真实 diff)
   ⏱️ 本块全部读数取于 2026-09-17T16:51Z
   git diff 72dd95fa5a..<head> -- packages/spec/src/ui/dashboard.zod.ts > d.patch
   node scripts/pm/check-widening-tells.mjs --declaration no --diff d.patch
   → EXIT=4
     ✗ T1 packages/spec/src/ui/dashboard.zod.ts:628
          — a new key on a Zod object schema — the accept set gains a spelling an author may now write

   而 :624-632 逐行打印出来是:
     export function checkDashboardWidgetMetricMeasureArity(
       widget: { id?: unknown; type?: unknown; values?: unknown },
       ctx: z.RefinementCtx,          ← :628,**第二个参数**
     ): void {
   ⇒ 现场**没有任何对象字面量**。

⭐ 真阳性对照(同一把 matcher、同一个文件路径,合成一条真的新键)
   +  brandNewAuthorableKey: z.string().optional(),
   → EXIT=4
     ✗ T1 packages/spec/src/ui/dashboard.zod.ts:701 — a new key on a Zod object schema
   ⇒ 匹配器对**真**新键是响的,所以上面那条是**假阳性**,⛔ 不是「匹配器不工作」。

⚠️ 本席第一次的亮控读 0 —— 那是**本席的对照建错了**(合成路径 `x.zod.ts` 不在已声明面上,匹配器压根不判它),
   ⛔ 不是关于匹配器的读数。换成仓内真实路径后它就响了。

形状是通用的,⛔ 不是这一个 PR 的偶然

ctx: z.RefinementCtx, 是本仓库对象级 refinement check 的固定签名。⇒ 每一个新增这类 check 的 PR 都会:

  1. 得一条假 T1;
  2. 于是 --pair 走 C5、exit 4;
  3. 而 C5 的处方是「要么改声明为 yes,要么修匹配器」—— 在这条假阳性上,改声明是错的补法,可它恰恰是最省事的那条。

⇒ 代价不是噪音,是把席位往错误的补法上推

⭐ 脚本自己就规定了本卡该存在

C5 行的失败文本逐字:「if the tell is FALSE, repair it here in the matcher (scripts/pm/check-widening-tells.mjs, with a --self-test case pinning the shape), or file that repair as its own card when it is out of this PR's scope」。

本轮 PR #18720 的文件面是 packages/spec/**,scripts/pm/** 在它之外 ⇒ 走「另立卡」那一支。

建议的修法(⛔ 非裁定)

  • A:T1 在判定前先排除函数参数列表上下文(在 export function …( 与其闭合 ) 之间的 名: 类型, 行),并加一条 --self-test 用例把 ctx: z.RefinementCtx, 这个形状钉死。
  • B:更窄 —— 只把 z.RefinementCtx 这个类型名列入例外。⚠️ 更省事但更脆:换一个参数类型名就漏。
  • C:A + 把真阳性对照也钉进 --self-test,免得修假阳性时把真阳性一起修没了。⭐ 本席认为这条最值,因为上面那次「亮控建错」说明这两个方向很容易只测一边

查重(MCP search_issues 含 closed)

#18560 / PR #18700 是近邻,⛔ 不是孪生 —— 本席逐个读过两者的态:都已 closed,题目是「check-widening-tells is BLIND to this repo's own declaring helpers」与「teach check-widening-tells the declaring helpers」。⇒ 那是假阴性方向(该响而没响),本卡是假阳性方向(不该响而响),同一把 matcher 的两个相反方向

⚠️ 它们大概率想要同一个复核者、同一块 --self-test;⛔ 但本席不代并卡,合不合由维护者定。

出处

domain:spec seat 2(座位贴 #18549)复核 PR #18720 / 卡 #17779 时,dev 在 out_of_scope_findings 里交出来的;本席自己重跑了假阳性、并补了它缺的真阳性对照(以及记录了本席第一次把对照建错的那一次)。


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions