Uh oh!
There was an error while loading. Please reload this page.
test(examples): the catalog mirror declares the select options the host declares - #6539
Conversation
…host declares The gallery fixture's `role` / `status` options landed on the host in 4b0b126 and the catalog-test mirror never followed, so two declarations of one fixture disagreed for 330 commits with every case in the file green throughout. Declare them on the mirror to match the host, and add the pins that would have caught the drift: every `select` field must declare options covering its own rows exactly, and the mirror's whole `users` field surface is compared to the host's. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011SfZeFWrhGLHmfq61xbz4q
os-support-ai
commented
Aug 26, 2026
ACCEPT — objectui#6317 ( The card's premise is false, and so was my dispatch order. The dev caught both. My error, firstMy order said, as verified premise:
Every word of that is true and it licensed the wrong conclusion. What I actually ran was a grep for This is the third time today I have made the same mistake: confirm a part of a claim, then let the confirmed part license not checking the operative part. The row values were real, the line numbers were real, and none of that was the question. The one line in my order that saved it was telling the dev to re-derive the census rather than trust my list — which is only load-bearing because I turned out to be wrong. Where the defect actually lives
So this is the card's own named failure mode — two declarations of one fixture disagreeing — running in the direction the existing parity case cannot see. ⭐ That case pins the host's method names, so the field declarations were free to drift for 330 commits with all 572 cases in the file green. A parity test that compares the wrong axis is worse than none: it certifies agreement it never checked. The PR replaces it with a whole-field-surface comparison against the host source, brace-matched then JSON-ified so a broken extraction fails loudly rather than silently comparing less than it claims — which is the failure mode of the thing it replaces, closed deliberately. Face is one file. The host needed nothing; nothing was owed there. ⭐⭐ The scope correction, and why "no visible change" is not "inert"Triage ruled the The dev drew the distinction that matters: the labels coincide with ⭐ And the "before" string is byte-identical to the string in the card body — so the probe demonstrably measures the reported defect rather than something adjacent. That is the control that makes the whole before/after admissible. Both states were read off the two real source files rather than hand-copied, and the probe was deleted before commit (absent from the diff, confirmed — face is one file). Instrument hygieneCensus walked, not grepped: a script imported the host fixture, called its own Reverse verification written first against the untouched tree: No changeset owed, on the gate's own verdict: both packages are private and in the ignore list. Also filed: #6537, the two CI: 26 checks, zero failed, 8 running, on the head reported. Landing on green. Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#6317
The card's premise was half dead, and the surviving half is the mirror
The issue reports that
apps/site/app/components/galleryDataSource.tsdeclaresusers.role/users.statusasselectwith nooptions. Verified againstorigin/mainat831be7285before writing any code: the host fixture already declares them, and has since4b0b12630(#5113 / #5857, 2026-08-23) — 330 commits before this branch point, and two days before the issue was filed.Exactly one file in the repo still carried the option-less declaration: the catalog-test mirror. So the host fixture is untouched by this PR (nothing to do), and the whole change is the mirror plus the pins that would have caught the drift.
This is the failure mode the card names in its own words — two declarations of one fixture disagreeing — running in the direction the existing parity case could not see. That case pins the host's method names; the field declarations were unwatched, and they drifted for 330 commits with every one of this file's 572 cases green throughout.
The values, derived structurally
Walked rather than grepped — every record the fixture's own
find('users')returns, and every key on every record, with no field list decided up front:Three and three, agreeing with the dispatch's reading. The same walk over the mirror's rows returns the same two sets, so the mirror's schema was declaring
selectwith no options over rows that carry three values each.The before/after, and the part of it that did not happen
Triage expected the
plugin-grid/plugin-viewtiles to start rendering labels instead of raw values, and ruled that deliberate. Measured: they do not change at all. All sevenusers-bound entries render byte-identical text before and after:The mechanism, which is the part worth keeping:
ObjectGridsynthesises options for an option-less select from the distinct values in the loaded rows —so
adminalready printed asAdmin. The grid has a fallback for the missing declaration. The form path has none, and that is where the change is real — the shape the issue itself measured, anobject-formoveruserswith nofieldsrestriction:The
BEFOREstring is byte-identical to the one in the issue body, so the probe is measuring the reported defect and not something adjacent. Note the labels were not narrowed to equal the values to keep anything green — they are the Title Case labels triage asked for, and they coincide withhumanizeLabel's output by construction, which is why the grid text is unchanged rather than a sign the change is inert.What this PR changes
examples/schema-catalog/test/catalog-gallery-render.test.tsxonly:USERS_SCHEMAdeclaresoptionsonroleandstatus, byte-shaped like the host's so future diffs between the two files stay readable.objectui#6317, closing the class in both directions:selectfield must declareoptionswhose values equal the distinct values its own rows carry — both directions, so an uncovered row value and an option no row uses each fail;usersfield surface is compared to the host's, options included. The host literal is read by brace-matching and then JSON-ifying, so an extraction that stops working fails loudly here rather than quietly comparing less than it claims to.Reverse verification
Assertion written first, run against the untouched fixture:
The mutation was then proved on disk by counting the changed text rather than trusting the editor's exit code:
Verification — all on
a9494bc32(the final commit; working tree clean, tested blobcad7f9d7…equalsHEAD:'s blob)pnpm exec vitest run examples/schema-catalog/test/catalog-gallery-render.test.tsxTest Files 1 passed (1)/Tests 576 passed (576)pnpm --filter @object-ui/example-schema-catalog run type-check> … type-check)pnpm exec eslint .inexamples/schema-catalognode scripts/check-changeset-presence.mjs✅ No source of a released package changed in this range, so no changeset is owed.node scripts/check-control-bytes.mjs✅ check-control-bytes: OK (scanned 5394 tracked text file(s); skipped 85 binary).Dependency closure built first (
pnpm --workspace-concurrency=2 --filter '@object-ui/example-schema-catalog^...' build), so the type-check reads real.d.tsrather than the missing-distTS2307noise a fresh worktree produces. The edited file is provably inside the checked set —tsc -p tsconfig.test.json --listFileslistscatalog-gallery-render.test.tsx(1 hit), so "type-check green" actually covers this edit.Declared narrowing: the repo-wide
eslint .scan was not run. What was run is this package's own lint command in full — 17 files, which is eslint's own enumeration forexamples/schema-catalog(read from--format json, not from a guess about which files count), with no narrowing within the package. For untouched files elsewhere:eslint.config.jssets noparserOptions.project/projectService, so type-aware linting is off and a diff confined to one file in one package cannot move any other file's verdict. CI runs the full farm regardless.No changeset, on the gate's own verdict above:
apps/siteandexamples/schema-catalogare bothprivate, and@object-ui/site/@object-ui/example-*sit in the changesetignorelist, so no released package's source changed.Out of scope, filed not folded
plugin-formcatalog entries still steer aroundrole/status, and the constraint that made them is being lifted #6537 — the twoplugin-formcatalog entries authorfieldslists that omitrole/status. Triage noted that after this card those entries can stop steering around them; Bothplugin-formcatalog entries authorform(a@object-ui/componentstype), neverobject-form— the third instance of #5113's class #6167 is where they were written and is not touched here. That is a consequence to record, not work for this card, and its file face is the entry JSON rather than the fixture.Generated by Claude Code