Skip to content

feat: generate a docs page per JSON Schema#10

Open
MentorFilou wants to merge 1 commit into
mainfrom
feat/schema-docs
Open

feat: generate a docs page per JSON Schema#10
MentorFilou wants to merge 1 commit into
mainfrom
feat/schema-docs

Conversation

@MentorFilou

Copy link
Copy Markdown
Member

Generates a human-readable reference page per schema from the files #9 serves, so the page and the machine-readable artifact cannot disagree — same bytes, same release checkout.

Based on feat/serve-schemas (#9), so the diff here is the generation only. GitHub retargets this to main automatically once #9 merges. No rush on this one — #9 is the part worth merging quickly.

What lands

URL What
/docs/schemas/report-json/ generated reference, one version shown at a time

Plus a "Schemas" group in the docs sidebar and a version picker on the title line.

Decisions worth reviewing

The renderer fails loudly. An unrecognized keyword aborts the build naming its JSON pointer (#/$defs/item/properties/tags/maxItems) rather than rendering a page that silently drops a constraint. Extending KNOWN_KEYWORDS in src/schema-doc.mjs means deciding how the new constraint displays — it should not be widened just to get a build green.

Conditionals are resolved, not dropped. The top-level allOf is walked alongside the base schema by instance location, so then.required: ["forwards"] annotates the top-level table and then.properties.items.items.required: ["wantedBy"] resolves through the element $ref and annotates the item definition. Both render as Required when mode is "rich" instead of a misleading Optional.

Page URL is format-qualified (report-json, not report), so a future v1.xml gets its own page instead of fighting over one URL.

A format we cannot render is still served. Only JSON gets a page; anything else is published and warns, rather than vanishing silently.

The version picker is JS-only. layout.mjs marks the document scripted before first paint, so the control is styled away without scripting and the version filtering never flashes in.

Verified locally

  • the full dist/ built from this branch is byte-identical to the build from the original combined branch (diff -r), so the split changed no output
  • the top-level field list on /docs/schemas/report-json/ matches the schema's required array, with forwards correctly shown as rich-mode-conditional
  • every on-page #anchor resolves to a heading that exists
  • strictness and version selection covered by a throwaway harness (12 cases): unknown keywords at root / in $defs / in a property / in a then-branch each report their pointer; unresolvable and remote $ref fail; allOf without if/then fails; v10 sorts above v9
  • without schemas/ upstream: warns, skips, builds 13 pages as before

Sequencing

Supersedes the documentation half of #8. schemas/ is not in a flashtrace release yet, so this stays dormant until a release ships it.

🤖 Generated with Claude Code

Renders /docs/schemas/<name>-<format>/ from the served schema files, so
the human-readable reference and the machine-readable artifact cannot
drift - they are the same bytes from the same release checkout.

The renderer fails loudly: an unrecognized keyword aborts the build
naming its JSON pointer rather than rendering a page that silently drops
a constraint. Conditionals are resolved rather than dropped, so a
top-level allOf/if/then annotates fields as conditionally required
instead of misreporting them as optional.

A version picker on the title line shows one version at a time, driven
by a JS-only control that is styled away when scripting is off.

Formats other than JSON are still served, just without a page, and the
build says so rather than letting them vanish.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
MentorFilou added a commit that referenced this pull request Jul 20, 2026
Every version entry carried the parsed document alongside its bytes, and
nothing in this PR read it - the site serves bytes and never a
re-serialisation.

The parse itself stays: it is what catches a release shipping a schema
that will not parse, and that check is the reason the URL can be treated
as a contract. Only the result is discarded, so there is no second
representation of a schema able to drift from the one being served.

Note for #10, which is stacked on this branch: src/schema-doc.mjs reads
versions[].json to render its page. It should parse the bytes where it
needs the document, keeping the parsed form local to the consumer that
wants it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Base automatically changed from feat/serve-schemas to main July 21, 2026 13:32
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