Skip to content

Codegen robustness + readability cleanup (4 failing regression tests now pass) - #1

Merged
amafjarkasi merged 19 commits into
masterfrom
cleanup/clippy-quick-wins
Jul 31, 2026
Merged

amafjarkasi merged 19 commits into
masterfrom
cleanup/clippy-quick-wins

Conversation

@amafjarkasi

Copy link
Copy Markdown
Owner

Summary

Code-quality pass across the emitters and core. Headline result: 4 regression tests that were failing now pass (github/stripe × rust/go), driven by two real codegen bugs fixed along the way.

Real bugs fixed

  • Doc-comment escaping (Rust + Go emitters) — real-world spec descriptions (GitHub 9MB, Stripe 7.6MB) contain embedded newlines, backticks, and /*/*/ sequences that broke generated code (parse errors, unterminated block comments, token errors). Emitters now escape these and prefix every line. → github+stripe × rust+go regression tests pass.
  • Reserved-name collisions (Go + Rust emitters) — a spec model named like a built-in SDK type (e.g. GitHub's `ValidationError`) redeclared it and broke compilation. Emitters now suffix colliding model names with `Model`.
  • Shadowed `Scalar::Binary` pattern — binary fields generated `"true"`/boolean asserts instead of byte arrays (found via the "unreachable pattern" clippy warning).
  • 5 `chars().next().unwrap()` sites replaced with self-safe `is_some_and`.

Readability + cleanup

  • Clippy warnings: 120 → 2 (~50 autofixes + manual: collapsed if-lets, `sort_by_key`, `matches!`, redundant closures, etc.)
  • Expanded ~15 golfed single-line functions in `diff.rs`/`security.rs`/`graph.rs`/`ir.rs`/`main.rs` into readable form
  • Removed dead `rust_method_doc_comment`; gated test-only `build_operation_entries` with `#[cfg(test)]`; made example `ReadmePlugin` pub
  • `# Panics` docs on 4 public functions; `ParsedRequest`/`LangLeg` type aliases in e2e tests

Docs

  • README accuracy pass: version 1.6.0→1.6.1, tests 227→259, removed phantom `security`/`graph` CLI commands, added real `profile`/`plugin`, fixed `wasm32-wasi`→`wasm32-wasip1`, added 7 missing modules to the TS layout tree, VS Code command count 23→24
  • CHANGELOG `[1.6.1]` entry

Verification (all run, not asserted)

  • `cargo build --workspace` ✓
  • 259 lib tests pass (242 core + 17 TS)
  • 11/11 regression tests pass (were 7/11)
  • All 3 example SDKs compile: `cargo check` (rust), `go build` (go), `tsc --noEmit` (ts)
  • Clippy: 2 remaining warnings (a verified-necessary `.clone()` and the IR enum variant-size — both deliberate non-fixes)

root added 19 commits July 30, 2026 07:59
Mechanical clippy suggestions (redundant closures, format! simplifications,
collapsed if-lets, sort_by_key, char comparisons, matches! macro, etc.).
No behavior change; lib tests (242) + TS (17) still pass.
- diff.rs: expand golfed fmt_md_msg into readable prefixed-if chain
  (fixes 13 clippy else-if warnings)
- testgen.rs: Scalar::Binary was shadowed by a Boolean|Base64|Binary arm,
  so binary fields generated "true"/boolean asserts instead of
  Uint8Array. Split Binary into its own arm (3 sites).
- spec.rs: collapse match to matches! macro
- resolve.rs: take &T instead of &Box<T>
- rust emitter: remove dead rust_method_doc_comment
- apply remaining clippy autofixes across crates
- testgen.rs: remove now-unreachable _ catch-alls (all 9 Scalar variants
  are covered after the Binary split) and give Binary its own assertion
- analyzer.rs, marketplace.rs: descending sorts via sort_by_key(Reverse(..))
- runtime.rs: collect() now builds the file list with vec![] instead of
  Vec::new() + 18 pushes (clearer intent)
- schema31.rs: drop redundant borrow in to_value() in test
- apply remaining clippy autofixes (collapsed if-lets)
- resolve.rs, models.rs, rust/lib.rs: collapse 3-deep if-let chains
- cli/main.rs: sort_by_key(Reverse) for marketplace entry sort
- e2e_smoke, e2e_advanced: ParsedRequest/LangLeg type aliases for
  readability of complex tuple signatures
- marketplace.rs: drop unused mut in test

Clippy warnings now: 4 (all deliberate non-fixes).
5 sites across rust/go/ts emitters checked the first char of a generated
identifier with .unwrap(), relying on a separate is_empty() guard above.
Replace with chars().next().is_some_and(|c| ...) so each check is
self-safe and the guard dependency is explicit. No behavior change;
all tests + generated-SDK compile test pass.

Audit of other unwrap()/expect() in non-test source found them guarded
by construction (len()==1, intersection membership, or infallible I/O).
Reformatted 9 crammed functions (diff_operations, diff_operation,
diff_schemas, diff_schema, type_to_string, type_changed, format_text,
format_colored, format_json, format_markdown, PropertyChange Display)
into properly indented multi-line form. No logic change; all 242 core
tests + 12 diff tests pass.
- diff.rs: format diff_detailed entry point
- security.rs: expand match arms in scheme_info_from_raw
- graph.rs: expand render_mermaid/render_dot node/edge loops

Readability only; all tests pass.
- changelog.rs: build_operation_entries is only used by tests, so gate
  it with #[cfg(test)] (removes dead-code warning from the lib build)
- plugin-example: make ReadmePlugin pub so the example is a usable,
  importable demonstration rather than an unused struct
Add # Panics sections to the 4 public functions flagged by
missing_panics_doc (marketplace built_in x2, demo spec, deprecation
migration guide). All document 'should never happen' panics on
compile-time-baked data or resolve()-invariant assumptions.
- diff.rs: format DiffSeverity/SchemaDiffDetail Display impls
- security.rs: expand analyze_common_issues/analyze_detailed_issues
  (multiple statements-per-line -> readable blocks), and use
  is_none() instead of !is_some() for OAuth2 flow checks
Reformat the text + markdown analysis report blocks in main.rs (each
was a single line with a for-loop body inline). No logic change.
- ir.rs: format SchemaRegistry impl + HttpMethod as_str/upper matches
- security.rs: expand scheme_info_from_ir, scheme_label,
  extract_scheme_names, op_key, build_op_security_map, and the
  OperationSecurity construction

Readability only; all tests pass.
Real bug: schema/operation descriptions from real-world specs (GitHub,
Stripe) contain embedded newlines, backticks, and '/*' '*/' sequences.
The emitters emitted them as single '// ' or '/// ' comments, so:
- continuation lines lost their comment prefix -> bare prose in source
  -> 'non-declaration statement' / parse errors
- '*/' closed enclosing block comments -> 'unterminated block comment'
- backticks -> 'looks like single quote' token errors

Fix:
- rust emitter: rust_doc now escapes /* */ and backticks; added
  rust_doc_indented for property docs (which were inline-format!ed
  without rust_doc at all)
- go emitter: go_doc escapes */ and prefixes every line; property docs
  now route through go_doc; param/body/returns docs use new
  go_doc_label helper

Result: github + stripe RUST regression tests now pass (were failing);
stripe GO now passes. github GO still fails on a separate, deeper
ValidationError name-collision bug (not doc-related).
Real bug: the GitHub spec defines its own 'ValidationError' model, which
collided with the emitter's hardcoded ValidationError validation type,
causing 'redeclared in this block' + missing-field compile errors.

Fix: export_ident now suffixes any user model whose name matches a
built-in SDK type (ValidationError, ServiceContainer, Client, Auth,
Middleware, RateLimiter, etc.) with 'Model'.

Result: github_generates_and_compiles_go now passes. Combined with the
prior doc-escaping fix, ALL 11 regression tests now pass (4 were failing
before this session: github+stripe x go+rust).
Same bug class as the Go ValidationError collision: a spec model named
Error/Client/Semaphore/etc. would redefine an SDK built-in and break
compilation. Add safe_model_name() that suffixes colliding names with
'Model', applied at both enum and object model emit sites.

github/stripe/petstore rust regression tests still pass; this guards
the latent case (none of these specs use the colliding names).
Reflects the doc-comment escaping + reserved-name fixes in the checked-in
example output. All three compile/typecheck clean (cargo check, go build,
tsc --noEmit).
…arget, TS tree

Accuracy pass:
- version badge 1.6.0 -> 1.6.1
- unit test count 227 -> 259
- CLI: remove phantom 'security'/'graph' subcommands (don't exist), add
  real 'profile'/'plugin', drop the now-wrong '22 commands' count, point
  readers to 'specforge help' as source of truth
- WASM build target wasm32-wasi -> wasm32-wasip1 (wasi was renamed in
  recent Rust; the old target no longer installs)
- TypeScript layout tree: add the 7 modules the emitter actually
  generates (cache, ratelimit, telemetry, logging, interceptors,
  validate, validation-middleware, service_container)
- VS Code extension command count 23 -> 24
- compile-gates: note the per-emitter regenerate-and-compile tests +
  regression.rs covering real GitHub/Stripe specs
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Harden codegen: safe doc comments, reserved-name avoidance, and compile tests

🐞 Bug fix 🧪 Tests 📝 Documentation ✨ Enhancement 🕐 40+ Minutes

Grey Divider

AI Description

• Escape doc comments in Rust/Go; fix reserved-name model collisions.
• Wire TS telemetry/validators and fix Binary scalar handling in test generation.
• Add compile/typecheck regression tests; update docs and regenerated examples.
Diagram

graph TD
  A["OpenAPI specs"] --> B["specforge-core IR"] --> C["Emitters (Rust/Go/TS)"] --> D["Generated SDKs"] --> E["Toolchains (cargo/go/tsc)"]
  T["Regression tests"] --> A --> B
  T --> E
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Centralize doc-comment escaping in core
  • ➕ Single escaping policy shared across emitters (less drift)
  • ➕ Easier to add fuzz/property tests around one implementation
  • ➖ May not fit language-specific comment/tokenization quirks cleanly
  • ➖ Requires emitter API changes to consume pre-sanitized doc strings
2. Snapshot/AST validation instead of invoking toolchains
  • ➕ Faster tests; avoids Go/Node toolchain dependencies
  • ➕ Deterministic diffs localized to generator output
  • ➖ Less realistic than compiling; can miss template-level breakages
  • ➖ Requires maintaining per-language parsing/snapshot baselines

Recommendation: The PR’s approach (language-appropriate escaping + real compiler/typechecker regression tests) provides the strongest correctness signal for codegen. Consider a follow-up to share common escaping test vectors (or a small shared helper) to prevent Rust/Go/TS behavior divergence.

Files changed (54) +2567 / -422

Enhancement (1) +2 / -1
lib.rsAdjust plugin example visibility for docs/usability +2/-1

Adjust plugin example visibility for docs/usability

• Makes the example plugin type publicly accessible so it can be referenced/used as intended by documentation and sample code.

examples/plugin-example/src/lib.rs

Bug fix (15) +1112 / -195
testgen.rsFix Scalar::Binary generation (examples/assertions) +7/-8

Fix Scalar::Binary generation (examples/assertions)

• Stops incorrectly treating Binary as Boolean/Base64 in example generation and assertions. Ensures byte-array examples/assertions are emitted correctly for TS/Go/Rust test generation.

crates/specforge-core/src/testgen.rs

lib.rsGo emitter: escape doc comments and avoid builtin type collisions +86/-26

Go emitter: escape doc comments and avoid builtin type collisions

• Introduces safe doc comment emission that prefixes every line and escapes dangerous sequences (notably stray '*/'). Adds a collision check so generated model names that match built-in SDK runtime types are suffixed with 'Model'.

crates/specforge-go/src/lib.rs

lib.rsRust emitter: escape rustdoc and avoid builtin type collisions +210/-95

Rust emitter: escape rustdoc and avoid builtin type collisions

• Hardens rustdoc emission by escaping '/*', '*/', and backticks and by supporting indentation for field docs. Adds safe model naming to suffix colliding names with 'Model' to prevent redefinition errors; includes additional template correctness fixes surfaced by compiling generated output.

crates/specforge-rust/src/lib.rs

runtime.rsTS runtime: wire TelemetryHooks and fix validator return behavior +48/-25

TS runtime: wire TelemetryHooks and fix validator return behavior

• Fixes generated per-model validators to accumulate errors and return 'ValidationError[]' (instead of returning 'void' from 'validateValue'). Wires 'TelemetryHooks' into 'ApiClient' (options/container storage + request/cache/retry lifecycle callbacks) and simplifies runtime file collection with 'vec!'.

crates/specforge-ts/src/runtime.rs

client.goRegenerate Go petstore SDK sources +45/-1

Regenerate Go petstore SDK sources

• Refreshes generated Go client code to reflect emitter fixes (doc comment handling and compilation robustness).

examples/petstore-go/sdk/client.go

validation_middleware.goRegenerate Go petstore validation middleware +113/-0

Regenerate Go petstore validation middleware

• Refreshes generated validation middleware to match updated generator output and ensure compilation.

examples/petstore-go/sdk/validation_middleware.go

client.rsRegenerate Rust petstore SDK client +122/-28

Regenerate Rust petstore SDK client

• Refreshes generated Rust client code to incorporate template fixes discovered by compile tests (control-flow and API signature correctness).

examples/petstore-rust/sdk/src/client.rs

lib.rsRegenerate Rust petstore SDK lib exports +4/-1

Regenerate Rust petstore SDK lib exports

• Updates module exports to match the current generated module layout.

examples/petstore-rust/sdk/src/lib.rs

models.rsRegenerate Rust petstore models output +1/-1

Regenerate Rust petstore models output

• Refreshes generated models to reflect emitter doc escaping/naming changes and regenerated output.

examples/petstore-rust/sdk/src/models.rs

validation_middleware.rsRegenerate Rust petstore validation middleware +146/-0

Regenerate Rust petstore validation middleware

• Refreshes validation middleware code to match updated runtime interfaces and compile cleanly.

examples/petstore-rust/sdk/src/validation_middleware.rs

client.tsRegenerate TS petstore ApiClient output +61/-7

Regenerate TS petstore ApiClient output

• Refreshes generated TS client to reflect telemetry wiring and request lifecycle logic fixes.

examples/petstore-ts/sdk/src/client.ts

service_container.tsRegenerate TS petstore service container +46/-0

Regenerate TS petstore service container

• Refreshes generated service container so ApiClient can pull shared dependencies (including telemetry) correctly.

examples/petstore-ts/sdk/src/service_container.ts

telemetry.tsRegenerate TS petstore telemetry module +69/-0

Regenerate TS petstore telemetry module

• Refreshes telemetry definitions consistent with newly wired TelemetryHooks usage in ApiClient.

examples/petstore-ts/sdk/src/telemetry.ts

validate.tsRegenerate TS petstore validators +9/-3

Regenerate TS petstore validators

• Refreshes validators to correctly return accumulated 'ValidationError[]' and match helper signatures.

examples/petstore-ts/sdk/src/validate.ts

validation-middleware.tsRegenerate TS petstore validation middleware +145/-0

Regenerate TS petstore validation middleware

• Refreshes validation middleware to match validator behavior changes and current runtime interfaces.

examples/petstore-ts/sdk/src/validation-middleware.ts

Refactor (22) +1060 / -184
main.rsCLI clippy cleanup and import pruning +107/-44

CLI clippy cleanup and import pruning

• Removes unused imports and applies clippy-driven simplifications. Stops discarding warn! results in error paths.

crates/specforge-cli/src/main.rs

analyzer.rsAnalyzer sorting cleanup (clippy) +3/-2

Analyzer sorting cleanup (clippy)

• Refactors descending sort logic to use sort_by_key(Reverse(..)) for clarity. No intended behavior change.

crates/specforge-core/src/analyzer.rs

changelog.rsChangelog generator minor cleanup +3/-4

Changelog generator minor cleanup

• Small refactors to reduce warnings and improve readability in changelog generation logic.

crates/specforge-core/src/changelog.rs

demo.rsDemo spec generation cleanup +6/-0

Demo spec generation cleanup

• Minor clippy/readability improvements in demo spec generation code paths.

crates/specforge-core/src/demo.rs

deprecation.rsDeprecation parsing/readability refactor +8/-2

Deprecation parsing/readability refactor

• Refactors deprecation helper logic for clarity and fewer clippy warnings.

crates/specforge-core/src/deprecation.rs

diff.rsRewrite diff display/helpers into readable structured code +507/-17

Rewrite diff display/helpers into readable structured code

• Expands previously golfed display implementations and diff helpers into maintainable blocks. Primarily a readability/clippy change intended to preserve behavior.

crates/specforge-core/src/diff.rs

graph.rsGraph DOT/Mermaid renderers refactored for readability +40/-6

Graph DOT/Mermaid renderers refactored for readability

• Expands node/edge rendering loops into clearer structured code with explicit formatting steps. Intended to be behavior-preserving.

crates/specforge-core/src/graph.rs

ir.rsIR helper impls expanded (SchemaRegistry, HttpMethod) +32/-2

IR helper impls expanded (SchemaRegistry, HttpMethod)

• Converts compact one-liners into readable method bodies and matches. No intended behavior change.

crates/specforge-core/src/ir.rs

marketplace.rsMarketplace ordering + clippy cleanup +16/-5

Marketplace ordering + clippy cleanup

• Refactors ordering/sorting logic and removes minor clippy issues. No intended behavior change.

crates/specforge-core/src/marketplace.rs

mock.rsMock module clippy cleanup +1/-1

Mock module clippy cleanup

• Small readability tweaks and clippy-driven simplifications.

crates/specforge-core/src/mock.rs

profiler.rsProfiler minor cleanup +2/-2

Profiler minor cleanup

• Minor refactors to reduce warnings and keep style consistent.

crates/specforge-core/src/profiler.rs

resolve.rsResolver refactors (boxing/reference handling) +37/-41

Resolver refactors (boxing/reference handling)

• Simplifies reference matching and avoids passing &Box<T> where unnecessary. Removes unused IR imports and applies small iterator simplifications.

crates/specforge-core/src/resolve.rs

schema31.rsSchema31 test cleanup +1/-1

Schema31 test cleanup

• Removes a redundant borrow to satisfy clippy in schema31-related test code.

crates/specforge-core/src/schema31.rs

security.rsSecurity analysis code expanded and helperized +191/-33

Security analysis code expanded and helperized

• De-golfs and restructures security analysis logic (scheme labeling, requirement extraction, op mapping) to improve readability while keeping behavior the same.

crates/specforge-core/src/security.rs

spec.rsSpec helper simplification using matches! +4/-4

Spec helper simplification using matches!

• Small match-to-matches! refactor for clarity and fewer clippy warnings.

crates/specforge-core/src/spec.rs

validate.rsValidator match refactor (boolean) +2/-3

Validator match refactor (boolean)

• Refactors boolean validation to use a match guard, reducing nesting and warnings. Intended to preserve behavior.

crates/specforge-core/src/validate.rs

verify.rsVerification module minor cleanup +1/-1

Verification module minor cleanup

• Small style/clippy cleanup in verification-related code.

crates/specforge-core/src/verify.rs

models.rsTS emitter models: simplify discriminant literal extraction +11/-13

TS emitter models: simplify discriminant literal extraction

• Refactors discriminant detection logic to reduce nesting while preserving behavior for union discriminator inference.

crates/specforge-ts/src/models.rs

name.rsTS naming helper micro-cleanup +1/-1

TS naming helper micro-cleanup

• Minor clippy/readability fix in TypeScript naming logic.

crates/specforge-ts/src/name.rs

operations.rsTS operations emitter small cleanup +2/-2

TS operations emitter small cleanup

• Minor refactor to reduce warnings and keep emitter style consistent.

crates/specforge-ts/src/operations.rs

index.tsRegenerate TS petstore index exports +2/-0

Regenerate TS petstore index exports

• Updates generated exports to match current module structure after regeneration.

examples/petstore-ts/sdk/src/index.ts

ratelimit.tsRegenerate TS petstore ratelimit runtime +83/-0

Regenerate TS petstore ratelimit runtime

• Refreshes generated runtime code as part of SDK regeneration.

examples/petstore-ts/sdk/src/ratelimit.ts

Tests (7) +199 / -8
e2e_advanced.rsE2E advanced test small cleanup +4/-1

E2E advanced test small cleanup

• Minor test tidying (type aliases / small readability adjustments) to reduce warnings and repetition.

crates/specforge-cli/tests/e2e_advanced.rs

e2e_smoke.rsE2E smoke test small cleanup +8/-2

E2E smoke test small cleanup

• Minor test tidying to keep smoke coverage consistent with updated SDK outputs and to reduce warnings.

crates/specforge-cli/tests/e2e_smoke.rs

edge_cases.rsEdge-case test micro-adjustment +1/-1

Edge-case test micro-adjustment

• Small update to keep edge-case coverage/expectations consistent after refactors.

crates/specforge-cli/tests/edge_cases.rs

sdk_integration.rsSDK integration test expectation updates +2/-4

SDK integration test expectation updates

• Adjusts integration assertions to align with regenerated SDK outputs and updated runtime/module behavior.

crates/specforge-cli/tests/sdk_integration.rs

gen_test.rsGo: add generated SDK compile regression test +60/-0

Go: add generated SDK compile regression test

• Adds a test that regenerates a Go SDK into a temp dir and runs 'go build ./...'. Skips cleanly when Go is missing or SKIP_COMPILE_TEST is set, ensuring CI can enforce compilation where available.

crates/specforge-go/tests/gen_test.rs

gen_test.rsRust: add generated SDK compile regression test +63/-0

Rust: add generated SDK compile regression test

• Adds a test that regenerates a Rust SDK into a temp crate and runs 'cargo check', ensuring the generated crate is treated as its own workspace. Skips cleanly when cargo is missing or SKIP_COMPILE_TEST is set.

crates/specforge-rust/tests/gen_test.rs

gen_test.rsTS: add generated SDK typecheck regression test +61/-0

TS: add generated SDK typecheck regression test

• Adds a test that regenerates a TS SDK, installs devDependencies, and runs 'tsc --noEmit'. Skips cleanly when node/npm/npx are missing or SKIP_COMPILE_TEST is set.

crates/specforge-ts/tests/gen_test.rs

Documentation (5) +189 / -34
CHANGELOG.mdAdd 1.6.1 release notes covering codegen fixes and new compile tests +22/-0

Add 1.6.1 release notes covering codegen fixes and new compile tests

• Adds a detailed 1.6.1 entry describing doc-comment escaping, reserved-name collision handling, Rust/TS runtime fixes, and new compile/typecheck regression tests. Updates version links to include v1.6.1.

CHANGELOG.md

README.mdREADME accuracy pass (version, commands, tests, SDK module trees) +39/-23

README accuracy pass (version, commands, tests, SDK module trees)

• Updates the version badge and test counts, corrects CLI subcommand documentation, and fixes WASM target naming. Expands/repairs TS and Rust SDK layout trees to match actual generated output.

README.md

intro.mdDocs intro: update Rust SDK layout tree +18/-11

Docs intro: update Rust SDK layout tree

• Updates the documented Rust generated SDK module tree to reflect current output (api/ module plus expanded runtime modules).

docs-site/docs/intro.md

changelog.mdDocs-site changelog page updated +16/-0

Docs-site changelog page updated

• Updates the docs-site changelog reference content to align with the repository changelog and latest release entry.

docs-site/docs/reference/changelog.md

README.mdRegenerate Rust petstore SDK README +94/-0

Regenerate Rust petstore SDK README

• Refreshes the generated README to reflect current modules/features (e.g., interceptors/validation/service container).

examples/petstore-rust/sdk/README.md

Other (4) +5 / -0
specforge-version.jsonUpdate Go example specforge-version.json +1/-0

Update Go example specforge-version.json

• Bumps generated metadata to match the updated specforge version/output.

examples/petstore-go/sdk/specforge-version.json

Cargo.tomlUpdate Rust petstore example manifest +2/-0

Update Rust petstore example manifest

• Adjusts the example crate manifest to match regenerated SDK output and versioning.

examples/petstore-rust/Cargo.toml

specforge-version.jsonUpdate Rust example specforge-version.json +1/-0

Update Rust example specforge-version.json

• Bumps generated metadata to match the updated specforge version/output.

examples/petstore-rust/sdk/specforge-version.json

specforge-version.jsonUpdate TS example specforge-version.json +1/-0

Update TS example specforge-version.json

• Bumps generated metadata to match the updated specforge version/output.

examples/petstore-ts/sdk/specforge-version.json

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Rust model rename mismatch 🐞 Bug ≡ Correctness
Description
The Rust emitter now suffixes colliding model/enum *declarations* with Model, but schema
references (e.g., render_type and union arms) still use the unsuffixed pascal(name), so
colliding schemas will either fail to compile or incorrectly bind to the SDK’s built-in types like
Error/Client. This breaks generated SDK correctness for any spec that defines a schema with one
of the built-in type names.
Code

crates/specforge-rust/src/lib.rs[2815]

+    let name = safe_model_name(&pascal(&e.name));
Evidence
Declarations are renamed via safe_model_name, but references continue to render the unsuffixed
PascalCase, so colliding schemas will not be referenced by their declared name.

crates/specforge-rust/src/lib.rs[2814-2816]
crates/specforge-rust/src/lib.rs[406-428]
crates/specforge-rust/src/lib.rs[2910-2926]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`safe_model_name()` is applied when emitting enum/object declarations, but type references still render as `pascal(name)` (and union arms use `pascal(arm)`), causing mismatches for colliding schema names (e.g. schema `Error` becomes `ErrorModel` when declared but is still referenced as `Error`).

## Issue Context
The PR’s intended behavior is “suffix colliding model names with `Model`”. That transformation must be applied consistently anywhere a schema name is converted into a Rust type identifier.

## Fix Focus Areas
- crates/specforge-rust/src/lib.rs[406-428]
- crates/specforge-rust/src/lib.rs[2814-2816]
- crates/specforge-rust/src/lib.rs[2910-2926]

## Suggested approach
1. Introduce a single helper for schema type identifiers, e.g. `fn rust_schema_type_ident(name: &str) -> String { safe_model_name(&pascal(name)) }`.
2. Use it in `render_type()` for `Type::Reference`.
3. Use it anywhere union/oneOf arms or other schema-derived type names are produced (e.g. `arm_ty`).
4. Add/extend a regression test where a schema named `Error` (or another built-in) is referenced from another model/operation, and ensure generated code compiles and types line up.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. export_ident renames methods 🐞 Bug ≡ Correctness
Description
In the Go emitter, export_ident() now appends Model for any identifier matching the built-in SDK
type list, but export_ident() is also used to derive operation method names from operation_id.
This will rename methods like Client() to ClientModel() when an operationId collides,
unexpectedly changing the generated SDK API surface.
Code

crates/specforge-go/src/lib.rs[R214-223]

+    let name = pascal(input);
+    // Avoid colliding with built-in SDK types emitted into the same package
+    // (e.g. a spec that defines its own `ValidationError` model would otherwise
+    // redeclare the emitter's validation type and break compilation).
+    if is_sdk_builtin_type(&name) {
+        format!("{name}Model")
+    } else {
+        name
+    }
+}
Evidence
The PR changes export_ident() to apply the Model suffix for built-in names, and method emission
uses export_ident(&op.operation_id), so the new suffixing behavior now affects method names as
well.

crates/specforge-go/src/lib.rs[212-223]
crates/specforge-go/src/lib.rs[2566-2568]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`export_ident()` now performs built-in type collision avoidance by suffixing `Model`, but it is used for both schema/type identifiers and operation method identifiers. As a result, colliding operationIds (e.g. `Client`, `Auth`, `Logger`) will have their method names changed.

## Issue Context
The PR description states reserved-name collision handling is for *models*. Operation method names generally should not be subject to the same collision list.

## Fix Focus Areas
- crates/specforge-go/src/lib.rs[212-261]
- crates/specforge-go/src/lib.rs[2566-2571]

## Suggested approach
1. Revert `export_ident()` to only do Go export casing (PascalCase + leading-digit guard).
2. Add a separate helper for model/type names only, e.g. `export_model_ident()` (or `safe_model_name()`), that applies the `is_sdk_builtin_type` suffix.
3. Update call sites that emit schema/type declarations and schema/type references to use the model-specific helper, but keep operation method naming using plain `export_ident()`.
4. Add a regression test with an operationId equal to a built-in type name to ensure the method name remains stable.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Binary examples emit TS 🐞 Bug ≡ Correctness
Description
In testgen.rs, the change that makes Scalar::Binary no longer match the boolean arm activates an
existing Scalar::Binary branch that returns new Uint8Array([1,2,3]) for Go and Rust example JSON
bodies. This produces invalid JSON in generated mock responses for Go/Rust testgen when Binary
fields exist (Binary is expected to be represented as JSON string/object).
Code

crates/specforge-core/src/testgen.rs[353]

+            Scalar::Boolean | Scalar::Base64 => "true".to_string(),
Evidence
The Go/Rust test generators embed these examples as JSON response bodies, while the system’s
validation logic expects Binary to be represented as JSON string/object; emitting `new
Uint8Array(...)` violates that expectation.

crates/specforge-core/src/testgen.rs[288-326]
crates/specforge-core/src/testgen.rs[345-355]
crates/specforge-core/src/testgen.rs[506-516]
crates/specforge-core/src/mock.rs[291-305]
crates/specforge-core/src/verify.rs[205-213]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`generate_go_example()` and `generate_rust_example()` now reach the `Scalar::Binary` arm, which returns a TypeScript expression (`new Uint8Array([1,2,3])`). These functions are used to generate `application/json` response bodies, so Binary scalars must be JSON-compatible.

## Issue Context
The verifier treats `Scalar::Binary` as JSON string/object, and mock generation uses a JSON string like `"binary"`.

## Fix Focus Areas
- crates/specforge-core/src/testgen.rs[345-355]
- crates/specforge-core/src/testgen.rs[506-516]

## Suggested approach
1. Change the Go/Rust testgen Binary example to a JSON string (e.g. `"binary"` or a base64-like string), consistent with `mock.rs` and `verify.rs` expectations.
2. Keep the TS generator’s `Uint8Array` example if it is used in actual TS code contexts.
3. Add a small unit/regression test ensuring generated Go/Rust mock response bodies remain valid JSON when a response type includes `Scalar::Binary`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo


fn emit_enum(e: &EnumModel) -> String {
let name = pascal(&e.name);
let name = safe_model_name(&pascal(&e.name));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Rust model rename mismatch 🐞 Bug ≡ Correctness

The Rust emitter now suffixes colliding model/enum *declarations* with Model, but schema
references (e.g., render_type and union arms) still use the unsuffixed pascal(name), so
colliding schemas will either fail to compile or incorrectly bind to the SDK’s built-in types like
Error/Client. This breaks generated SDK correctness for any spec that defines a schema with one
of the built-in type names.
Agent Prompt
## Issue description
`safe_model_name()` is applied when emitting enum/object declarations, but type references still render as `pascal(name)` (and union arms use `pascal(arm)`), causing mismatches for colliding schema names (e.g. schema `Error` becomes `ErrorModel` when declared but is still referenced as `Error`).

## Issue Context
The PR’s intended behavior is “suffix colliding model names with `Model`”. That transformation must be applied consistently anywhere a schema name is converted into a Rust type identifier.

## Fix Focus Areas
- crates/specforge-rust/src/lib.rs[406-428]
- crates/specforge-rust/src/lib.rs[2814-2816]
- crates/specforge-rust/src/lib.rs[2910-2926]

## Suggested approach
1. Introduce a single helper for schema type identifiers, e.g. `fn rust_schema_type_ident(name: &str) -> String { safe_model_name(&pascal(name)) }`.
2. Use it in `render_type()` for `Type::Reference`.
3. Use it anywhere union/oneOf arms or other schema-derived type names are produced (e.g. `arm_ty`).
4. Add/extend a regression test where a schema named `Error` (or another built-in) is referenced from another model/operation, and ensure generated code compiles and types line up.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +214 to +223
let name = pascal(input);
// Avoid colliding with built-in SDK types emitted into the same package
// (e.g. a spec that defines its own `ValidationError` model would otherwise
// redeclare the emitter's validation type and break compilation).
if is_sdk_builtin_type(&name) {
format!("{name}Model")
} else {
name
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

2. Export_ident renames methods 🐞 Bug ≡ Correctness

In the Go emitter, export_ident() now appends Model for any identifier matching the built-in SDK
type list, but export_ident() is also used to derive operation method names from operation_id.
This will rename methods like Client() to ClientModel() when an operationId collides,
unexpectedly changing the generated SDK API surface.
Agent Prompt
## Issue description
`export_ident()` now performs built-in type collision avoidance by suffixing `Model`, but it is used for both schema/type identifiers and operation method identifiers. As a result, colliding operationIds (e.g. `Client`, `Auth`, `Logger`) will have their method names changed.

## Issue Context
The PR description states reserved-name collision handling is for *models*. Operation method names generally should not be subject to the same collision list.

## Fix Focus Areas
- crates/specforge-go/src/lib.rs[212-261]
- crates/specforge-go/src/lib.rs[2566-2571]

## Suggested approach
1. Revert `export_ident()` to only do Go export casing (PascalCase + leading-digit guard).
2. Add a separate helper for model/type names only, e.g. `export_model_ident()` (or `safe_model_name()`), that applies the `is_sdk_builtin_type` suffix.
3. Update call sites that emit schema/type declarations and schema/type references to use the model-specific helper, but keep operation method naming using plain `export_ident()`.
4. Add a regression test with an operationId equal to a built-in type name to ensure the method name remains stable.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Scalar::Integer | Scalar::Integer64 => "1".to_string(),
Scalar::Float => "1.0".to_string(),
Scalar::Boolean | Scalar::Base64 | Scalar::Binary => "true".to_string(),
Scalar::Boolean | Scalar::Base64 => "true".to_string(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

3. Binary examples emit ts 🐞 Bug ≡ Correctness

In testgen.rs, the change that makes Scalar::Binary no longer match the boolean arm activates an
existing Scalar::Binary branch that returns new Uint8Array([1,2,3]) for Go and Rust example JSON
bodies. This produces invalid JSON in generated mock responses for Go/Rust testgen when Binary
fields exist (Binary is expected to be represented as JSON string/object).
Agent Prompt
## Issue description
`generate_go_example()` and `generate_rust_example()` now reach the `Scalar::Binary` arm, which returns a TypeScript expression (`new Uint8Array([1,2,3])`). These functions are used to generate `application/json` response bodies, so Binary scalars must be JSON-compatible.

## Issue Context
The verifier treats `Scalar::Binary` as JSON string/object, and mock generation uses a JSON string like `"binary"`.

## Fix Focus Areas
- crates/specforge-core/src/testgen.rs[345-355]
- crates/specforge-core/src/testgen.rs[506-516]

## Suggested approach
1. Change the Go/Rust testgen Binary example to a JSON string (e.g. `"binary"` or a base64-like string), consistent with `mock.rs` and `verify.rs` expectations.
2. Keep the TS generator’s `Uint8Array` example if it is used in actual TS code contexts.
3. Add a small unit/regression test ensuring generated Go/Rust mock response bodies remain valid JSON when a response type includes `Scalar::Binary`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@amafjarkasi
amafjarkasi merged commit 9a202c5 into master Jul 31, 2026
3 of 5 checks passed
@amafjarkasi
amafjarkasi deleted the cleanup/clippy-quick-wins branch July 31, 2026 02:13
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