Skip to content

docs(ui): name the 5 remaining nameless form sections in content/docs/ui - #10827

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-10709-form-section-name
Aug 21, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/issue-10709-form-section-name

Conversation

@claude

@claude claude Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Fixes #10709

A form section without name has no i18n anchor: the heading resolves through
objects.<object>._sections.<name>.label, so a nameless section renders its authored
label in every locale. This adds the missing name to the section examples under
content/docs/ui/** that still lacked one.

Is name required, or conventional?

Conventional — not schema-required. packages/spec/src/ui/component.zod.ts:825:

name: z.string().optional().describe('Stable section identifier for i18n lookup (snake_case) — resolves `objects.<object>._sections.<name>.label`; a nameless section renders its authored label in every locale'),

So these examples were valid, not invalid — the weaker framing is the correct one.
What nudges authors is packages/lint's translation-section-name-missing
(packages/lint/src/validate-translatable-sections.ts:95), and its severity is
'warning' — "one heading stays in the source locale; nothing breaks".

That also answers why nothing caught these. Two mechanisms could have, and neither can:

  1. The lint rule walks app metadata — collectionEntries, walkPageComponents,
    viewContainerSites. It never sees an .mdx code fence.
  2. {/* os:check */} fences are type-checked against the live spec by
    packages/spec/scripts/check-skill-examples.ts — and forms.mdx's first block is
    marked. But because name is .optional(), a nameless section type-checks clean.

So the docs could drift from the convention indefinitely without a single gate reddening.

The census — re-derived, and it differs from the card

Multi-line-aware: bracket-match each sections: [ … ], split into top-level object
literals, check each for a name key at its own depth-1. (Script:
/tmp/.../issue-10709/census.py, reproduced in the issue report.)

this PR's census card #10709 claimed
pages with a sections: [ array 5 5
section object literals 16 15
nameless before the #10616 sweep (b6bb2ee454^) 8 7
nameless on this PR's base (f4e5d916d6) 5 4

The card undercounted by exactly one, and it is
content/docs/ui/forms.mdx:244 (label: 'About you'). That literal is written
sections: [{ — the opening brace on the same line as the [. The card's scan was
multi-line-aware enough to find the sites its predecessor #10579 missed, but still
required { to start a fresh line, so it reproduced a smaller copy of the same
instrument error it was filed to correct. Per the dispatch ("trust yours and say so"),
this PR fixes five sites, not four.

Per-page, on this PR's base: forms.mdx 3 nameless of 3 · views.mdx 2 of 5 ·
create-vs-edit-form.mdx 0 of 5 · field-grouping-and-order.mdx 0 of 2 ·
public-data-collection.mdx 0 of 1. After: 0 of 16.

(Two further sections: [ arrays in forms.mdx are elided — [/* … */] — and hold no
object literals, so they carry no name to add. Counted as arrays, not as examples.)

Sites, before and after

Site Label Added
forms.mdx:68 Tell us about yourself name: 'about_you'
forms.mdx:244 About you name: 'about_you' ← not in the card's table
forms.mdx:328 Lead name: 'lead'
views.mdx:352 Basic Information name: 'basic_information'
views.mdx:363 Details name: 'details'

Whole diff is +5 lines, 0 deletions.

The naming convention followed

Not invented — read off the 11 already-named sections in these same files. It is
consistent, so there was no dominant form to choose between:

  • snake_case, lowercase, derived from the label
  • placed first in the literal, ahead of label — all 11 do this

The single-word noun labels transliterate directly, which fixes four of the five:
views.mdx:53 { name: 'task', label: 'Task' }, views.mdx:475
name: 'details', label: 'Details' (same file, same spelling this PR gives
views.mdx:363), plus contact/work/status/notes in create-vs-edit-form.mdx:69-72.

The two about_you sites lean on a stronger precedent than convention:
public-data-collection.mdx:24 already carries
{ name: 'about_you', label: 'Tell us about yourself' } — the identical label, for the
same public contact-us form
that forms.mdx:68 documents. That is the sibling
declaration, not a guess.

basic_information is the only judgment call. Rejected: basics, which has real
repo precedent (packages/cli/test/i18n-section-coverage.test.ts:372 uses
{ name: 'basics', label: 'Basic Information' }, and app-showcase has
step_basics/'Basics'). Chosen against because within content/docs/ui/** the
shortening rule applies only to interrogative sentence labels ('Who is this?' → who,
'Tell us about yourself' → about_you); every noun-phrase label transliterates
whole, including the two-word case ('Budget & Schedule' → budget_schedule in
app-showcase). Basic Information is a noun phrase.

Scope

#10579's three sites (views.mdx:53, create-vs-edit-form.mdx:82,
public-data-collection.mdx:24) are untouched — all three were already addressed by the
#10616 sweep (b6bb2ee454) and stay as that card left them. No section that already had a
name is renamed, no example restructured, no surrounding prose edited.

Verification

node scripts/pm/dispatch-gates.mjs (no paths — it derives its own change set) named 14
families for content/docs/ui/{forms,views}.mdx. All 14 run green at 3b9d3ecce1,
the final commit; exit codes captured before any pipe (cmd > file 2>&1; ec=$?):

EXIT=0  pnpm check:cross-package-test-inputs          EXIT=0  pnpm check:published-readme-links
EXIT=0  pnpm check:doc-anchors                        EXIT=0  pnpm check:role-word
EXIT=0  pnpm check:doc-authoring                      EXIT=0  pnpm --filter @objectstack/spec run check:strictness-ledger
EXIT=0  pnpm --filter @objectstack/lint run check:doc-formula-expressions
EXIT=0  pnpm check:docs-audit-scope                   EXIT=0  pnpm --filter @objectstack/spec run check:variant-docs
EXIT=0  pnpm check:docs-redirects                     EXIT=0  node scripts/check-cross-package-test-inputs.mjs
EXIT=0  pnpm --filter @objectstack/spec run check:empty-state
EXIT=0  pnpm --filter @objectstack/spec run check:liveness
EXIT=0  node scripts/check-doc-frontmatter.mjs

check:doc-formula-expressions failed once on first run with
ERR_MODULE_NOT_FOUND: @objectstack/formula/dist/index.mjs — the unbuilt dependency
closure in a fresh worktree, not this change. After
pnpm --filter '@objectstack/lint^...' build it reports
self-test: 30 cases passed and 22 record-scoped formula example(s) across 416 files / 1443 TS blocks judged clean.

No ablation applies — this is docs-only with no guard under test, so there is nothing
to mutate and re-measure. Correctness is carried by the census re-run instead: 5 nameless
before the edit, 0 after, same script, same tree.

Control-character scan of both changed files:
grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' → exit 1, no matches.

skip-changeset: confirmed for the files actually touched, not defaulted —
content/docs/** is consumed only by apps/docs, whose package.json is
"private": true. Nothing publishes.

⚠️ Lint & Repo Gates may be red from scripts/pm/git-history.mjs --self-test (#10807,
patch in flight as #10811) — pre-existing on main, unrelated to this PR.

Generated by Claude Code


Generated by Claude Code

A section without `name` has no i18n anchor: the heading resolves through
`objects.<object>._sections.<name>.label`, so a nameless section renders its
authored label in every locale. `name` is `.optional()` in the schema, so
nothing rejects these — they are valid, just silently un-localizable.

Adds `name` to the five section literals under content/docs/ui/** that still
lacked one, following the convention the already-named examples in these same
files establish: snake_case, derived from the label, placed first in the
literal (ahead of `label`).

  forms.mdx  'Tell us about yourself' -> about_you
  forms.mdx  'About you'              -> about_you
  forms.mdx  'Lead'                   -> lead
  views.mdx  'Basic Information'      -> basic_information
  views.mdx  'Details'                -> details

No section that already had a `name` is renamed, no example restructured, no
surrounding prose touched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DdCnBGcHeufjrq7drTD3wt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[finding] form-section name: the ui/ census is 7 of 15 across 5 pages, not "three of five" — #10579 missed forms.mdx entirely

2 participants