Skip to content

finding(plugin-grid/docs): the published docs and skills teach { name, label } columns on a directly-authored object-grid, which ObjectGrid silently drops — before and after #5068 #5352

Description

@os-support-ai

Found while running #5120's census (not claiming; observation class). Baseline objectui main @ 9c60144, i.e. after PR5345 (#5068) landed.

The fact

Two published corpora author object-grid columns in the name spelling:

  • content/docs/api/schema-reference.md:748-755 — a mixed array: "columns": ["name", "email", "company", "phone", { "name": "status", "label": "Status", "sortable": true }]
  • skills/objectui/guides/page-builder.md:304 — all-object: { "name": "name", "label": "Name", "type": "text" }, etc.

ObjectGrid renders neither. Both shapes are dropped silently — no throw, no console line, no empty header cell; the column is simply absent.

Not a #5068 regression — verified both paths

Worth stating explicitly, because the timing invites the wrong conclusion:

So the outcome is identical on both sides of PR5345. This is a pre-existing docs-vs-runtime divergence that #5068's census did not surface because that census was looking for the accessorKey/header spelling, not this one.

Why it is not merely a docs fix

ObjectGrid is not downstream of normalizeListViewSchema when an object-grid node is authored directly — its own test file says so (packages/plugin-grid/src/__tests__/columnIdentity.test.tsx, docblock). So the name → field fold that rescues a list view's columns (normalizeColumnIdentities, #3104) never runs here. The same { name: 'status' } column therefore does reach $select (getSelectFields resolves through columnIdentity, which accepts name) while not reaching the rendered column set: the server is asked for the field and the user is never shown it.

That asymmetry is the part worth a decision — whether the fix is the docs, the fold, or the filter.

Recheck

sed -n '745,757p' content/docs/api/schema-reference.md
sed -n '298,312p' skills/objectui/guides/page-builder.md
sed -n '1448,1460p' packages/plugin-grid/src/ObjectGrid.tsx   # the field filter
sed -n '1652,1658p' packages/plugin-grid/src/ObjectGrid.tsx   # the string arm's filter
sed -n '9,21p'  packages/plugin-grid/src/__tests__/columnIdentity.test.tsx

Grading

finding, not pm:queue. Related: #5068, #5349 (the same silence, asked as a diagnostics question), #5120.

Activity

  1. os-zhuang commented on Aug 20, 2026

    @os-zhuang
    Contributor

    Triage first-touch grading (finding centralized round, 2026-08-20, triage seat session session_016A4EBi3ky1mjTi6vD2kCvA): promote to pm:queue, type Task, scope = the docs half only. Re-verified on origin/main: schema-reference.md:748-755 and the skills page-builder guide still teach {name,label} columns on directly-authored object-grid, which ObjectGrid.tsx:1477 silently drops (while columnIdentity still ships the dead column name to $select). The docs correction needs no ruling — object-grid's contract is already settled (strict ListColumnSchema, field/label) — so fixing the two published examples that actively teach a broken shape is severable; the fold-vs-filter renderer question stays with #5349, and the wider alias-family ruling stays with #5120.


    Generated by Claude Code

  2. added theissue type on Aug 20, 2026
  3. claude commented on Aug 21, 2026

    @claude
    Contributor

    Claim: PM loop round 21
    Session: session_01RV6yuVCxymHYE16PL9vQkE
    Branch: claude/issue-5352-grid-column-spelling-docs
    Worktree: objectui-issue-5352
    Domain: repo:objectui
    File surface: content/docs/api/schema-reference.md + skills/objectui/guides/page-builder.md — docs half only, per triage (stop on breach; explain in the report)
    Container & model: M, mode:subagent
    Clause-②: no — docs only, no accept-set change
    Serial constraints cleared: packages/plugin-grid is free (#5349/PR5456 MERGED). ⚠️ Premise partially moved: #5349 landed a diagnostic, so the drop this card calls "silent" is no longer silent — re-verify wording before writing.


    Generated by Claude Code

  4. claude commented on Aug 21, 2026

    @claude
    Contributor
    {
      "issue": 5352,
      "status": "done",
      "branch": "claude/issue-5352-grid-column-spelling-docs",
      "pr": "https://github.com/objectstack-ai/objectui/pull/5463",
      "premise_still_valid": true,
      "summary": "The card's core premise held and is fixed: both published corpora authored object-grid columns in a `name` spelling ObjectGrid does not read, and both now spell `field`. Docs half only, per triage — ObjectGrid is untouched. TWO CORRECTIONS to the card's description. (1) 'Silently — no throw, no console line' is now only half true, and not the half the card implies: #5349/PR5456 landed a diagnostic, so the ALL-OBJECT array in page-builder.md now emits one console.warn naming each column; but the MIXED array in schema-reference.md is STILL completely silent, because partitionAuthoredColumns returns null when columns[0] is not an object and deliberately declines to judge the string[] arm. (2) The card frames schema-reference.md as one spelling defect; rendering proved a second, independent one — normalizeColumns dispatches the WHOLE array on columns[0], so with a bare string first the array takes the string arm and the trailing column object is dropped WHATEVER it spells. Renaming name->field alone left Status still missing (measured); the example had to become uniformly ListColumn objects. Also added the `columns` property-table row naming `field` plus the no-mixing rule, and a note in page-builder.md between the adjacent grid and form examples, which mean the opposite thing by the same pair of words (ListColumn.field vs FormField.name) — the documented cause of this defect family per packages/core/src/utils/column-identity.ts. The adjacent object-form example was verified correct and left alone. File surface honoured exactly: the two named corpora, plus the mandated changeset (.changeset/grid-column-spelling-docs-5352.md, empty frontmatter — docs/skills only, publishes nothing; objectui has no skip-changeset label).",
      "tests": "All readings on committed head e8714f782 (working tree clean); heavy runs wrapped in flock -E 99 -w 540 /tmp/os-heavy-verify.lock. RENDER MEASUREMENT (not type-reading): a throwaway vitest harness in packages/plugin-grid/src/__tests__/ extracted the object-grid JSON blocks OUT OF THE DOC BYTES themselves — `git show origin/main:FILE` for the before leg, working tree for the after leg — and rendered each through the real ObjectGrid; harness deleted before the commit (diff is 3 files). Note vitest.config.mts aliases every @object-ui/* specifier to src/, so no dist build gates this measurement and no ablation is involved. schema-reference.md: BEFORE headers [#,Name,Email,Company,Phone,Actions] body [1Open,Ada,ada@x.com,Analytical,555-1,''] DIAGNOSTICS 0 -> AFTER headers [#,Name,Email,Company,Phone,Status,Actions] body [...,Active,''] DIAGNOSTICS 0 (silent in BOTH legs — the drop was and would have stayed unreported). page-builder.md: BEFORE headers [#] only (row-number column, ZERO data columns) body [1Open] DIAGNOSTICS 1 ('[ObjectUI] ObjectGrid columns: object-grid (objectName: products) — 3 of 3 authored columns resolve to nothing... columns[0]: keys seen: name, label, type — no field key') -> AFTER headers [#,Name,Price,Status] body [1Open,Widget,9.50,Live] DIAGNOSTICS 0. NEGATIVE CONTROL: field-spelling-but-still-mixed rendered headers [#,Name,Email,Company,Phone] — Status STILL dropped, which is what forced the all-object rewrite. CONTRACT PROBE against the real strict ListColumnSchema (@objectstack/spec/ui 17.0.0): all 8 corrected columns -> PARSES; both old shapes -> REFUSED, invalid_type:['field'] + unrecognized_keys:['name']. SWEEP: a scanner parsed EVERY fenced json block in both corpora and applied the renderer's own two filters, recursing for object-grid/view:grid anywhere in the tree (grep alone misses the two nested grids). BEFORE: 35 blocks, 35 parsed, 0 parse-failed, 4 grid blocks found, 4 dropped entries. AFTER: 35 blocks, 35 parsed, 0 parse-failed, 4 grid blocks found, 0 dropped entries. COUNTER-PROBE for the zero: the same scan still reports 4 grid blocks by name after the fix (so the search works), parse failures are reported rather than skipped (0 of 35, so no block went silently unread), and the arm reading for schema-reference.md flipped string->object, confirming the dispatch change landed. GATES (green on e8714f782): check:control-bytes OK (4521 tracked text files); check:skills-paths OK (95/96 stated paths resolve, 1 baselined); check:doc-types OK (183 doc files, 1052 code blocks, every documented component type registered); check-changeset-presence.mjs OK (1 changeset added); check-changeset-no-major.mjs OK. Plus a manual control-byte grep over the three touched files: none found. NOT RUN — check:doc-snippets: it needs 15 built package dists and reads ONLY fenced ts/tsx snippets; this diff changes zero ts/tsx fences (mechanically: git diff --merge-base over the two files matches 4 json-language fences and zero ts or tsx fences). CI builds and runs it. CI on the PR was not awaited, per the report-at-draft-PR contract.",
      "open_questions": [],
      "out_of_scope_findings": [
        "NOT filed, already open and unassigned as #5350: the type:'table' and type:'crud' examples in the SAME schema-reference.md also spell name/label against TableColumn (which declares header/accessorKey), and packages/components/src/renderers/complex/table.tsx tolerates both via `col.header || col.label` and `row[col.accessorKey || col.name]`. #5350 quotes the same property-table row and the same table.tsx line, so filing would have duplicated it. Not fixed here: different component, different contract, and the correct direction (retire the alias vs declare name on TableColumn) is an unruled maintainer call.",
        "NOT filed, already open as #5373: type:'crud' is documented in api/schema-reference.md as reference material but has no renderer — covers the crud half of the block above.",
        "No new issue was filed this round. Observation, deliberately not filed as it is already stated inside check-doc-snippet-types.mjs as #5138 shape 1 (left unruled on purpose): no gate in this repo could have caught this defect — check:doc-types verified the one key that was right (the 'object-grid' type literal), while check:doc-snippets excludes schema-key validity of JSON metadata blocks. That blind spot is how both corpora drifted."
      ]
    }

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions