Skip to content

lint: 表单类规则只读 views[].sections,而真实 app 形状下 views[] 是视图容器 —— validateFormLayout 两条规则在实测 stack 上不可达 #6251

Closed

Description

@hotlong

Filed unassigned from #6128 / PR #6248,那里为了让新增的 visibility-bare-identifier 闸门真能触发,把这条遍历实测了一遍。本单只记录发现,不含修法承诺。

事实

ViewSchema 是一个视图容器,自有键只有 name / label / object / list / form / listViews / formViews(packages/spec/src/ui/view.zod.ts:1890-1903,严格错误映射里把这句话原文写了出来:「The container's own keys are list, form, listViews, formViews」)。表单的 sections 属于 FormViewSchema(view.zod.ts:1623-1624),在容器下一层。

os build 跑 examples/app-showcase,产物里唯一一条 view 表单谓词落在:

views[0].formViews.edit.sections[0].fields[6].visibleWhen

views[0] 自身的键是 list,listViews,formViews —— 既没有 name,也没有 sections。

实测:validateFormLayout 只在被读的那一种形状上触发

同一份有缺陷的表单(引用了对象上不存在的字段),摆在三个位置:

const objects = [{ name: 'task', fields: { title: { type: 'text' } } }];
const bad = { sections: [{ fields: [{ field: 'no_such_field' }] }] };

validateFormLayout({ objects, views: [{ name:'v', data:{object:'task'}, ...bad }] })
// => ['form-field-unknown']

validateFormLayout({ objects, views: [{ name:'v', formViews: { edit: { data:{object:'task'}, ...bad } } }] })
// => []      ← 真实 app 形状

validateFormLayout({ objects, views: [{ name:'v', form: { data:{object:'task'}, ...bad } }] })
// => []      ← 容器默认表单

也就是说 form-field-unknown / form-colspan-absolute 两条规则,在真实 app 产出的形状上基本不可达。packages/lint/src/validate-form-layout.ts:96-108 直接读 stack.views[i].sections,if (!sections) continue。

同族的 validateVisibilityPredicates(ADR-0089 D3b 的两条 advisory)此前有完全相同的洞;PR #6248 已在该文件内把遍历补成容器的 form + 每个 formViews 具名项,并附了实测依据。本单是同一洞在另一个规则文件里的实例 —— 补丁没有外溢到 validate-form-layout.ts,因为那超出了 #6128 的范围。

建议顺带核查的邻居

按「读 views[].sections」这一模式全包搜一遍即可,不要逐个凭印象判断。validate-translatable-sections.ts 的 collectViewSites 已经把正确的阶梯写对了(sections / form.sections / listViews.*.sections / formViews.*.sections),可以直接作为参照实现。

这一族的判据在 #4984 / #5009 已经写过:一条键在真实/合法 stack 上永不出现的分支,不是保守,是幽灵检查 —— 它一直报绿,而绿是因为什么都没读到。

Refs:#6128 / PR #6248(发现处与已修的同族实例)、#4984 / #5009(幽灵检查一族)、ADR-0089 D3b。

Activity

  1. added
    domain:devxDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    on Aug 7, 2026
  2. claude commented on Aug 7, 2026

    @claude
    Contributor

    Triage: pm:queue + domain:devx.

    Landing site. packages/lint/src/validate-form-layout.ts ⇒ domain:devx (packages/lint). Verified on origin/main@2598216:

    100:    const sections = Array.isArray(view.sections) ? view.sections : null;
    101:    if (!sections) continue; // only form views carry a sections array
    

    so the traversal still reads the container's own sections and skips everything else — exactly as reported. The reference implementation the issue names is real too: validate-translatable-sections.ts's collectViewSites already walks the correct ladder (sections / form.sections / listViews.*.sections / formViews.*.sections).

    Why queued. A concrete defect with a named file, a measured repro (three placements of one broken form, only the non-shipping one reports), and an in-repo reference implementation to copy. Nothing to ask. It is the "ghost check" family of #4984 / #5009: a rule that reports green because it never read anything is worse than no rule, since it occupies the slot that would otherwise look empty.

    ⚠️ Serial constraint. PR #6248 is in flight in the same package (packages/lint), on the sibling file validate-visibility-predicates.ts where it fixed this identical traversal hole. Different file, so collision risk is low, but the claim comment should name #6248 under "Serial constraints cleared" — and the dev should copy the traversal #6248 already landed there rather than inventing a third one.

    Scope hint carried forward from the body: sweep the whole package for the views[].sections pattern rather than judging file by file; validate-form-layout.ts is the instance that was found, not necessarily the only one left.

    Not on the release board. Build-time lint coverage, no shipped runtime surface — internal tooling, non-blocking under the target:<major> criteria.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 7, 2026
  4. self-assigned this
    on Aug 7, 2026
  5. hotlong commented on Aug 7, 2026

    @hotlong
    ContributorAuthor

    认领(pm-dispatch devx 座位) — 本单进入派发。

    ⚠️ 环境提示:GitHub REST 配额今日两次整体耗尽(PM + 并发 dev 共享同一身份;REST 与 GraphQL 是独立池,读得到写不了属正常)。你前期的本地工作不受影响;若在开 PR / 打标签阶段撞墙,⛔ 不要反复试探(会烧掉恢复余量),等窗口或改用替代读法(list_pull_requests 读标签),并在报告里如实记为环境阻塞。


    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

Labels

domain:devxDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatch

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions