From 819e30500e96ca4777a1f462413b548fd2c0e33e Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 23 Aug 2026 15:15:16 +0000 Subject: [PATCH] fix(spec): COMPONENT_NODE_VISIBILITY_GUIDANCE prescription no longer claims a hoisted properties visibility key is evaluated by nothing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `COMPONENT_NODE_VISIBILITY_GUIDANCE`'s prescription — the user-facing text emitted when a visibility key (`visible`/`visibleWhen`/…) is authored inside `properties` instead of on the component node — said the hoisted value is "evaluated by nothing" and "silently does not gate". That was true when it was written and is false since objectui#5505 (`c86185eb5`, merged 2026-08-21): SchemaRenderer's node-level `visibleWhen` evaluator now binds `record`, so the hoisted value IS evaluated by the node-level gate; the two gates evaluate the same value and compose as an idempotent AND. The move-it-up advice stays — it now rests on the ADR-0089 canonical-spelling / layer-discipline reason (beside `type` and `id`), not on the props-level form being inert. Message text only: no schema shape change, no accept/reject verdict change. Claude-Session: https://claude.ai/code/session_01T9cDbY2NBiVJWYx3BpWfH2 --- ...nent-node-visibility-guidance-post-5505.md | 29 +++++++++++++++++++ packages/spec/src/ui/component.zod.ts | 8 +++-- 2 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 .changeset/component-node-visibility-guidance-post-5505.md diff --git a/.changeset/component-node-visibility-guidance-post-5505.md b/.changeset/component-node-visibility-guidance-post-5505.md new file mode 100644 index 0000000000..ba37e77c74 --- /dev/null +++ b/.changeset/component-node-visibility-guidance-post-5505.md @@ -0,0 +1,29 @@ +--- +"@objectstack/spec": patch +--- + +fix(spec): `COMPONENT_NODE_VISIBILITY_GUIDANCE` no longer claims a hoisted `properties` visibility key is evaluated by nothing (#11033) + +The `COMPONENT_NODE_VISIBILITY_KEYS` key-set guard's `prescription` — the text +emitted to an author when a visibility key (`visible` / `visibleWhen` / …) is +written inside `properties` instead of on the component node — closed with: + +> Inside `properties` it is hoisted onto the node by the renderer but evaluated +> by nothing — the component renders unconditionally, which is a visibility +> gate that silently does not gate. + +That was true when it was written and is false since objectui#5505 +(`c86185eb5`, merged 2026-08-21): `SchemaRenderer`'s node-level `visibleWhen` +evaluator now binds `record`, so the hoisted value IS evaluated by the +node-level gate. Post-#5505 the props-level and node-level forms evaluate the +same value over the same `RecordContext` and compose as an idempotent AND — +there is no gate that silently fails to gate. + +The prescription now states that truth instead, and keeps its move-it-up +advice resting on the reason that still holds: `visibleWhen` at the node, +beside `type` and `id`, is the ADR-0089 canonical spelling — a layer-discipline +argument, not an inertness one. + +Message text only. No accept/reject verdict changes, no schema shape changes, +and no runtime behaviour changes — both gates already evaluated the value +identically before and after this change. diff --git a/packages/spec/src/ui/component.zod.ts b/packages/spec/src/ui/component.zod.ts index ee2b29f6fe..e21e1612a5 100644 --- a/packages/spec/src/ui/component.zod.ts +++ b/packages/spec/src/ui/component.zod.ts @@ -275,9 +275,11 @@ const COMPONENT_NODE_VISIBILITY_GUIDANCE: KeySetGuidance = prescription: 'Visibility is a COMPONENT-level predicate, not a prop: move it up one level to the ' + 'component node\'s own `visibleWhen` (ADR-0089 canonical spelling), beside `type` and ' - + '`id`. Inside `properties` it is hoisted onto the node by the renderer but evaluated by ' - + 'nothing — the component renders unconditionally, which is a visibility gate that ' - + 'silently does not gate.', + + '`id` — one canonical spelling per layer, not because the props-level form is inert. ' + + 'Since objectui#5505 (`c86185eb5`, merged 2026-08-21) the hoisted form IS evaluated by ' + + 'the node-level gate: the two gates evaluate the same value and compose as an ' + + 'idempotent AND, so leaving it in `properties` duplicates the canonical key rather ' + + 'than silently failing to gate.', }; const COMPONENT_NODE_KEYS_GUIDANCE: KeySetGuidance =