Skip to content

Commit 907c11d

Browse files
Elon Muskclaude
andauthored
docs(showcase): the record header speaks CEL — correct the stale dialect-split note (#9281) (#10006)
Measured in a real browser against the pinned objectui (.objectui-sha 82a94170c4058d451ce3ac179d99296d90554479), signed in as the seeded admin, on both Field Zoo specimens. The authoring-rules bullet claimed the record header evaluates action predicates on objectui's legacy JS evaluator, so `.size()`, `.contains()`, `.matches()`, `in` and `today()` all throw there and fail-closed hide the action. That is stale (pre-objectui#3314 behaviour). Measured on Specimen — Full, the record header `⋯` menu offers all 51 header-located gates, including every CEL-only construct. On Specimen — Minimal the same menu offers 10 — the ones whose predicate is true on that record. The verdicts invert per record (`NOT — !boolean` appears only on Minimal; `tags — any` only on Full), so the header is evaluating, not passing everything through. No `page:header action "…" visible` fail-closed warning was emitted on either record. That outcome also clears the risk this note was carrying: every gate in this file opens with `has(...)` since #8990, and `has()` is not a function in the legacy evaluator — had the claim still been true, all 51 would have been silently absent from the header today. Prose only. No predicate, action, gate or pin is changed. Claude-Session: https://claude.ai/code/session_019yDEhPBC3tcGkW9bkce1HM Co-authored-by: Claude <noreply@anthropic.com>
1 parent f80ccf9 commit 907c11d

1 file changed

Lines changed: 62 additions & 25 deletions

File tree

examples/app-showcase/src/ui/actions/predicate-matrix.action.ts

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,29 @@
8989
* them at all, so a predicate using one silently stops being portable.
9090
* - **A relation field is its FOREIGN KEY**, on every surface and on the
9191
* server: `record.f_lookup == "<id>"`, never `record.f_lookup.id`.
92-
* - **The RECORD HEADER does not speak CEL** (objectui#3521). It evaluates
93-
* header-action predicates on objectui's legacy JS evaluator, so `.size()`,
94-
* `.contains()`, `.matches()`, the `in` operator and stdlib calls like
95-
* `today()` all THROW there and fail-closed hide the action, while the same
96-
* predicate is correct in the row kebab and the selection bar. Every gate
97-
* below that uses one of those is therefore absent from the `⋯` menu today
98-
* and present in the list — see `ZooDialectSplitAction` for the one-screen
99-
* comparison. Predicates built only from `==` / `!=` / `<` / `&&` / `||` /
100-
* `!` agree on both.
92+
* - **The RECORD HEADER speaks CEL, like every other record surface.**
93+
* Measured in a browser at the pinned objectui (`.objectui-sha`
94+
* `82a94170c405`), on both specimens: `.contains()`, `.size()`,
95+
* `.matches()`, the `in` operator, `has()` and stdlib calls like `today()`
96+
* all evaluate on the record header and in its `⋯` overflow. Where the same
97+
* action is also declared elsewhere it agrees: the row `⋮` menu matches the
98+
* header on both specimens, and so does the selection bar for the six
99+
* specimens the view names in `bulkActions`. `record_header` / `record_more`
100+
* hand the predicate to `evalRowPredicate` WHOLE, so the
101+
* `{ dialect: 'cel' }` envelope `defineAction` normalizes to is routed to
102+
* the canonical engine rather than flattened onto a dialect guess.
103+
*
104+
* ⚠️ This bullet used to say the opposite — that the header ran objectui's
105+
* legacy JS evaluator and fail-closed hid every CEL-only gate (objectui#3521,
106+
* pre-#3314 behaviour). That was stale, and it is recorded rather than
107+
* deleted because of what it would have cost: after #8990 every gate in this
108+
* file opens with `has(...)`, which the legacy evaluator answers with
109+
* `"has" is not a function`, so had the claim still been true, all 51
110+
* header-located gates would have been silently absent from the `⋯` menu.
111+
* Measured instead: the menu offers them, and hides exactly the ones whose
112+
* predicate is false on that record. ⛔ Do not restore the claim from a
113+
* source read — it is falsifiable in a browser in one click, which is the
114+
* only way it was ever settled (objectstack#9281).
101115
*
102116
* ## `visible` has three authoring forms, one meaning
103117
*
@@ -227,26 +241,49 @@ export const ZooUserIdentityGateAction = defineAction({
227241
});
228242

229243
/**
230-
* **The dialect split.** One action, one predicate, two surfaces — and, as of
231-
* this writing, two different answers.
244+
* **The dialect PIN.** One action, one CEL-only predicate, declared on all
245+
* three `RECORD_SURFACES` — and, measured, one answer on each of them.
246+
*
247+
* `.contains()` is ordinary CEL, and this action is where "the record header
248+
* runs the same engine as the row kebab" is falsifiable in one click. Measured
249+
* in a browser at pinned objectui `82a94170c405`, signed in as the seeded
250+
* admin (objectstack#9281):
251+
*
252+
* | surface | Specimen — Full | Specimen — Minimal |
253+
* |---|---|---|
254+
* | record header `⋯` (`record_more`) | OFFERED | absent |
255+
* | row `⋮` menu (`list_item`) | OFFERED | absent |
256+
*
257+
* ⚠️ The selection bar is deliberately NOT a row of that table: this action is
258+
* not named in either view's `bulkActions` (`field-zoo.view.ts`), so it never
259+
* reaches that surface at all — an absence of DECLARATION, which would read as
260+
* an absence of dialect support if tabulated beside the other two. The
261+
* three-surface agreement is pinned instead by the neighbours that ARE declared
262+
* on all three: `ZooVisibleStringAction` and its two twins, and
263+
* `ZooRelationGateAction` — whose `.size()` call is CEL-only and which likewise
264+
* appears on all three for Full and on none for Minimal.
232265
*
233-
* `.contains()` is ordinary CEL and evaluates correctly wherever the canonical
234-
* engine runs: the row `⋮` menu, the selection bar, conditional formatting. The
235-
* RECORD HEADER does not run that engine — it evaluates header-action
236-
* predicates on objectui's legacy JS evaluator — so the same predicate throws
237-
* there (`.contains` is not a JS string method) and the action is fail-closed
238-
* hidden. Measured, not assumed: the browser console carries
239-
* `[page:header] action "…" hidden: its predicate threw`.
266+
* Both columns are load-bearing. `f_textarea` is `'Line one\nLine two'` on Full
267+
* and `null` on Minimal, so the RIGHT column is what proves the header is
268+
* evaluating rather than offering everything: the same action on the same
269+
* surface flips with the record. The browser console carries no
270+
* `page:header action "…" visible` fail-closed warning on either record — the
271+
* predicate is answering, not faulting.
240272
*
241-
* The same split hides every CEL-only construct on that one surface —
242-
* `.size()`, `.matches()`, the `in` operator, and stdlib calls like `today()`
243-
* (`"today" is not a function`). Filed as objectui#3521; kept here as a LIVE
244-
* fixture rather than papered over, because "works in the list, silently gone
245-
* on the detail page" is invisible to any test that exercises one surface.
273+
* ⚠️ This action used to be framed as **the dialect SPLIT** — the live
274+
* demonstration that the header ran objectui's legacy JS evaluator and threw on
275+
* `.contains()` (objectui#3521), with "when #3521 lands, this action should
276+
* appear in the header too — that is the test." That test has since passed:
277+
* objectui#3314 stopped the header hand-unwrapping the envelope, and
278+
* `evalRowPredicate` routes `{ dialect: 'cel' }` to `@objectstack/formula`. The
279+
* fixture keeps its name and its value — inverted. It no longer demonstrates a
280+
* split; it is the sentinel that FAILS if a surface ever demotes to the legacy
281+
* dialect again, which is why it keeps all three `locations` rather than being
282+
* deleted along with the claim.
246283
*
247284
* Compare it against `ZooVisibleStringAction` above, whose predicate uses only
248-
* operators BOTH dialects share and therefore agrees on every surface. When
249-
* #3521 lands, this action should appear in the header too — that is the test.
285+
* operators both dialects share: that one agreed across surfaces even while the
286+
* split was real, so it cannot detect a demotion. This one can.
250287
*/
251288
export const ZooDialectSplitAction = defineAction({
252289
name: 'showcase_zoo_dialect_split',

0 commit comments

Comments
 (0)