Skip to content

fix(spec): the @module marker line is machinery, not the opening line of a reference page - #14464

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-13796-module-tag-line-render
Sep 2, 2026
Merged

fix(spec): the @module marker line is machinery, not the opening line of a reference page#14464
os-zhuang merged 2 commits into
mainfrom
claude/issue-13796-module-tag-line-render

Conversation

@claude

@claude claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #13796

The @module PATH tag tells findModuleDocBlock which doc block describes the
module. It is machinery for the selector — but renderFileDescription emitted
it like any other prose line, so it became the opening line of every published
reference page whose source carries it. content/docs/references/ui/sharing.mdx
opened on the literal text @module ui/sharing instead of on
Sharing & Embedding Protocol.

Emit site

packages/spec/scripts/lib/file-description.ts, in renderFileDescription — the
prose-line filter applied to the gutter-stripped block before the render
classification. Selection is untouched: findModuleDocBlock and
hasModuleMarker still read the marker, and the marker stays in the source.

Mechanism mirrored, not invented

The same function already drops one machinery line at exactly this point: the
check:skill-examples opt-in marker (SKILL_EXAMPLE_MARKER). This adds
MODULE_MARKER beside it and routes both through one isMarkerLine predicate, so
there is one convention and one call site, not two. The sibling surface has never
had the defect — packages/spec/scripts/build-skill-references.ts filters
@-opening lines before taking a module's one-line description, which is why the
skill index already reads Sharing & Embedding Protocol for the same file.

The marker is judged with the same untrimmed ^@module\b test the selector
uses, and only on lines classified as prose, so a mid-sentence mention and one
shown inside a fenced example both survive.

Scope: @module only, deliberately

Not ^@\w+ at large. The two other block tags that reach a page carry a payload
a reader needs — @example Basic field mapping is the caption of the fence
beneath it, @category Security is a classification — so a blanket line-drop
would take that prose off the page, which is the one thing this fix may not do.
@see shows the shape those two want instead: renderProse rewrites it into
See also: … rather than dropping it. Those two leaks are filed separately as
#14455 (not addressed here).

Page count, before and after

The issue body says 16 pages; the measured number on origin/main is 14.

# before
grep -rn '^@module' content/docs/references/ | wc -l   ->  14
# regenerate
pnpm --filter @objectstack/spec run gen:schema   # json-schema/ is gitignored; gen:docs refuses without it
pnpm --filter @objectstack/spec run gen:docs
# after
grep -rn '^@module' content/docs/references/ | wc -l   ->   0

The two-page delta is not a page that kept the marker: 16 spec sources carry the
tag, and two of them — shared/retry-policy.zod.ts and
shared/metadata-collection.zod.ts — publish no reference page at all, so they
never leaked and nothing about them changes here.

Every changed page is 0 added, 2 deleted — the marker line and the blank
line under it — and the union of all removed lines across the 14 pages is exactly
the 14 @module lines, with zero added lines. No page loses non-tag prose:

git diff --numstat -- content/docs/references/    # 14 files, each 0 / 2
git diff -U0 -- content/docs/references/ | grep -E '^\+[^+]'   # empty

shared/mapping and system/cache are on the list because PR #13794 added the
marker to those two sources; the other twelve carried it already.

Tests

packages/spec/scripts/file-description.test.ts — a unit block pinning both
halves together (selection still reads the marker, the page never shows it), the
bare @module with no path, the fenced and mid-sentence negatives, and a scope
case asserting @example / @category survive; plus a corpus invariant
re-derived from the real packages/spec/src tree, so a source that acquires the
marker tomorrow cannot re-acquire the defect with it.

Reverse verification (renderer reverted to its pre-fix bytes from HEAD~1,
mutation confirmed on disk by blob hash before the run, restored by
git checkout HEAD -- PATH and confirmed byte-identical afterwards): 4 failed,
89 passed
— the three drop-asserting unit cases and the corpus invariant, with
the two scope negatives green in both legs by design. Restored: 93 passed.

Gates

Derived union at b0e155aa7node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack,
63 commands, all run:

  • 57 green, including check:docs (229 generated files in sync),
    check:generated (all 15 artifacts up to date), check:skill-refs,
    check:docs-single-h1, check:doc-anchors, check:corpus-claim-drift,
    check:cross-package-test-inputs, check:test-source-alias,
    check:empty-changeset.
  • check:skill-examples needed @objectstack/client-react built first; with the
    closure built it is green — 263 prose examples type-check across 3 surfaces.
  • 5 gates return their own exit code 3 (NOT MEASURED, closure not built here, not
    a finding): check-test-completeness, check:doc-formula-expressions,
    check:doc-security-posture, check:dual-build-cjs-loads,
    check:type-check-debt. check-dev-prereqs exits 1 for the same reason and
    says so in its own words ("1 unmet precondition, not a list of problems").
  • pnpm --filter @objectstack/spec typecheck green, and --listFiles confirms
    its program really includes both edited files.

An earlier check:generated run reported api-surface/ stale; that was the
phantom the gate itself warns about (it reads a dist that did not exist yet in a
fresh worktree). Re-run after pnpm --filter @objectstack/spec build: green.

Changeset

A @objectstack/spec patch changeset, not the skip-changeset label — matching
PR #13794, the immediate predecessor on this same file, which shipped the same
"no schema behavior changes" shape with a patch changeset.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21


Generated by Claude Code

The `@module <path>` tag selects a module's doc block (#13334) but is
machinery for the selector, not prose. `renderFileDescription` emitted it
verbatim, so fourteen published reference pages opened on the literal text
`@module ui/sharing` instead of on their first sentence. `check:docs` could
not see it: it compares the artifact against the source, and the artifact
reproduced the marker faithfully.

Mirrors the existing `os:check` marker drop in the same function — a
prose-level filter applied before the render classification — rather than
inventing a second convention, and matches the filter
`build-skill-references.ts` has always had on the skill-index surface. The
marker stays in the source and `findModuleDocBlock` still reads it.

Scope is `@module` alone, not `^@\w+`: `@example <caption>` and
`@category <value>` carry prose a line-drop would take off the page.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
`pnpm --filter @objectstack/spec gen:docs` after the renderer fix. Every page
loses exactly two lines — its `@module <path>` marker and the blank line under
it — and none gains any, so no page loses prose.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDA48PuRFrHyRfdkBz8m21
@github-actions github-actions Bot added the size/m label Sep 2, 2026
@github-actions

github-actions Bot commented Sep 2, 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 1d8ad0ffe51caae6892ccece9f8abad9794ac545packageMentionDocs.

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Sep 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 08:30
@os-zhuang
os-zhuang enabled auto-merge September 2, 2026 08:30
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 2, 2026
Merged via the queue into main with commit e5812fa Sep 2, 2026
36 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-13796-module-tag-line-render branch September 2, 2026 09:04
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