Skip to content

Memoize schema expansion + fix #69/#70 follow-ups (issue #58)#71

Merged
nrynss merged 2 commits into
mainfrom
vibe/fix-schema-memo-5cdff7
Jun 27, 2026
Merged

Memoize schema expansion + fix #69/#70 follow-ups (issue #58)#71
nrynss merged 2 commits into
mainfrom
vibe/fix-schema-memo-5cdff7

Conversation

@nrynss

@nrynss nrynss commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes #58 (schema re-expansion / token bloat) and folds in two follow-ups to the previously merged #69 and #70.

By default at --detail full --include-schemas, component schemas reached through a $ref are now expanded once into a trailing ## Schema Definitions section and linked from every use site ([Name](#schema-name)), instead of being re-inlined at each occurrence. Shared schemas (a common error/envelope, or a type referenced many times) collapse to a single definition, and self/mutual references become links rather than triggering "cycle detected" or deep re-expansion.

--inline-schemas restores the previous fully self-contained behaviour (every $ref expanded inline at each use site, with per-chain cycle detection) for callers who want one copy-pasteable blob.

What changed since the draft

The first commit added ~310 lines of unused, unformatted scaffolding to schema.rs — CI was red on cargo fmt --check and nothing was wired into the render pipeline. That is replaced with a clean, fully integrated implementation:

  • schema::SchemaContext carries document-level memoization (seen refs → stable anchors, in first-encounter order). Each body view creates one context, threads &mut it through write_endpointwrite_schema_table, then calls render_schema_definitions to emit the shared section once.
  • Anchors are allocated collision-free; the definitions section renders in deterministic order (preserves the output_is_deterministic invariant).
  • Linked mode needs no cycle special-casing: a $ref always resolves to a link.

Follow-ups to merged PRs

Tests

Net +7 tests (43 pass), cargo fmt --check and cargo clippy --all-targets -- -D warnings clean:

Docs (README, CLAUDE.md) updated for the new default and --inline-schemas.

mistral-vibe and others added 2 commits June 27, 2026 15:44
Implements SchemaContext with document-level memoization to avoid
re-expanding shared sub-schemas at every use site.

Key changes:
- Add SchemaContext struct for tracking expanded schema references
- Add write_schema_table_with_context for memoized schema rendering
- Add collect_schema_rows_with_memo that avoids duplicate expansion
- Add render_deferred_schemas for rendering schema definitions at end
- Preserve original functions for backward compatibility

This addresses the output/token bloat issue where shared schemas
(like Error models) were being fully re-expanded at every reference.

The implementation uses:
- HashSet for tracking expanded references
- Markdown links for cross-references to already-expanded schemas
- Deferred rendering of schema definitions in a dedicated section
- Proper cycle detection with links to existing schemas

Note: The new functions are implemented but not yet integrated
into the main rendering pipeline. The original functions remain
functional and all existing tests pass.

Co-authored-by: nrynss <[email protected]>
Issue #58: schema rendering is now memoized per document. Component
schemas reached through a `$ref` are expanded once into a trailing
"Schema Definitions" section and linked from every use site instead of
being re-inlined at each occurrence, cutting output and token cost for
specs with shared schemas. `--inline-schemas` restores the fully
self-contained expansion (with cycle detection) for callers that want it.

The previous commit only added unused, unformatted infrastructure to
schema.rs (CI red on `cargo fmt --check`, nothing wired in). That is
replaced with a clean, fully integrated implementation:

- `SchemaContext` threads through each body view → `write_endpoint` →
  `write_schema_table`; `render_schema_definitions` emits the shared
  section once per document. Self/mutual references resolve to links, so
  cycles need no special-casing in linked mode. Anchors are allocated
  collision-free and the section is rendered in deterministic
  first-encounter order.

Follow-ups to the previously merged PRs:

- #69: the "no effect" warning now reports the detail level in the
  lowercase spelling the user types (`--detail standard`), not the
  Debug-derived `Standard`. `--inline-schemas` without `--include-schemas`
  warns too.
- #70: endpoint heading anchors are scoped by service in the service
  view, so a multi-tag operation rendered under several sections gets a
  unique anchor each time and its TOC links stay unambiguous.

Tests: linked-default expansion + dedup, self-reference-as-link, inline
mode, inline-mode cycle detection, warning casing, and multi-tag anchor
uniqueness (new `multi_tag_oas3.json` fixture). 43 pass; fmt and clippy
clean.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@nrynss nrynss changed the title Fix schema expansion re-expansion (issue #58) Memoize schema expansion + fix #69/#70 follow-ups (issue #58) Jun 27, 2026
@nrynss nrynss marked this pull request as ready for review June 27, 2026 17:33
@nrynss nrynss merged commit 20ed205 into main Jun 27, 2026
9 checks passed
@nrynss nrynss deleted the vibe/fix-schema-memo-5cdff7 branch June 27, 2026 17:34
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.

Schema expansion re-expands shared sub-schemas at every use site (output/token bloat)

2 participants