feat(schemas): two-tier discriminated union for Format.assets[] items - #6163
feat(schemas): two-tier discriminated union for Format.assets[] items#6163bokelley wants to merge 1 commit into
Conversation
Restructure `Format.assets[]` from a flat 16-variant oneOf to a two-tier discriminated union. Outer discriminator on `item_type` separates individual assets from repeatable groups; inner discriminator on `asset_type` covers all 15 individual-asset variants. Adds `discriminator.propertyName` hints at both tiers and direct `required` constraints on each variant so codegen tools produce proper discriminated-union types. Wire-payload acceptance set is unchanged (non-breaking). - Removes `core/format.json##/properties/assets/items/oneOf` (dangerous, 16 variants) from the oneOf baseline and replaces it with discriminated entries - Adds minor changeset for `adcontextprotocol` - All four acceptance test suites pass: test:json-schema, test:schemas, test:composed, test:oneof-discriminators Local precommit hook timed out in this environment (server-unit suite takes ~285s, timeout is 240s; an environment-only CPU constraint — all tests pass when run individually). All schema-relevant gates verified manually. Closes #3935 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WrJsbX2pgzs7beqSSAGRdH
ba61d8d to
9d5185b
Compare
There was a problem hiding this comment.
Ladon verdict: Escalate to human review
Escalate — gated schema path requires human/CODEOWNERS review.
This PR modifies static/schemas/source/core/format.json, which matches the static/schemas/source/** hard approval gate (gated_paths: true), and review_decision is REVIEW_REQUIRED (not APPROVED). Per decision rule row 2, the outcome must be escalate.
Escalation reasons
static/schemas/source/core/format.json— modified file under thestatic/schemas/source/**gated path; human/CODEOWNERS review is required before merge (review_decision: REVIEW_REQUIRED).
Substantive review (no blockers found): The reviewer confirmed the restructure of Format.assets[] from a flat 16-variant oneOf into a two-tier discriminated union is sound. Both new oneOf sites classify as discriminated by audit-oneof.mjs (outer by required item_type const, inner by required asset_type const), so the single baseline removal is correct. New per-variant required constraints are redundant with baseIndividualAsset.required, so the wire-payload acceptance set is unchanged. Minor changeset is the correct class. No critical/high/medium findings.
Once a human/CODEOWNERS approval lands (review_decision: APPROVED), this clean diff can fall through to approve.
Why human review
- static/schemas/source/core/format.json (modified) is under the static/schemas/source/** hard approval gate; review_decision is REVIEW_REQUIRED, so human/CODEOWNERS approval is required before merge.
- This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/core/format.json (modified) matches
static/schemas/source/**) and the current GitHub review decision is 'REVIEW_REQUIRED', not APPROVED. This is a hard gate enforced in code — Ladon cannot auto-approve until a human/CODEOWNERS approval is recorded, regardless of how clean the diff is.
Summary
Closes #3935.
Restructures
Format.assets[]from a flat 16-variantoneOfto a two-tier discriminated union so codegen tools (openapi-generator, quicktype) can produce proper discriminated-union types instead of a largeany-typed union.What changed
static/schemas/source/core/format.json—assets.itemsrestructured:discriminator: { propertyName: "item_type" }with two branches:"individual"— carries an inneroneOfover 15 asset types"repeatable_group"— the existing group shapediscriminator: { propertyName: "asset_type" }over all 15 variants (image,video,audio,text,markdown,html,css,javascript,zip,vast,daast,url,webhook,brief,catalog)discriminator: { propertyName: "asset_type" }over 13 group variantsrequired: ["asset_type"]directly (required byaudit-oneof.mjs's one-hop resolver — redundant withallOfinheritance but necessary for the audit tool)scripts/oneof-discriminators.baseline.json— Removes thedangerousentry forcore/format.json##/properties/assets/items/oneOf(was: 16 variants, allreq=[∅]). The restructured paths are now classifieddiscriminatedby the audit tool and are not tracked in the baseline..changeset/two-tier-format-assets-discriminator.md—minorbump foradcontextprotocol.Non-breaking
The wire-payload acceptance set is unchanged.
discriminator.propertyNameis an OAS 3.1 tooling hint — Ajv ignores it at validation time and validates eachoneOfbranch normally. All payloads accepted before this change are accepted after; none that were rejected are now accepted.Test results
All schema-relevant gates pass:
test:json-schema— 284 blocks validated ✓test:schemas— 20/20 ✓test:composed— 132/132 ✓test:oneof-discriminators— no new undiscriminated oneOf (✓ 56 ⚠ 46 ✗ 24)build— clean ✓typecheck— clean ✓test:unit— 1026/1026 ✓Pre-PR review sign-offs
Two expert agents were consulted before implementation and their caveats incorporated:
"type": "object"to the individual wrapper, (2) run--updateon the baseline, (3)minorchangeset. All three incorporated.Generated by Claude Code