Filed unassigned by the #7727 dev (PM loop R3, session session_01YBWFb5YgMU5dw8p2VKj16S) after contract review of PR #8164 named it. ⛔ Not folded into that PR: same defect class, different component, and three of the six mounts below need a per-surface verdict this card's author does not get to make.
What the search that found #7727 missed
#7727 and its triage both looked for the explicit spelling scope="flattened". CelPredicateField also reaches the flattened lint by callers omitting the prop — celAuthoring.ts reads hint.scope ?? 'flattened'. Measured on origin/main = c14d3a090, every CelPredicateField mount in the repo:
| mount |
scope= in that file |
scope in effect |
ConditionalFormattingEditor.tsx:341 |
1 |
record (PR #8164) |
inspectors/ObjectFieldInspector.tsx:760, :874, :888, :902 |
4 |
record |
PermissionAdvancedFacets.tsx:356, :372 |
0 |
flattened — CORRECT, RLS is not a row surface (#5738 stand-down 3) |
inspectors/ConditionBuilder.tsx:368 |
0 |
flattened — and this is the problem |
grep -c 'scope=' inspectors/ConditionBuilder.tsx is 0. It has no scope prop on its own public interface either, so no caller can override it.
Why one of its callers is a defect today
packages/core/src/evaluator/rowPredicateCanon.ts:16-18 names the surface, verbatim:
A row predicate — visible / disabled / enabled on an action renderer, a row scope, a record:alert, a conditional-formatting condition — used to bind the row THREE ways
and packages/react/src/hooks/useExpression.ts:153-158 is what binds it now:
export function usePredicateRecordContext(record: unknown): Record<string, any> {
return useMemo(() => {
if (record == null || typeof record !== 'object' || Array.isArray(record)) return {};
return { record: record as Record<string, any> };
}, [record]);
}
record and nothing else. So a bare status == 'done' typed into Visible when on an action lints clean and never matches — #7727's defect exactly, on a surface #7727 does not touch.
The six ConditionBuilder mounts, with what I could and could not settle
| mount |
authors |
verdict |
inspectors/ActionDefaultInspector.tsx:671 |
action visible |
⛔ DEFECT — row surface by the canon's own words |
inspectors/ActionDefaultInspector.tsx:672 |
action disabled |
⛔ DEFECT — same |
views/studio-design/ObjectValidationsPanel.tsx:313 |
validation rule condition |
⚠️ LIKELY DEFECT — the draft-level validator for the sibling surface already runs scope: 'record' (clientValidation.ts:792, :806), so the editor and the validator disagree |
inspectors/PageBlockInspector.tsx:689 |
page block visibleWhen |
❓ needs a verdict — node tier, not classified by #5330 |
widgets.tsx:2369 (ConditionWidget) |
any schema-driven predicate key |
❓ needs a verdict — its surface is whatever the host schema points it at, so it may need the scope to become a prop |
inspectors/FlowNodeConfigField.tsx:96 |
flow node condition |
✅ CORRECT as-is — flow tier is not a row surface (#5738 stand-down 3) |
inspectors/HookDefaultInspector.tsx:291 |
hook condition |
❓ needs a verdict — server trigger tier |
⇒ the fix is not "flip ConditionBuilder to record scope". Two of its callers are known-flattened or known-not-row, so the scope has to become a prop that each caller sets, and three callers need the tier question answered first.
What this card is NOT
⛔ Not a duplicate of #8155 (the app root is refused although bound) or #8166 (data.* is accepted although dead). Those are about the engine's root vocabulary at scope:'record'; this is about which sites reach scope:'record' at all. All three are tails of #5741 Phase 2, and this one is the only one with a mount site still teaching the bare shorthand.
Dedup
search_issues (REST is 403 from this seat class) — the same query returned #7727 and #8155, so the search was live. Nearest hits, none covering this: #6226 (ConditionBuilder rollout), #6293 (its row-mode quoting), #4527 (its blocking-issue reporting), #4421 (action visible and permissions). No open card names ConditionBuilder's lint scope.
Filed unassigned by the #7727 dev (PM loop R3, session
session_01YBWFb5YgMU5dw8p2VKj16S) after contract review of PR #8164 named it. ⛔ Not folded into that PR: same defect class, different component, and three of the six mounts below need a per-surface verdict this card's author does not get to make.What the search that found #7727 missed
#7727 and its triage both looked for the explicit spelling
scope="flattened".CelPredicateFieldalso reaches the flattened lint by callers omitting the prop —celAuthoring.tsreadshint.scope ?? 'flattened'. Measured onorigin/main=c14d3a090, everyCelPredicateFieldmount in the repo:scope=in that fileConditionalFormattingEditor.tsx:341record(PR #8164)inspectors/ObjectFieldInspector.tsx:760, :874, :888, :902recordPermissionAdvancedFacets.tsx:356, :372inspectors/ConditionBuilder.tsx:368grep -c 'scope=' inspectors/ConditionBuilder.tsxis 0. It has noscopeprop on its own public interface either, so no caller can override it.Why one of its callers is a defect today
packages/core/src/evaluator/rowPredicateCanon.ts:16-18names the surface, verbatim:and
packages/react/src/hooks/useExpression.ts:153-158is what binds it now:recordand nothing else. So a barestatus == 'done'typed into Visible when on an action lints clean and never matches — #7727's defect exactly, on a surface #7727 does not touch.The six
ConditionBuildermounts, with what I could and could not settleinspectors/ActionDefaultInspector.tsx:671visibleinspectors/ActionDefaultInspector.tsx:672disabledviews/studio-design/ObjectValidationsPanel.tsx:313conditionscope: 'record'(clientValidation.ts:792,:806), so the editor and the validator disagreeinspectors/PageBlockInspector.tsx:689visibleWhenwidgets.tsx:2369(ConditionWidget)inspectors/FlowNodeConfigField.tsx:96inspectors/HookDefaultInspector.tsx:291condition⇒ the fix is not "flip ConditionBuilder to record scope". Two of its callers are known-flattened or known-not-row, so the scope has to become a prop that each caller sets, and three callers need the tier question answered first.
What this card is NOT
⛔ Not a duplicate of #8155 (the
approot is refused although bound) or #8166 (data.*is accepted although dead). Those are about the engine's root vocabulary atscope:'record'; this is about which sites reachscope:'record'at all. All three are tails of #5741 Phase 2, and this one is the only one with a mount site still teaching the bare shorthand.Dedup
search_issues(REST is 403 from this seat class) — the same query returned #7727 and #8155, so the search was live. Nearest hits, none covering this: #6226 (ConditionBuilder rollout), #6293 (its row-mode quoting), #4527 (its blocking-issue reporting), #4421 (actionvisibleand permissions). No open card names ConditionBuilder's lint scope.