Skip to content

fix(docs): resync content manifest with meta.json and guard the IA against drift#316

Merged
rejifald merged 1 commit into
mainfrom
claude/zealous-mclaren-6a2112
Jun 21, 2026
Merged

fix(docs): resync content manifest with meta.json and guard the IA against drift#316
rejifald merged 1 commit into
mainfrom
claude/zealous-mclaren-6a2112

Conversation

@rejifald

Copy link
Copy Markdown
Owner

Why

apps/docs/content.manifest.ts is the source of truth for the docs sidebar IA, but pages had been added straight into the per-folder meta.json files for months, so the manifest silently rotted. gen:docs is manual (not wired into CI), so the drift never fired — but running it on a clean tree would have silently deleted real, committed pages from the sidebars:

  • the entire recipes/ section (15 .mdx + its meta.json)
  • the guides/testing/ section
  • the root meta.json description
  • agents/adopt-in-your-project, guides/authoring/hooks, guides/data/url-shaping, guides/resilience/accept-status, reference/surfaces, reference/conformance-kits

Root cause: the manifest header claimed "a test will enforce" two-way sync, but no such test was ever written.

What

Re-sync the manifest so the generator reproduces the committed meta.json files byte-for-byte:

  • Added the recipes and guides/testing sections, the root description, and the six dropped pages. Descriptions are the real frontmatter sentences.
  • Added HAND_MAINTAINED_SECTIONS (single-sourced in the manifest, consumed by both the generator and the test). integrations is excluded — its 24 pages are added per-PR as each @stitchapi/* package ships, so it curates its own meta.json; the generator skips it but keeps its sidebar slot.
  • Gave the generator a Prettier-stable meta.json serializer (objects break; the pages array stays inline when it fits in 80 cols, else one item per line) so codegen output matches the committed, Prettier-governed files exactly. Exported the pure helpers and gated the FS work behind a direct-run check.

Lock the door so it can't rot again:

  • apps/docs/test/content-manifest.spec.ts (vitest) — the two-way-sync test the header always promised: fails when any .mdx under content/docs is absent from the manifest or vice versa, plus a formatting-independent "committed meta.json matches the manifest" check. Hand-maintained sections are exempted. Wired vitest into apps/docs (test script + devDep).
  • CI gate in verify.yml (mirrors the existing gen:completions pattern): re-runs gen:docs then git diff --exit-code apps/docs/content/docs, so byte-level drift fails the build.
  • Documented the hand-maintained exception in AUTHORING.md.

Verification

  • pnpm gen:docs then git diff apps/docs/content/docsempty
  • pnpm --filter @stitchapi/docs test → 7 passing; a stray .mdx makes it fail with an actionable message, removing it restores green (negative-tested) ✅
  • check:format, eslint, tsc --noEmit (full check:types) all clean ✅

🤖 Generated with Claude Code

…ainst drift

`content.manifest.ts` is the source of truth for the docs sidebar, but pages
were added straight into the per-folder `meta.json` files for months, so the
manifest silently rotted. `gen:docs` is manual (not wired into CI), so the drift
never fired — but running it would have SILENTLY DELETED real, committed pages
(the whole `recipes/` section, `guides/testing/`, the root `description`, and
six individual pages) from the sidebars.

This makes the generator reproduce the committed `meta.json` byte-for-byte again,
then locks the door so it can't rot:

- Re-sync the manifest: add the `recipes` section (15 pages), the `guides/testing`
  section, the root `description`, and the dropped pages (`agents/adopt-in-your-
  project`, `guides/authoring/hooks`, `guides/data/url-shaping`, `guides/
  resilience/accept-status`, `reference/surfaces`, `reference/conformance-kits`).
  Descriptions are the real frontmatter sentences, not placeholders.
- Add `HAND_MAINTAINED_SECTIONS` (single-sourced in the manifest, consumed by the
  generator and the test). `integrations` joins it: its 24 pages are added per-PR
  as each `@stitchapi/*` package ships, so it curates its own `meta.json` and the
  generator skips it while keeping its sidebar slot.
- Give the generator a Prettier-stable `meta.json` serializer (objects break, the
  `pages` array stays inline when it fits in 80 cols) so codegen output matches
  the committed, Prettier-governed files exactly — `gen:docs` is now a true no-op
  on a synced tree. Export the pure helpers and run the FS work only when the file
  is executed directly.
- Write the two-way-sync test the manifest header always promised but never had
  (`apps/docs/test/content-manifest.spec.ts`, vitest): fails when any `.mdx`
  under `content/docs` is missing from the manifest or vice versa, with the
  hand-maintained exemption. Wire vitest into `apps/docs`.
- Add a CI gate (mirrors the `gen:completions` pattern): re-run `gen:docs` and
  `git diff --exit-code apps/docs/content/docs`, so byte-level drift fails the
  build instead of waiting for someone to run the generator by hand.

After this, `pnpm gen:docs` followed by `git diff apps/docs/content/docs` is empty.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rejifald rejifald merged commit eab7704 into main Jun 21, 2026
9 checks passed
@rejifald rejifald deleted the claude/zealous-mclaren-6a2112 branch June 21, 2026 11:46
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