Repository navigation
Description
在 #6073 的测量过程中发现,未在该单的范围内修复。观察类,只记录发现,不含修法承诺。
规则自陈的机制
packages/lint/src/validate-visibility-predicates.ts:8-13:
The deprecated spellings —
visibleOn(view form) andvisibility(page component) — stay accepted and are folded intovisibleWhenat the schema boundary (a zod.transform()). Because that fold happens duringparse(), the aliases are gone from the parsed stack — so this rule runs on the pre-parse (normalized) stack … to see what the author actually wrote.
visibility-alias-deprecated 因此被注册为 input: 'normalized'(authoring-rules.ts 第六条)。
实测:折叠发生在 normalizeStackInput 之内,即 normalized 层的上一层
ADR-0087 D2 的两条转换 —— view-visibleOn-to-visibleWhen(packages/spec/src/conversions/registry.ts:438)与 page-component-visibility-to-visibleWhen(:549)—— 由 normalizeStackInput 执行。而 normalizeStackInput 的输出就是 normalized 层的定义。所以规则拿到手时别名已经不在了。
在 origin/main @ a7e7851 的 worktree 上逐个 site 实测(spec/lint 均为本地 dist 构建):
| 别名 site | 规则读原始对象(= 单测的喂法) | 规则读 normalized 层(= 三条命令的喂法) |
defineStack |
|---|---|---|---|
views[].form.sections[].visibleOn |
1 finding | 0 | 通过,发 1 条转换通知 |
views[].formViews.edit.sections[].visibleOn |
1 finding | 0 | 通过,发 1 条转换通知 |
pages[].regions[].components[].visibility |
1 finding | 0 | 通过,发 1 条转换通知 |
views[].sections[].visibleOn(单测 :42 用的形状) |
1 finding | 1 finding | 抛错:views.0: Unrecognized key(s) on this view container: + 反引号 sections |
即:三个 spec-合法的别名 site 上,规则在 normalized 层一律报 0;唯一还能报的形状(容器顶层 sections)被 .strict() 的 ViewSchema 直接拒收 —— 正是 #4984 / #6251 那一族的签名:单测绿,是因为 fixture 用的形状生产环境永远不会送进来。
但作者并没有被静默
同一条转换在 defineStack 里会经 warnConversionNotice 喊出来,措辞比规则本身更好(带退役窗口):
defineStack: views[0].form.sections[0].visibleWhen: 'visibleOn' -> 'visibleWhen'
(converted at load; conversion 'view-visibleOn-to-visibleWhen', retires in protocol 16).
Update the source to the canonical shape — the conversion stops running then.
所以今天没有用户受损,这也是本单按观察类归档、不打 pm:queue 的理由。受影响的只是这条 advisory 规则本身:它是一条永不触发的分支,而它的单测一直报绿。
同文件另外两条规则(visibility-bare-identifier、visibility-root-mislayered)判的是谓词值,值在折叠后原样搬进 visibleWhen,实测在 normalized 层照常各报 1 条 —— 不受影响,不要连坐。
两种读法,交分诊评级
- 可以退役:D2 转换通知已经完整覆盖这条 advisory 的证据面,且措辞更好、带退役期。按 ADR-0049「declared ≠ enforced」,一条不可达的规则分支应当摘掉,而不是留着当假覆盖。
- 可以修活:若希望
os lint的报告里出现这条(转换通知走的是defineStack的console.warn,不进 lint 的 findings 列表,--json里也看不到),那就得让规则读真正的 pre-parse 值 —— 而这会改动runAuthoringRules的对外输入契约,属于 lint 包公共 API 的措辞问题,须由维护者定。
我倾向第一种:通知通道已经存在、更准确、且随 protocol 16 一起退役,重复一遍只是多一个声音;但严重性由分诊轮判,不由我判。
复现
packages/lint 内即可复现,不需要跑 CLI:
import { normalizeStackInput } from '@objectstack/spec';
import { validateVisibilityPredicates } from '@objectstack/lint';
const stack = { views: [{ name: 'f',
form: { type: 'simple', sections: [{ label: 'S', visibleOn: "record.a == 1", fields: [{ field: 'name' }] }] } }] };
validateVisibilityPredicates(stack); // => 1 (visibility-alias-deprecated)
validateVisibilityPredicates(normalizeStackInput(stack)); // => 0 ← 三条命令走的就是这条Refs:#6073(发现处,该单的 PR 已按实测把 AuthoringRuleInputTier 注释里「别名靠 pre-parse 层才看得见」这句改掉并附回归 pin)、#6251(同族:规则遍历面 vs 真实 stack 形状)、#4984 / #5009(幽灵检查一族)、ADR-0089 D3b、ADR-0087 D2。
Activity
os-project-manager commentedon Aug 8, 2026
Findings sweep (maintainer-authorized one-off, 2026-08-07 — registered on #6015): promoted to the queue. A deprecation rule that can never fire on any real input is an inert gate telling readers a surface is guarded when it isn't — restore-invariant class. Fix: re-anchor the rule to the layer where the aliases still exist (pre-
normalizeStackInput), or retire it with the alias fold as the recorded guard.finding→pm:queue.Generated by Claude Code
hotlong commentedon Aug 8, 2026
认领 — devx 车道执行座位。
pm:queue→pm:dispatched,assignee 已置。session_01BDmDsu2575gDxeMCxXhDE3claude/issue-6318-visibility-alias-unreachablepackages/lint/src/validate-visibility-predicates.ts、packages/lint/src/authoring-rules.ts(规则注册)及其测试。⛔ 不碰packages/spec/src/conversions/registry.ts(ADR-0087 D2 转换是证据,不是待修点)、⛔ 不碰同文件另两条规则visibility-bare-identifier/visibility-root-mislayered(它们判谓词值,值在折叠后原样搬进visibleWhen,实测在normalized层照常各报 1 条 —— 不受影响,不要连坐)、⛔ 不碰content/docs/releases/。sweep 写了两条:「re-anchor the rule to the layer where the aliases still exist (pre-
normalizeStackInput), or retire it with the alias fold as the recorded guard」。但它没有回应立单正文里的一句话:重锚那条会改动runAuthoringRules的对外输入契约,属于 lint 包公共 API 的措辞问题,「须由维护者定」。⇒ 可派的是「退役」那条(ADR-0049 declared ≠ enforced 是既有仓规,且立单人本人倾向它:D2 转换通知已完整覆盖这条 advisory 的证据面、措辞更好、带退役窗口)。
⇒ ⛔ 若你测量后认为必须重锚,停下来上报,不要自行改公共输入契约。
这张单钉的是什么
不是「这条规则报错了」,而是它永远不报:三个 spec-合法的别名 site 在
normalized层一律 0 finding,而唯一还能报的形状(容器顶层sections)被.strict()的ViewSchema直接拒收。单测绿,是因为 fixture 用的形状生产环境永远不会送进来——#4984 / #6251 那一族的签名。packages/lint属于那 19 个「排除自身测试」的包 ⇒ 必跑pnpm check:type-check-debt。包级typecheck结构性看不见测试文件的类型错误,今日已有一张 PR 因此本地全绿、CI 红。Generated by Claude Code
docs(deployment): give the "gate" table its fourth column — the runti…
docs(deployment): reconcile the gate section with the four doors, the…