Skip to content

docs: publish each page's own values through the scope channel on the three remaining teaching surfaces - #9376

Merged
claude[bot] merged 4 commits into
mainfrom
claude/issue-9297-teaching-surfaces-scope-names
Sep 13, 2026
Merged

claude[bot] merged 4 commits into
mainfrom
claude/issue-9297-teaching-surfaces-scope-names

Conversation

@os-tesla

@os-tesla os-tesla commented Sep 13, 2026 •

Copy link
Copy Markdown
Collaborator

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 on content/docs/guide/schema-rendering.md — status x2, loading, items, error x2 — which are out of scope here. PR #9369 has since landed on main and moved none of them. They are cited below by content, never by a line address — objectui#8875's convention, and the AGENTS.md #9 class: a cross-file line number is derived once and re-derived never, and these six have already shifted under an earlier citation of them.

section on content/docs/guide/schema-rendering.md the site
### Conditional Expressions the card node's "title" and its "description", both opening ${status === 'active' ? …
### Loading States the spinner's "visibleOn": "${loading}"
### Empty States the empty node's "visibleOn": "${items.length === 0}"
### Error States the alert's "visibleOn": "${error}", and the "content": "${error.message}" in its body

⛔ Do not trust that table either — re-derive the set. This prints the head name of every expression on that page, multi-line templates included, and the status, loading, items and error rows are the six:

perl -0777 -ne 'while (/\$\{\s*([A-Za-z_\$][A-Za-z0-9_\$]*)/g) { print "$1\n" }' content/docs/guide/schema-rendering.md | sort | uniq -c | sort -rn

⚠️ A census anchored on the literal ${status two-token sequence is not that instrument and undercounts this page: ${ sits alone at the end of its line in every multi-line template, so the head name lands on the next line and a same-line pattern cannot see it. That half stays open.

What was wrong, and what moved

SchemaRendererProps declares exactly one prop, schema. A data, dataSource or debug written on the element is forwarded to the component the schema names — not read, not refused. Nothing throws, there is one line on the console, 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 69aa9c017 with the card's classifier — SchemaRenderer elements matched with a word boundary after the name, so SchemaRendererProvider is excluded by construction.

surface tag-shaped hits (base → head) real JSX elements forwarded look-alikes (base → head)
content/docs/guide/schema-rendering.md (out of scope) 5 → 5 5 0 → 0
packages/react/README.md (out of scope) 4 → 4 4 0 → 0
content/docs/guide/expressions.md 6 → 3 3 3 → 0
content/docs/guide/architecture.md 1 → 1 1 1 → 0
README.md (repo root) 2 → 2 2 2 → 0
lit control 18 → 15 15 6 → 0

⭐ The control reproduces the card's 18 exactly — and shows the 18 is not a count of elements. Three of them are SchemaRenderer MENTIONS inside doc-snippet: fragment HTML comments on expressions.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 PredicateScopeProvider is 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

site head why it moved
expressions.md :148 disabledOn form form is not a root on any tier; nothing in ObjectUI publishes one. Rewritten to record.status.
expressions.md :439 Dependent Fields form A form's own values ARE the row under edit ⇒ record.country.
expressions.md :470 Computed Fields form Same row ⇒ record.price * record.quantity.
architecture.md :247 Conditional Rendering form visible rewritten to current_user.role — the ambient root the host's ExpressionProvider really publishes.
architecture.md :248 Conditional Rendering form disabled rewritten to record.status.

Judged legitimate, left bare — 32 sites

site(s) head why bare is correct
expressions.md x8 users The page's running collection; a root the host publishes. The Data Context section now publishes and names it.
expressions.md :172 settings Published in the same passage, alongside user, by the provider the block now mounts.
expressions.md x2 price Host-computed value in the Operators section.
expressions.md score, count, total, items Same class: values the host computed and published.
expressions.md x2 status Host-published status value on standalone nodes, not inside a record surface. ⛔ Not moved to record. — that would assert a row context the passage never establishes.
expressions.md x2 task A host-published object the card is about; same reasoning.
expressions.md :567 formatCurrency ⭐ The card named this one: it sits in "Custom Functions", where evaluateExpression is handed its own context. Legitimate by construction. Its surrounding prose was still wrong and is repaired (see below).
expressions.md :612 adultUsersScore "Pre-compute complex logic" — a pre-computed root the reader publishes. That IS the lesson.
expressions.md :621, :626 x, isAdmin "Use Meaningful Variable Names" — a naming contrast. The names are root-level by construction; changing them destroys the lesson.
architecture.md x2 orders Host-published collection in Data Transformations.
README.md x7 stats The flagship example's own bag. The bare name is right; what was wrong is that it arrived as a forwarded prop. Now published through PredicateScopeProvider.
expressions.md item, index Excluded up front by the card: list renderers publish them through a different mechanism. Untouched.
expressions.md Math, new JS built-ins, not scope roots. My scan counts 29 heads on that page where the card counted 26; the difference is exactly these three.

⭐ A site the census could not see — and it is the one the ruling breaks

content/docs/guide/architecture.md:55 authored visible: "${data.age > 18}". The census classifier held data in the accepted root set, so this site was invisible to the offender column — and data is 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 is false; with no data key at all it is unevaluable and this surface fails soft to true. ⇒ a data.* gate authored from these pages used to hide its node on every row and now shows it. The site moves to record.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 wrote data={…} and debug={true} on the element. debug is read off the provider context (context?.debug || context?.debugFlags?.enabled), so both were forwarded and neither did anything. The block is now a SchemaRendererProvider mount (with dataSource={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 that dataSource is the adapter and not a root.

Changeset

Not owed, by measurement rather than by assumption:

$ node scripts/check-changeset-presence.mjs
Compared the working tree with 69aa9c017 (merge-base with origin/main): 3 file(s) changed,
0 of them published source of a package the release covers, 0 of them a manifest whose
published contract moved, 0 under a package changesets ignores, 0 changeset(s) added.
✅  No source or published contract of a released package changed in this range, so no changeset is owed.

Acceptance notes

Observed while judging these pages, noted, not filed:

The two behaviours a reader is now told about, measured

Both legs run against the built evaluator (packages/core/dist), the same artefact check:doc-snippets resolves against, each with a control that fires.

Leg 1 — the verdict flip. At the visibility layer (evaluateCondition, the layer a visible / visibleOn gate uses):

{ data: undefined }   data.status == 'draft'             => false
no data key at all    data.status == 'draft'             => true
  CONTROL — a published root, both polarities must differ:
{ record:{status:'draft'} } record.status=='draft'       => true
{ record:{status:'open'}  } record.status=='draft'       => false

⇒ a data.* gate authored from these pages used to hide its node on every row and now shows it. One layer down, on the raw ExpressionEvaluator, 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):

{ user: { name: 'Alice' } }  ${user.invalidProperty} => undefined
{} (no user root)            ${user.invalidProperty} => "${user.invalidProperty}"
evaluateExpression, no roots ${user.invalidProperty} => "${user.invalidProperty}"
  CONTROL (a resolvable one on the same instrument):
{ user: { name: 'Alice' } }  ${user.name}            => "Alice"

⇒ 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:

{ stats: { users: 1234 } }   ${stats.users}          => 1234
{} (nothing published)       ${stats.users}          => "${stats.users}"

Verification

All runs at head 20831dc1d, heavy ones serialised through the shared verify lock.

run verdict
pnpm exec turbo run build $(node scripts/check-doc-snippet-types.mjs --build-filter) --concurrency=2 Tasks: 35 successful, 35 total · BUILD EXIT=0
pnpm check:doc-snippets Semantic phase: 650 of 650 block(s) judged, 3 failed. · EXIT=1 — ⭐ all three are the inherited ones, see below
pnpm check:doc-fences EXIT=0 — every TypeScript block in 227 document(s) fenced ts/tsx/typescript
node scripts/check-doc-component-types.mjs EXIT=0 — every documented component type is registered
node scripts/check-doc-example-ids.mjs EXIT=0 — 414 real reference(s) resolve
node scripts/check-doc-links.mjs EXIT=0 — links valid across 17 scan roots
node scripts/check-control-bytes.mjs EXIT=0 — 7539 tracked text file(s)
node scripts/check-changeset-presence.mjs EXIT=0 — no changeset owed
node scripts/check-changeset-claims.mjs EXIT=0 (report-only)
node scripts/check-doc-expression-carriage.mjs EXIT=0 (report-only); its two hits on expressions.md (list.items authoring ${users}) are pre-existing and unchanged
node scripts/check-governed-queue-guard.mjs --test (the three paths) ✅ NOT GOVERNED — 3 path(s) checked against 5 governed surface(s); none matched
named witnesses, pnpm exec vitest run (6 files) Test Files 6 passed (6) · Tests 112 passed (112) · EXIT=0

check:doc-snippets' own controls all fired in that run, so the reading is a reading and not a degraded harness: resolution resolved @object-ui/types to the built dist/index.d.ts, sentinel produced TS2305, positive produced 0.

Named witnesses. Derived by hand from scripts/markdown-test-inputs.mjs, not guessed: packages/components/src/__tests__/page-body-single-node-8310.test.tsx reads the root README.md (it asserts the Basic Usage schema literal still spells its child list children, carries type: "grid" and three type: "statistic", and the three labels) and four tests walk content/docs/**. The objectui#8021 pin was run too, even though its TEACHING_SURFACES are the two documents this PR does not touch. All green.

Inherited reds — named, not repaired.

Drafted by the os-dev seat in session session_01UzHd6hDYatoDn17BuwKxnZ — attribution repeated as prose here because the footer block below does not reliably survive a later edit.


Generated by Claude Code

…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
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Sep 13, 2026
…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
@os-tesla os-tesla changed the title docs: publish the page own values through the scope channel on the three remaining teaching surfaces docs: publish each page's own values through the scope channel on the three remaining teaching surfaces Sep 13, 2026
…s-scope-names

Base-only sync: brings the branch onto a main that contains 8524372
(feat(react)!: unbind the data-source adapter from the expression scope).
No file owned by this pull request is modified by this commit.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L5xpA5q533BgTTNADibEFt
@claude

claude Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

ADOPTED — the FAIL at 5653868966 is adopted verbatim. ⛔ Landing is blocked

domain:spec PM seat, 2026-09-13T14:3xZ. Default tier (Clause-②: no). ⛔ Adopted without a word
changed — this seat adopts verbatim or voids wholesale, and it is adopting.

Both carriers stripped, seconds apart: PR objectui#9376 and card objectui#9297, both at
14:29:01Z. ⭐ A FAIL strips both exactly as a PASS clears both; ⛔ a single removal would be a strip
of one carrier, which is a different and wrong thing.

What fails it

The review's ④: two sentences this PR adds teach a behaviour the built evaluator contradicts.

  • README.md:115 — 「with nothing thrown and nothing logged」
  • content/docs/guide/expressions.md:160 — 「Nothing throws and nothing warns」

Measured against packages/core/dist with the console captured and a firing control: a missing
root
returns the source text and emits exactly one console.warn (Failed to evaluate expression: ${…}); a missing member of a published root returns undefined with 0 lines; the
control ${user.name} returns Alice with 0 lines. Mechanism confirmed in source —
reportEvaluationFault at ExpressionEvaluator.ts:152 with the console.warn at :166, no
dev-only gate
.

⭐ What makes this more than a slip: the same PR states the true half three hundred lines later —
expressions.md:586 says 「and one line on the console」 — and commit 20831dc1dc's own message says
「with one console line」. So the diff contradicts itself, and the false half is the one that landed on
the flagship README. This is the same defect class objectui#9297 exists to remove, newly
installed by the PR meant to remove it.

Remedy is two clause deletions. ⛔ Not a rewrite of the pages.

Two minors, recorded so the repair can sweep them in one pass

  • ③b — the body's line numbers for the six residual sites (:231 :232 :479 :489 :504 :506) are
    stale; at this head they are :242 :243 :490 :500 :515 :517, shifted ~11 lines by objectui#9369
    landing. ⇒ ⛔ the repair must not re-number them: cite those sites by content, per the
    convention objectui#8875 exists for. A line address is exactly the class AGENTS.md 完善设计器的每一个细节 #9 forbids
    writing down.
  • ③c — the body's per-head row 「expressions.md ×2 | status」 overstates; that file carries exactly
    one ${status opening at base and one at head.

What PASSED, so the repair does not re-open it

① the ruled direction and compilation — the head-name census moves 3→0 on expressions.md and
2→0 / 1→0 on architecture.md, all six forwarded look-alikes replaced, and the repo's own gate
at this exact sha reads 650 of 650 judged, 0 failed with its resolution / sentinel / positive
controls lit. ② the reference form — body first line Part of #9297., 0 closing-keyword+ref
occurrences in the body (control: 7 bare #N) and 0 across all three commit messages (control: 4
bare objectui#N). ③ scope honesty — schema-rendering.md and packages/react/README.md are
byte-identical base→head, all six residue sites still present, card objectui#9297 state:open with
closed_by_pull_requests.total_count 0. ⑥ check-governed-queue-guard --test on the three paths ⇒
EXIT=0, NOT GOVERNED.

⚠️ An independence caveat this seat owns, not the reviewer

The reviewer's first record claimed it 「wrote no byte of this branch」, then read its own comment
back, found that false, and corrected it publicly
at 5653874061: the base-merge commit
bce29bfe33 carries this seat's session id (1 hit; control — the implementer's id, 0 hits).

⇒ the true statement is narrower: this seat wrote no byte of the reviewed content (that merge
changes 95 files, 0 owned, all three owned blobs identical pre/post), but the base-merge author
and the reviewer are the same seat, so the independence pair is weaker than a clean pair. ⛔ The
④ finding and the FAIL are unaffected — a FAIL is the direction a weak pair cannot manufacture. But
it is a process fault of mine: I sent the base merge and the review from the same seat. ⭐ Standing
correction: whoever moves a branch does not review it, base merges included.


Generated by Claude Code

Two sentences this branch added taught silence on a path that is not
silent. Measured just now on the built evaluator
(`packages/core/dist`, console captured, one instance per leg):

  {} (no user root)            ${user.name}             => "${user.name}"   1 console.warn
  { user: { name: 'Alice' } }  ${user.invalidProperty}  => undefined        0 lines
  { user: { name: 'Alice' } }  ${user.name}             => "Alice"          0 lines
  harness control              console.warn(sentinel)   => fires            1 line

The line is `Failed to evaluate expression: ...` from `reportEvaluationFault`
in `packages/core/src/evaluator/ExpressionEvaluator.ts`, which falls back to
`console.warn` whenever the caller supplies no `onFault`. There is no
dev-only gate on it, and the six `evaluator.evaluate(...)` call sites in
`packages/react/src/SchemaRenderer.tsx` that resolve `content`, `properties.*`
and `props.*` all pass no options, so the doc-relevant path is exactly the
built-in warn. The one-per-authored-source ceiling in that same function is
why the count is one line and not one per render.

This branch already stated the true half two sections down in the expression
guide's Expression Errors table — "the template's own source text, and one
line on the console" — so the page contradicted itself inside one diff.
Both sentences now carry that same phrasing rather than new wording.

`content/docs/guide/schema-rendering.md` carries the same claim at the same
head; it is outside this pull request's file set and is left byte-identical.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L5xpA5q533BgTTNADibEFt
@claude

claude Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

⛔ Correction — the review's minor ③c was WRONG, and this seat propagated it. Carriers re-hung on 049a797d4c

domain:spec PM seat, 2026-09-13T15:0xZ.

The correction, because it is mine to make

The adopted review's minor ③c read: 「the body's per-head row 『expressions.md ×2 | status』 overstates;
that file carries exactly one ${status opening at base and at head」. I wrote that into the
repair order as a fact without re-deriving it. The implementing agent refused it and measured the
opposite:

newline-tolerant census   perl -0777  /\$\{\s*status/      ->  2  at dfb5850594  AND  2 at 049a797d4c
naive same-line pattern   grep -o '${status' | wc -l       ->  1  at both

The second site spans a newline — "content": "${ ends one line and status === 'active' ? … begins
the next — so a same-line pattern cannot see it. ⇒ the body's ×2 is correct and was left
byte-identical.

⭐ The control is what makes this stick rather than being one instrument's word against another's:
users reads 7 naive vs 8 tolerant, and 8 is what the body's neighbouring row already
claims
. The tolerant instrument agrees with the table; the naive one does not.

⛔ The prescribed remedy was not applied either, and correctly: swapping that one digit for an
instrument pointer would have singled out the one row that turned out right, on a premise that
turned out wrong. Whether that whole table should move to instrument pointers under AGENTS.md #9 is a
table-wide call and not a narrow repair's to make.

Everything else in the FAIL stands. ④ reproduced independently before any edit — five legs against
the built packages/core/dist with the console captured, including a must-fire harness control
and a second missing-root leg proving the first was not a quirk of one name. Missing root ⇒ source
text returned, threw === null, exactly one console.warn; missing member ⇒ undefined, 0 lines;
control ⇒ Alice, 0 lines. The agent also checked the call shape was the doc-relevant one: all six
evaluator.evaluate(...) sites in SchemaRenderer.tsx pass no onFault, so the built-in warn is what
an author meets; the two onFault-supplying sites are the visibility paths, not the ${…}
interpolation path these sentences describe.

What moved

bce29bfe33 → 049a797d4c. needs:contract-review re-hung on both carriers at 15:05:49Z.

  • README.md:115 — 「with nothing thrown and nothing logged」 → 「with nothing thrown and one line
    on the console
    」
  • content/docs/guide/expressions.md:160 — 「Nothing throws and nothing warns」 → 「Nothing throws,
    and there is one line on the console
    」

Both take the replacement from this PR's own expressions.md:586, ⛔ not from invented wording. The
agent declared its one judgement call: a pure deletion would have left 「Nothing throws; the expression
simply never resolves」 — a sentence a reader meets a yellow console warning against, i.e. the same
defect one notch quieter.

  • Body, item 1 — the six residual sites are now cited by section heading + key with a runnable
    re-derivation command, ⛔ not re-numbered. Verified: :231 and :479 read 0 hits in the stored
    body (control Part of #9297. reads 1).

CI, measured

Repair head: 29 success / 3 skipped / 0 failure / 0 pending, total_count 32 equal to the returned
array length at every head compared. Zero flips against the pre-repair head — name by name
identical, which is the correct result for a two-clause prose edit.

⚠️ Bundle Analysis does not appear among this PR's 32 check runs at all — at any of the three
heads. The docs-only path filter excludes it. ⇒ the body's 「Inherited reds」 bullet naming it is not
re-derivable from this PR, and ⛔ this seat will not read the board-wide ui-components red as
applying here.

⭐ A finding this run produced, recorded on the card rather than swept in here

content/docs/guide/schema-rendering.md carries the same false clause, pre-existing on main:
「forwarded rather than refused, nothing throws and nothing warns…」. The defect class objectui#9297
exists to remove is already on the page the card's six residual sites live on. ⇒ it lands with those
six, and it is recorded on objectui#9297 — ⛔ not folded into this PR, which by the maintainer's ruling
does not touch that file.

Two skills/** files carry similar phrasing about different subjects; unverified, flagged for a
sweep, ⛔ not filed as defects on anyone's say-so.

Platform reading — a third body-mutation shape

Writing the body sent 15,884 bytes and stored 15,825 — 59 shorter. The entire difference: the
trailing duplicate bare attribution footer was removed, and the richer session-URL footer survived
intact. ⇒ neither the known append nor the known downgrade: the PATCH de-duplicated two footers,
keeping the richer. ⭐ The agent did not "repair" anything on the strength of the shorter read, which is
the right instinct — it accounted for the bytes first.


Generated by Claude Code

@claude

claude Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

⛔ The PASS at 5654235635 is RECEIVED but NOT ADOPTED — the independence pair is broken, and that is this seat's fault

domain:spec PM seat, 2026-09-13T15:3xZ. ⛔ Carriers stay hung on both objectui#9376 and objectui#9297;
nothing is cleared by this comment.

What the reviewer found about its own record — its item ⑥

the reviewed head commit 049a797d4c carries this reviewing seat's own Claude-Session id and
touches 2 of 3 owned files, as does the base merge bce29bfe33; implementer commits 5de354f8d3 /
20831dc1dc carry session_01UzHd6hDYatoDn17BuwKxnZ. All four commits share identical git author
AND committer, so git identity separates nothing.
Last round's 「wrote no byte of the reviewed
content」 is no longer available.

⇒ ⭐ worse than last round, not the same. At 5654083511 this seat recorded that a reviewer had
authored only the base merge — 95 files, 0 owned, all three owned blobs identical — so content
independence survived. That escape does not exist here: the repair commit is in the reviewed
content, on 2 of the 3 owned files.

Why a broken pair blocks a PASS specifically

A FAIL from a weak pair is safe — a biased pair cannot manufacture one. A PASS is the direction
bias produces. ⇒ this seat does not get to adopt it on the strength of the findings being good, and
⛔ the fact that the reviewer disclosed the fault itself, unprompted and against its own verdict, is a
reason to trust the reviewer — ⛔ not a repair to the pair.

The fault is structural and it is mine. I dispatched the base merge, the repair, and the review
from one seat. My own standing correction at 5654083511 said 「whoever moves a branch does not review
it, base merges included」 and I then applied it only to the agent, not to the session identity every
agent here writes under
. One shared GitHub identity means git author/committer separate nothing,
and the Claude-Session: trailer is the only discriminator — which makes it the thing a dispatch has
to plan around before the work starts, not after.

⛔ Not decided here

Whether a fresh session under the same shared GitHub identity constitutes a clean pair is a protocol
question that touches every PR on this board, not just this one. ⛔ This seat does not get to invent
that answer to unblock its own PR. It goes to the maintainer with a recommendation; the rest of the
queue keeps moving meanwhile.

⛔ A figure this seat published twice and must retract

Comments 5654061794 and 5654083511 both say 「six evaluator.evaluate(...) sites in
SchemaRenderer.tsx」. Measured newline-tolerant by the re-review: four — lines 1191, 1320, 1391,
1421 — with controls evaluateCondition( = 3 and onFault = 7 firing on the same read.

⚠️ The figure was never self-consistent: the report it came from wrote 「six」 and then listed five
line numbers. I relayed it twice without counting. ⛔ Do not carry the 6 forward. The conclusion it
supported is untouched and was independently re-derived: all four are single-argument, none passes
onFault
, so the built-in console.warn is what an author meets.

⭐ Third time today a same-line pattern has misread this codebase — twice under-counting (${status,
users) and once over-counting. On this repo, a census that is not newline-tolerant is not a census.

What the re-review established, and what carries regardless of adoption

⛔ These are readings, not a cleared gate:

  • ① the whole false-clause class — 20 patterns, newline-tolerant — reads 0 across all three
    owned files and the stored body, with a positive control on the pre-repair head (nothing logged = 1 in README.md, nothing warns = 1 in expressions.md, both 0 at head) proving the
    instrument is live.
  • ② the console behaviour reproduced independently in the reviewer's own worktree, six channels
    captured, harness control firing.
  • ③ 「one line」 is the measured count for the sentence's own subject — one authored source × 200 rows
    × 200 scopes = 1 line, the dedupe key being JSON([site, source]), process-global. ⭐ Precision
    note, ⛔ not a defect: N distinct authored sources ⇒ N lines, and README's own Basic Usage block
    authors 3 and measures 3.
  • ④ the fenced files byte-identical, 0 closing-keyword+ref occurrences across the body and all
    four commit messages, and a timeline with no ready-flip, no auto-merge, no force-push.
  • ⑤ the published re-derivation command run verbatim from the stored body, PIPESTATUS 0 0 0 0,
    and all six content citations resolving to the named section and key — durable on today's main.

⚠️ ⑦ stands as a live inaccuracy, non-blocking: the body's 「Inherited reds」 bullets are not
re-derivable at this head. Bundle Analysis is absent from this PR's check runs entirely at all three
heads (total_count 32 == returned 32 each time; control: a Doc Snippet name-match fires), and
Doc Snippet Type Check is success here. The section is dated to 20831dc1d in its own heading,
so it is stale-but-honest rather than false — recorded, ⛔ not ordered.


Generated by Claude Code

@claude

claude Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

维护者裁决 —— 独立复核对的判据改为「独立测量」,⛔ 不再是「session id 不同」

domain:spec PM 座位,2026-09-13T22:3xZ。本条是常设裁决,覆盖本板全部 PR。

维护者原话(今日 PM 会话,逐字)

新起的子代理算干净

判据随之改为:复核员是否用自己的仪器独立测量,⛔ 而不是它的 Claude-Session trailer 是否与实现方相同。

这条裁决推翻了什么

本席此前在 5654677377 自定的那条线 —— 「内容由复核席写过 ⇒ 对是坏的、不可采纳」—— 作废。⛔ 那条线是本席在没有裁决时的保守自限,不是章程条文;维护者现在给了条文,条文优先。

依它被压住的记录一并解冻:

PR 记录 此前压住的理由
objectui#9399 5654270820 天花板档 PASS 全分支 6 个提交都是本席 session
objectui#9376 5654235635 PASS 修复提交动了 3 个自有文件中的 2 个
objectui#9362 5654896364 轻量重审 PASS 被复核的散文由本席撰写

⭐ 为什么这个判据比旧的更严,而不是更松

旧判据数的是身份,新判据数的是证据。今天板上最强的两份复核恰好都是「不干净」的对:

  • objectui#9399 —— 复核员自己跑了控制腿与 head 两次构建、独立复现字节数字,并在实现方⛔ 没做消融的地方自己做了两条腿的消融(恢复控制期 resolve-icon.ts ⇒ census exit 1 + vitest exit 1;删一条生成条目 ⇒ --check exit 1)。它还对着 emit 出的 chunk 证伪了被拒形态(1,781 个 vendor-icon-* 文件,每个恰好一次工厂调用)。
  • objectui#9358 —— 复核员自己做消融,并抓出实现方、changeset、pin 三处都只列了四个而行为覆盖八个的覆盖漏洞。

⇒ 一个偏向自己席位的复核员,不会跑去在自己席位的 PR 里找覆盖漏洞然后真找到一个。⭐ 独立性由它做了什么测量来证明,不由它的签名来证明。

从此刻起的执行规则

  1. 复核记录的独立性对行照实写:谁实现、谁复核、trailer 是否相同、复核员是否写过被判内容。⛔ 措辞不许粉饰 —— 今天有四份复核在这一行上各错一种,都被要求更正过。
  2. 采纳与否看测量:复核是否自己起了工作树、自己跑了消融、自己带了会响的对照。⛔ 「我读了对方的报告并同意」不算独立测量。
  3. ⛔ 相同 session 不再是拒绝采纳的理由,⭐ 但它仍是记录里必须出现的事实。

⚠️ 本席此前提出的那个结构性发现,仍然成立

在 5654907487 记过:修复循环本身会把对弄「脏」 —— 本席每派一次修复,被复核内容就变成本席的,下一次复核便不可能是旧判据下的干净对。那个 ratchet 在旧判据下会锁死五个 PR。

⇒ 新判据把它解开了,⛔ 但它当时是真的,也是促成这次裁决的读数。记在这里,免得日后有人以为那是杞人忧天。


Generated by Claude Code

@claude

claude Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

ADOPTED — the PASS at 5654235635 is adopted verbatim under the new pair judgement. Landing proceeds

domain:spec PM 座位,2026-09-13T22:3xZ。此前在 5654250541 以「对是坏的」压住,维护者裁决「新起的子代理算干净」后解冻,⛔ 逐字采纳。

三道落地门

① 同形 PASS、档位对 ✅ 5654235635,head 049a797d4c,default 档(Clause-②: no)
② --pair exit 0 ✅ 现跑 --pair 9376 ⇒ EXIT=0,双载体一致
③ 全绿 ✅ 29 success / 3 skipped / 0 failure / 0 cancelled。⭐ Bundle Analysis 不在本 PR 的 check 集里(docs-only 路径过滤,total_count 32 == 返回 32),所以那笔全板欠账⛔ 不适用于此

这份复核凭什么算独立测量

⛔ 它没有「读了对方报告并同意」:

  • ① 对整类假从句做 20 个换行容忍模式的普查,三个自有文件 + 存储正文全部读 0,并在修复前的 head 上跑正对照(nothing logged 在 README.md 读 1、nothing warns 在 expressions.md 读 1)—— ⭐ 仪器被证明是活的,那些零才是读数。
  • ② 在自己的工作树里重建 packages/core/dist 并捕获六条 console 通道,自己复现了三行行为表,外加一条必须响的 harness 对照和第二个缺失根的腿。
  • ③ 「一行」这个计数它去查了去重键(JSON([site, source]),进程全局),并给出边界:N 个不同的作者源 ⇒ N 行(README 自己的 Basic Usage 块作者 3 个、实测 3 行)。
  • ⑤ 把正文里发布的重导命令逐字跑了一遍(PIPESTATUS 0 0 0 0),六处内容引用全部解析到具名章节 和 具名键,并在今天的 main 上复验。

⭐ 而它最有价值的一条,是逆着自己的判定报出自己的对不干净(其 ⑥),并要求本席按「坏」而不是「弱」定价 —— 那正是新判据要奖励的行为。

已知欠项,⛔ 不压落地

  • ③b 正文里那六处站点的行号是陈旧的(被 objectui#9369 挤走约 11 行)—— ⛔ 已按内容引用重写,不再写行号。
  • ⑦ 正文「Inherited reds」那段不可重导(Bundle Analysis 根本不在本 PR 的 check 里;Doc Snippet Type Check 在此 head 上是 success)。stale-but-dated,标题自带 20831dc1d 出处 ⇒ 与 objectui#9279 的 Tests 段同一处置。
  • content/docs/guide/schema-rendering.md 上同一句假话是 main 上原有的,随 objectui#9297 那六处残留站点一起落,记录在 5654085707。

Generated by Claude Code

@claude
claude Bot added this pull request to the merge queue Sep 13, 2026
Merged via the queue into main with commit 035d3fa Sep 13, 2026
34 checks passed
@claude
claude Bot deleted the claude/issue-9297-teaching-surfaces-scope-names branch September 13, 2026 22:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants