docs: publish each page's own values through the scope channel on the three remaining teaching surfaces - #9376
Draft
os-tesla wants to merge 2 commits into
Draft
Conversation
…me the three props the renderer never reads The three remaining teaching surfaces from the objectui#8021 sweep — the root README, the expression guide and the architecture guide — each wrote the page's values onto the `SchemaRenderer` element and read them back under a bare head name. `SchemaRendererProps` declares exactly one prop, `schema`; `data`, `dataSource` and `debug` are forwarded to the component the schema names, so nothing throws, nothing warns, and the expression reaches the screen as the characters the author typed. Both coordinates move together on every site, per objectui#8021 leg D: * the six forwarded look-alikes become the provider that actually carries the value — `PredicateScopeProvider` for the expression scope, `SchemaRendererProvider` for the adapter and for `debug`; * the head names are judged one at a time against the scope the tree builds. Thirty-two stay bare, because after the objectui#9308 ruling the root set is open: every key the host publishes is a root. Five move to `record.*` — the two form-row sites and the three predicates written against a `form` root that nothing in ObjectUI publishes. `content/docs/guide/architecture.md` also carried the one `data.*` gate on these pages. The census could not see it — its classifier held `data` in the ACCEPTED root set — and it is exactly the spelling the ruling retires, so it moves to `record.age` and the guide states the verdict flip: a missing root and a present-but-undefined root are not the same, so a `data.*` gate that used to hide its node on every row now shows it. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UzHd6hDYatoDn17BuwKxnZ
…s, measured
The Expression Errors block claimed `${user.invalidProperty}` yields
`Cannot read property 'invalidProperty' of undefined`. objectui#9297's addendum
flagged that as looking wrong and explicitly left it NOT MEASURED. Measured now,
on the built evaluator, and it is wrong in both directions:
{ user: { name: 'Alice' } } ${user.invalidProperty} => undefined
{} (no user root) ${user.invalidProperty} => "${user.invalidProperty}"
control, same instrument: ${user.name} => "Alice"
Nothing is thrown on either path. A missing MEMBER of a published root renders
as nothing; a missing ROOT renders as the characters the author typed, with one
console line.
Repaired here rather than filed because the same commit series now states, two
sections up, that an unresolvable template is returned as its own source text —
leaving the old sentence would have made the page contradict itself.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UzHd6hDYatoDn17BuwKxnZ
Collaborator
|
Ruled: option A. The maintainer took option A on this PR's open question ( The body already implements it — verified at head ⛔ Binding on whoever lands this: do not add a closing keyword in the body, the squash message or a review suggestion, and do not close objectui#9297 at merge. Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #9297.⚠️ Deliberately not a closing keyword: this repair covers the three surfaces that card's dispatch scoped, and the card's own addendum (comment
5646840050) measured six more sites oncontent/docs/guide/schema-rendering.md—statusx2,loading,items,errorx2 — which are out of scope here and are not moved by PR #9369 either (its hunks land at:68,:79-131and:409-446; those six sit at:231,:232,:479,:489,:504,:506). That half stays open.What was wrong, and what moved
SchemaRendererPropsdeclares exactly one prop,schema. Adata,dataSourceordebugwritten on the element is forwarded to the component the schema names — not read, not refused. Nothing throws, nothing warns, and the expression reaches the screen as the characters the author typed.Per objectui#8021 leg D, moving only the wiring produces a page that reads as repaired and still prints raw source. So both coordinates move together on every site: the wiring becomes the provider that actually carries the value, and every head name on the page is judged against the scope the tree builds.
Re-measured census, with the card's own lit control
Measured on this branch's base
69aa9c017with the card's classifier — SchemaRenderer elements matched with a word boundary after the name, soSchemaRendererProvideris excluded by construction.content/docs/guide/schema-rendering.md(out of scope)packages/react/README.md(out of scope)content/docs/guide/expressions.mdcontent/docs/guide/architecture.mdREADME.md(repo root)⭐ The control reproduces the card's 18 exactly — and shows the 18 is not a count of elements. Three of them are
SchemaRendererMENTIONS insidedoc-snippet: fragmentHTML comments onexpressions.md, which the regex cannot tell from an element. Strip HTML comments first and the base has 15 real JSX elements, not 18. The tag-shaped count falls to 15 here only because those three comments were rewritten; no renderer element was added or deleted (real elements: 15 → 15).Per-site judgement — 37 bare head names, individually judged
The ruling on objectui#9308 (option B) changed the question. Before it, the renderer bound a closed five-name root set, so "head name not in the set" was close to a verdict. After it, the root set is open: every key the host publishes through
PredicateScopeProvideris a root. ⇒ the test is no longer is this name in the set, it is does the page publish this name, and does it say so.The rule applied, stated once so each row can be checked against it: a head name moves to
record.when the passage says the value is the row the surface is bound to; it stays bare when the passage presents it as a value the host computed and published.Moved — 5 sites
expressions.md:148disabledOnformformis not a root on any tier; nothing in ObjectUI publishes one. Rewritten torecord.status.expressions.md:439Dependent Fieldsformrecord.country.expressions.md:470Computed Fieldsformrecord.price * record.quantity.architecture.md:247Conditional Renderingformvisiblerewritten tocurrent_user.role— the ambient root the host'sExpressionProviderreally publishes.architecture.md:248Conditional Renderingformdisabledrewritten torecord.status.Judged legitimate, left bare — 32 sites
expressions.mdx8usersexpressions.md:172settingsuser, by the provider the block now mounts.expressions.mdx2priceexpressions.mdscore,count,total,itemsexpressions.mdx2statusrecord.— that would assert a row context the passage never establishes.expressions.mdx2taskexpressions.md:567formatCurrencyevaluateExpressionis handed its own context. Legitimate by construction. Its surrounding prose was still wrong and is repaired (see below).expressions.md:612adultUsersScoreexpressions.md:621,:626x,isAdminarchitecture.mdx2ordersREADME.mdx7statsPredicateScopeProvider.expressions.mditem,indexexpressions.mdMath,new⭐ A site the census could not see — and it is the one the ruling breaks
content/docs/guide/architecture.md:55authoredvisible: "${data.age > 18}". The census classifier helddatain the accepted root set, so this site was invisible to the offender column — anddatais precisely the root objectui#9308 retires.Measured on the built evaluator (control and both legs in the "Verification" section): a missing root and a present-but-undefined root are not the same. With
{ data: undefined }the predicate isfalse; with nodatakey at all it is unevaluable and this surface fails soft totrue. ⇒ adata.*gate authored from these pages used to hide its node on every row and now shows it. The site moves torecord.age(the runtime layer's canonical root, ADR-0089 D3) and the guide states the flip in the migration note, rather than only renaming a provider.The Debug Mode block — both wrong props, not one
expressions.md's Debug Mode block wrotedata={…}anddebug={true}on the element.debugis read off the provider context (context?.debug || context?.debugFlags?.enabled), so both were forwarded and neither did anything. The block is now aSchemaRendererProvidermount (withdataSource={null}, since that prop is required and this mount is about the flag), and the prose names the mechanism for both props.Adjacent to it, the Custom Functions passage still stated the old scope verbatim — "the provider's data source (as
data), the host scope and page variables". That sentence is what the ruling deletes; it is rewritten in the same commit, because leaving it would have contradicted the new Data Context table on the same page.Shape
Matched to PR #9369, which moved the equivalent teaching on the two surfaces this card excludes: publish host values under a real name through
PredicateScopeProvider, read them by that name, and state thatdataSourceis the adapter and not a root.Changeset
Not owed, by measurement rather than by assumption:
Acceptance notes
Observed while judging these pages, noted, not filed:
AGENTS.md§3 quotes the same retired spelling this PR repairs atarchitecture.md:55—expression eval ("visible: "${data.age > 18}"")in the@object-ui/coretopology row. Not touched:AGENTS.mdis a governed surface, and one path there would move this whole PR to the human-merge route. The carrier would be whoever next edits that table.content/docs/guide/expressions.md:226/:242author${users}onlist.items, a key with no carriage row — reported (report-only) bycheck-doc-expression-carriage. Pre-existing and unchanged by this PR; the gate's own header routes this class to objectui#7440 / finding(examples,docs): thecolorkey three catalogtextnodes author — and the docs page teaches — is declared by nothing and read by nothing #7444 / finding(docs):docs/ARCHITECTURE.mdteaches theObjectRendererphantom in 3 blocks — third file, anddocs/**is in no gate's scan surface #7838.content/docs/guide/expressions.mdExpression Errors claimed an invalid expression yieldsCannot read property … of undefined. The card's addendum flagged it as NOT MEASURED. It is measured below, it is wrong in both directions, and it is repaired here under the bounded in-place carve-out rather than filed: the first commit states two sections up that an unresolvable template is returned as its own source text, so leaving the old sentence would have made the page contradict itself in the same pull request.The two behaviours a reader is now told about, measured
Both legs run against the built evaluator (
packages/core/dist), the same artefactcheck:doc-snippetsresolves against, each with a control that fires.Leg 1 — the verdict flip. At the visibility layer (
evaluateCondition, the layer avisible/visibleOngate uses):⇒ a
data.*gate authored from these pages used to hide its node on every row and now shows it. One layer down, on the rawExpressionEvaluator, the missing-root case returns the template's own source text — which is the interpolation half of the same fact. Both halves are in the migration note.Leg 2 — what an unresolvable expression really does (the card addendum's NOT-MEASURED item):
⇒ nothing is thrown on either path. The guide said
Cannot read property 'invalidProperty' of undefined; that is false whether or not the root exists.Leg 3 — a bare head name IS a root when the host publishes it, which is what makes 32 of the 37 sites legitimate:
Verification
All runs at head
20831dc1d, heavy ones serialised through the shared verify lock.pnpm exec turbo run build $(node scripts/check-doc-snippet-types.mjs --build-filter) --concurrency=2Tasks: 35 successful, 35 total·BUILD EXIT=0pnpm check:doc-snippetsSemantic phase: 650 of 650 block(s) judged, 3 failed.·EXIT=1— ⭐ all three are the inherited ones, see belowpnpm check:doc-fencesEXIT=0— every TypeScript block in 227 document(s) fenced ts/tsx/typescriptnode scripts/check-doc-component-types.mjsEXIT=0— every documented component type is registerednode scripts/check-doc-example-ids.mjsEXIT=0— 414 real reference(s) resolvenode scripts/check-doc-links.mjsEXIT=0— links valid across 17 scan rootsnode scripts/check-control-bytes.mjsEXIT=0— 7539 tracked text file(s)node scripts/check-changeset-presence.mjsEXIT=0— no changeset owednode scripts/check-changeset-claims.mjsEXIT=0(report-only)node scripts/check-doc-expression-carriage.mjsEXIT=0(report-only); its two hits onexpressions.md(list.itemsauthoring${users}) are pre-existing and unchangednode scripts/check-governed-queue-guard.mjs --test(the three paths)✅ NOT GOVERNED — 3 path(s) checked against 5 governed surface(s); none matchedpnpm exec vitest run(6 files)Test Files 6 passed (6)·Tests 112 passed (112)·EXIT=0check:doc-snippets' own controls all fired in that run, so the reading is a reading and not a degraded harness:resolutionresolved@object-ui/typesto the builtdist/index.d.ts,sentinelproduced TS2305,positiveproduced 0.Named witnesses. Derived by hand from
scripts/markdown-test-inputs.mjs, not guessed:packages/components/src/__tests__/page-body-single-node-8310.test.tsxreads the rootREADME.md(it asserts the Basic Usage schema literal still spells its child listchildren, carriestype: "grid"and threetype: "statistic", and the three labels) and four tests walkcontent/docs/**. The objectui#8021 pin was run too, even though itsTEACHING_SURFACESare the two documents this PR does not touch. All green.Inherited reds — named, not repaired.
content/docs/guide/schema-rendering.md:99,:434andpackages/react/README.md:73, all TS2740, all on the two surfaces this PR must not touch. They are objectui#9346 verbatim, and PR feat(react)!: unbind the data-source adapter from the expression scope, and pointbindat the scope channel #9369 is what moves them.mainwith chore(deps): runpnpm dedupe --lockfile-onlyon an untouched main — the measurement (objectui#9215) #9316, a maintainer decision.Drafted by the
os-devseat in sessionsession_01UzHd6hDYatoDn17BuwKxnZ— attribution repeated as prose here because the footer block below does not reliably survive a later edit.Generated by Claude Code
Generated by Claude Code