Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .changeset/component-node-visibility-guidance-post-5505.md
Original file line numberDiff line numberDiff line change
@@ -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.
8 changes: 5 additions & 3 deletions packages/spec/src/ui/component.zod.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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 =
Expand Down
Loading