Skip to content

feat(codegen): add directional schema slicing and $ref alignment - #82

Merged
gsmith85 merged 3 commits into
mainfrom
feat/codegen-slicing
Oct 14, 2026
Merged

gsmith85 merged 3 commits into
mainfrom
feat/codegen-slicing

Conversation

@gsmith85

@gsmith85 gsmith85 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Implements Task 2 (PR 1b) of the two-layer ucp-schema code-generation pipeline: directional schema slicing and reference alignment passes in src/codegen/normalizer.rs, stacked on #81.

Changes

  • normalize_def_schema: strip UCP keywords, rewrite $ref targets to #/$defs/<PascalName>, synchronize canonical top-level titles, and normalize additionalProperties: true onto open object definitions.
  • has_directional_annotations and schema_supports_complete: detect ucp_request/ucp_response annotations and "complete" lifecycle operations via loader::for_each_schema_object (skipping instance data inside const/enum/default/examples).
  • slice_directional_schemas: resolve CreateRequest, UpdateRequest, optional CompleteRequest, and Response ("read") slices via resolver::resolve, omitting empty request slices for response-only nested value types.
  • align_directional_refs: rewrite #/$defs/<Target> inside directional request slices to #/$defs/<Target><Suffix> when present in known_defs (falling back to <Target>UpdateRequest for CompleteRequest slices).

Stacked PR Series Roadmap

  1. PR 1a (feat(codegen): add identifier naming, UCP keyword stripping, and $defs ref rewriting #81): Identifier qualification, UCP keyword stripping, $ref rewriting (src/codegen/normalizer.rs)
  2. PR 1b (this PR): Directional schema slicing & $ref alignment (src/codegen/normalizer.rs)
  3. PR 1c (feat(codegen): add capability reachability, composition, and generate_types() API #83): Capability/extension reachability, composition & generate_types() library API (src/codegen/{mod,reachability,hoist,compose}.rs)
  4. PR 1d (feat(cli): add generate-types subcommand #84): CLI generate-types subcommand (src/bin/ucp-schema.rs, tests/generate_types_test.rs)
  5. PR 2 (feat(codegen): add self-contained .well-known/ucp profile scoping for generate-types #85): Self-contained .well-known/ucp --profile scoping (src/codegen/profile.rs)
  6. PR 3a (feat(codegen): add AST shape normalizers and inline conditional variant hoisting #86): Codegen AST shape normalizers & inline conditional variant hoisting (src/codegen/normalizer.rs, src/codegen/reify.rs)
  7. PR 3b (feat(codegen): lower open string discriminator unions into ordered anyOf with <Union>Base #87): Open string discriminator union lowering (<Union>Base) (src/codegen/reify.rs)
  8. PR 3c (feat(codegen): discover and register decentralized extended subtypes into open unions #88): Cross-file extended subtype discovery & registration (src/codegen/reify.rs)
  9. PR 4a (python-sdk#101): Python SDK direct JSON Schema codegen (generate_models.sh, postprocess_models.py, src/ucp_sdk/models/)
  10. PR 4b (js-sdk#87): JS/TS SDK direct JSON Schema codegen (generate_models.sh, scripts/generate-zod-from-types.mjs, src/spec_generated.ts)
  11. PR 5 (feat(openapi): add profile-driven OpenAPI 3.1 service and type binding (generate-openapi) #89): OpenAPI 3.1 REST service & type binding (ucp-schema generate-openapi, src/openapi/mod.rs)

Test Plan

  • cargo fmt --check
  • cargo test --all-targets
  • cargo clippy --all-targets -- -D warnings

@damaz91 damaz91 added the status:needs-triage Signal that the PR is ready for human triage label Sep 30, 2026
gsmith85 added a commit that referenced this pull request Oct 1, 2026
Implement Task 4 (PR 1d) of the ucp-schema codegen pipeline:
- Wire Commands::GenerateTypes in src/bin/ucp-schema.rs with --profile, --capability, --extension, --schema-dir (alias --schema-local-base), --schema-remote-base, --output, and --pretty.
- Implement CliExitCode for CodegenError and generalize write_json_output to <T: serde::Serialize + ?Sized>.
- Add CLI integration tests in tests/generate_types_test.rs covering stdout pretty/compact output, file output, repeatable/comma-delimited flags, and error exit codes.

Stacked PR Roadmap:
- PR 1a (#81): Identifier qualification, UCP keyword stripping, $ref rewriting
- PR 1b (#82): Directional schema slicing and $ref alignment
- PR 1c (#83): Capability/extension reachability, composition, and generate_types() library API
- PR 1d (this PR): CLI generate-types subcommand
- PR 2: Self-contained .well-known/ucp --profile scoping
- PR 3: Inline conditional variant hoisting and ordered anyOf union lowering
- PR 4: OpenAPI 3.1 REST binding assembly (generate-openapi)
gsmith85 added a commit that referenced this pull request Oct 1, 2026
Implement Task 4 (PR 1d) of the ucp-schema codegen pipeline:
- Wire Commands::GenerateTypes in src/bin/ucp-schema.rs with --profile, --capability, --extension, --schema-dir (alias --schema-local-base), --schema-remote-base, --output, and --pretty.
- Implement CliExitCode for CodegenError and generalize write_json_output to <T: serde::Serialize + ?Sized>.
- Add CLI integration tests in tests/generate_types_test.rs covering stdout pretty/compact output, file output, repeatable/comma-delimited flags, and error exit codes.

Stacked PR Roadmap:
- PR 1a (#81): Identifier qualification, UCP keyword stripping, $ref rewriting
- PR 1b (#82): Directional schema slicing and $ref alignment
- PR 1c (#83): Capability/extension reachability, composition, and generate_types() library API
- PR 1d (this PR): CLI generate-types subcommand
- PR 2: Self-contained .well-known/ucp --profile scoping
- PR 3: Inline conditional variant hoisting and ordered anyOf union lowering
- PR 4: OpenAPI 3.1 REST binding assembly (generate-openapi)
gsmith85 added a commit that referenced this pull request Oct 1, 2026
Implement Task 4 (PR 1d) of the ucp-schema codegen pipeline:
- Wire Commands::GenerateTypes in src/bin/ucp-schema.rs with --profile, --capability, --extension, --schema-dir (alias --schema-local-base), --schema-remote-base, --output, and --pretty.
- Implement CliExitCode for CodegenError and generalize write_json_output to <T: serde::Serialize + ?Sized>.
- Add CLI integration tests in tests/generate_types_test.rs covering stdout pretty/compact output, file output, repeatable/comma-delimited flags, and error exit codes.

Stacked PR Roadmap:
- PR 1a (#81): Identifier qualification, UCP keyword stripping, $ref rewriting
- PR 1b (#82): Directional schema slicing and $ref alignment
- PR 1c (#83): Capability/extension reachability, composition, and generate_types() library API
- PR 1d (this PR): CLI generate-types subcommand
- PR 2: Self-contained .well-known/ucp --profile scoping
- PR 3: Inline conditional variant hoisting and ordered anyOf union lowering
- PR 4: OpenAPI 3.1 REST binding assembly (generate-openapi)
@gsmith85
gsmith85 force-pushed the feat/codegen-slicing branch from b6fcada to 88c578b Compare October 1, 2026 23:45
gsmith85 added a commit that referenced this pull request Oct 1, 2026
Implement Task 4 (PR 1d) of the ucp-schema codegen pipeline:
- Wire Commands::GenerateTypes in src/bin/ucp-schema.rs with --profile, --capability, --extension, --schema-dir (alias --schema-local-base), --schema-remote-base, --output, and --pretty.
- Implement CliExitCode for CodegenError and generalize write_json_output to <T: serde::Serialize + ?Sized>.
- Add CLI integration tests in tests/generate_types_test.rs covering stdout pretty/compact output, file output, repeatable/comma-delimited flags, and error exit codes.

Stacked PR Roadmap:
- PR 1a (#81): Identifier qualification, UCP keyword stripping, $ref rewriting
- PR 1b (#82): Directional schema slicing and $ref alignment
- PR 1c (#83): Capability/extension reachability, composition, and generate_types() library API
- PR 1d (this PR): CLI generate-types subcommand
- PR 2: Self-contained .well-known/ucp --profile scoping
- PR 3: Inline conditional variant hoisting and ordered anyOf union lowering
- PR 4: OpenAPI 3.1 REST binding assembly (generate-openapi)
gsmith85 added a commit that referenced this pull request Oct 2, 2026
Implement Task 4 (PR 1d) of the ucp-schema codegen pipeline:
- Wire Commands::GenerateTypes in src/bin/ucp-schema.rs with --profile, --capability, --extension, --schema-dir (alias --schema-local-base), --schema-remote-base, --output, and --pretty.
- Implement CliExitCode for CodegenError and generalize write_json_output to <T: serde::Serialize + ?Sized>.
- Add CLI integration tests in tests/generate_types_test.rs covering stdout pretty/compact output, file output, repeatable/comma-delimited flags, and error exit codes.

Stacked PR Roadmap:
- PR 1a (#81): Identifier qualification, UCP keyword stripping, $ref rewriting
- PR 1b (#82): Directional schema slicing and $ref alignment
- PR 1c (#83): Capability/extension reachability, composition, and generate_types() library API
- PR 1d (this PR): CLI generate-types subcommand
- PR 2: Self-contained .well-known/ucp --profile scoping
- PR 3: Inline conditional variant hoisting and ordered anyOf union lowering
- PR 4: OpenAPI 3.1 REST binding assembly (generate-openapi)
gsmith85 added a commit that referenced this pull request Oct 2, 2026
Implement Task 4 (PR 1d) of the ucp-schema codegen pipeline:
- Wire Commands::GenerateTypes in src/bin/ucp-schema.rs with --profile, --capability, --extension, --schema-dir (alias --schema-local-base), --schema-remote-base, --output, and --pretty.
- Implement CliExitCode for CodegenError and generalize write_json_output to <T: serde::Serialize + ?Sized>.
- Add CLI integration tests in tests/generate_types_test.rs covering stdout pretty/compact output, file output, repeatable/comma-delimited flags, and error exit codes.

Stacked PR Roadmap:
- PR 1a (#81): Identifier qualification, UCP keyword stripping, $ref rewriting
- PR 1b (#82): Directional schema slicing and $ref alignment
- PR 1c (#83): Capability/extension reachability, composition, and generate_types() library API
- PR 1d (this PR): CLI generate-types subcommand
- PR 2: Self-contained .well-known/ucp --profile scoping
- PR 3: Inline conditional variant hoisting and ordered anyOf union lowering
- PR 4: OpenAPI 3.1 REST binding assembly (generate-openapi)
@gsmith85
gsmith85 force-pushed the feat/codegen-slicing branch from 88c578b to 4ed1ea1 Compare October 2, 2026 16:37
@gsmith85
gsmith85 force-pushed the feat/codegen-slicing branch from 4ed1ea1 to 7b74335 Compare October 7, 2026 06:00
@gsmith85
gsmith85 force-pushed the feat/codegen-slicing branch 2 times, most recently from 9380b3c to e626830 Compare October 8, 2026 00:32
Base automatically changed from feat/codegen-normalizer to main October 13, 2026 16:45
@damaz91 damaz91 added status:under-review and removed status:needs-triage Signal that the PR is ready for human triage labels Oct 14, 2026

@damaz91 damaz91 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM! Clean separation between directional slicing and $ref alignment, and nice handling of the CompleteRequest -> UpdateRequest fallback.

(Noted while reading ahead that the total.json / totals.json / order.json edge cases in is_non_empty_request_slice and has_directional_annotations are already addressed up-stack in #86.)

Comment thread src/codegen/normalizer.rs Resolved
Comment thread src/codegen/normalizer.rs Resolved
Extend `src/codegen/normalizer.rs` with the directional slicing and reference alignment passes needed to compile UCP-annotated schemas into standard JSON Schema `$defs` entries:
- `normalize_def_schema`: strip UCP keywords, rewrite `$ref` targets to `#/$defs/<PascalName>`, and normalize `additionalProperties: true` onto open object definitions
- `has_directional_annotations` and `schema_supports_complete`: detect `ucp_request`/`ucp_response` annotations and `"complete"` lifecycle operations via `loader::for_each_schema_object`
- `slice_directional_schemas`: resolve `CreateRequest`, `UpdateRequest`, optional `CompleteRequest`, and `Response` ("read") slices via `resolver::resolve`, omitting empty request slices for response-only nested value types
- `align_directional_refs`: rewrite `#/$defs/<Target>` inside directional request slices to `#/$defs/<Target><Suffix>` when present in `known_defs` (falling back to `<Target>UpdateRequest` for `CompleteRequest` slices)

This PR is **Part 2 (PR 1b)** of a stacked series introducing a unified two-layer codegen pipeline to `ucp-schema` so downstream SDKs (`python-sdk`, `js-sdk`, `java-sdk`) can delete their bespoke schema preprocessors and generate idiomatic models directly from UCP schemas:

- **PR 1a (`feat/codegen-normalizer`, #81)**: Naming qualification, UCP keyword stripping, and `$ref` rewriting utilities (`src/codegen/normalizer.rs`).
- **PR 1b (this PR)**: Base definition normalization, directional request/response slicing (`CreateRequest` / `UpdateRequest` / `CompleteRequest` / `Response`), and directional `$ref` alignment.
- **PR 1c**: Capability/extension reachability, extension composition, and the `generate_types()` library API (`src/codegen/mod.rs`).
- **PR 1d**: `ucp-schema generate-types` CLI subcommand (`--schema-dir`, `--capability`, `--extension`, `--output`, `--pretty`).
- **Phase 2 (PR 2)**: `--profile` discovery, remote schema fetching via `ucp.capabilities[].schema` URLs, and self-describing `x-ucp-metadata`.
- **Phase 3 (PRs 3a-3d)**: Polymorphic union reification (open-union `anyOf` with `<Union>Base` fallback) and `ucp-schema generate-openapi` (Layer 2 REST path projection).
@gsmith85
gsmith85 force-pushed the feat/codegen-slicing branch from e626830 to dd19a22 Compare October 14, 2026 22:04
@gsmith85
gsmith85 merged commit b8433ff into main Oct 14, 2026
22 checks passed
@gsmith85
gsmith85 deleted the feat/codegen-slicing branch October 14, 2026 22:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants