Skip to content

test(website): guard the mechanical MDX authoring rules the audit fixed by hand - #1061

Merged
blove merged 4 commits into
mainfrom
blove/docs-content-guards
Sep 8, 2026
Merged

test(website): guard the mechanical MDX authoring rules the audit fixed by hand#1061
blove merged 4 commits into
mainfrom
blove/docs-content-guards

Conversation

@blove

@blove blove commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Yesterday's accuracy audit fixed roughly 160 wrong claims across 89 docs pages. Several of those defect classes are mechanical: the page still renders, it just renders wrong, and nothing in the build notices. This adds one guard spec that walks the MDX tree and fails with the offending path:line.

The guard — apps/website/src/lib/docs-content-rules.spec.ts

  1. No icon prop on Card. Card rendered {icon} straight into a div with no lookup, so icon="rocket" printed the word "rocket" above the title. Scans all of content/**.
  2. Every docs page declares a usable description. A page with none falls through to the first-paragraph heuristic and then to the library blurb, so unrelated pages ship identical meta descriptions. The bound is META_DESCRIPTION_MAX imported from site-metadata, asserted as clampMetaDescription(d) === d, so the rule tracks the code instead of a magic number.
  3. Callout type must be one of the component's union. type="note" renders an empty icon and an unstyled band. The allowed set is parsed out of Callout.tsx, with a canary assertion so a parse failure fails loudly rather than allowing everything.
  4. No contractions in docs prose. The patterns match no possessive: the 's pattern is a closed list of pronouns and determiners, and the others end in suffixes (n't, 're, 've, 'll, 'm, 'd) no possessive uses. ## What's Next is exempt structurally — a heading test, not a file list. Fenced blocks, inline code spans, and MDX comments are blanked out with line numbers preserved. The current tree needed zero exceptions.

Each detector also has a unit test over synthetic content, so a rule that quietly stops firing fails instead of passing vacuously.

Two real defects the guard surfaced

The frontmatter description parser could not read an apostrophe. FRONTMATTER_DESCRIPTION_PATTERN captured [^'"\n]+?, which excluded every quote character, so any description containing a possessive never matched. Nine pages declared a description and silently shipped the first-paragraph fallback. Fixed by capturing the value whole and stripping only a matched pair of surrounding quotes, with a failing-first test in docs.spec.ts.

Nine more descriptions ran past the clamp and were truncated mid-sentence by clampMetaDescription() (META_DESCRIPTION_MAX is 160, not the 180 in the follow-up note). Trimmed each to say the same thing in under 160.

Also deleted: the dead icon prop on Card, its .mdx-card-icon rule, and the four glyph icons the two interrupt blog posts passed. The cards keep their title and arrow.

Mutation evidence

Each rule was broken in the real content tree, the spec re-run, and the mutation reverted:

mutation result
icon="rocket" on a Card in langgraph/getting-started/introduction.mdx FAIL — passes no icon prop to Card
description: line deleted from chat/guides/theming.mdx FAIL — gives every docs page its own frontmatter description
same description padded past the clamp FAIL — gives every docs page its own frontmatter description
<Callout type="info">type="note" FAIL — uses only Callout types the component styles
"The token doesn't apply and you're done." inserted as prose FAIL — writes docs prose without contractions
reverted tree green

The docs.ts parser fix was likewise written failing-first: both new docs.spec.ts tests failed before the pattern change and pass after.

Verification

  • npx vitest run --root apps/website --reporter=dot — 138 files, 1394 tests, all green
  • npx nx run-many -t lint,test --projects=website --skip-nx-cache — success; lint reports 0 errors (65 pre-existing warnings)
  • GROWTH_FORM_POLICY=growth_v1 npx nx build website — success

🤖 Generated with Claude Code

@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
threadplane Ready Ready Preview Sep 8, 2026 3:50pm UTC

Request Review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval: this PR received an intelligent (AI) code review. See the review comments on this PR.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

blove and others added 4 commits September 8, 2026 08:46
The description value pattern excluded every quote character, so any
`description:` holding a possessive never matched. Nine docs pages
declared a description and silently shipped the first-paragraph fallback
instead. Capture the value whole and strip only a matched pair of
surrounding quotes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`Card` rendered `{icon}` straight into a div, so `icon="rocket"` printed
the word "rocket" above the title. Nothing looked the value up. Remove
the prop, its `.mdx-card-icon` rule, and the four glyph icons the two
interrupt blog posts passed; the cards keep their title and arrow.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nine descriptions ran past META_DESCRIPTION_MAX and were truncated
mid-sentence by clampMetaDescription(). Trim each to say the same thing
in under 160 characters.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The accuracy audit fixed roughly 160 wrong claims by hand; several of the
defect classes render fine and return silently. Walk `content/**` and
fail with the offending `path:line` when a page:

- passes an `icon` prop to `Card`, which does not accept one;
- (docs only) declares no frontmatter `description`, or one long enough
  that `clampMetaDescription()` truncates it;
- gives `Callout` a `type` outside the union, read out of Callout.tsx so
  the guard cannot drift from the component;
- (docs only) uses a contraction. The patterns match no possessive, and
  the `## What's Next` heading is exempt structurally, not by file list.

Each detector also has a unit test over synthetic content, so a rule that
stops firing fails rather than passing vacuously.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@blove
blove force-pushed the blove/docs-content-guards branch from 38e0463 to 5df08b9 Compare September 8, 2026 15:46
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

@blove
blove merged commit 08158e9 into main Sep 8, 2026
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant