Skip to content

fix(spec): render @example captions and drop @category on reference pages - #15443

Merged
os-sales merged 4 commits into
mainfrom
claude/issue-14455-doc-tag-payload-render
Sep 4, 2026
Merged

fix(spec): render @example captions and drop @category on reference pages#15443
os-sales merged 4 commits into
mainfrom
claude/issue-14455-doc-tag-payload-render

Conversation

@claude

@claude claude Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Fixes #14455

A module docblock is JSDoc, so its header carries block tags, and renderFileDescription emitted a tag written on a prose line verbatim. 18 such lines reached 14 customer-facing reference pages. #13796 removed @module and deliberately left these two open, because a blanket ^@\w+ line filter would take reader prose off the page and orphan the fences below it.

The verdict is per tag, and the axis is the payload

tag lines / pages verdict why
@example CAPTION 12 / 10 rewritten to **CAPTION** the caption of the block directly beneath it — the shape @see beside it already had
@example bare 2 / 2 dropped no payload at all, which is the @module case exactly
@category VALUE 4 / 4 dropped a payload with no consumer anywhere in the repo

Bold rather than a heading. withHeadingsAtSectionLevel has already renumbered the block by the time the rewrite runs, so a heading emitted here would carry a level chosen blind of the page and would not move with the rest — on top of adding 12 entries to 8 pages' tables of contents and putting a caption in reach of check:docs-single-h1. Strong emphasis cannot touch a page's heading structure at all.

Bold rather than Example: CAPTION, the literal parallel of See also:. @see needs its label because a bare URL says nothing about why it is on the page; a fenced block under a caption is already visibly an example, so the label only restates the fence (Example: Endpoints).

@category is a seat ruling, and it rests on a measurement rather than on taste. Nothing in this repo reads the tag: no typedoc or api-extractor (neither is used here), no search index, no gate — the only matches outside packages/spec/src were the pin that asserted the defect, the renderer's own comment, and a CHANGELOG line. Four pages, one value (Security), under a system/ section that already says as much. Routing it into page frontmatter instead would publish a field with no consumer, which is the declared-but-unenforced shape ADR-0049 refuses. It is dropped from the rendered PAGE only — @category stays in the source, where it is a legitimate JSDoc tag, and the day something reads it, CATEGORY_MARKER is what gets revisited rather than the four docblocks.

Measurements

The card's own repro, re-run before editing (the card's counts were from 2026-09-02): unchanged at 18 lines — grep -rn '^@example\|^@category' content/docs/references/ gave 14 + 4, the identical set. It now returns zero. One correction: the card and its title say 13 pages; the two disjoint sets are 10 + 4, so the real figure is 14.

Blast radius. The renderer moves, so gen:docs regenerates corpus-wide: 230 files regenerated, exactly 14 changed — the 14 the repro names and no others. The whole corpus diff is 12 line rewrites and 6 deletions, every one of them one of the 18 lines. No page moved for an unrelated reason.

Reverse verification. Restoring origin/main's file-description.ts and re-running turns 8 cases red: 5 of the 7 new unit cases, both new corpus assertions, and the retriaged #10924 case. The two that stay green assert the ABSENCE of over-reach (a tag inside a fence, a mid-sentence mention), which the pre-fix renderer also satisfied by doing nothing — the asymmetry is the point, and those two are guards against a future over-broad filter rather than against the old state. No dist is involved in either leg: the test imports ./lib/file-description by relative path inside the same package, so there is nothing to rebuild between them. The mutation was confirmed on disk by blob hash (differs from the HEAD blob, and EXAMPLE_CAPTION / CATEGORY_MARKER both at 0 occurrences); the restore by hash equality with the HEAD blob plus an empty git diff HEAD on the path.

Two fixtures were retriaged, not re-spelled

Both pinned the branch this card removes, and both kept passing precisely because the tag was still being published:

  • #13796leaves every other block tag alone asserted @example Basic field mapping and @category Security reached the page. Rewritten to assert what #13796 actually owns — its drop is scoped to its own tag and the caption prose beside it is not collateral.
  • #10924drops a marker line above a fence asserted the bare @example above the os:check marker survived. Rewritten to assert the fence attaches directly to the prose above it, with the reason for the flip named in place.

Pins

Assert on the rendered fragment, never on the emitted .mdx: check:docs compares the artifact against the source and reproduced all 18 tag lines faithfully, so it was green through every one of them. Two corpus assertions re-derive from the real packages/spec/src tree — an invariant (no rendered line opens with either tag) plus its necessary other half (every @example caption still reaches its page, so a fix that got the partition backwards cannot pass by deleting the prose), with a vacuity guard on the caption count.

Verification

Union re-run on the final head 954d10c76, after merging main through scripts/pm/os-regen-merge.sh and re-regenerating the whole chain (regeneration came back byte-identical, so nothing was silently dropped by the os-regen merge driver).

  • pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2470 files / 12,649 tests passed, 1 skipped, 0 failed
  • pnpm --filter @objectstack/spec typecheck — exit 0. tsconfig.scripts.json verifiably reads both edited files (--listFiles counts 1 each, not 0), so the green verdict covers them
  • pnpm lint (repo-wide eslint . --no-inline-config) — exit 0
  • pnpm --filter @objectstack/spec check:docs230 generated files in sync with packages/spec
  • gate family re-derived from the real changeset with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (17 paths, unchanged across the merge); the implicated families all exit 0: check:skill-refs · check:skill-docs · check:docs-single-h1 · check:doc-anchors · check:doc-authoring · check:docs-redirects · check:corpus-claim-drift · check:quick-reference-counts · check:page-declaration-shape · check:docs-audit-scope · check:nul-bytes · check:cross-package-test-inputs · check:test-source-alias · check:changeset-gate-self-tests · check:published-files

Out of scope

Filed separately as #15440: api/automation-api and api/package-api write their endpoint listing unfenced, so it publishes as a run-on paragraph. This card rewrites the caption line above those listings and deliberately does not touch what is beneath it; the fix belongs in the two sources.

🤖 Generated with Claude Code

https://claude.ai/code/session_01G4138K1EG7kQ81FNba5Kp4


Generated by Claude Code

…ce pages

`renderFileDescription` emitted a module docblock's prose verbatim, so a
JSDoc block tag written on a prose line reached the published page as
literal tag text: 18 lines across 14 customer-facing reference pages.

The verdict is per tag, on the payload rather than the spelling:

- `@example CAPTION` (12 lines, 10 pages) captions the block directly
  beneath it, so it is REWRITTEN into that caption in bold — the shape
  `@see` beside it already had.
- a bare `@example` (2 lines) has no payload, which is the `@module`
  case exactly, so it is DROPPED before classification alongside the
  `os:check` marker it sits against.
- `@category Security` (4 lines, 4 pages) is dropped. Measured: one
  value on four pages, and no consumer anywhere in the repo — no
  typedoc, no api-extractor, no search index, no gate.

Pins assert on the rendered fragment, never on the emitted `.mdx`:
`check:docs` compares the artifact to the source and reproduced all 18
tag lines faithfully.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G4138K1EG7kQ81FNba5Kp4
18 tag lines across 14 pages: 12 `@example CAPTION` become bold
captions, 2 bare `@example` and 4 `@category Security` come off.
The card's own repro (`grep -rn '^@example\|^@category'
content/docs/references/`) now returns zero, and no other page in the
230-file regeneration moved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G4138K1EG7kQ81FNba5Kp4
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Sep 4, 2026
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json a256cd45fbb0c1badf6bc3725b87550e018c804epackageMentionDocs.

@os-sales
os-sales marked this pull request as ready for review September 4, 2026 16:20
@os-sales
os-sales enabled auto-merge September 4, 2026 16:20
@os-sales
os-sales added this pull request to the merge queue Sep 4, 2026
Merged via the queue into main with commit 0db2947 Sep 4, 2026
36 checks passed
@os-sales
os-sales deleted the claude/issue-14455-doc-tag-payload-render branch September 4, 2026 16:48
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/m tests tooling

Projects

None yet

2 participants