Repository navigation
Four fields docs pages import a cell renderer @object-ui/fields does not export — and two of them name a renderer that has no export at all #6107
Description
Found while taking batch 1 of #5867 (PR #6106). Filed unassigned, out of that batch's scope, and the four files are excluded from it for this reason.
The measurement
Four content/docs/fields/*.mdx pages document a "Cell Renderer" example whose import names a symbol @object-ui/fields does not export. Measured, not read off the prose: the four pages' plaintext fences were re-fenced as ts in a throwaway probe, node scripts/check-doc-snippet-types.mjs was run against the built dist/*.d.ts, and the tree was restored by an EXIT trap (git status clean afterwards). The gate's own lines:
[semantic] content/docs/fields/grid.mdx:164:10 TS2724: '"@object-ui/fields"' has no exported member named 'GridCellRenderer'. Did you mean 'UrlCellRenderer'?
[semantic] content/docs/fields/object.mdx:128:10 TS2724: '"@object-ui/fields"' has no exported member named 'ObjectCellRenderer'. Did you mean 'getCellRenderer'?
[semantic] content/docs/fields/summary.mdx:105:10 TS2724: '"@object-ui/fields"' has no exported member named 'SummaryCellRenderer'. Did you mean 'UrlCellRenderer'?
[semantic] content/docs/fields/vector.mdx:73:10 TS2724: '"@object-ui/fields"' has no exported member named 'VectorCellRenderer'. Did you mean 'getCellRenderer'?
Each hit is zero occurrences of the name in packages/fields/dist/index.d.ts. A reader copying any of those four blocks gets an import that does not resolve — today, independent of what the fence says.
The four are not one defect, they are two
summary and object have a real renderer under a different name. getCellRenderer's standardMap in packages/fields/src/index.tsx routes summary to the exported FormulaCellRenderer and object to the exported JsonCellRenderer. A rename in the doc is probably the whole fix, but which name a reference page should teach — the concrete export or getCellRenderer(type) — is a documentation decision, not a mechanical substitution.
grid and vector have no exported renderer at all. The same map answers both with an inline anonymous component:
vector: () => (a span reading "[Vector]"),
grid: () => (a span reading "[Grid]"),
There is no symbol for those pages to import. So the page cannot be corrected by renaming — either the pages stop showing an import (documenting getCellRenderer('vector') instead), or @object-ui/fields grows the two named exports the docs have been promising. That is the ruling this card wants; it is deliberately not made here.
Why this is worth its own card rather than a rider
This is the objectui#5053 class: a name that came from prose rather than from the package's exports. It is wrong regardless of fence language, and it will not be visible to check-doc-snippet-types until the four pages are re-fenced — which is exactly what #5867's later batches will do. Whoever takes those four files in a later batch needs this answered first, otherwise the only routes left are a FRAGMENT_MARKER on a block that is genuinely TypeScript (a lie the ledger would then carry) or leaving the page out of coverage indefinitely.
Refs: #5867 (the batch lane that surfaced it) · PR #6106 (batch 1, which excludes these four files) · #5044 · #5053.
Activity
yinlianghui-tw commentedon Aug 24, 2026
PM ruling — so #5867's later batches are not blocked
Ruled by the
domain:devx@ objectui execution seat (#5748), PM sessionsession_019b5UBNMtTzKbVtZZGvFuxe. Filed by the #5867 batch-1 dev and correctly excluded from that batch.The two halves resolve differently, and only one is a rename
summaryandobject— rename the import. A real renderer exists under a different name (FormulaCellRenderer,JsonCellRenderer). The documentation is simply wrong about the identifier, and correcting it is the same mislabel-correction class this lane has been clearing all day. Verify the renamed import actually compiles against the shipped@object-ui/fieldstypes rather than assuming the name is the only difference — the shape may have moved too.gridandvector— correct the documentation to the real API. ⛔ Do NOT mint new exports.These pages teach
import { GridCellRenderer } from '@object-ui/fields'when no such export exists andgetCellRendereranswers both with an inline anonymous component. There are two ways to make the doc true, and only one is right:$schemamarker — the producer-side half of #5127's Option B #5329 asked for a$schemaURL to be stamped across 429 files, and the maintainer's ruling was that inventing the identifier before the thing it names exists is backwards. Documentation follows the code; the code does not acquire members to make documentation retroactively honest.getCellRenderer, which is the real, supported path. If that reads worse than the fiction did, that is information about the API worth having, not a reason to fake it.getCellRenderer, the honest snippet turns out to be genuinely unwritable — e.g. the inline component is not reachable through any public surface at all — stop and report. That would mean these two field types have no documentable rendering API, which is a real finding and a different card, not something to paper over with either route.The constraint that survives whatever you write
⛔ No
FRAGMENT_MARKERon any of these four blocks. They are genuinely TypeScript, and #5867's own ruling forbids using a marker to excuse a block that should compile. A marker here would be a lie the ledger then carries indefinitely — the exact debt shape #6054 was filed to clean up.The acceptance criterion is the same as its parent's: these four pages join the compile population with diagnostics at 0, or they are excluded with a stated, measured reason.
Sequencing
This card lands before the #5867 batch that takes
content/docs/fields' remaining 27 blocks — otherwise that dev inherits exactly the two-bad-routes trap batch 1 avoided. Whoever takes it: do the four pages as one PR, since they share the diagnosis and the ruling.Left
pm:queueand unassigned for the triage seat to grade; the ruling above is the direction, not a claim.Refs: #5867 / PR #6106 (batch 1, where this was measured) · #5044 (the class) · #5329 (the precedent against minting identifiers to match prose) · #6054.
Generated by Claude Code
yinlianghui-tw commentedon Aug 24, 2026
os-dev-report
{ "issue": 6107, "status": "done", "branch": "claude/issue-6107-fields-cell-renderer-imports", "pr": "https://github.com/objectstack-ai/objectui/pull/6119", "premise_still_valid": true, "summary": "Re-derived the card's four TS2724 diagnostics on origin/main (b9c367717) with a throwaway re-fence probe under an EXIT trap, then fixed both halves per the ruling. summary and object were renames: getCellRenderer's standardMap routes summary to the exported FormulaCellRenderer and object to the exported JsonCellRenderer, and the shape had NOT moved -- both are declared in the shipped packages/fields/dist/index.d.ts (lines 261, 287) with the same signature taking CellRendererProps and returning React.ReactElement, so renaming was the whole fix. grid and vector have no export at all, so their snippets were rewritten to getCellRenderer(type), declared at dist/index.d.ts:331 as a function taking fieldType string and returning React.FC parameterised by CellRendererProps -- the honest snippet was writable, so the ruling's stop-and-report branch did not apply. NO new exports were minted and NO FRAGMENT_MARKER was added: declared fragments are unmoved at 111 while blocks-to-compile goes 181 to 185. I also corrected the rendered-output comment beside each import in the same pass, because each asserted output the code does not produce (grid renders the literal placeholder [Grid], not '5 rows'; vector renders [Vector], not a component preview; FormulaCellRenderer is font-mono and does String(safe), so no thousands separator and no precision; JsonCellRenderer never emits a literal [Object]) -- leaving a knowingly-false comment beside a corrected import would have shipped half the fix. Docs-only diff, 4 files, +31/-16, no changeset owed.", "tests": "All results measured at the final commit 53ce33ca1 against BUILT dist -- packages were built first via `pnpm exec turbo run build $(node scripts/check-doc-snippet-types.mjs --build-filter) --concurrency=2` (20 packages, all under the shared verify lock), and the gate's own resolution control confirms it each run: \"resolved to '.../packages/types/dist/index.d.ts'\". BEFORE (origin/main b9c367717, unmodified): \"Covered blocks: 292 -- 181 to compile, 111 declared fragment(s).\" / \"Semantic phase: 181 of 181 block(s) judged, 0 failed.\" BEFORE + PROBE (re-fenced the four plaintext blocks as ts, EXIT trap restored the tree; the trap printed an empty `git status --porcelain` for the four files): 4 diagnostics, exactly the card's, e.g. \"[semantic] content/docs/fields/grid.mdx:164:10 TS2724: '\\\"@object-ui/fields\\\"' has no exported member named 'GridCellRenderer'. Did you mean 'UrlCellRenderer'?\" and \"Semantic phase: 185 of 185 block(s) judged, 4 failed.\" AFTER (this branch): \"Covered blocks: 296 -- 185 to compile, 111 declared fragment(s).\" / \"Semantic phase: 185 of 185 block(s) judged, 0 failed.\" / \"Every covered documentation snippet compiles against the built types.\" So blocks-to-compile 181->185, declared fragments 111->111 UNMOVED, diagnostics 4->0. ABLATION (run AFTER committing the fix, so the restore leg could not destroy it): all four corrected import names replaced with bogus ones; mutation confirmed on disk per file by anchored counts -- removed-text count 1 to 0 and injected-text count 1 for each of the four, plus a non-empty `git diff --stat` -- and an EXIT trap restored the tree, verified by grepping the bogus name back to 0 in all four files. The gate then went red on exactly the four blocks, each naming its own file, e.g. \"[semantic] content/docs/fields/summary.mdx:106:10 TS2305: Module '\\\"@object-ui/fields\\\"' has no exported member 'FormulaCellRendererNotAnExport'.\" and \"Semantic phase: 185 of 185 block(s) judged, 4 failed.\" No rebuild leg was needed on either ablation: the mutation lives in the documents, not in a package whose dist the program reads, and the build was already current. OTHER GATES, each quoting its own printed verdict line rather than a bare exit code: check:doc-types -- \"Every documented component type is registered.\"; docs:check-links -- \"Links are valid across 15 scan roots.\"; check:control-bytes -- \"check-control-bytes: OK (scanned 5062 tracked text file(s); skipped 85 binary).\"; check-changeset-presence.mjs -- \"No source of a released package changed in this range, so no changeset is owed.\" (docs-only; nothing under a released package's src, so no changeset and no empty-frontmatter declaration is owed). VITEST from the repo ROOT (never package-scoped): `pnpm exec vitest run scripts/__tests__/check-doc-snippet-types.test.ts scripts/__tests__/check-doc-component-types.test.ts --maxWorkers=2` -- \"Test Files 2 passed (2) / Tests 54 passed (54)\". DOCS RENDER, a DECLARED NARROWING with its measurement: instead of a full apps/site Next build I compiled the four changed pages directly with the repo's own @mdx-js/mdx@3.1.1 -- 4 of 4 compiled, MDX_COMPILE_FAILURES=0, and the corrected snippet text is present in each compiled output, so the blocks survive into the rendered page. The narrowing is safe because fumadocs compiles each page file independently and this diff touches four .mdx pages only, no MDX config, plugin or shared component, so no untouched page's compilation can move. ESLINT, also a declared narrowing but with its population read from eslint's OWN config rather than guessed: eslint.config.js declares files as star-star slash star dot-brace-ts-tsx, and .mdx appears in no config block; measured via `eslint --no-inline-config --format json` over the four changed files -- 4 files reported, 0 errors, each message \"File ignored because no matching configuration was supplied.\" A diff confined to .mdx cannot move any ESLint verdict. CI is not waited on per the dispatch contract; the PM verifies the real gate jobs.", "open_questions": [], "out_of_scope_findings": [] }Two notes for the PM that do not fit the JSON
Process incident, self-reported. My first ablation ran against the fix while it was
still UNCOMMITTED, and its
EXITtrap'sgit checkout -- FILESrestored to HEAD, whichsilently wiped the fix. The ablation result itself was valid, but I had to re-apply the
four edits (byte-identical: same
4 files changed, 31 insertions(+), 16 deletions(-)),commit, and then re-run both the ablation and the final gate on the committed tree. Every
number reported above comes from a run made AFTER the commit at
53ce33ca1. This isexactly the hazard AGENTS.md's "commit the fix before reverse-verification" clause names;
I hit it and am recording it rather than quietly re-running.
Sequencing, for your awareness only. The ruling said this card lands before the finding(docs): TypeScript examples fenced as plaintext escape check-doc-snippet-types — 211 blocks in 122 files, and #5044 proved one of them taught a type error under a gate that reports the file as covered #5867
batch that takes
content/docs/fields' remaining blocks. A sibling worktreeclaude/issue-5867-plaintext-fenced-ts-batch2is live in this container right now, basedon the same
b9c367717. I did not inspect its work and it may well be on a differentdirectory. If it does take
content/docs/fields, the two diffs touch the same four filesand one will need a rebase — the remaining 27 blocks on these pages are untouched by me,
so the overlap would be confined to the four
## Cell Renderersections.Generated by Claude Code
Generated by Claude Code