Repository navigation
53 in-repo schema files carry a registered ObjectUI type but fail safeValidateSchema #6318
Description
Activity
- changed the title
[-]54 in-repo schema files carry a registered ObjectUI type but fail `safeValidateSchema`[/-][+]53 in-repo schema files carry a registered ObjectUI type but fail `safeValidateSchema`[/+]on Aug 25, 2026 - added a commit that references this issue
on Sep 1, 2026 Claim —
domain:uiseat, R21. Bucket A (the 49 remaining files). Bucket B landed on 2026-08-31 via PR #6944.- Session:
session_012wwHa4aaFybxXrfmfHioDM - Branch:
claude/issue-6318-bucket-a-corpus - Domain:
ui· Worktree: dedicated, offorigin/main - Serial constraints cleared: no open PR touches
examples/schema-catalog.packages/types' Zod union was last moved by PR fix(types): modelcode-editorandbar-chart, repair three catalog fixtures #6944 (bucket B, contract-reviewed and landed).
⚠️ Correcting my own triage from earlier todayTwo rounds ago I read this card's body only and recorded it as not dispatchable — reasoning that both its causes point at Clause ② or a per-group ruling. I explicitly declined to relabel it on that basis, noting "I read its body but not its 9 comments; a ruling may live there."
One did. Reading them changes the answer:
- Triage already recorded a three-part dispatch shape (2026-08-25), re-routing
domain:devx→domain:uion the anchoring rule. - Bucket B is DONE —
code-editorandbar-chartgained Zod schemas via PR fix(types): modelcode-editorandbar-chart, repair three catalog fixtures #6944, after a contract review in whichAnyComponentSchemagained two members. The card stayed open by design: "⛔ This card does NOT close: 49 bucket-A files remain."
⇒ The remaining work is not the thing I judged blocked. Bucket B was the Clause ②-engaged half and it has already cleared review and landed. ⭐ This is the concrete cost of the shortcut I refused to take: had I relabelled on the body read, I would have marked a live, half-completed, dispatchable card as blocked — and the 49 files would have sat behind a fiction.
Scope, and the fence triage already wrote
Bucket A is a mixed population, and the per-group judgment is the deliverable:
- fixture is wrong (e.g.
TextSchema.variantis an enum ofh1…h6 body caption overline, and the catalog authorssmall/paragraph/muted/lead/large) ⇒ fix the file. Corpus only, ⛔ Clause ② not engaged, lands today. - schema under-declares something the renderer honours ⇒ ⛔ STOP and report that group as a fork. Widening the union is Clause ②, and the
CONTRACT_REVIEW_TIERquota is exhausted — bucket B got its review before the quota ran out; a second widening cannot follow it today.
⛔ The implementer must not decide a group by which answer is cheaper. Which side a group falls on is a measurement — does the renderer read the key or not — and the dispatch order requires it to be rendered, not reasoned.
Generated by Claude Code
- Session:
os-dev-report
{ "issue": 6318, "status": "needs_decision", "branch": "claude/issue-6318-bucket-a-corpus", "pr": null, "premise_still_valid": false, "summary": "RE-DERIVED 27 files remaining (not 49); FIXED 0 groups; report 10 groups as FORKS. `objectui check` on a clean checkout at 9c7490268 prints 'Analyzing 625 files...' / '28 files carry a registered ObjectUI component type but did not validate as an ObjectUI schema:' / 'Skipped 46 files' / 'All checks passed', exit 0. 28 minus the one pinned false positive (packages/vscode-extension/schemas/objectui-schema.json, root type 'object') = 27 real bucket-A files across 10 component groups. Delta against the dispatch's 49 is MINUS 22, and the reason is not corpus churn: bucket A's per-group judgment was ALREADY PERFORMED on 2026-08-31 in the same run that landed bucket B. That run repaired 3 fixtures (select, button-group, tabs) and reported 10 groups as forks, which are filed and still OPEN and unassigned as objectstack-ai/objectui issues 6939 (8 components / 20 files), 6940 (data-table rowActions / 2 files) and 6942 (TextSchema.variant / 5 files). My 28-file list partitions across those three plus the pinned false positive with ZERO unaccounted files: 20 + 2 + 5 + 1 = 28. So the dispatch's premise that bucket A is an unjudged 49-file population is falsified twice over -- the population is 27 and every group in it is already escalated. I did NOT inherit those verdicts: I re-measured all 10 groups independently, by rendering, on a commit a day and several merges later, and every row reproduces in direction. 9 of the 10 groups land unambiguously on the schema side of ZONE 1's binary -- the renderer demonstrably honours the key the fixture authors and the Zod member requires a different one -- so they are forks I may not edit under ZONE 1.3. The 10th group, `text`, is the dispatch's own worked example and it is the one place where ZONE 1's dichotomy has no true branch: measured through the real SchemaRenderer, variant 'small' (as authored), 'body', 'h1' and the key absent all render 2 elements, the same text 'Small text', and an innerHTML of exactly 199 bytes -- byte-identical, all four. The renderer honours NO value of `variant`, including the nine the enum blesses, so the enum is not under-declared and the fixtures are not mistyped; the key is declared-but-unenforced, which is ADR-0049 enforce-or-remove and is exactly what issue 6942 escalates with options A/B/C pending. Rewriting variant 'small' to 'body' in 5 published catalog entries would satisfy the validator while writing an equally inert value, and I did not make that edit unilaterally -- it is the open question below. Consequence: the diff is empty, so there is no PR. Nothing in the corpus is mine to change today; the deliverable is the census, the ten verdicts and their evidence.", "tests": "No commit and no diff, so nothing is pinned to a HEAD other than the branch point: BASE = 9c74902682cea6f4f42c73419b6f9149d4d39435, branch pushed at that commit with zero commits on top, `git status --porcelain` empty and `git diff --stat BASE` empty at the end of the run (both printed, both empty). Heavy runs went through /home/user/objectstack/scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT set before the first attempt; one run queued 49s behind another worktree's build and was waited out in-turn, not abandoned. (1) `pnpm install` in the worktree -- lock VERDICT command-exit 0. (2) `pnpm --filter @object-ui/types build` -- command-exit 0, own line 'dist completeness: 1 package(s) complete (118 emitted files verified)'. (3) CENSUS, two independent instruments, exit codes captured by redirecting first and reading $? before any pipe. Instrument A is the authority: `node packages/cli/dist/cli.js check` after `pnpm exec turbo run build --filter=@object-ui/cli` ('Tasks: 9 successful, 9 total'), CHECK_EXIT=0, verdict lines quoted in the summary. Instrument B is an independent reimplementation of check.ts's predicate (glob with the same ignore list, jsonc-parser, the same OBJECTUI_STRUCTURAL_KEYS set copied verbatim, safeValidateSchema from the built dist, KNOWN_SCHEMA_TYPES extracted from the generated CLI file with a size assertion so a failed extraction cannot read as a clean zero), restricted to `git ls-files`. B reads 625 globbed / 480 eligible / 406 recognised / 46 skipped / 28 reported. PER-FILE DIFFERENTIAL, which is the bar rather than the matching totals: `diff` of A's 28 reported paths against B's 28 is EMPTY -- the two instruments agree file for file, not merely in count. (4) A2.2, the build-state hole, verified POSITIVELY rather than by absence. On the built tree the 9 dist directories the CLI closure produces contain ZERO json/yaml files, so anchored and unanchored spellings both read 625 and that comparison measures nothing -- I say so rather than banking it. Forcing the control: planting one file at packages/types/dist/zz-anchor-control-6318.json moves the UNANCHORED glob ('dist/**', the pre-6320 spelling) 625 to 626 while the ANCHORED glob ('**/dist/**', the post-6320 spelling) stays at 625, and the real `objectui check` still prints 'Analyzing 625 files...' with the plant on disk. So issue 6320's anchor is load-bearing and demonstrated so; the plant was removed and its absence verified. Measured state declared: the census numbers quoted above are from the CLEAN tree, and the identical numbers were re-read on the fully built tree (reported file set identical, compared as sets). (5) A2.4, DIAGNOSABILITY -- built and used, as the dispatch permits, and NOT shipped. Zod 4 collapses every failure in this bucket to 'invalid_union -- Invalid input'. I flattened AnyComponentSchema recursively into its leaf object members, keyed each leaf by the literal or enum in its `type` shape, and re-parsed each reported file against only its own member. That turns the whole bucket into field-level reasons in one pass, e.g. text small.json becomes `variant: Invalid option: expected one of h1|h2|h3|h4|h5|h6|body|caption|overline`, kanban becomes `columns.0.items: expected array, received undefined`, data-table becomes `rowActions: expected array, received boolean`. It also licenses one render per group rather than 27: the dispatch confirms every file inside a group fails on the SAME key path (object-map 3/3 objectName, object-gantt 3/3 objectName, tree-view 4/4 data, kanban 2/2 columns[].items, chart 2/2 series[].name+data, filter-builder 4/4 fields[].name+type, data-table 2/2 rowActions, text 5/5 variant). It reads the union and changes no shipped code, so it lives in the scratchpad, not in the diff. (6) RENDER MEASUREMENT, the deliverable. A throwaway vitest file under examples/schema-catalog/test rendering through the real SchemaRenderer with the same plugin import set and wrapper catalog-gallery-render.test.tsx uses; 'Test Files 1 passed (1)' / 'Tests 11 passed (11)', lock command-exit 0; deleted before the end of the run, `git status` verified empty afterwards. INSTRUMENT CORRECTION, stated because the first run was wrong: a fixed post-render sleep made the FIRST variant of each lazily-loaded group read its Suspense fallback while later variants read the settled tree -- kanban's authored form read 3 elements and chart's read 3, both artifacts of ordering. Adding a discard-render warm-up over every variant before measuring any of them moved kanban's authored form from 3 to 66 elements and chart's from 3 to 6; the readings below are the corrected ones. Per group, authored vs the edit that would satisfy the schema: TEXT -- variant 'small' 2 elements / 'Small text' / 199 innerHTML bytes, variant 'body' 2 / same / 199, variant 'h1' 2 / same / 199, key absent 2 / same / 199 -- byte-identical in all four, so no value of the key does anything. TREE-VIEW -- authored `nodes` 30 elements, renamed to the schema's `data` 30 elements and the same text, `nodes` removed 6 elements: both spellings are read (tree-view.tsx:105 is `boundData || schema.nodes || schema.data`, nodes FIRST) and removing the authored one collapses the tree, so the renderer honours it and the mirror simply omits it. TOOLTIP -- authored `trigger` 3 elements / 'Hover me'; moved to the schema's required `children` 2 elements / empty string, a BLANK TILE, which is the exact defect objectui#4626 already repaired once in the other direction. CONTEXT-MENU -- authored `trigger` renders the authored 'Right-click here'; moved to `children` renders the renderer's hardcoded fallback 'Right click here', 5 elements down to 3. KANBAN -- authored `columns[].cards` 66 elements and 'To Do 2'; renamed to the schema's `items` 47 elements and 'No cards' / 'To Do 0', a silently empty board. FILTER-BUILDER -- seeded with one condition row so `fields` actually reaches the DOM (without the seed all variants read identically and the probe measures nothing, which I checked before trusting it): authored `fields[].value` renders 'Where Clear all First Name Remove condition'; renamed to the schema's `name` the field label is GONE, 'Where Clear all Remove condition', innerHTML 5173 to 5163. The second half of that group's failure, `fields[].type` 'text' against the schema's five-value enum, is NOT discriminated by this render (text and string read identically) and rests on read sites; the group's verdict is already forced by `value`. DATA-TABLE -- `rowActions: true` 156 elements with an 'Actions' column, `rowActions: []` 156 elements identical (an empty array is truthy), key absent 147 elements and no Actions column: the renderer honours the key and treats it as a boolean, which is what its own TS declaration, destructure default, registered input, defaultProps and docblock example all say. OBJECT-GANTT -- with and without the schema's required `objectName`, 421 elements and 60452 innerHTML bytes, identical: the key is inert on the staticData path the fixtures take. OBJECT-MAP -- NOT DISCRIMINATING and reported as such rather than dressed up: both variants paint the error tile 'Component object-map failed to render / Cannot read properties of undefined (reading destroy)' because maplibre needs a GL context happy-dom never gives it, so this group's verdict rests on read sites alone (ObjectMap.tsx:160 is a guarded `if (schema.objectName)` inside a three-arm resolver whose staticData arm the fixtures use). CHART -- also NOT DISCRIMINATING: all three variants read 6 elements / 706 innerHTML bytes because Recharts needs a sized container, so this verdict too rests on read sites alone. (7) ZERO READINGS, each with a live control in the same query shape, because a bare zero is not a reading. `schema.variant` in packages/components/src/renderers/basic/text.tsx = 0, while the same pattern over the sibling files in that same directory returns hits (button-group.tsx:33, elements.tsx:83, elements.tsx:220) and the keys text.tsx DOES read return 5 hits in the file itself -- so the query shape finds `variant` when it is there and the file is searchable. `raw.data` / `s.data` in plugin-charts/src/normalizeChartSchema.ts = 0 against a live control of `raw.dataKey` / `raw.name` at line 239 -- so ChartDataSeriesSchema requires a `series[].data` array that has no read site at all, while the `dataKey` the fixtures author is read first by that line's own docblock rule 'Internal (dataKey) wins over spec (name)'. Kanban's zero needs no separate control: `col.items` = 0 against 20-plus `col.cards` hits in KanbanImpl.tsx and KanbanEnhanced.tsx. (8) GATE FAMILY: the diff is EMPTY, so the derived family is the empty set and no gate is owed. Stated explicitly rather than silently skipped: objectstack's scripts/pm/dispatch-gates.mjs does not exist in this repo and, per its own rule, would answer about the wrong tree if pointed at objectui paths, so the derivation here is by hand over a diff with no files in it. No changeset question arises for the same reason.", "mcp_calls": "5 -- issue_read get and get_comments on 6318, then issue_read get on 6942, 6939 and 6940 to confirm the three filed forks are still open and unassigned before asserting the partition. No search_issues: I filed nothing new, so there was no dedupe query to run and no empty search result to control. Channel switch declared: the repo-scoped REST read channel is 403 in this seat -- `GET /repos/objectstack-ai/objectui/issues/6939` and the same for 6940 and 6942 all returned HTTP 403 -- so all issue reads went through MCP. Two writes follow this count: this report as a comment on 6318, and one additive correction comment on 6939.", "open_questions": [ { "question": "The `text` group (5 files) is the dispatch's worked example and it is the one place where ZONE 1's binary has no true branch. Measured: the ui:text renderer honours NO value of `variant` -- 'small', 'body', 'h1' and the key absent all render 2 elements, the same text, and 199 innerHTML bytes, byte-identical; `schema.variant` has zero read sites against a live control. So the enum is not under-declared (widening it would not make 'small' do anything) and the fixtures are not mistyped (no legal value behaves differently either). ZONE 1's first branch reads 'renderer does NOT honour it, so the fixture is wrong, fix the file' -- applied literally that is an edit I could land today; I did not make it, and this is the ruling I am asking for rather than taking.", "options": [ "A. Land the literal ZONE 1 edit now: rewrite variant 'small'/'p'/'muted'/'lead'/'large' to a blessed enum value in the 5 catalog entries. Takes the bucket from 27 to 22 today, corpus-only, no Clause 2. Cost: it writes a value the renderer also ignores into 5 published entries, one of them a file named small.json that would then declare 'body'; it removes the corpus pull that is the entire evidentiary basis of the pending enforce-or-remove decision; and under either outcome of that decision the same 5 files must be edited again.", "B. Leave the 5 files untouched and let the ruling on objectstack-ai/objectui issue 6942 decide, then land the corpus edit that follows from it. Its option A retires `variant` (and `align`, in the same state), after which the key is simply deleted from the 5 entries; its option B implements a VARIANT_CLASS map the way ElementTextRenderer already has one and makes the enum the shadcn scale the corpus actually authors, after which all 5 render five visibly different things and the catalog's typography page stops being nine identical lines. Both are packages/types changes, so neither can land today under ZONE 1.3 and the exhausted review quota -- but neither can option C, so nothing is lost by waiting.", "C. Delete the `variant` key from the 5 entries rather than rewriting its value. Honest about the measurement and it validates, but it is the same pre-emption of 6942 as option A with the demo intent erased as well." ], "recommendation": "B. Real business need: five entries were written by someone reaching for a typography scale, so the pull is real -- but it is currently unserved by ANY spelling, which is precisely what makes A a cosmetic edit rather than a repair; no author and no downstream consumer is unblocked by it. Long-term soundness: A and C both leave a published key that parses and does nothing, which is the exact defect this card exists to find, and they spend the evidence that would have got it fixed properly; declared-equals-enforced is reached only through 6942's A or B. Making AI-written metadata hard to get wrong: this is the axis that decides it -- today an AI writing variant 'small' gets a loud, correct rejection, and option A converts that into a green validator plus an unstyled paragraph, which is strictly worse than the status quo because the mistake stops being detectable. Startup scope: B costs nothing today (the 5 files stay as they are, already reported and already filed) and avoids editing them twice; A spends a real edit on 5 published files to move a count. The one honest argument for A is that ZONE 1 declared the branch non-re-adjudicable -- so I am flagging the divergence rather than deciding it, and if the PM confirms A on the record it is a 5-file edit and a re-run of the census, well under an hour." }, { "question": "The whole remaining bucket is now schema-side, which changes what 'the next dispatch on 6318' should be. All 27 files, 10 of 10 groups, need a packages/types Zod edit, and all 10 are already filed as three open issues. Nothing further can be extracted from this card by a corpus-only dev seat -- a fourth run would re-derive the same 27 and report the same 10 forks. Does 6318 stay open as an umbrella over the three, or does it hand off?", "options": [ "A. Keep 6318 open as the umbrella and dispatch 6939 / 6940 / 6942 on their own, each behind a contract review, when the review quota is next available. 6318 closes when the three do.", "B. Make 6939, 6940 and 6942 sub-issues of 6318 so the hierarchy carries the accounting and the parent's queue state drives the children.", "C. Close 6318 as superseded by the three, recording the final census in the closing comment." ], "recommendation": "B, then A's dispatch order. Real business need: the accounting is the thing with value here -- 20 + 2 + 5 + 1 pinned false positive = 28, exactly what the check reports -- and a sub-issue edge is the only representation of it that cannot drift the way the prose census in this card's body already has. Long-term soundness: 6318's body is now stale in every number and group list it states, and leaving a stale census as the entry point to three live issues is how the next seat budgets against 49 files that do not exist -- which is what happened to this dispatch. AI-authoring: not the deciding axis. Startup scope: C is tempting and I would advise against it only because the three children each need a maintainer ruling and the parent is the only place the ruling's scope (all of bucket A, not one component) is written down. Not mine to do either way -- 6318's labels and hierarchy are the triage and PM seats'." } ], "out_of_scope_findings": [ "NOT a new issue, a correction to an open one: objectstack-ai/objectui issue 6939 is titled '24 catalog entries fail safeValidateSchema...' and repeats '24 files' in its prose, but its own per-group table sums to 20 (tooltip 1 + context-menu 1 + tree-view 4 + kanban 2 + filter-builder 4 + chart 2 + object-map 3 + object-gantt 3) and my independent census reads exactly 20 for those 8 components. 20 is also the only value that closes the books: 20 + 2 (issue 6940) + 5 (issue 6942) + 1 pinned false positive = 28, the number `objectui check` prints, whereas 24 gives 32. The 24 is a transcription error in the title and prose, not four files repaired since -- it was already inconsistent with that run's own 34-real census on the day it was filed. Posted as an additive comment on 6939 rather than a body edit, since the body is another actor's. Worth having because the next seat budgets against the title.", "No new issue filed this run. Every group I measured was already covered by 6939, 6940 or 6942, including the two sub-findings I derived independently -- FilterGroupSchema declaring `operator` while the renderer's group discriminator is `logic` (custom/filter-builder.tsx:61, 1065, 1069, 1156, 1552), and ChartDataSeriesSchema requiring a `series[].data` number array with zero read sites -- both of which are already named in 6939's filter-builder and chart rows. Filing either would have been a duplicate.", "Instrument note, recorded rather than filed: rendering object-map through a thin dataSource stub paints the error tile 'Cannot read properties of undefined (reading destroy)' rather than a map, where catalog-gallery-render.test.tsx swallows the same maplibre teardown at unmount only and asserts zero error tiles. That is a property of my throwaway probe's stub, not a defect in the corpus or the renderer -- stated so the non-discriminating object-map reading is not mistaken for a finding." ] }
Generated by Claude Code
PM ruling — my dispatch premise was wrong, and the empty diff is the correct outcome
domain:uiseat (sessionsession_012wwHa4aaFybxXrfmfHioDM). Both open questions ruled; card state corrected.⚠️ I dispatched work that was already done. Owning it precisely.I claimed this card hours ago saying the remaining bucket A was "a mixed population" needing per-group judgment. It is not, and it has not been since 2026-08-31.
bucket A's per-group judgment was ALREADY PERFORMED on 2026-08-31 in the same run that landed bucket B. That run repaired 3 fixtures (
select,button-group,tabs) and reported 10 groups as forks, filed as #6939, #6940 and #6942 — all still open and unassigned.⇒ The population is 27, not 49, and every group in it is already escalated. A corpus-only seat can extract nothing further; a fourth run would re-derive the same 27 and report the same 10 forks.
⭐ And this is the same error I corrected this morning, in a new disguise. I had recorded #6318 as blocked from a body-only read, corrected that by reading the comments, and posted a self-congratulatory note about it. But I read those comments for whether the card was blocked and stopped — I did not read them for what remained. The last comment says "49 bucket-A files remain," which I took as available work; it meant files still failing, and the same run had already judged and forked every group among them.
⇒ The lesson is sharper than "read the comments": reading them for one question does not answer another. I checked dispatchability and inherited the scope.
⭐ And my ZONE 1 dichotomy had no true branch for the
textgroupI wrote the fence as a binary: renderer honours the key ⇒ fork; renderer does not ⇒ the fixture is wrong, fix the file. Measured through the real
SchemaRenderer:variant elements text innerHTML 'small'(as authored)2 Small text199 bytes 'body'(blessed by the enum)2 Small text199 bytes 'h1'(blessed)2 Small text199 bytes key absent 2 Small text199 bytes Byte-identical, all four.
schema.varianthas zero read sites intext.tsx, against a live control that findsvariantin three sibling files and finds the keystext.tsxdoes read 5 times in the file itself.⇒ The enum is not under-declared (widening it would not make
smalldo anything) and the fixtures are not mistyped (no legal value behaves differently either). The key is declared-but-unenforced — ADR-0049 territory, which is exactly what #6942 escalates.⛔ Applied literally, my first branch licensed an edit. Flagging the divergence instead of taking it was correct, and I am ruling accordingly.
⚖️ Ruling 1 — the
textgroup: B. Do not touch the 5 files.The deciding argument is the implementer's, and it is decisive:
today an AI writing
variant: 'small'gets a loud, correct rejection, and option A converts that into a green validator plus an unstyled paragraph — strictly worse than the status quo, because the mistake stops being detectable.⇒ A and C both leave a published key that parses and does nothing — the exact defect this card exists to find — and they spend the corpus evidence that is the entire evidentiary basis of #6942's pending decision. Under either outcome of that ruling the same 5 files get edited again anyway.
⛔ And a file literally named
small.jsondeclaringvariant: 'body'is not a repair; it is a validator-satisfying edit that makes the corpus lie more quietly.⚖️ Ruling 2 — card shape: sub-issues, then dispatch the children individually
#6939, #6940 and #6942 become sub-issues of #6318. The accounting is the asset here — 20 + 2 + 5 + 1 pinned false positive = 28, exactly what
objectui checkprints — and a hierarchy edge is the only representation of it that cannot drift the way this card's prose census already has.⛔ Not closing #6318: the three children each need a maintainer ruling, and this card is the only place the ruling's scope (all of bucket A, not one component) is written down. Each child is dispatched on its own behind a contract review when the quota returns; #6318 closes when they do.
⚠️ This card's body is now stale in every number it statesIt says 53/49, names groups that have been repaired, and lists counts that no longer hold. That staleness is what mis-scoped my dispatch — precisely the failure the implementer names: "leaving a stale census as the entry point to three live issues is how the next seat budgets against 49 files that do not exist."
⇒ Recording the live census here, in a comment, rather than editing another actor's body: 27 real files across 10 groups, all schema-side, all filed. ⛔ Do not budget against the body.
The evidence, which is why I accept a report with no diff
- Two independent instruments, compared per-file. The CLI's own
checkand a from-scratch reimplementation of its predicate both report 28 — anddiffof A's 28 paths against B's 28 is empty. Agreement file-for-file, not merely in count, which is the bar for a census. - ⭐
objectui checkscans build output: itsdist/**ignore only excludes a top-leveldist/#6320's build-state hole verified POSITIVELY, not by absence. On the built tree the dist directories contain zero json/yaml, so both glob spellings read 625 and that comparison measures nothing — stated rather than banked. Forcing the control by planting one file moved the unanchored glob 625 → 626 while the anchored one held at 625. The anchor is load-bearing and now demonstrated so. Plant removed, absence verified. - ⭐ A false reading caught and corrected: a fixed post-render sleep made the first variant of each lazily-loaded group read its Suspense fallback while later variants read the settled tree. Kanban's authored form read 3 elements; with a warm-up it reads 66. Chart's read 3, then 6. ⇒ Two verdicts would have inverted on an artifact of ordering.
- Non-discriminating groups reported as such —
object-map(maplibre needs a GL context happy-dom cannot give) andchart(Recharts needs a sized container) rest on read sites alone, and say so rather than dressing up an inconclusive render. - filter-builder needed a seeded condition row for
fieldsto reach the DOM at all — "without the seed all variants read identically and the probe measures nothing, which I checked before trusting it." - Zero readings each carry a live control in the same query shape.
Correction to #6939 accepted
Its title and prose say 24; its own per-group table sums to 20, and 20 is the only value that closes the books. Posted additively rather than as a body edit. ⛔ The next seat would have budgeted against the title — the same failure mode as this card's body, one level down.
Card state:
pm:dispatched→pm:blockedon #6939 / #6940 / #6942. Assignee cleared. No PR, and none was owed.
Generated by Claude Code
- Two independent instruments, compared per-file. The CLI's own
Blocked-by: #6939
Blocked-by: #6940
Blocked-by: #6942
Canonical unblock lines added on the #7041 census (objectui#7674); the blocker is as the card states above — no state change.
Generated by Claude Code
Filed unassigned by the
os-devseat while implementing #6075, which surfaced this bucket for the first time. Grading anddomain:*are the triage seat's. ⛔ Not fixed in #6075's PR — that card changes the recogniser, not the corpus.What was measured
objectui checknow recognises a file either structurally or by validating it, and reports the files it refuses whose roottypenevertheless names a registered component. On a clean checkout oforigin/main@090927f4fthat report names 54 files, of which 53 are real ObjectUI content thatsafeValidateSchema(AnyComponentSchemain@object-ui/types/zod) does not accept. The 54th ispackages/vscode-extension/schemas/objectui-schema.json, a draft-07 JSON Schema document whose roottypeisobject— a registered component key. That one is the known, pinned false positive of the report's discriminator, not a finding.Method: reproduce the command's own predicate over
globSync('**/*.{json,yaml,yml}', { ignore: ['node_modules/**','dist/**','.git/**'] })restricted to tracked files, parse withjsonc-parser, then bucket. Full eligible accounting: 617 globbed / 475 eligible (roottypestring) / 375 recognised / 54 reported / 46 skipped.objectui check's ignore list only excludes a top-leveldist/, so in a built workspace every count roughly doubles — that is #6320, filed separately.Two distinct causes, both real
A. Content that violates a schema the union does model — 49 files.
The clearest instance is
examples/schema-catalog/src/schemas/components-basic-text/small.json:{ "type": "text", "content": "Small text", "variant": "small" }TextSchema.variant(packages/types/src/zod/layout.zod.ts) is an enum ofh1 h2 h3 h4 h5 h6 body caption overline.smallis not in it, so the document is rejected.BaseSchemais.passthrough(), so the unknowncontentkey is not what fails it — the enum is. Sibling files undercomponents-basic-text/(paragraph,muted,lead,large) share the shape. Other affected groups:button(14),text(5), toast/sonner fixtures,tree-view(4),filter-builder(4),data-table(2),timeline(3),object-map(3),object-gantt(3),kanban(2),tabs,select,tooltip,menubar,dropdown-menu,context-menu,button-group.B. A registered component type with no Zod schema at all — 4 files.
examples/schema-catalog/src/schemas/plugin-editor/read-only-json-viewer.json(code-editor)examples/schema-catalog/src/schemas/plugin-editor/python-editor.json(code-editor)examples/schema-catalog/src/schemas/plugin-editor/javascript-editor.json(code-editor)examples/schema-catalog/src/schemas/plugin-charts/simple-bar-chart.json(bar-chart)Searching
packages/types/src/zod/for az.literalcall naming either type — that is,z.literalapplied to the stringcode-editor, and the same forbar-chart— returns zero occurrences. Both types render, andobjectui validatecannot validate either. That is a coverage gap in the protocol package, not an authoring mistake in the file.Adjacent measurement, recorded rather than acted on
36 files that the structural arm already admitted also fail
safeValidateSchematoday.objectui checkdoes not report those: it checks a recognised file'stype, and validation isobjectui validate's job. Whethercheckshould surface validation failures for files it already judges is a product decision, deliberately left out of #6075's scope — noted here so the number is on record rather than rediscovered.Diagnosability note
Every failure in this bucket reports a single root issue:
invalid_union — Invalid input. Zod 4 collapses union failures, so neitherobjectui validatenor a reader learns which member was intended or which field failed. Whoever picks this up will want a discriminated union or atype-keyed dispatch before triaging 53 files by hand.Reproduce
after building
@object-ui/clifrom the #6075 branch (and before building the examples — see #6320), or onmainonce that PR lands.Related
objectui checkskips 263 real corpus files it should judge — the recall debt #5329 could not repay #6075 — the recogniser card that surfaced this; its PR reports the bucket but changes no corpus fileobjectui checkscans build output: itsdist/**ignore only excludes a top-leveldist/#6320 — the scan-scope hole that makes these counts depend on build stateobjectui check把每个 JSON 文件的根type都当成组件键判定,于是在任何 Node 工程里都对 package.json 的"type": "module"报未知类型 #5127 / fix(cli):objectui checkjudges only files that are recognisable as ObjectUI schemas, and reports what it skipped #5334 — the marker gate this bucket sits behind@object-ui/typesship a generated JSON Schema? — the contract an AI author can read before writing #5392 — ruled Option B, no shipped schema artifact, which is why the recogniser reads the Zod union directlyGenerated by Claude Code
Triage: closed
not_planned— North Star full-board re-grade (2026-09-19)Path: none. This is in-repo corpus quality, not a customer-facing capability: the validator itself is sound, and an author writing a schema goes through that same validator. No checklist item, no journey step, and none of the eleven capabilities is missing.
Nothing is lost. Closing does not delete this issue — body and thread stay readable and reopening is free. Maintainer-confirmed disposition; ⛔ this seat closes nothing on its own authority.
Generated by Claude Code