Uh oh!
There was an error while loading. Please reload this page.
fix(spec): stop emitting meta.json for a reference category with no pages (#7303) - #7622
Merged
Merged
Conversation
…ages (#7303) `gen:docs` wrote `content/docs/references/<category>/meta.json` for every category it iterated, including one whose page list came out empty. The result was a directory holding a single `{ "title": …, "pages": [] }` and nothing else: no reference page, no `index.mdx` (§2.5 already skipped that), and no entry in the root `meta.json`, so the route could not resolve and the link checker never saw it. Its one measurable effect was on whoever enumerated the tree — human or agent — who counted one category more than the docs publish. That is exactly how #7303 came to be filed. `contracts/` was the standing case: it holds TypeScript service interfaces rather than `.zod.ts` schemas, so `gen:schema` creates `json-schema/contracts/` and leaves it empty. `conversions`/`migrations` have no schema directory at all and `groupSchemasByPage` skips them outright, while `contracts` fell through to the emit with zero pages. The `meta.json` emit is now guarded on the page list being non-empty, mirroring the guard the category `index.mdx` emit already carries, so all three now emit nothing and produce no directory. The guard is on the page count, not on that schema-directory asymmetry, so a future category in either shape lands the same way. The directory is generated output (`content/docs/references/**` is routed `merge=os-regen`), so it is removed here as the generator's output rather than by hand: a hand delete alone reds `check:docs` with `+ .../contracts/meta.json (missing — spec adds it)` and the next `gen:docs` restores it byte-for-byte. The emitted file count goes 231 → 230 and `content/docs/references/` goes from 15 category directories to 14. `contracts/` is not `manageDir`'d (it has no JSON Schema to regenerate from, so step 1 returns before claiming it), which is why the generator cannot delete the file it no longer writes and the tracked copy is dropped in this commit. `contracts` stays declared in `scripts/lib/category-title.ts`: measured, not assumed — `resolveCategoryTitles` is total over the directories under `packages/spec/src/`, and removing the declaration stops the build while the module's 84 source files exist. Also drops the now-stale `contracts` row from the quick-reference Categories-Without-a-Section table (leaving it reds `check:quick-reference-counts` with "`contracts` is declared as having no section, but content/docs/references/contracts/ does not exist") and the same category from that gate's docblock prose. The Contracts Protocol pages themselves are untouched — they live at `content/docs/kernel/contracts/`. Fixes#7303 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Mqbd23qE51QfBjgJv3Zsp
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckNo hand-written docs reference the 0 changed package(s). ✅ |
os-help
marked this pull request as ready for review
August 11, 2026 09:41
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#7303
What
gen:docswrotecontent/docs/references/<category>/meta.jsonfor every category it iterated, including one whose page list came out empty. The result was a directory holding a single{ "title": …, "pages": [] }and nothing else: no reference page, noindex.mdx(§2.5 already skipped that), and no entry in the rootmeta.json— so the route could not resolve and the link checker never saw it. Its one measurable effect was on whoever enumerated the tree, human or agent, who counted one category more than the docs publish. Which is exactly how #7303 came to be filed.The
meta.jsonemit is now guarded on the page list being non-empty, mirroring the guard the categoryindex.mdxemit already carries.content/docs/references/: 15 category directories → 14. Emitted files: 231 → 230.Why the delete happens at the generator
content/docs/references/**is routedmerge=os-regen— the repo's own declaration that the tree is generated output. A hand delete reds the gate and the next regeneration undoes it, measured twice before this PR:That is also this PR's positive control that the gate can see the file at all.
contractsis the standing caseIt holds TypeScript service interfaces rather than
.zod.tsschemas, sogen:schemacreatespackages/spec/json-schema/contracts/and leaves it empty.conversions/migrationshave no schema directory at all andgroupSchemasByPageskips them outright;contractsfell through to the emit with zero pages. All three now emit nothing and produce no directory:The
⚠ Skipping clean of contracts/ …warning that every build printed is gone too.The guard is on the page count, not on that schema-directory asymmetry, so a future category in either shape lands the same way.
One mechanical note worth a reviewer's eye
contracts/is notmanageDir'd — step 1 returns before claiming it, because it has no JSON Schema to regenerate from. So the generator cannot delete the file it no longer writes, and the tracked copy is dropped in this commit as the one-time reconciliation. The removal is durable because the guard exists:gen:docswas run four times after the guard landed and the directory never came back, andcheck:docsis green at 230 files.category-title.ts— measured, not assumedcontracts: 'Contracts Protocol'stays.resolveCategoryTitlesis total over the directories underpackages/spec/src/, andpackages/spec/src/contracts/has 84 live source files. Removing the declaration was tested and is build-stopping:conversionsis the in-repo precedent: declared, emits nothing, and that is the supported steady state.contractsis a declared category with 84 live source files, and that emptymeta.jsonwas the only committed trace in the docs tree that the category exists. After this change the references tree silently stops representing it. That is the ruled outcome. The Contracts Protocol prose documentation is unaffected — it lives atcontent/docs/kernel/contracts/(7 files) and is not generated from this tree.Also changed
contractsrow in the quick-reference Categories Without a Section table, plus the sentence above it ("two more category directories" → "one more"). Reverse-controlled: leaving the row in place reds the gate with[coverage] `contracts` is declared as having no section, but content/docs/references/contracts/ does not exist.scripts/check-quick-reference-counts.mjs's docblock prose, which would otherwise state something now false. The gate's syntheticGOOD_CATALOG/GOOD_PAGEself-test fixtures are untouched — they do not read the real tree and still exercise a reachable parse case.Gates run (with invocation scope)
pnpm --filter @objectstack/spec check:docspnpm --filter @objectstack/spec gen:docs×4pnpm --filter @objectstack/spec testpnpm --filter @objectstack/spec typecheckcheck:scripts-typecheck,check:test-typecheck)pnpm run check:quick-reference-countspnpm run check:doc-authoringpnpm run check:docs-audit-scopepnpm run check:empty-changesetpnpm run check:nul-bytespnpm run check:adr-anchors/check:adr-linksnpx eslinton the two touched sourcesChangeset included (
@objectstack/spec: patch).Not verified
No heading or link fragment was touched, so no
github-sluggercheck was needed. The docs site was not booted — this PR changes no published page. CI has not been consulted; that is the PM's.Generated by Claude Code