Skip to content

Fix AutoDetectionDraft falling back to Draft 07 for every property-level schema - #187

Merged
wol-soft merged 7 commits into
masterfrom
claude/autodetection-draft-ref-bug-dyf4j3
Aug 7, 2026
Merged

Fix AutoDetectionDraft falling back to Draft 07 for every property-level schema#187
wol-soft merged 7 commits into
masterfrom
claude/autodetection-draft-ref-bug-dyf4j3

Conversation

@wol-soft

@wol-soft wol-soft commented Aug 7, 2026

Copy link
Copy Markdown
Owner

$schema is a document-root-only keyword, but AutoDetectionDraft re-derived it
from whichever JsonSchema node it was handed. Every navigated subschema
(properties, $ref targets, composition branches, ...) never carries $schema,
so draft detection always fell back to Draft 07 outside the literal document
root, silently dropping Draft 2019-09-only behavior like minContains/maxContains.

JsonSchema now tracks the $schema URI in effect for each node: the node's own
$schema if declared, otherwise inherited from the nearest ancestor. navigate()
and withJson() re-derive it after cloning, so the inherited value survives
down the whole tree while a local override on an embedded schema resource
(a subschema with its own $id, per the JSON Schema core spec) still takes
effect for its own descendants.

Fixes #186

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_019nLMK2e753YDaXexRr1Z1B

claude added 3 commits August 6, 2026 23:38
…vel schema

$schema is a document-root-only keyword, but AutoDetectionDraft re-derived it
from whichever JsonSchema node it was handed. Every navigated subschema
(properties, $ref targets, composition branches, ...) never carries $schema,
so draft detection always fell back to Draft 07 outside the literal document
root, silently dropping Draft 2019-09-only behavior like minContains/maxContains.

JsonSchema now tracks the $schema URI in effect for each node: the node's own
$schema if declared, otherwise inherited from the nearest ancestor. navigate()
and withJson() re-derive it after cloning, so the inherited value survives
down the whole tree while a local override on an embedded schema resource
(a subschema with its own $id, per the JSON Schema core spec) still takes
effect for its own descendants.

Fixes #186

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nLMK2e753YDaXexRr1Z1B
An allOf branch failure surfaces as a generic AllOfException in fail-fast
mode, discarding the underlying MinContainsException/MaxContainsException;
the specific error is only preserved in the branch's error collection when
collecting errors. Switch the AutoDetectionDraft regression test to collect
errors and unwrap the branch-specific exception, matching the existing
RequiredPropertyTest pattern for allOf branch assertions.

Verified against master: the full suite (2971 tests) passes, and the new
test fails as expected when the fix in JsonSchema/AutoDetectionDraft is
reverted, confirming it actually exercises the regression.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nLMK2e753YDaXexRr1Z1B
Claude's session-local issue/topic tracking notes under .claude/ are
working context only and must never be committed (per this repo's own
CLAUDE.md policy); ignoring the directory keeps it out of git status
without requiring it to be staged or tracked.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nLMK2e753YDaXexRr1Z1B
@coveralls

coveralls commented Aug 7, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 31141920609

Coverage increased (+0.001%) to 98.76%

Details

  • Coverage increased (+0.001%) from the base build.
  • Patch coverage: 8 of 8 lines across 2 files are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 7341
Covered Lines: 7250
Line Coverage: 98.76%
Coverage Strength: 580.19 hits per line

💛 - Coveralls

claude added 4 commits August 7, 2026 02:10
The previous tests only covered inheritance (a node with no $schema of its
own picking up the document root's declared draft). They didn't cover the
other half of the fix: a node that IS itself an embedded schema resource
(carries its own $id) may re-declare $schema per the JSON Schema core spec,
and that override must win locally and keep propagating to its own
descendants rather than reverting to the root's value one level down.

Adds unit coverage on JsonSchema directly (inherit / override / propagate
to descendants / withJson parity) plus a pipeline-level test proving
AutoDetectionDraft actually honours the override end-to-end: a $defs entry
that re-declares the draft-07 $schema drops minContains/maxContains
enforcement while a sibling $defs entry with no override keeps it, despite
both being reached from the same 2019-09 document root.

All 6 new assertions fail against the pre-fix source, confirming they
exercise the fix rather than passing vacuously.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nLMK2e753YDaXexRr1Z1B
testAutoDetectionDraftAppliesRootDraftToPropertyLevelRefSiblingMerge and
its fixture reached a $ref target through an allOf composition branch, but
that path funnels through the same JsonSchema::navigate()/withJson() the
fix lives in — the composition wrapper's synthetic JSON carries no $schema
of its own, so it just re-derives the already-inherited value and hands
off to the same navigate() call the plain-$ref test already exercises.

testAutoDetectionDraftHonoursASchemaOverrideDeclaredByAnEmbeddedResource
covers inheritance AND override more directly (and without the
AllOfException-unwrapping boilerplate this test needed), so the allOf
variant added no coverage beyond mirroring the issue's literal reproduction
shape.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nLMK2e753YDaXexRr1Z1B
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nLMK2e753YDaXexRr1Z1B
Relocates the $schema-override regression coverage out of ArrayContainsTest
into tests/Issues/Issue/Issue186Test.php with its fixture under
tests/Schema/Issues/186/, matching this repo's convention for issue-driven
regression tests (see Issue179Test, Issue169Test, etc.) instead of living
alongside the general contains/minContains/maxContains behavior tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nLMK2e753YDaXexRr1Z1B
@wol-soft wol-soft closed this Aug 7, 2026
@wol-soft wol-soft reopened this Aug 7, 2026
@wol-soft
wol-soft merged commit f647e32 into master Aug 7, 2026
9 checks passed
wol-soft added a commit that referenced this pull request Aug 7, 2026
…-draft-aware

Pulls in the AutoDetectionDraft fix (#187) for property-level $schema
inheritance/override, which this branch's own investigation (see
.claude/topics/property-merger-consolidation/) had independently found and
was about to fix separately.

# Conflicts:
#	src/Model/SchemaDefinition/JsonSchema.php
@wol-soft
wol-soft deleted the claude/autodetection-draft-ref-bug-dyf4j3 branch August 8, 2026 09:22
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.

AutoDetectionDraft silently falls back to Draft 07 for every property-level schema

3 participants