fix(validation): count a scoped @context term only where it is a property - #135
Merged
Conversation
…erty A schema must reflect every $ref in its @context (OOLD-CMP-b926), including the ones reached from $defs, so the root context carries terms for properties the root object never holds. embedded_properties counted every scoped term, which put an unmatchable property into the derived frame and made framing return nothing. Closes OO-LD/oold-schema#149
Contributor
Release previewMerging this PR would release v0.18.1 (current: Changelog preview (truncated)## v0.18.1 (2026-08-27)
### Bug Fixes
- **validation**: Count a scoped @context term only where it is a property
([`4f4c39c`](https://github.com/OO-LD/oold-python/commit/4f4c39c0723a423d49df54ff742abb389d239f43))
### Code Style
- Apply ruff format to the new test
([`c23383d`](https://github.com/OO-LD/oold-python/commit/c23383dad981c03c46960a362094090b333831c2))
### Continuous Integration
- Gate the parity check against the reference
([`fdb9007`](https://github.com/OO-LD/oold-python/commit/fdb9007377aab115da3b2661e59834090af79314))
### Documentation
- **validation**: State invariants in comments, not prior behaviour
([`4baf212`](https://github.com/OO-LD/oold-python/commit/4baf212f85a6f97fc9f6f16eee07ab2a0bcd42d5))
Preview via python-semantic-release and conventional commits. |
This was referenced Aug 27, 2026
Contributor
📊 Benchmark ResultsClick to see benchmark comparisonThreshold: 1.3x (30% slower triggers a regression warning) Note: Benchmarks are informational only and won't fail the build. 💡 Tip: Download the |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Contributor
📊 Benchmark ResultsClick to see benchmark comparisonThreshold: 1.3x (30% slower triggers a regression warning) Note: Benchmarks are informational only and won't fail the build. 💡 Tip: Download the |
simontaurus
added a commit
to OO-LD/oold-schema
that referenced
this pull request
Aug 27, 2026
#151) Mirrors OO-LD/oold-python#135 so the reference implementation and oold-python stay in parity, and so the fix travels with validate.mjs into oold-js. Refs #149
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes OO-LD/oold-schema#149. Repro from the issue now passes:
30 ok, 0 failed, 0 warning(s).Cause
embedded_properties(src/oold/validation/frame.py) took every@contextterm carrying a scoped@context, without checking that the schema declares a property of that name.OOLD-CMP-b926requires a schema to reflect every$refin its@context, including$refs reached from$defs. In the repro,amountlives in$defs/Component, so its term is in the root context by that rule, but the root object has noamountproperty and no instance of it can. Counting the term had two effects, both from the same call:roundtrip()choseframedovercompactedschema_to_frame()emitted"amount": {}A frame property is a match filter, so the frame selected nodes carrying
amount. The generated instance{"type": ["Composition"]}carries none, framing returned nothing, andtypewas reported lost.typewas never involved; it was just the only property present.This is why the two branches in the issue looked contradictory: removing the scoped
@contextremoved the phantom embed, so the round-trip fell back to compaction and passed, whileOOLD-CMP-5266returned. The rule and the check never actually disagreed.Fix
Require a scoped term to name a property the schema declares.
schemahere is dereferenced, socollect_composed_propertiessees properties inherited throughallOfas well.No spec change:
OOLD-CMP-5266recommends exactly what the round-trip supports, and the three warnings in the materials schemas can now be acted on.Verification
pytest: 558 passed, 9 skipped, plus a regression test for the$defscaseoold-schema/examples: 380 ok, 0 failed, unchanged warningsvalidate.mjs: 6 passedscripts/schema_to_frame.mjsin oold-schema has the same defect; it is not exercised by the parity fixtures. Fixed there in OO-LD/oold-schema#151 so the reference implementation carries it intooold-js.