Skip to content

Commit 99b63c3

Browse files
os-support-aiclaude
andcommitted
chore(changeset): patch — per-shape surface strings + select-option editability boundary (#8202, #8201)
Reachability measured rather than inherited: both halves are parse-reachable error strings, #8201's paragraph also reaches `dist/**/*.d.ts` hover, and the generated reference page is measured NOT to render schema-level JSDoc. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016YBUGvukaeVu9DjKdsHJa9
1 parent 05b7333 commit 99b63c3

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
docs(spec): a rejection says which shape refused the key, and a select option gets the editability boundary (#8202, #8201)
6+
7+
Two text-face halves finishing the story PR #8199 started. No key is added
8+
anywhere, every spelling rejected before is rejected after, and everything that
9+
parsed before parses identically — only the sentence an author reads moves.
10+
11+
## #8202 — per-shape `surface` strings
12+
13+
`FormFieldSchema`, `FormSectionSchema` and `PageComponentSchema` shared one
14+
surface string, so every rejection opened `Unrecognized key(s) on this view/page
15+
schema`. Harmless while the three answered a key identically; since #8199 they
16+
do not:
17+
18+
- on a **field**, `disabled` gets a rename pointer — *Did you mean `disabled` →
19+
`readonly`?*
20+
- on a **section** or **page component**, it gets the editability-boundary
21+
prescription — *write `readonly` on the form field(s) inside instead.*
22+
23+
Those two answers contradict each other by design, and the contradiction only
24+
reads correctly if the message says which shape the author is on. It now does:
25+
`this form field` / `this form section` / `this page component`. Per #8199's
26+
placement rule the strings are filed at the three call sites rather than in the
27+
shared options table — a table shared by three shapes can no more carry one
28+
shape's name than it can carry one shape's prescription. The shared table keeps
29+
the family name, and no live declaration may still report it
30+
(`alias-integrity.test.ts`).
31+
32+
## #8201 — `SelectOptionSchema` inherits the #7887 ruling
33+
34+
The maintainer ruling of 2026-08-12 (a form section / page component gates
35+
visibility only; editability lives on fields) was scoped to two shapes, and
36+
#8199 left the third — a select option — with a bare rejection. It has the
37+
boundary now, on the ruling's own premise re-measured for this shape rather than
38+
by analogy: on objectui `origin/main` @ `aca27fa` the object-field pipeline these
39+
options feed has **zero** per-option `disabled` consumers (`SelectField.tsx:161`
40+
calls the root-level `disabled` "the single authority"; `RadioField.tsx:124`
41+
reads only `props.disabled`). The shown-but-unselectable option that does exist
42+
lives in objectui's SDUI vocabulary, which is not this shape.
43+
44+
Its prescription is **not** the siblings' text, because the siblings'
45+
destination does not exist here — a section redirects to the fields inside, and
46+
an option has no inside. Writing `disabled` on an option now points at the two
47+
things that are real: per-option `visibleWhen` to withdraw that one option (the
48+
only `*When` surface that binds `current_user`, ADR-0068 — and the rule
49+
validator refuses a write of a value whose predicate is false), and
50+
`readonly` / `readonlyWhen` on the **field** to freeze the whole picker. It
51+
states what the platform honours today; a non-selectable field option remains a
52+
spec decision someone may ask for, not a key an author writes.
53+
54+
## Why `patch`, measured rather than inherited
55+
56+
The criterion is whether the prose reaches a consumer:
57+
58+
- **Parse-reachable error string — YES.** Both halves are `unrecognized_keys`
59+
message text an author reads out of a failed parse, and every claim is pinned
60+
against a real `safeParse` error rather than against the options table.
61+
- **`dist/**/*.d.ts` hover — YES for #8201.** The boundary paragraph is JSDoc on
62+
the exported `SelectOptionSchema` const.
63+
- **Generated reference page — NO, measured.** `content/docs/references/data/`
64+
`field.mdx` is built from the file-level doc block plus per-property
65+
`.describe()` text; a schema's own JSDoc is not rendered (grepping the page
66+
for `SelectOptionSchema`'s existing docblock text returns nothing, while its
67+
per-key `.describe()` string hits). No `.describe()` was touched, so the page
68+
and `authorable-surface.base.json` do not move.
69+
70+
One reachable consumer is enough and no public export is added, so `patch`.

0 commit comments

Comments
 (0)