Strict descriptions + endpoint-libs 2.0 lockstep - #27
Merged
Conversation
Descriptions in the RON are not cosmetic: an endpoint description becomes the MCP tool description an agent reads to decide whether to call the tool, and enum-variant descriptions are emitted into the generated JSON schemas and doc comments. A blank one produces a tool an agent cannot use correctly and a doc page that says nothing, with no signal at generation time. Generation now fails on missing or whitespace-only descriptions for endpoints (both EndpointSchema and EndpointSchemaList) and enum variants (both Enum and EnumList). Violations are collected across all files and reported together — one run tells you everything to fix, rather than one item per run — and each line names the file, the service and the item. `--allow-empty-descriptions` restores the previous behaviour for consumers not ready to annotate everything. Also stops emitting an empty `///` line for blank descriptions, which tripped clippy::empty_docs in downstream crates. This is fixed in both enum-emitting paths — EnumElement::to_rust_decl for RON enum definitions and Type::to_rust_decl for shared Type::Enum definitions — which are separate near-identical code paths, hence a test for each. Struct fields are deliberately not validated: Field.description is #[serde(skip)] upstream, so a RON file cannot express one. Verified end to end, not just by unit test: a RON with one blank endpoint description and one blank enum variant fails with both violations listed; --allow-empty-descriptions generates successfully; and the generated model.rs contains a doc comment for the documented variant, no doc line for the blank one, and zero bare `///` lines. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
endpoint-libs 2.0 makes several schema-model types #[non_exhaustive] so that OpenAPI/AsyncAPI emission can ship as a 2.1 minor rather than a 3.0. That forbids struct literals and exhaustive matches from outside that crate, which breaks endpoint-gen in exactly three places: - `From<EndpointSchemaElement> for EndpointSchema` was a field-by-field copy. It is now a move of the inner schema — which is what it always meant, and which also stops it silently dropping fields added later (it would have dropped the new `meta` field). - The `Type` match in `to_rust_ref` gains a wildcard arm that panics with an actionable message. Panicking is right: emitting Rust for a type this version does not understand would produce silently wrong generated code. - A test constructing `EndpointErrorSchema` by literal now uses the constructor added upstream for this purpose. The `[patch.crates-io]` override is TEMPORARY and must be removed once endpoint-libs 2.0 is published — endpoint-libs 2.0.0-alpha.1 is not on crates.io, so the pair cannot build together without it. Verified: endpoint-gen builds and all 10 tests pass against the local endpoint-libs 2.0.0-alpha.1. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The previous commit validated endpoints and enum variants but skipped
ErrorCodeList through a catch-all `_ => {}` arm. That looks like an oversight
rather than a decision: the test asserting the exclusion was named
`..._ignores_structs_and_error_codes` but only exercised structs, and its
comment justified only the struct case.
Error-code descriptions are load-bearing in the same way. They become the doc
comments on the generated `EnumErrorCode` variants (via
EnumVariant::new_with_description in rust.rs) and the third column of
docs/error_codes/error_codes.md. A blank one yields an error a caller cannot
interpret from either artifact.
- `description_violations` now reports blank error-code descriptions, naming
the code and its numeric value.
- The catch-all arm is replaced with an explicit `Struct | StructList` arm, so
a future Definition variant is a compile error here rather than a silent
gap — the same failure mode this commit is fixing.
- The misnamed test is split into `..._ignores_structs` (unchanged behaviour,
honest name) and a new `..._flags_blank_error_codes`.
- The top-level failure message now names all three validated kinds, since it
previously understated what runs.
Verified end to end: a RON with a blank error-code description fails with the
code and number named; documenting it generates successfully and the text
appears in both error_codes.md and the generated model.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drops the temporary [patch.crates-io] override. endpoint-libs 2.0.0-alpha.1 is now on crates.io, so the pair resolves normally — Cargo.lock records `source = "registry+https://github.com/rust-lang/crates.io-index"` rather than a local path. Note the exact-version requirement is deliberate: 2.0.0-alpha.1 is a pre-release, and a plain "2.0" requirement would not match it. Verified against the published crate: builds, 11 tests green, clippy clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pathscale
marked this pull request as ready for review
July 25, 2026 11:24
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 free
to 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.
Note
Unblocked. pathscale/endpoint-libs#41 is merged and
endpoint-libs 2.0.0-alpha.1is published to crates.io. The temporary[patch.crates-io]override has been removed (bb41d73) and the dependency now resolves from the registry. Ready to merge.Two independent pieces of work that happened to share a working tree, committed separately.
1. Strict descriptions (
b856571)Descriptions in the RON are not cosmetic. An endpoint description is the MCP tool description an agent reads to decide whether to call the tool; enum-variant descriptions are emitted into generated JSON schemas and doc comments. A blank one produces a tool an agent cannot use correctly and a doc page that says nothing — with no signal at generation time.
Generation now fails on missing or whitespace-only descriptions for endpoints (
EndpointSchemaandEndpointSchemaList) and enum variants (EnumandEnumList). Violations are collected across all files and reported together, so one run tells you everything to fix rather than one item per run. Each line names the file, service and item:--allow-empty-descriptionsrestores the previous behaviour for consumers not ready to annotate everything.Also stops emitting an empty
///line for blank descriptions, which trippedclippy::empty_docsdownstream. Fixed in both enum-emitting paths —EnumElement::to_rust_decl(RON enum definitions) andType::to_rust_decl(sharedType::Enum) — which are separate near-identical code paths, hence a test for each.Struct fields are deliberately not validated:
Field.descriptionis#[serde(skip)]upstream, so a RON file cannot express one.2. Error-code validation (
9c710a2)ErrorCodeListwas falling through a catch-all_ => {}arm. That looked like an oversight rather than a decision — the test asserting the exclusion was named..._ignores_structs_and_error_codesbut only exercised structs, and its comment justified only the struct case.Error-code descriptions are load-bearing the same way: they become the doc comments on the generated
EnumErrorCodevariants and the third column ofdocs/error_codes/error_codes.md. A blank one yields an error a caller cannot interpret from either artifact.Struct | StructListarm, so a futureDefinitionvariant becomes a compile error here rather than another silent gap — the same failure mode this commit fixes...._ignores_structsand a new..._flags_blank_error_codes.3. endpoint-libs 2.0 lockstep (
d9e67c3,bb41d73)2.0 makes several schema-model types
#[non_exhaustive]so OpenAPI/AsyncAPI emission can ship as a 2.1 minor rather than a 3.0. That forbids struct literals and exhaustive matches from outside that crate, breaking endpoint-gen in three places:From<EndpointSchemaElement> for EndpointSchemawas a field-by-field copy. Now a move of the inner schema — what it always meant, and it stops silently dropping fields added later (it would have dropped the newmetafield).Typematch into_rust_refgains a wildcard arm that panics with an actionable message. Panicking is right: emitting Rust for an unknown type would produce silently wrong generated code.EndpointErrorSchemaby literal now uses the constructor added upstream for this purpose.Verification
Not just unit tests — the real CLI was driven against scratch RON files:
--allow-empty-descriptionsgenerates successfullymodel.rshas a doc comment on the documented variant, no doc line on the blank one, and zero bare///lineserror_codes.mdand the generated model-D warnings)b856571was verified to build and test green against publishedendpoint-libs1.9.0 before the lockstep commit was applied, so the feature stands on its own. The final state is verified against the published 2.0.0-alpha.1 from crates.io, not a local path.Note the exact-version pin is deliberate:
2.0.0-alpha.1is a pre-release, and a plain"2.0"requirement would not match it.🤖 Generated with Claude Code