Repository navigation
Run contracts SHACL validation of examples in CI - #262
Merged
Merged
Conversation
The contracts unit tests validate inline snippets only, so a regression in an example file or a malformed shape (e.g. a property shape that loses its sh:path) could reach develop unnoticed. Add a build step that runs dprod-contracts/validate.py, which parses every contracts TTL and validates each example against the shapes, failing the build on any error. Resolves: #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tonyseale
requested review from
FroehlichMarcel,
jgeluk,
joshcornejo,
matthiasautrata and
rivettp
as code owners
October 8, 2026 15:57
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
15 tasks
matthiasautrata
approved these changes
Oct 13, 2026
matthiasautrata
left a comment
Contributor
There was a problem hiding this comment.
Reviewed: up to date with develop, checks green; validate.py passes on develop and exits 1 on failure, so the step gates the build. Step 1 of #275.
This was referenced Oct 13, 2026
jgeluk
added a commit
to matthiasautrata/dprod
that referenced
this pull request
Oct 21, 2026
[Carried forward onto develop for EKGF#275 by Matthias Autrata: conflicts resolved against EKGF#244/EKGF#245/EKGF#262/EKGF#268/EKGF#270/EKGF#272, the namespace changed from https://www.omg.org/spec/DPROD/dprod/ to https://ekgf.org/dprod/spec/develop/, and EKGF#244's duty-only shape and test migrated from dprod:recurrence to dprod:schedule, which is not duty-only.]
jgeluk
added a commit
to matthiasautrata/dprod
that referenced
this pull request
Oct 21, 2026
Shapes: accept tab-separated POSIX crontab fields and reject smuggled tab/CR/LF content; allow EXDATE/RDATE lines in RFC 5545 expressions while rejecting non-standard or duplicate RRULE parts; reject a dprod:scheduleTimeZone that conflicts with the embedded TZID; move the IRI-identifier message onto its own shape so it no longer annotates unrelated violations. Ontology: every dprod:ScheduleFormat now declares dprod:carriesTimeZone, and the timezone-required rule keys on it so extension formats get the same enforcement as POSIX crontab. Semantics: schedule errors freeze the affected duty (Rule D-FREEZE), surface in the result's errors field, and the processor registry is part of Σ, so the totality and determinism theorems hold for unprocessable schedules too. Tests and CI: every schedule case is validated both with the ontology graph and in the bare documented CLI configuration, making the sh:class constraints falsifiable; the obsolete-recurrence sweep covers specification.md; validate.py runs in the build workflow. Docs: define the previously missing example schedules, rewrite the RRULE components table as complete expressions, and sync the guide checklist and specification with the new rules. [Carried forward onto develop for EKGF#275 by Matthias Autrata: the build-spec.yml change is dropped (EKGF#262 already runs validate.py in CI), and the namespace in the new shapes is the develop one. Schedule errors are fitted to the error model of EKGF#267: instead of an `errors` field on a Permit result, an unprocessable schedule of a collected duty is gathered in E₅ and gives Failure on the Permit path, like E₃ and E₄. Deny and NotApplicable are unaffected, since resolving the schedule can only add duties or violations. EvaluationError admits ScheduleError, and §9.7's completion covers schedule errors.] Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jgeluk
added a commit
to matthiasautrata/dprod
that referenced
this pull request
Oct 21, 2026
[Carried forward onto develop for EKGF#275 by Matthias Autrata: conflicts resolved against EKGF#244/EKGF#245/EKGF#262/EKGF#268/EKGF#270/EKGF#272, the namespace changed from https://www.omg.org/spec/DPROD/dprod/ to https://ekgf.org/dprod/spec/develop/, and EKGF#244's duty-only shape and test migrated from dprod:recurrence to dprod:schedule, which is not duty-only.]
jgeluk
added a commit
to matthiasautrata/dprod
that referenced
this pull request
Oct 21, 2026
Shapes: accept tab-separated POSIX crontab fields and reject smuggled tab/CR/LF content; allow EXDATE/RDATE lines in RFC 5545 expressions while rejecting non-standard or duplicate RRULE parts; reject a dprod:scheduleTimeZone that conflicts with the embedded TZID; move the IRI-identifier message onto its own shape so it no longer annotates unrelated violations. Ontology: every dprod:ScheduleFormat now declares dprod:carriesTimeZone, and the timezone-required rule keys on it so extension formats get the same enforcement as POSIX crontab. Semantics: schedule errors freeze the affected duty (Rule D-FREEZE), surface in the result's errors field, and the processor registry is part of Σ, so the totality and determinism theorems hold for unprocessable schedules too. Tests and CI: every schedule case is validated both with the ontology graph and in the bare documented CLI configuration, making the sh:class constraints falsifiable; the obsolete-recurrence sweep covers specification.md; validate.py runs in the build workflow. Docs: define the previously missing example schedules, rewrite the RRULE components table as complete expressions, and sync the guide checklist and specification with the new rules. [Carried forward onto develop for EKGF#275 by Matthias Autrata: the build-spec.yml change is dropped (EKGF#262 already runs validate.py in CI), and the namespace in the new shapes is the develop one. Schedule errors are fitted to the error model of EKGF#267: instead of an `errors` field on a Permit result, an unprocessable schedule of a collected duty is gathered in E₅ and gives Failure on the Permit path, like E₃ and E₄. Deny and NotApplicable are unaffected, since resolving the schedule can only add duties or violations. EvaluationError admits ScheduleError, and §9.7's completion covers schedule errors.] Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tonyseale
pushed a commit
to matthiasautrata/dprod
that referenced
this pull request
Oct 29, 2026
[Carried forward onto develop for EKGF#275 by Matthias Autrata: conflicts resolved against EKGF#244/EKGF#245/EKGF#262/EKGF#268/EKGF#270/EKGF#272, the namespace changed from https://www.omg.org/spec/DPROD/dprod/ to https://ekgf.org/dprod/spec/develop/, and EKGF#244's duty-only shape and test migrated from dprod:recurrence to dprod:schedule, which is not duty-only.]
tonyseale
pushed a commit
to matthiasautrata/dprod
that referenced
this pull request
Oct 29, 2026
Shapes: accept tab-separated POSIX crontab fields and reject smuggled tab/CR/LF content; allow EXDATE/RDATE lines in RFC 5545 expressions while rejecting non-standard or duplicate RRULE parts; reject a dprod:scheduleTimeZone that conflicts with the embedded TZID; move the IRI-identifier message onto its own shape so it no longer annotates unrelated violations. Ontology: every dprod:ScheduleFormat now declares dprod:carriesTimeZone, and the timezone-required rule keys on it so extension formats get the same enforcement as POSIX crontab. Semantics: schedule errors freeze the affected duty (Rule D-FREEZE), surface in the result's errors field, and the processor registry is part of Σ, so the totality and determinism theorems hold for unprocessable schedules too. Tests and CI: every schedule case is validated both with the ontology graph and in the bare documented CLI configuration, making the sh:class constraints falsifiable; the obsolete-recurrence sweep covers specification.md; validate.py runs in the build workflow. Docs: define the previously missing example schedules, rewrite the RRULE components table as complete expressions, and sync the guide checklist and specification with the new rules. [Carried forward onto develop for EKGF#275 by Matthias Autrata: the build-spec.yml change is dropped (EKGF#262 already runs validate.py in CI), and the namespace in the new shapes is the develop one. Schedule errors are fitted to the error model of EKGF#267: instead of an `errors` field on a Permit result, an unprocessable schedule of a collected duty is gathered in E₅ and gives Failure on the Permit path, like E₃ and E₄. Deny and NotApplicable are unaffected, since resolving the schedule can only add duties or violations. EvaluationError admits ScheduleError, and §9.7's completion covers schedule errors.] Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tonyseale
pushed a commit
to matthiasautrata/dprod
that referenced
this pull request
Oct 29, 2026
…KGF#275) The spec says every Data Contract worked example validates against dprod-contracts-shapes.ttl, but nothing checked it: validate.py and the CI job from EKGF#262 cover only the Turtle examples in dprod-contracts/examples/. tests/test_examples.py now validates the contracts examples, their README blocks and the spec's eg-contract with the same settings as validate.py (RDFS inference, the vocabulary as ont_graph, advanced SHACL). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tonyseale
pushed a commit
to matthiasautrata/dprod
that referenced
this pull request
Oct 29, 2026
[Carried forward onto develop for EKGF#275 by Matthias Autrata: conflicts resolved against EKGF#244/EKGF#245/EKGF#262/EKGF#268/EKGF#270/EKGF#272, the namespace changed from https://www.omg.org/spec/DPROD/dprod/ to https://ekgf.org/dprod/spec/develop/, and EKGF#244's duty-only shape and test migrated from dprod:recurrence to dprod:schedule, which is not duty-only.]
tonyseale
pushed a commit
to matthiasautrata/dprod
that referenced
this pull request
Oct 29, 2026
Shapes: accept tab-separated POSIX crontab fields and reject smuggled tab/CR/LF content; allow EXDATE/RDATE lines in RFC 5545 expressions while rejecting non-standard or duplicate RRULE parts; reject a dprod:scheduleTimeZone that conflicts with the embedded TZID; move the IRI-identifier message onto its own shape so it no longer annotates unrelated violations. Ontology: every dprod:ScheduleFormat now declares dprod:carriesTimeZone, and the timezone-required rule keys on it so extension formats get the same enforcement as POSIX crontab. Semantics: schedule errors freeze the affected duty (Rule D-FREEZE), surface in the result's errors field, and the processor registry is part of Σ, so the totality and determinism theorems hold for unprocessable schedules too. Tests and CI: every schedule case is validated both with the ontology graph and in the bare documented CLI configuration, making the sh:class constraints falsifiable; the obsolete-recurrence sweep covers specification.md; validate.py runs in the build workflow. Docs: define the previously missing example schedules, rewrite the RRULE components table as complete expressions, and sync the guide checklist and specification with the new rules. [Carried forward onto develop for EKGF#275 by Matthias Autrata: the build-spec.yml change is dropped (EKGF#262 already runs validate.py in CI), and the namespace in the new shapes is the develop one. Schedule errors are fitted to the error model of EKGF#267: instead of an `errors` field on a Permit result, an unprocessable schedule of a collected duty is gathered in E₅ and gives Failure on the Permit path, like E₃ and E₄. Deny and NotApplicable are unaffected, since resolving the schedule can only add duties or violations. EvaluationError admits ScheduleError, and §9.7's completion covers schedule errors.] Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tonyseale
pushed a commit
that referenced
this pull request
Oct 29, 2026
Resolves #184. Supersedes #234. Step 7 of #275. Carries Jacobus Geluk's reusable schedule model (#234) forward onto `develop`. His two commits are kept with their authorship (`047dcb4`, `81777dd`); each has a note recording what changed while carrying it forward. Following Tony's and Jacobus's decision on #184, the anchor rule is: **the schedule's DTSTART/TZ sets the occurrence times, and activation only limits the range.** ## Stacking This branch is built on #268 → #272, plus a merge of #270 (`687ea77`), because the schedule errors use #268's error model and §3.2 combines with #270's `asset`. Until those three merge, this PR also shows their commits. The schedule work is the last four commits: - `047dcb4` Implement reusable schedule model (Jacobus) - `81777dd` Address review findings on the schedule model (Jacobus) - `7c67d39` Migrate the spec and examples from `dprod:recurrence` to `dprod:schedule` - `257e65c` Bump the contracts modification dates **Merge after #270, #268 and #272.** Then squash-merge directly (the shared changes are identical) or first rebase the four commits onto `develop`. ## Changes compared with #234 - **No frozen-archive changes, and no duplicate of #244.** #244's duty-only shape and test now cover `dprod:deadline`, `dprod:subjectOfDuty` and `dprod:objectOfDuty`. `dprod:schedule` is not duty-only. The obsolete `dprod:recurrence` is rejected by `RejectObsoleteRecurrenceShape` on every rule type, and there are tests for both. - **Develop namespace.** `https://www.omg.org/spec/DPROD/dprod/` is replaced throughout, including the TZID-conflict SPARQL. The namespace move stays at step 10 of #275. - **Schedule errors fit #267's fail-closed model.** There is no `errors` field on the Result. A schedule that can't be processed adds its error to a new set E₅ (`occurrences(d, Σ) = Error(e)`, computed in Step 3), and Step 7 returns `Failure(E₃ ∪ E₄ ∪ E₅)`. D-FREEZE: a duty whose schedule is in error makes no transition, so only the Permit path is affected; Deny and NotApplicable are not. `EvaluationError = Set<ResolutionError | ScheduleError>`, and the §9.7 completion argument also replaces each schedule error with some set of occurrence times. - **The workflow change is dropped.** #262 already runs `validate.py` in CI. - **`ScheduleIdentifierShape` is renamed `RejectAnonymousScheduleShape`.** The spec generator renders every NodeShape that has a `sh:targetClass` as a class except `Reject*` shapes, so the old name appeared as a spurious "ScheduleIdentifier" class. - **The core spec and examples move to `dprod:schedule`.** The data-offer-and-contract, lifecycle-and-versioning, provider-duties and odcs-mapping examples, plus the `respec/template.html` contract example, now use identified `Schedule` nodes with an explicit `DTSTART;TZID=…` and an RRULE. The overview diagram is regenerated, and `tests/test_spec_contract_sections.py` expects `Schedule` and `ScheduleFormat` classes. - **The modification dates are bumped** in the contracts docs and in `dct:modified` on the profile, shapes and vocabulary. All 9 review findings on #234 were checked and are addressed. They are: crontab whitespace, the RFC 5545 regex (EXDATE/RDATE order, duplicate FREQ), the TZ conflict and `carriesTimeZone`, how ScheduleError is consumed and totality, the `expand` signature, bare-config tests, undefined guide examples, the identifier message on its own shape, the RRULE table, and the recurrence sweep of specification.md. ## Tests - This branch: core 26 OK, contracts 98 OK, `validate.py` clean. - Integrated with #264, #266, #270, #268 and #272: core 26 OK, contracts 102 OK, `validate.py` clean. Every JSON-LD example that uses a schedule conforms to the contracts shapes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Jacobus Geluk <jacobus.geluk@ekgf.org> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This branch was successfully deployed
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.
Resolves #200.
What
Adds a step to
build-spec.yml, after the contracts unit tests, that runspython dprod-contracts/validate.py. The script parses everydprod-contracts/**/*.ttland SHACL-validates each file indprod-contracts/examples/againstdprod-contracts-shapes.ttl(RDFS inference on), exiting non-zero on any parse error, violation or malformed shape.Why
CI already runs
tests/anddprod-contracts/tests/, but the contracts tests validate inline snippets only. No step validates the example files themselves, so a regression in an example or in the shapes could land unnoticed.This happened in practice: a property shape in
ConstraintShapethat lost itssh:path odrl:operatorstill parsed as Turtle and passed every unit test, but made pyshacl abort on every example.Verified locally
python -m unittest discover -s tests: 26 tests OKpython -m unittest discover -s dprod-contracts/tests: 49 tests OKpython dprod-contracts/validate.py: all 7 TTLs parse, all 4 examples conform, exit 0sh:path odrl:operatorremoved:validate.pyexits 1, so the step fails the build🤖 Generated with Claude Code