<!-- os-decision-facets -->
Filed by the triage seat (round of ~14:47Z 2026-08-19, session session_01FJEQvfQBfvi1cBQet4UkpG). This question has been referenced as "#4075 step 3, parked in the decision inbox" by #4807's sequencing note, but no card ever carried it — #4075 closed 08-10 with no step-3 text anywhere in its thread, so #4807 has been blocked on a ruling that had no carrier. This card is that carrier. Dedup: full decision-inbox enumeration (only #5301 / #5240 open) plus keyword search; no existing card covers it.
The question
Row predicates (visible / disabled / enabled on action renderers, row scopes, record:alert) currently evaluate against THREE spellings of the same row: canonical record.status, bare shorthand status, and legacy data.status. #4075/PR #4079 deliberately bound all four action renderers all three ways (via usePredicateRecordContext), matching evalRowPredicate on the header/rows — restoring consistency without deciding which spellings are contract. The server enforces with record.*. What is the declared contract, and what happens to the other two spellings?
- A — canonize all three: document the three-way binding as the contract in the evaluator/spec prose; every future predicate surface owes all three bindings forever.
- B — canon is
record.*; shorthand + data.* enter a deprecation window: renderers keep binding three ways for stored metadata, authoring warns on non-canonical spellings now, removal scheduled after a stored-metadata survey (the exact option-② shape the maintainer ruled for the dashboard globalFilters[].options bare-string shorthand on objectstack#7917). - C — status quo (tolerated but undocumented): rejected by AGENTS.md #0.1 — a renderer tolerance quietly becoming a second de-facto contract is the named failure shape.
Four-facet analysis
Recommendation: B — canon record.*, shorthand + data.* deprecated behind a survey-sized window, mirroring the #7917 ruling.
Confidence gap (what this analysis cannot see): customer-stored predicate spellings (needs the survey before any removal fires); and whether the server-side CEL evaluator also accepts the bare shorthand — if it does, "canon" must state the server's own accept set, not just the client's.
Downstream
#4807 (record:alert's missing row binding) is pm:blocked on this ruling: its fix is a one-line switch to usePredicateRecordContext plus pins whose spelling coverage depends on the answer here.
Refs: #4075 / PR #4079 (the three-way binding), #4077 (DeclaredActionsBar half), objectstack#7917 (the option-② precedent), #4807 (blocked consumer).
<!-- os-decision-facets -->
Filed by the triage seat (round of ~14:47Z 2026-08-19, session
session_01FJEQvfQBfvi1cBQet4UkpG). This question has been referenced as "#4075 step 3, parked in the decision inbox" by #4807's sequencing note, but no card ever carried it — #4075 closed 08-10 with no step-3 text anywhere in its thread, so #4807 has been blocked on a ruling that had no carrier. This card is that carrier. Dedup: full decision-inbox enumeration (only #5301 / #5240 open) plus keyword search; no existing card covers it.The question
Row predicates (
visible/disabled/enabledon action renderers, row scopes, record:alert) currently evaluate against THREE spellings of the same row: canonicalrecord.status, bare shorthandstatus, and legacydata.status. #4075/PR #4079 deliberately bound all four action renderers all three ways (viausePredicateRecordContext), matchingevalRowPredicateon the header/rows — restoring consistency without deciding which spellings are contract. The server enforces withrecord.*. What is the declared contract, and what happens to the other two spellings?record.*; shorthand +data.*enter a deprecation window: renderers keep binding three ways for stored metadata, authoring warns on non-canonical spellings now, removal scheduled after a stored-metadata survey (the exact option-② shape the maintainer ruled for the dashboardglobalFilters[].optionsbare-string shorthand on objectstack#7917).Four-facet analysis
visiblewritten asrecord.*faults and fails closed #4075 family exists because surfaces drifted on exactly this).record.*(e.g.sys_approval_request'srecord.viewer.can_actgates); the bare shorthand appears in row-action authoring habits;data.*is legacy. Split in customer-stored metadata is unmeasured — a survey (as delivered for #7917) must size any removal window.visiblewritten asrecord.*faults and fails closed #4075 fail-closed family (entire approval action set invisible) for months.Recommendation: B — canon
record.*, shorthand +data.*deprecated behind a survey-sized window, mirroring the #7917 ruling.Confidence gap (what this analysis cannot see): customer-stored predicate spellings (needs the survey before any removal fires); and whether the server-side CEL evaluator also accepts the bare shorthand — if it does, "canon" must state the server's own accept set, not just the client's.
Downstream
#4807 (record:alert's missing row binding) is
pm:blockedon this ruling: its fix is a one-line switch tousePredicateRecordContextplus pins whose spelling coverage depends on the answer here.Refs: #4075 / PR #4079 (the three-way binding), #4077 (DeclaredActionsBar half), objectstack#7917 (the option-② precedent), #4807 (blocked consumer).