Filed unassigned, unlabelled, by the #5741 dev (PM loop round R1, third wave; dev of session_01BAZFhALsQsGqxui8sNqM8s's dispatch) for PM triage. Not a rider on the Phase 2 PR: packages/app-shell source is read-only on that card.
Blocked-by: #5741
What
packages/app-shell/src/views/metadata-admin/ConditionalFormattingEditor.tsx:
:45 exports ROW_PREDICATE_ROOTS, the roots the editor advertises for a conditional-formatting condition.
:329-334 renders CelPredicateField with scope="flattened" and roots={ROW_PREDICATE_ROOTS}, under the comment: "Row predicates bind the row's fields BARE at runtime (status == 'overdue' works — evalRowPredicate spreads the row), so lint stays in the flattened scope".
ConditionalFormattingEditor.test.tsx:137 pins condition: "status == 'overdue'" as lint-clean.
celAuthoring.ts:53-61 defines the two scopes: 'flattened' (default; a bare identifier is legal) vs 'record' (the record is bound ONLY as the record namespace; a bare field ref is flagged as an ERROR with the record.FIELD fix). CelTestRunDialog.tsx:18 describes its bind recipe as "record namespace + flattened fields".
Why it matters
#5741 was ruled B (director seat, 2026-09-02): on runtime record surfaces renderers bind only record.*; the bare-field shorthand and data.* stop resolving. Conditional formatting evaluates through evalRowPredicate (packages/core/src/evaluator/listConditional.ts, resolveConditionalFormatting), so it is one of those surfaces. The moment Phase 2 lands, this editor's lint keeps accepting a spelling the runtime faults with Unknown variable: status — declared-but-unenforced, the exact shape ADR-0089 D3's wrong-root lint exists to prevent — and the metadata-admin editor becomes the last place still teaching the retired spelling to an author (including an AI author, which is the population the lint is for).
Measured on origin/main = adb2a86 (2026-09-05): the runtime engine with a record-only scope returns { ok: false, error: { kind: 'type', message: 'Unknown variable: status' } } for status == 'active'; the same predicate lints clean in the flattened scope.
Fix shape (for triage, not ruled)
Switch the conditional-formatting CelPredicateField to scope="record" (the scope field conditional rules already use), remove any bare-field advertisement from ROW_PREDICATE_ROOTS, flip the :137 pin to expect the record.FIELD diagnostic, and re-read CelTestRunDialog's bind recipe against the post-Phase-2 binding. Whether the same applies to other 'flattened'-scoped authoring sites (celAuthoring.ts:214, :315) depends on which surface each authors for; the flow tier is NOT a row surface (#5738's stand-down 3) and must stay flattened.
Dedup
Searched via MCP search_issues (REST is 403 from this seat class) with a control query that returned #5741 itself. Nearest hits, none covering this: #1582 (the editor's origin), #4075 (the runtime binding side), #3796. No open card names the editor's lint scope after Phase 2.
Filed unassigned, unlabelled, by the #5741 dev (PM loop round R1, third wave; dev of
session_01BAZFhALsQsGqxui8sNqM8s's dispatch) for PM triage. Not a rider on the Phase 2 PR:packages/app-shellsource is read-only on that card.Blocked-by: #5741
What
packages/app-shell/src/views/metadata-admin/ConditionalFormattingEditor.tsx::45exportsROW_PREDICATE_ROOTS, the roots the editor advertises for a conditional-formattingcondition.:329-334rendersCelPredicateFieldwithscope="flattened"androots={ROW_PREDICATE_ROOTS}, under the comment: "Row predicates bind the row's fields BARE at runtime (status == 'overdue'works — evalRowPredicate spreads the row), so lint stays in the flattened scope".ConditionalFormattingEditor.test.tsx:137pinscondition: "status == 'overdue'"as lint-clean.celAuthoring.ts:53-61defines the two scopes:'flattened'(default; a bare identifier is legal) vs'record'(the record is bound ONLY as therecordnamespace; a bare field ref is flagged as an ERROR with therecord.FIELDfix).CelTestRunDialog.tsx:18describes its bind recipe as "record namespace + flattened fields".Why it matters
#5741 was ruled B (director seat, 2026-09-02): on runtime record surfaces renderers bind only
record.*; the bare-field shorthand anddata.*stop resolving. Conditional formatting evaluates throughevalRowPredicate(packages/core/src/evaluator/listConditional.ts,resolveConditionalFormatting), so it is one of those surfaces. The moment Phase 2 lands, this editor's lint keeps accepting a spelling the runtime faults withUnknown variable: status— declared-but-unenforced, the exact shape ADR-0089 D3's wrong-root lint exists to prevent — and the metadata-admin editor becomes the last place still teaching the retired spelling to an author (including an AI author, which is the population the lint is for).Measured on
origin/main=adb2a86(2026-09-05): the runtime engine with a record-only scope returns{ ok: false, error: { kind: 'type', message: 'Unknown variable: status' } }forstatus == 'active'; the same predicate lints clean in theflattenedscope.Fix shape (for triage, not ruled)
Switch the conditional-formatting
CelPredicateFieldtoscope="record"(the scope field conditional rules already use), remove any bare-field advertisement fromROW_PREDICATE_ROOTS, flip the:137pin to expect therecord.FIELDdiagnostic, and re-readCelTestRunDialog's bind recipe against the post-Phase-2 binding. Whether the same applies to other'flattened'-scoped authoring sites (celAuthoring.ts:214,:315) depends on which surface each authors for; the flow tier is NOT a row surface (#5738's stand-down 3) and must stay flattened.Dedup
Searched via MCP
search_issues(REST is 403 from this seat class) with a control query that returned #5741 itself. Nearest hits, none covering this: #1582 (the editor's origin), #4075 (the runtime binding side), #3796. No open card names the editor's lint scope after Phase 2.