test(sysml2): grade the parser on 310 official models instead of our own fixtures - #442
Open
avrabe wants to merge 1 commit into
Open
test(sysml2): grade the parser on 310 official models instead of our own fixtures#442avrabe wants to merge 1 commit into
avrabe wants to merge 1 commit into
Conversation
…own fixtures
REQ-SYSML2-CONFORMANCE-001. The SysML v2 crate is 8378 LOC — the second-largest
parsing effort in the repo — and until now nothing outside the repo had ever
graded it.
## The suite could not fail
`conformance_tests.rs` had eight tests. Seven asserted on the CST's TEXT:
assert!(!result.syntax_node().text().is_empty());
assert!(text.contains("part def Vehicle"));
assert!(u32::from(result.syntax_node().text().len()) > 50000);
The CST is lossless, so it echoes the input back whether or not a single token
parsed. Not one of the eight called `errors()` or `ok()`.
`parse_annex_a_simple_vehicle` reported ok while the SysML v2 specification's
own Annex A model failed on line 3.
Correcting something I got wrong while auditing this: `grep sysml
.github/workflows/*.yml` returns nothing, and I inferred none of it ran in CI.
The inference was wrong — `cargo nextest run --workspace` has been running
these tests on every PR, and the job log names `conformance_tests` seventeen
times. They ran. They just measured nothing, which is worse: it was a green
required check reporting on a parser that rejects the standard's own examples.
No CI wiring is added here for that reason; the new tests are picked up by the
same workspace run.
## What lands
The official corpus, VENDORED at a pin rather than fetched. 310 model files
from Systems-Modeling/SysML-v2-Release @29a3d2ac (EPL-2.0, LICENSE copied
unaltered) — 56 validation, 100 training, 96 examples, 58 KerML examples.
`download-official-suite.sh` is deleted: it fetched `master` through the GitHub
API with `|| true` on every download, so a network blip silently produced a
SMALLER corpus, and a smaller corpus of still-failing files reads as a BETTER
parse rate. Its target directories were empty, which is how 43 self-written
fixtures came to stand in for a conformance suite.
`tools/vendor-sysml2-corpus.sh` replaces it, pinned, and refuses to exit 0
having copied nothing.
`official_corpus.rs` — the bulk gate. OFFICIAL_PARSING is EXACT, not a floor:
below fails as a regression, above fails until the constant is raised, the same
two-sided discipline as MAX_TOO_PERMISSIVE. OFFICIAL_TOTAL is asserted
separately so a vanished corpus cannot masquerade as a parser regression.
`conformance_tests.rs` — rewritten to DECLARED verdicts. Asserting whatever the
parser currently does would have been just as inert; each named file instead
carries its expected verdict and the construct responsible, so closing a gap
turns a named test red rather than only moving a number. The one honest
assertion in the original suite — lossless round-trip — is kept, and is
precisely why the other seven could pass on files that never parsed.
## The number, measured for the first time
.sysml 0 / 252
.kerml 1 / 58
TOTAL 1 / 310 (0.3%)
A rate is a property of the corpus as much as the parser, so the failures were
classified rather than counted. Five distinct first-error kinds across 309
failing files, not 309 problems:
161 expected name quoted names: package 'Application Layer';
97 expected member declaration visibility: private import Objects::*;
41 expected SEMICOLON KerML class definitions
9 expected package/import/definition visibility-modified import at file scope
1 expected definition after abstract abstract type A specializes ...
Quoted names and visibility modifiers alone account for 258 of the 309.
REQ-SYSML2-VISIBILITY-001 is scoped to those two; the KerML `class` and
`abstract type` kinds were NOT in its original scope and are a finding of this
vendoring — recheck that requirement before planning its release.
## Non-vacuity, executed
Four mutations, each reddening a distinct assertion, then restored:
OFFICIAL_PARSING 1->0 fails (regression path), 1->2 fails (below-floor path),
OFFICIAL_TOTAL 310->309 fails (corpus guard, two tests), and stubbing the parse
predicate to `true` fails. Restoring greens all four. Both verdicts of
`parse().ok()` are separately pinned so the count cannot be produced by a
predicate stuck on one answer.
Full suite green under the CI flags: `RUSTFLAGS="-D warnings" cargo test -p
spar-sysml2` -> 277 passed, 0 failed. `-D warnings` initially REJECTED the
crate over an unconstructed `Parses` variant; that is allowed with a note
rather than deleted, because it is the variant every entry is headed for.
NOT CLAIMED: that a parsing file is correctly lowered. `Parse::ok()` is a
syntax predicate. Nothing here says the parser is good — only that its score is
now measured by somebody else's models and can only go up.
Refs #441.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
avrabe
added a commit
that referenced
this pull request
Aug 26, 2026
The requirement said no workflow mentions sysml "so none of it executes in CI". The grep was right; the inference was not. `cargo nextest run --workspace` has been running the SysML v2 tests on every PR — the Test job's log names `conformance_tests` seventeen times. That makes the finding worse rather than better: the vacuous suite was not dormant code nobody ran, it was a green REQUIRED check reporting on a parser that rejects the SysML v2 specification's own examples. It also means the requirement needs no CI wiring at all — only tests capable of failing, which is what #442 lands. Found while implementing the requirement, which is the point of implementing it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rivet verification gate✅ 20/20 passed
Filter: Failed artifacts(none) Updated automatically by |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
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.
First item of v0.43.0 "stop grading ourselves" —
REQ-SYSML2-CONFORMANCE-001(proposed in #441). Everything else in that release depends on this one, because
until it lands no SysML v2 number this project quotes means anything.
The suite could not fail
conformance_tests.rshad eight tests. Seven asserted on the CST's text:Not one of the eight called
errors()orok().parse_annex_a_simple_vehiclereported
okwhile the SysML v2 specification's own Annex A model failed on line 3.What lands
The official corpus, vendored at a pin. 310 model files from
Systems-Modeling/SysML-v2-Release@29a3d2ac— EPL-2.0,LICENSEcopiedunaltered, same arrangement as the vendored OSATE corpus. 56 validation, 100
training, 96 examples, 58 KerML examples.
download-official-suite.shis deleted. It fetchedmasterthrough theGitHub contents API with
|| trueon every download — so a network blip silentlyproduced a smaller corpus, and a smaller corpus of still-failing files reads as
a better parse rate. The error path yielded the flattering answer. Its target
directories were empty, which is how 43 self-written fixtures came to stand in for
a conformance suite.
tools/vendor-sysml2-corpus.shreplaces it: pinned, verifiesthe checkout matches the requested SHA, and refuses to exit 0 having copied nothing.
official_corpus.rs— the bulk gate.OFFICIAL_PARSINGis exact, not afloor: below fails as a regression, above fails until the constant is raised. Same
two-sided discipline as
MAX_TOO_PERMISSIVE.OFFICIAL_TOTALis assertedseparately so a vanished corpus cannot masquerade as a parser regression.
conformance_tests.rs— rewritten to declared verdicts. Asserting whateverthe parser currently does would have been just as inert; each named file carries
its expected verdict and the construct responsible, so closing a gap turns a
named test red rather than only moving a number. The one honest assertion in the
original suite — lossless round-trip — is kept, and is exactly why the other seven
could pass on files that never parsed.
The number, measured for the first time
A rate is a property of the corpus as much as the parser, so the failures were
classified, not just counted. Five distinct first-error kinds across 309
failing files — not 309 problems:
expected namepackage 'Application Layer';expected member declarationprivate import Objects::*;expected SEMICOLONclassdefinitionsexpected package, import, or definitionexpected definition after abstractabstract type A specializes …Quoted names and visibility modifiers alone are 258 of the 309.
REQ-SYSML2-VISIBILITY-001is scoped to those two; the KerMLclassandabstract typekinds were not in its original scope and are a finding of thisvendoring — recheck that requirement before planning its release.
Non-vacuity, executed
Four mutations, each reddening a distinct assertion, then restored:
Both verdicts of
parse().ok()are separately pinned, so the count cannot beproduced by a predicate that only ever says yes.
RUSTFLAGS="-D warnings" cargo test -p spar-sysml2→ 277 passed, 0 failed.-D warningsinitially rejected the crate over an unconstructedParsesvariant; it is allowed with a note rather than deleted, because it is the variant
every entry is headed for.
Not claimed
That a parsing file is correctly lowered —
Parse::ok()is a syntax predicate.That the parser is good. Only that its score is now measured by somebody else's
models, and can only go up.
Refs #441.
🤖 Generated with Claude Code