feat(conformance): make FLUID's claims executable - #44
Merged
Merged
Conversation
FLUID is published as "the open, declarative standard for Data Products"
and, until this commit, shipped twelve schema files, no tests, no
conformance vectors, and a backward-compatibility promise checked by
nothing. Its sibling FLUX already ships enforcement vectors and a
regression suite. This closes that gap on the flagship.
It is not only about third parties. The FLUID contract already has more
than one first-party reader -- FluidSchemaManager in forge-cli, the FLUX
engine's seam/, and the Command Center -- and nothing has ever proved
they agree about what a contract means. A shared corpus is how they get
held to one answer.
tests/0.7.5/ 267 vectors across 11 groups
tests/optional/0.7.5/ 2 vectors for behaviour the spec permits but
does not require (format assertion)
conformance/run.py the runner; assertions are on JSON Schema
keyword + RFC 6901 pointer, never message text,
so the corpus ports to any language
conformance/check_reference.py
runs the corpus against forge-cli, which is
implementation #1 under test, never the referee
conformance/mutation_coverage.py
deletes one schema constraint at a time and
reports which ones no case would catch
scripts/check-compat.py the backward-compatibility gate: a static
narrowing diff plus an empirical replay of the
previous version's corpus
tests/meta_test.py 19 checks proving both gates can actually fail
What the gates found on their first run:
* 0.7.2 is NOT backward compatible with 0.7.1, contrary to
docs/releases/0.7.2.md. $defs/notification gained
additionalProperties: false, so a contract with any extra member on a
build.execution.notifications[] entry validated under 0.7.1 and is
rejected by 0.7.2. Proven with a document plus a negative control that
isolates the cause. Waived, because it cannot be un-shipped, with the
evidence recorded; the release note still needs correcting.
* FLUID never says whether `format` is assertive. JSON Schema 2020-12
makes it an annotation by default and the reference implementation does
not assert it, so a contract can validate with a malformed
metadata.owner.email. The core tier follows the weak reading and the
question is written down rather than silently assumed.
* forge-cli validates a 2020-12 schema with a Draft 7 validator. Latent
today, because the schemas use only $defs from the 2020-12-only keyword
set. It becomes a silent-acceptance bug the moment a schema uses
prefixItems, unevaluatedProperties, dependentRequired, minContains or
maxContains.
Mutation coverage is 16.8% (191 of 1140 constraints). That is the honest
baseline, not a good number: 269 cases sound like more coverage than they
buy. exposePolicy and semanticModel have no cases at all.
Borrowed, with the reasoning recorded in each file: the corpus shape and
core/optional split from json-schema-org/JSON-Schema-Test-Suite (MIT);
the failure-list file from protocolbuffers/protobuf (BSD-3-Clause); the
still-execute-known-failures refinement from connectrpc/conformance
(Apache-2.0); expected-error-code assertions from w3c/json-ld-api; and
the vectors envelope and meta-test discipline from flux-spec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 7, 2026
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.
FLUID is published as "the open, declarative standard for Data Products". Until this PR it shipped twelve schema files, zero tests, zero conformance vectors, and a backward-compatibility promise — repeated in the README and every release note — that nothing checked. Its sibling FLUX already ships enforcement vectors, a regression suite and a meta-test. This closes that gap on the flagship.
It is not only about third parties. The FLUID contract already has more than one first-party reader —
FluidSchemaManagerin forge-cli, the FLUX engine'sseam/(which resolves and compiles a referenced contract with its own type parser and its ownFLX-####codes), and the Command Center — and nothing has ever proved they agree about what a contract means. A shared corpus is how they get held to one answer.What's here
tests/0.7.5/tests/optional/0.7.5/conformance/run.py--version,--group,--junit,--listconformance/check_reference.pyconformance/mutation_coverage.pyconformance/known-failures.txtscripts/check-compat.pyscripts/compat-waivers.txttests/meta_test.py.github/workflows/conformance.ymlmeta→conformance+compatAssertions are on JSON Schema keyword + RFC 6901 pointer, never message text, so the corpus ports to ajv,
check-jsonschema, or an implementation in a language nobody has written yet. An invalid case that declares no reason is refused by the loader — it would pass for any reason at all.What the gates found on their first run
0.7.2is not backward compatible with0.7.1, contrary todocs/releases/0.7.2.md("100% backward compatible", "No breaking changes").$defs/notificationgainedadditionalProperties: false, so a contract carrying any extra member on abuild.execution.notifications[]entry validated under 0.7.1 and is rejected by 0.7.2.Proven with a document, plus a negative control isolating the cause:
Waived, because it cannot be un-shipped — but the waiver records it as a real break, and the release note still needs correcting. The other two flags were checked and are not bugs: the
identifierpattern change is a strict widening (verified exhaustively over 11,110 generated strings, zero counterexamples) and thefluidVersionenum is the version gate working as intended.FLUID never says whether
formatis assertive. JSON Schema 2020-12 makes it an annotation by default and the reference implementation does not assert it — so a contract can validate with a malformedmetadata.owner.email. The core tier follows the weak reading, format cases live inoptional/, and the open question is written intotests/README.mdrather than silently assumed. This wants a decision.forge-cli validates a 2020-12 schema with
Draft7Validator. Latent today — the schemas use only$defsfrom the 2020-12-only keyword set, which resolves under Draft 7 as ordinary JSON pointers. It becomes a silent-acceptance bug the moment a schema usesprefixItems,unevaluatedProperties,dependentRequired,minContainsormaxContains.The number to hold this to
Mutation coverage is 16.8% — of 1,140 constraints in the 0.7.5 schema, only 191 have a case that goes red if you delete them. 269 cases sound like more coverage than they buy. Most of the gap is
typeconstraints (701), but 84 enums, 67 closed objects and 56 required members are unpinned, andexposePolicyandsemanticModelhave no cases at all. That is the honest baseline to ratchet up, not a result to celebrate.Tested
Every gate run in a clean venv built from scratch (Python 3.14,
jsonschema[format]>=4.22only), not just the dev environment:That clean-venv run caught a real "passes locally, fails CI" bug before push:
jsonschemaonly registers adate-timechecker whenrfc3339-validatoris present, which the dev environment had transitively and CI would not. Reproduced red with barejsonschema, fixed by requiring the[format]extra, re-verified green. Hence the extra is pinned in all three jobs, with a comment saying why.Notes for review
.gitignore. No overlap with the two open PRs (Add FLUID schema 0.7.2 (Semantic Truth Engine) #21 touchesschema/,specs/,schema-diffs/; Enhance FLUID Documentation and Structure for Better Accessibility and Adoption #1 touches root docs). Nothing here modifiesschema/, soschema-syncis unaffected, andlink-checkis path-filtered todocs/**.conformancejob installsdata-product-forgeunpinned and is allowed to fail the build if the engine disagrees with the corpus. That is the point of the check, not an oversight.pull_request(notpull_request_target) withcontents: read, no secrets and no${{ }}interpolation;meta_test.pywas confirmed non-destructive by hashing all 1,690 repo files before and after a run.Borrowed
Corpus shape and core/optional split from JSON-Schema-Test-Suite (MIT) · failure-list file from protobuf (BSD-3-Clause) · still-execute-known-failures from connectrpc/conformance (Apache-2.0) · expected-error-code assertions from w3c/json-ld-api · vectors envelope and meta-test discipline from flux-spec. Reasoning is recorded in each file's docstring.
🤖 Generated with Claude Code