Skip to content

Navigation and validation - #31

Merged
handrews merged 3 commits into
mainfrom
navigation-and-validation
Sep 24, 2026
Merged

handrews merged 3 commits into
mainfrom
navigation-and-validation

Conversation

@handrews

Copy link
Copy Markdown
Owner

No description provided.

handrews and others added 3 commits September 23, 2026 11:52
…(P16)

`resolve_ref`'s pointer walk and `child` applied the identifier extractor
to every object they stepped onto, data included. A `$ref` into `enum`,
`examples` or an unknown keyword that held an `$id` rebased onto it:
evaluation raised `unknown schema` for a URI that was never an
identifier, or resolved relative `$ref`s against the wrong base.

Navigation cannot tell a schema position from data without re-running
the walk, so it now asks what the walk concluded. It rebases only when
the registry holds a resource at that URI and the node is that resource:
by identity, or `json_equal` for a resource an equal copy elsewhere took
over (P15). The check runs only where an `$id` is present, so `child`'s
hot path costs what it did. `_entered` replaces `_dialect_after`, whose
fallback existed for exactly this drift.

One test pinned the old behavior and now asserts the new answer: a
draft-07 `$id` beside a `$ref` is not a base, so a pointer through it
stays in the enclosing resource.

Resolves DESIGN.md §7 "Pointer navigation reads identifiers in
non-schema positions".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only the registration walk knows which positions are schemas, which
`$id`s start resources, and which dialect each resource is under.
`survey` runs that walk through the same P13 transaction, reads the
completed indexes, and rolls everything back unconditionally. It
returns one `SurveyedResource` per resource: base URI, dialect, document
pointer, parent, and the location chain and source captured before the
rollback.

The engine's embedded-dialect retry loop now takes the attempt as a
callable, so a survey assembles dialects the same way a registration
does. No behavior change; groundwork for per-resource metaschema
validation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`validate_schemas` applied the root dialect's metaschema to the whole
document, which cut both ways. A valid draft-07 resource embedded in a
2020-12 document was refused for its array-form `items`, and an invalid
2020-12 resource embedded in a draft-07 document registered, because
draft-07's metaschema knows none of its keywords.

Following 2020-12 core §9.3.3, the root and every embedded resource
whose dialect differs from its parent's now form separate regions. Each
region is checked against its own metaschema, with the regions nested
inside it masked to `{}`; a same-dialect resource is checked within its
parent. A survey (registration dry run) finds the regions before
anything registers, and a failure names the region's resource, with the
chain and source the survey captured. A region whose metaschema is
unavailable is skipped, as the root always was (owner ruling). If the
walk itself refuses the document, the root is checked against its
metaschema first, so a document broken both ways still reports
`SchemaValidationError`.

Also fills in the missing Why and Revisit cells of the P15 and P16 rows.

Resolves DESIGN.md §7 "Per-resource metaschema validation".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@handrews
handrews merged commit 2ace310 into main Sep 24, 2026
6 checks passed
@handrews
handrews deleted the navigation-and-validation branch September 24, 2026 19:36
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.

1 participant