⏱️ 本卡所有读数取自同一动作:2026-09-17T16:51Z。逐条本席第一手实测,真阳性对照与假阳性并列。
一句话
scripts/pm/check-widening-tells.mjs 的 T1 匹配器把函数参数的类型标注读成了「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 都会:
- 得一条假 T1;
- 于是
--pair 走 C5、exit 4;
- 而 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
⏱️ 本卡所有读数取自同一动作:2026-09-17T16:51Z。逐条本席第一手实测,真阳性对照与假阳性并列。
一句话
scripts/pm/check-widening-tells.mjs的 T1 匹配器把函数参数的类型标注读成了「Zod object schema 上的新键」。本仓库每一个导出的对象级 refinement check 都带同一个ctx: z.RefinementCtx,参数 ⇒ 任何新增一个这种 check 的 PR 都会白得一条 T1,并因此在check-clause2-carriers --pair上白得一个 C5 / exit 4。实测:假阳性与它的真阳性对照并排
形状是通用的,⛔ 不是这一个 PR 的偶然
ctx: z.RefinementCtx,是本仓库对象级 refinement check 的固定签名。⇒ 每一个新增这类 check 的 PR 都会:--pair走 C5、exit 4;yes,要么修匹配器」—— 在这条假阳性上,改声明是错的补法,可它恰恰是最省事的那条。⇒ 代价不是噪音,是把席位往错误的补法上推。
⭐ 脚本自己就规定了本卡该存在
C5 行的失败文本逐字:「if the tell is FALSE, repair it here in the matcher (
scripts/pm/check-widening-tells.mjs, with a--self-testcase 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/**在它之外 ⇒ 走「另立卡」那一支。建议的修法(⛔ 非裁定)
export function …(与其闭合)之间的名: 类型,行),并加一条--self-test用例把ctx: z.RefinementCtx,这个形状钉死。z.RefinementCtx这个类型名列入例外。--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:specseat 2(座位贴 #18549)复核 PR #18720 / 卡 #17779 时,dev 在out_of_scope_findings里交出来的;本席自己重跑了假阳性、并补了它缺的真阳性对照(以及记录了本席第一次把对照建错的那一次)。Generated by Claude Code