Skip to content

lint: promote relationship/master-detail-required from warning to error, scoped to controlled_by_parent — ruled for the v18 boundary (Direction 1 of #8772) #9139

Description

@os-zhuang

Provenance

Slice C (Direction 1) of the #8772 maintainer ruling (2026-08-16, comment 5306089973): promote the lint rule from warning to error, scoped to controlled_by_parent objects only, landing at the v18 major boundary — not before. Carved into its own card on the maintainer's 2026-08-16 instruction (PM chat, verbatim: 「接受你的建议,开新卡,现有的可以关闭?」), recorded by PM session session_01NYgmGheCzM6NrHZN436Cxf. Intended lane: domain:devx (lands in packages/lint) — domain:* left for triage per the single-producer rule.

Hold record (pm:on-hold — decision made, answer is "at v18")

  • Date: 2026-08-16.
  • Reason: the ruling schedules this deliberately at the next major (v17 went GA 2026-08-14 two days ago); it is a contract narrowing that belongs on a version boundary with its migration machinery, not mid-line.
  • Named restart condition: the v18 major window opens (first v18 RC branch cut / the protocol-18 migration window becomes the active target). Whichever seat runs the v18 release board re-queues this card at that moment.
  • Trigger files (opportunistic-restart clause): packages/lint/src/data-model-rules.ts and packages/lint/src/validate-security-posture.test.ts — any dispatch whose file surface intersects them must name this card.

Scope when restarted

  • error fires only for a master reference on a controlled_by_parent object, covering all three unsafe shapes: missing required; required: true + readonly; required: true + system (the latter two skipped by record-validator.ts's provenance-flag continue).
  • Retire the validate-security-posture.test.ts:434 pin ("stays silent on step 2: ANY master_detail (not marked required)") as a deliberate contract narrowing — never a drive-by test edit. Correction on record: that pin lives in packages/lint/, not plugin-security (the A controlled_by_parent object may declare its master reference without required, so the master-access guard is the only thing preventing an unreachable orphan detail row #8772 body mis-homed it).
  • Ships with a v18 migration entry + upgrade-checklist line.
  • model: claude-fable-5 mandatory when implemented (accept-set narrowing).
  • ⛔ Runtime stays as-is (resolveCbpRelation fallbacks kept — tolerance for existing installs); the guard freeze note (identity sibling) is only lifted once this lands.

Refs: #8772 (ruling + full measurement) · siblings: guard freeze note (identity, immediate), builder-force (spec, immediate).

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