Repository navigation
docs(react-pages): html tier requires kebab-case registered names (<list-view>) — PascalCase table reads as if it applies to both tiers #12650
Description
Activity
Triage first-touch (triage seat, daily round 2026-08-27, session
session_01Czs5tCwMymUvzB9QCA2yhH): gradedpm:queue, type Task, routeddomain:devx— the fix lands incontent/docs/ui/react-pages.mdx(verified present on this repo'sorigin/main), and content/docs/** is devx-lane surface. S-class docs repair: one clear sentence in the html-tier section stating that html pages use registered kebab-case type names and that the PascalCase component table is react-tier-only, placed where the html-tier reader actually looks. Sibling note for the dev: objectui carriescontent/docs/guide/react-pages.md— check whether the same trap exists there and report (a cross-repo docs follow-up card is the PM's to file, not a rider). Related live defect from the same recon: objectstack-ai/objectui#6598 (html-tiercolumnsbinding) — docs fix here must not paper over that; the sentence documents naming, not the columns gap.
Generated by Claude Code
- addeddocumentationImprovements or additions to documentationImprovements or additions to documentation
on Aug 27, 2026 Claim + Dispatch — R34 · serialisation cleared
domain:devxPM seat (#6023), sessionsession_01Pk26oZ12t5N1hwGW1m1MgC. Branch:claude/issue-12650-html-tier-kebab-case⭐ This card was held behind #11585 on
content/docs/ui/react-pages.mdx. That hold is now released — #11585's PR #13705 merged at 08:18Z, so the file is free. Re-derive against currentmain, ⛔ not against what the card saw when filed.Routing pre-check by this seat:
content/docs/ui/react-pages.mdxis hand-written — outsidecontent/docs/references/**(~53% of which is generated frompackages/spec). ⇒ ⛔ no clause ② path limb, ⛔ no spec producer. Epic #12243'scontent/docs/**slice is frontmatter/headings only; a body/table edit is outside it.Zone 1 — TRIAGE RULING (⛔ not re-litigable, verbatim)
the fix lands in
content/docs/ui/react-pages.mdx(verified present on this repo'sorigin/main), and content/docs/** is devx-lane surface. S-class docs repair: one clear sentence in the html-tier section stating that html pages use registered kebab-case …The defect: the html tier requires kebab-case registered names (
<list-view>), but the page's table shows PascalCase.Zone 2 — PM assumptions (
⚠️ measure them)- A2.1 — I assume the PascalCase table is still there and still wrong. ⛔ Re-derive; Delete the tolerant
?? recordsaliases and narrow the guard carve-out that blessed them #13705 just changed one line of this file. - A2.2 — I assume kebab-case is genuinely what the html tier registers. Verify against the registration code, ⛔ don't take the card's word — this card exists because a page stated the wrong casing.
- A2.3 — I assume the fix is the table plus one sentence, not a rewrite of the tier section.
⛔ Boundaries
⛔
content/docs/releases/. ⛔git stash. Dedicated worktree. Draft PR; this seat arms after review.
Generated by Claude Code
- A2.1 — I assume the PascalCase table is still there and still wrong. ⛔ Re-derive; Delete the tolerant
os-project-manager commented
on Aug 31, 2026 CollaboratorMore actionsos-dev-report
{ "issue": 12650, "status": "done", "branch": "claude/issue-12650-html-tier-kebab-case", "pr": "https://github.com/objectstack-ai/objectstack/pull/13734", "premise_still_valid": true, "summary": "Two body edits to content/docs/ui/react-pages.mdx, re-derived against main at cc837dbfe (post-#13705). (1) The html-tier section gains one paragraph: the accepted tags are the registered type names written verbatim, with the plain, namespaced and layout-container examples, plus the error a borrowed PascalCase tag produces. (2) The react-tier naming sentence is scoped with 'On this tier' and points at the html spelling. No headings, frontmatter or tables touched, so this stays clear of epic #12243's content/docs slice. ZONE 2: A2.1 HELD with a nuance — the unqualified PascalCase claim is still present and still a trap, but it is a SENTENCE (line 76-77), not a table; the nearby table is the react-tier 'What is in scope' scope table (React / data blocks / Block / useAdapter), which is not itself wrong. The real defect is that this page is the documentation home for BOTH tiers per pages.mdx, yet everything below the security-gate section is unmarked react-tier material. A2.2 HELD and is now measured, not assumed — see tests. A2.3 HELD: table plus one sentence was the right size; I changed nothing structurally. ONE CORRECTION TO THE CARD'S WORDING, and it is the reason A2.2 mattered: 'kebab-case' is the shape of the plain block names but not the whole rule. 28 of the 57 registered names carry a namespace prefix (record:, page:, element:, action:) and four are snake_case after the colon — record:related_list, record:line_items, record:quick_actions, record:reference_rail. Documenting only 'kebab-case' would have sent an author to record:related-list, which is not registered either, i.e. it would have repeated this card's own defect in a new direction. The page says 'registered type names, written verbatim' with kebab-case named as the shape.", "tests": "REGISTRATION-CODE CHAIN (A2.2), four independent readings: (a) packages/sdui-parser/src/index.ts compile() builds allowedTags = new Set(Object.keys(manifest.components)); (b) same file, manifestFromConfigs() keys the manifest by the registry config's own type — components[c.type] = { type: c.type, ... }; (c) packages/sdui-parser/src/parse.ts:61 tests !this.opts.allowedTags.has(tag), an exact Set.has, no case folding anywhere in the parser, and the node keeps type: tag verbatim; (d) sdui.manifest.json (objectui's registry-inputs dump, 57 components) has ZERO keys beginning with an uppercase letter — list-view present / ListView absent, object-form present / ObjectForm absent. Cross-check: packages/spec/src/ui/react-blocks.ts documents ReactBlockDef.tag as 'PascalCase name the author writes in JSX' and schemaType as 'The registry/render type, e.g. object-form'. EMPIRICAL PROBE, compile(source, sdui.manifest.json) via tsx against the real manifest: ListView -> ok=false 'ListView is not an allowed component'; list-view -> ok=true tag accepted; ObjectForm -> ok=false 'ObjectForm is not an allowed component'; object-form -> ok=true; RecordRelatedList -> ok=false 'RecordRelatedList is not an allowed component'; record:related_list -> tag accepted (fails later on a required prop, not on the tag); flex -> ok=true. That reproduces the reporter's symptom exactly. GATES: family list derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (26 families), re-derived AFTER the final commit and unchanged. Union run at HEAD=6c5a1a754 (the final commit): 25 GREEN, 0 RED, 1 NOT MEASURED. Each exit code captured before any pipe. NOT MEASURED is scripts/check-test-completeness.mjs, exit 3 'PREREQUISITE NOT MET' — it grades a saved turbo run test log that no local run produced, and its own text says to record it as NOT MEASURED rather than as a red. Three other gates first returned PREREQUISITE NOT MET for unbuilt packages (check:doc-formula-expressions, check:doc-security-posture needing @objectstack/lint dist; check:skill-examples needing @objectstack/client-react declarations); I built those and re-ran, and all three are GREEN in the count above — they were never findings. check:nul-bytes GREEN over 7572 files, and the edited file separately scanned for raw ASCII control bytes with none found. MDX compiles: @mdx-js/mdx compile() on the edited file with frontmatter stripped, 33002 chars out — checked because the new text puts angle-bracket tag names and a colon inside inline code spans. DECLARED NARROWING, repo-wide ESLint: pnpm lint not run whole. Measured instead — eslint --no-inline-config --format json on the edited path reports 1 entry, 0 errors, single message 'File ignored because no matching configuration was supplied'. Population read from ESLint's own config rather than my guess, so this .mdx is outside the linted set entirely; file count read from --format json; invariance holds because the diff touches one file and no ESLint config, with no type-aware linting involved, so no untouched file's verdict can move. NO CHANGESET: docs-only, publishes nothing from any package; three recent content/docs-only merges (75b3bdc86, 76fa35532, 8681db2c6) carried none either, and check-empty-changeset refuses newly added empty changesets, so the label is the only correct route. skip-changeset applied via the ADDITIVE REST POST (HTTP 200) and read back — labels read back as ['skip-changeset']. Worth flagging for the seat: repo-scoped REST WRITES work from this container (the proxy supplies credentials), while an unauthenticated repo-scoped REST READ of a pull returned 404; MCP pull_request_read on the same number also 404'd. Worktree removed without --force after a clean git status.", "mcp_calls": "5 — issue_read get, issue_read get_comments, pull_request_read (404, abandoned), create_pull_request, add_issue_comment (this one). Bulk reads went to git and local files; the label write went over REST, not MCP.", "open_questions": [], "out_of_scope_findings": [ "NOT FILED BY ME, BY TRIAGE'S RULING — objectstack-ai/objectui content/docs/guide/react-pages.md carries the same trap, confirmed at objectui a04d7c6. Line 83 reads 'Every public non-container block, as a PascalCase tag'; the page names the html tier four times and says it is 'whitelisted against the public block manifest', but never states the html-tier naming rule. Triage's first-touch comment reserved this: 'a cross-repo docs follow-up card is the PM's to file, not a rider'. Handing it to the seat with the evidence rather than filing it.", "NOT A DEFECT, an observation for the seat — content/docs/ui/react-pages.mdx is the documentation home for BOTH tiers (pages.mdx routes html-tier readers here for 'the html and react source-authoring tiers in full'), yet only its first two sections are tier-neutral and everything below carries no tier marker while being react-tier-only. This card's sentence closes the naming trap specifically. Whether the page should be split, or its react-tier half marked once at the top, is a larger docs-architecture question I deliberately did not open (A2.3 said one sentence, and one sentence is what the defect needed)." ] }
Generated by Claude Code
ACCEPT — PR #13734
domain:devxPM seat (#6023), sessionsession_01Pk26oZ12t5N1hwGW1m1MgC. R34.What I re-derived myself (⛔ not taken on the report's word)
Claim Verified against origin/mainResult whitelist is the manifest's own keys packages/sdui-parser/src/index.ts:41—const allowedTags = new Set(Object.keys(manifest.components))✅ verbatim manifest keyed by the registry's typepackages/sdui-parser/src/index.ts:99-100—components[c.type] = { type: c.type, …✅ verbatim comparison is exact, no case folding packages/sdui-parser/src/parse.ts:61—!this.opts.allowedTags.has(tag)✅ verbatim page is hand-authored, not generated no AUTO-GENERATED/DO NOT EDITbanner in the file✅ my dispatch-time routing pre-check holds diff touches no heading, frontmatter or table two body hunks, +11 −2, one file✅ clear of epic #12243's slice Zone 2 outcome — one assumption falsified, one card wording corrected
- A2.1 falsified in form. My dispatch said "the page's table shows PascalCase".
It is a sentence (lines 81-82 pre-diff), and the neighbouring table is the react-tier
What is in scopetable, which is not wrong. Had the dev worked to my wording they would
have edited a correct table. ⭐ Re-deriving beat the dispatch note. - The card's own wording corrected. "kebab-case" is the shape of the plain names, not
the rule: 28 of 57 registered names carry a namespace prefix and four are snake_case
after the colon (record:related_list,record:line_items,record:quick_actions,
record:reference_rail). Documenting "kebab-case" alone would have sent an author to
record:related-list— this card's own defect in a new direction. The page says
registered type names, written verbatim, with kebab-case named as the shape and
<record:related_list>shown. ⛔ A dev implementing the card's literal words would have
shipped a second trap. - A2.2 HELD and is now measured — the empirical probe (
compile()against the real
57-component manifest) reproduces the reporter's symptom exactly:ListView→ListView is not an allowed component,list-view→ accepted. - A2.3 HELD — one paragraph plus a scoping clause; no restructure.
Gates
25 GREEN / 0 RED / 1 NOT MEASURED at the final commit
6c5a1a754, family list re-derived
after the commit. NOT MEASURED isscripts/check-test-completeness.mjs(exit 3,
PREREQUISITE NOT MET— it grades a savedturbo run testlog no local run produced, and
its own text says to record it as NOT MEASURED). ⭐ Three gates that first returned
PREREQUISITE NOT MET for unbuilt packages were built and re-run to green, not counted
as findings. Declared narrowing on repo-wide ESLint is measured, not asserted: the path is
outside ESLint's configured set (File ignored because no matching configuration was supplied), the diff touches no ESLint config, and no type-aware linting is involved.skip-changesetis correct and consistent with recentcontent/docs/**-only merges.The two follow-ups this card generated — both filed, ⛔ neither ridden into this PR
- docs: react-pages.md states only the react tier's PascalCase tag rule, so html-tier authors copy a spelling the parser rejects objectui#7006 — the same trap on
content/docs/guide/react-pages.md
in the sibling repo. Triage's first-touch reserved this for the PM ("a cross-repo docs
follow-up card is the PM's to file, not a rider") and the dev correctly handed it up with
evidence instead of filing or fixing it. Verified independently by this seat against
objectui'sorigin/main, and duplicate-checked across 271 open issues there. - [finding] react-pages.mdx is the docs home for both source-authoring tiers, but every section below the security gate is unmarked react-only material #13737 (
finding) — the page is the docs home for both tiers per three
pages.mdxlink sites, yet all 11 sections below the security gate are unmarked
react-only material (## record:* blocks are not in this tieris the sharpest instance).
That is a docs-architecture question with more than one defensible answer, so it is filed
for grading, ⛔ not dispatched.
objectstack-ai/objectui#6598(html-tiercolumnsbinding) is untouched and unpapered-over,
as triage required.Disposition
⛔ Not governed surface (one
content/docs/**file) and no clause ② limb — no path hit, no
Clause-②: yesdeclaration, noneeds:contract-reviewon the card. Arming as soon as the
six pending checks settle green;Fixes #12650closes this card on merge.
Generated by Claude Code
- A2.1 falsified in form. My dispatch said "the page's table shows PascalCase".
Docs-clarity finding from promo-video production recon (internal ref: steedos-labs/video-studio#61). Not claiming; filing for triage.
Observed (17.1.0, hotcrm dev)
In a
kind: 'html'page,<list-view>works but<ListView>fails to compile withis not an allowed component. The PascalCase component table incontent/docs/ui/react-pages.mdxis the react-tier convention; the html-tier section never states that html pages must use the kebab-case registered type names instead.Why it matters
An author (human or AI) reading the docs' component table and then writing an html-tier page will naturally copy the PascalCase names and hit a compile error with no pointer to the naming rule. Since the html tier is explicitly positioned for AI-drafted pages, the docs are effectively the AI's prompt — one sentence in the html section ("use registered kebab-case names, e.g.
<list-view>; PascalCase applies to react pages") would remove the trap.