Conversation
Introduce a validation harness that ensures every JSON example in the spec
docs is either validated against UCP schemas or explicitly skipped. This
catches documentation drift — when schemas change, stale examples break CI
instead of silently misleading readers.
## Contract
Every ```json block requires an annotation on the preceding line:
<!-- ucp:example schema=shopping/checkout op=read -->
<!-- ucp:example schema=shopping/checkout path=$.totals op=read -->
<!-- ucp:example schema=shopping/cart op=create direction=request -->
<!-- ucp:example skip reason="JSON-RPC transport binding" -->
Unannotated blocks are hard failures.
Principle: "if you open it, you own it." When an example opens an object's
braces, every required field (per the resolved schema for the declared
op + direction) must be shown or acknowledged. This applies recursively.
Three-tier value contract for annotated (non-skip) examples:
- Full value: validated against schema (types, constraints, enums)
- Required fields ({ ... }, [ ... ], "..."): field must exists but
values are optional; scaffold fills it for validation.
- Absent fields only permitted for optional schema fields
## Pipeline
1. Extract — find annotated ```json blocks (handles tab indentation)
2. Unwrap — strip HTTP headers from request/response examples
3. Expand — substitute {{ ucp_version }} with valid date
4. Preprocess — convert bare ... to valid JSON ({ ... } → {"...":"..."})
5. Coverage — walk resolved schema, verify required fields acknowledged
6. Strip — remove ellipsis markers
7. Merge — deep-merge into scaffold (example wins, scaffold fills gaps)
8. Validate — ucp-schema validate on merged payload
9. Report — map errors to source file:line
## Bugs caught and fixed
- checkout.md: item missing required `price` field in disclosure example
- checkout.md: totals array missing required `subtotal` entry
- checkout-rest.md: business outcome used non-schema `available_quantity`
field on line_item; replaced with message-based pattern
- discount.md (4 instances): `quantity` wrongly nested inside `item`
object instead of on `line_item` — schema requires quantity at line_item
level
- discount.md: `price` and `title` shown in create requests where schema
omits them (request-only fields: only `item.id` is valid)
## Current state
268 blocks across 39 files:
- 52 validated (REST request/response pairs, core spec examples, error
responses, extension examples)
- 216 skipped (transport bindings, schema definitions, configs — future
work: payload_path= for JSON-RPC unwrap)
Run: python3 scripts/validate_examples.py --schema-base source/schemas/
drewolson-google
left a comment
There was a problem hiding this comment.
Looks good, one small comment on empty request bodies.
|
|
||
| === "Request" | ||
|
|
||
| <!-- ucp:example skip reason="empty request body" --> |
There was a problem hiding this comment.
Can we make the validator / annotation handle empty request bodies? This is a valid request, so having to skip it feels off.
There was a problem hiding this comment.
The scaffold approach would require that we write (and maintain) a scaffold for most types, right? An alternative approach that I was exploring was:
- Force every example to not omit any required root level properties (value can be ellipsis)
- Use ucp-schema to resolve the schema based on the annotation
- Use jsonschema library to validate the example against the schema
- Use jsonschema's extend function to create a custom validator class that skips ellipses
May be more convoluted, but would save the extra work of maintaining additional scaffold files. Curious to hear your thoughts.
|
I have no issue with this PR, but I would love to also challenge the fundamental requirement to have all required top-level keys be provided in an unignored example. Can we solve this using a custom key like This can be viewed as non-blocking if we just want to get V0 out, but it could be nice to disallow the "skip" unless you are providing completely custom, non-ucp json 😄 |
Validation harness that ensures every JSON example in the spec docs is validated against UCP schemas. Catches documentation drift — when schemas change, stale examples break CI and docs builds.
Contract
Every json block requires an HTML comment annotation on the preceding line:
Unannotated blocks are hard failures.
Core rule: "if you open it, you own it." When an example opens an object's braces, every required field (per the resolved schema for the declared op + direction) must be shown or acknowledged with an ellipsis. This applies recursively.
Three-tier value contract for annotated (non-skip) examples:
{ ... },[ ... ],"..."Pipeline
{{ ucp_version }}with valid date...to valid JSON ({ ... }→{"...":"..."})ucp-schema validateon merged payloadfile:lineBugs caught and fixed
pricefield in disclosure examplesubtotalentryavailable_quantityfield on line_item; replaced with message-based patternquantitywrongly nested insideitemobject instead of online_item— schema requires quantity at line_item levelpriceandtitleshown in create requests where schema omits them (request-only fields: onlyitem.idis valid)Current state
python3 scripts/validate_examples.py --schema-base source/schemas/— 52 passed, 0 failed, 0 errors268 blocks across 39 files:
payload_path=for JSON-RPC unwrap)🟢 Pausing fixing the rest (skipped) to get feedback: 🟢
Type of change