Skip to content

docs(specification): centralize shared types per reference.md (#412)#443

Open
sriakula1 wants to merge 1 commit into
Universal-Commerce-Protocol:mainfrom
xpaysh:docs/centralize-shared-types-412
Open

docs(specification): centralize shared types per reference.md (#412)#443
sriakula1 wants to merge 1 commit into
Universal-Commerce-Protocol:mainfrom
xpaysh:docs/centralize-shared-types-412

Conversation

@sriakula1
Copy link
Copy Markdown

Description

Closes #412.

PR #226 made reference.md the canonical render destination for all types/ schemas — cross-references already resolve there via the redirect in create_link. The gap @igrigorik called out: capability pages still re-render the same types/... field tables inline, so each shared type (Buyer, Signals, Attribution, Total, Line Item, Message, Link, …) is rendered three times — once each in cart.md, checkout.md, catalog/index.md — alongside the canonical render in reference.md.

From the issue, the desired end state:

  1. Capability pages stop rendering types/... tables inline. Each entity section keeps its heading and brief prose context (the "what is this and why is it here" paragraph), but links to reference.md#<anchor> instead of duplicating the table render.
  2. reference.md is the single source of truth for shared-type field tables.

This PR implements that without churning a single .md file.

What changed

main.py only. Two macros now detect when the requested schema lives under a types/ directory (common/types/ or any <vertical>/types/) and, when the caller is anything other than reference.md, emit a Markdown link to the canonical entry instead of rendering the table inline:

  • schema_fields(entity, spec) — handles calls like schema_fields('types/signals', 'cart'), schema_fields('buyer', 'checkout'), schema_fields('types/line_item_create_req', 'cart'), etc. Renders:

    See [Signals](site:specification/reference/#signals) in the [Schema Reference](reference.md) for the canonical field definition.
    
  • extension_schema_fields(entity, spec) — handles calls like extension_schema_fields('types/pagination.json#/$defs/response', 'cart') and extension_schema_fields('types/payment_instrument.json#/$defs/selected_payment_instrument', 'checkout'). Renders a single anchor link.

  • reference.md still renders the full tables (via auto_generate_schema_reference and direct macro calls with spec_file_name='reference'); the source of truth is unchanged.

All existing capability-page macro calls ({{ schema_fields('types/signals', 'cart') }}, etc.) work unmodified — no .md edits required. The surrounding prose context already present on each capability page (e.g. cart.md's paragraphs above Signals/Attribution/Total) is preserved untouched.

Tradeoff acknowledged

As @igrigorik noted in the issue: cross-linking out to reference.md does break the flow of reading a single capability page end-to-end. The counter-argument — that UCP has many shared types and replicating them across every capability page creates anchor-resolution problems and maintenance churn — is the reason #226 went this way, and is the same reason here.

Files changed

  • main.py — added _resolves_to_shared_type() and _render_shared_type_link() helpers; one early-return branch in schema_fields; one early-return branch in extension_schema_fields.

Local build

mkdocs build exercises the modified macros and they short-circuit cleanly for every types/... capability-page caller. The full build still needs the ucp-schema Rust CLI for the remaining (non-types) macro calls on reference.md itself — that's unchanged from main, and CI runs the canonical build.

Verified via a small harness (mock mkdocs env, call the macro directly):

  • schema_fields('types/signals', 'cart') → link to reference.md#signals
  • schema_fields('buyer', 'checkout') → link to reference.md#buyer
  • schema_fields('types/line_item_create_req', 'cart') → link to reference.md#line-item-create-request
  • extension_schema_fields('types/pagination.json#/$defs/response', 'cart')reference.md#pagination-response
  • schema_fields('types/signals', 'reference') → falls through to inline render (correct) ✓

Deferred (worth a separate issue)

@wry-ry suggested replacing the "Required" column with a "Visibility" column (required / optional / omit) on rendered tables. That's a great direction but needs an explicit omit annotation in the schemas, which isn't in the data model today. I left it out of this PR so the diff stays narrow and reviewable — happy to follow up with a separate proposal once the schema-side question is settled.

Type of change

  • Documentation update
  • Bug fix
  • New feature
  • Breaking change

Reviewer notes

Tagging @igrigorik and @wry-ry since you both engaged on the issue. Per MAINTAINERS.md, docs/specification/ ultimately wants tech-council eyes — please route as appropriate.

@google-cla
Copy link
Copy Markdown

google-cla Bot commented May 16, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

…sal-Commerce-Protocol#412)

PR Universal-Commerce-Protocol#226 made `reference.md` the canonical render destination for all
`types/` schemas (cross-references already resolve there via the
redirect logic in `main.py`). However, capability pages still
re-rendered the same `types/...` field tables inline, leaving three
copies of each shared type (cart.md, checkout.md, catalog/index.md)
alongside the canonical render in reference.md.

This change finishes the centralization:

* `schema_fields(entity, spec)` and `extension_schema_fields(entity,
  spec)` now detect when the requested schema lives under a `types/`
  directory (common or vertical) and, for any caller other than
  `reference.md`, emit a Markdown link to the canonical entry instead
  of an inline table.
* `reference.md` continues to render the full tables via
  `auto_generate_schema_reference`, so the source of truth is
  unchanged.
* Existing capability-page macro calls (`{{ schema_fields('types/
  signals', 'cart') }}`, etc.) work unmodified; the surrounding prose
  context on each capability page is preserved.

The macro change is intentionally minimal: no `.md` files are touched,
keeping the diff narrow and reversible.

Out of scope (follow-ups):

* wry-ry's suggestion in the issue thread to replace the "Required"
  column with a "Visibility" column (`required` / `optional` / `omit`)
  is deferred — it needs an `omit` annotation in the schemas which
  doesn't exist today. Worth a separate issue once the data model is
  agreed.
@sriakula1 sriakula1 force-pushed the docs/centralize-shared-types-412 branch from f8d385f to 3ff2d30 Compare May 16, 2026 06:32
@sriakula1
Copy link
Copy Markdown
Author

@googlebot I signed it!

1 similar comment
@sriakula1
Copy link
Copy Markdown
Author

@googlebot I signed it!

@igrigorik igrigorik added this to the Working Draft milestone May 22, 2026
@igrigorik igrigorik self-assigned this May 22, 2026
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.

Complete the shared-type centralization started in #226

2 participants