Repository navigation
fix(tools): score the pilot's JVM-dependent api-json values in a pilot-nondeterministic column - #1555
Merged
Merged
Conversation
…t-nondeterministic column pilot-apijson-diff -check failed on develop because the pinned pilot exports FeatureChainExpression.featuringType differently from one JVM to the next: three expressions in its ServerSequenceModelOutside example gain or lose a reference to an element the pilot never exports. The comparison now carries a declared list of such properties with the evidence, scores every comparison of a declared row in a seventh scorecard column and nowhere else, writes the list into the report and the baseline, and the baseline is re-recorded once on the seven-column scorecard; only that row moved. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Contributor
Author
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
A pilot-nondeterministic comparison scores no value, so the references it mentions are not compared and are not counted unkeyed either; the count otherwise moved by three between OpenJDK 21 and 25 while every bucket held. Baseline re-recorded on the fixed count: unkeyedReferences 112272 -> 112263, nothing else moved. Co-Authored-By: jason.han <hanhuijun@gmail.com>
6 tasks done
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.
What and why
develop's scheduled Oracle-reproduction workflow fails ongo run -C tools ./cmd/pilot-apijson-diff -check:scorecard.FeatureChainExpression.featuringType[2]: 287 -> 284, [4]: 227 -> 230. Nothing in this repository moved; the pinned pilot's api-json export of that property is not reproducible across JVMs, so re-recording the baseline only chases the flip. This PR proves where the flip comes from, scores the property in a new, visiblepilot-nondeterministicscorecard column so the baseline reproduces on every JVM, and re-records the baseline once. Comparison code, the baseline and its docs only.The nondeterminism, proved
The pinned exporter (
scripts/download-pilot-json-exporter.sh, pin2026-08,jupyter-sysml-kernel-0.62.0) was run over all nine corpus roots four times on one checkout and every keyed element's every property compared across runs (ids mapped through the bridge's key table):setup-java)FeatureChainExpression.featuringType, nothing elseThe nine values are three elements written into three documents each (the pilot writes an element into every file whose traversal reaches it; the copies collapse to three matched elements = the 287/284 flip), the
FeatureChainExpressions valuing the three event occurrences ofServerSequenceModelOutside::PubSubSequenceOutside:…::server::publish_target_event/FeatureChainExpression[0]then event occurrence :>> publish_target_event = publish_message.done;examples/pilot-corpora/sysml-examples/Interaction Sequencing Examples/ServerSequenceModelOutside.sysml, re-exported byServerSequenceOutsideRealization-2.sysmlandServerSequenceOutsideRealization-3.sysml(they import it)…::server::deliver_source_event/FeatureChainExpression[0]then event occurrence :>> deliver_source_event = deliver_message.start;…::consumer::deliver_target_event/FeatureChainExpression[0]then event occurrence :>> deliver_target_event = deliver_message.done;Shape of the difference — not an ordering of a multi-valued reference and not a moving
@id, but presence: under OpenJDK 21 each has"featuringType": []; under OpenJDK 25 each has"featuringType": [{"@id": <x>}]wherexis thedefaultFeaturingTypeof the enclosingSuccessionAsUsage(ConnectorAsUsage::defaultFeaturingType), an element the pilot neither exports nor keys in any document (hence the row's singleunkeyedreference). Mechanism, from the pilot'sorg.omg.sysml.logicat the pinned commit: an expression'sfeaturingTypeis derived from its adapter's implicit featuring types, whichFeatureAdapter.addImplicitFeaturingTypesIfNecessaryfills while the owner is transformed andFeatureUtil.insertImplicitTypeFeaturingsmaterializes as impliedTypeFeaturings — the result depends on transformation order, not on the model. Both answers are legitimate JSON shapes, so a single comparison cannot tell a stable value from an unstable one; sorting would not help (the difference is presence, not order).The fix, at the comparison
tools/referee/apijson/nondeterminism.go: a declared listpilotNondeterminismof(metaclass, property)rows with the evidence as text; one entry,FeatureChainExpression.featuringType. The list is written into the report and the baseline (pilotNondeterministic), so a declaration change is itself a baseline movement-checkshows.compare.go: a seventh bucketpilot-nondeterministic. Every comparison of a declared row is scored there and in no other bucket, never recorded as an example; undeclared properties — the same metaclass's included — are scored exactly as before. Nothing is dropped and no tolerance is widened: the row and the headline show the 514 comparisons the oracle cannot answer reproducibly.report.go: the scorecard is[7]int(present-equal, present-different, ours-missing, pilot-missing, absent-both, indeterminate, pilot-nondeterministic); the headline and the text report carry the column.docs/project/api-json-differential.mddocuments the column semantics, the evidence and the declared list (new section "Declared pilot nondeterminism"), and its headline is the re-recorded one;docs/project/pilot-differential.md's oracle-reproduction bullet names the third kind of-checkfailure (the reference disagreeing with itself) and what to do; the api-json row ofdocs/project/spec-compliance.mdstates the declared row and its metamodel basis.Baseline movement (
-updateonce, on the fixed comparison)11730 rows before and after; one row moved, nothing else (totals, element counts, every other row and the provenance block are byte-identical in meaning):
FeatureChainExpression.featuringType[0, 0, 287, 0, 227, 0][0, 0, 0, 0, 0, 0, 514]Totals: ours-missing 1076508 → 1076221 (−287), absent-both 1978076 → 1977849 (−227), pilot-nondeterministic 0 → 514; present-equal, present-different, pilot-missing and indeterminate unchanged.
totals.unkeyedReferences112272 → 112263: the declared row's values are not compared, so the 9 unkeyed references they carried (3 of them the JVM-dependent ones — under OpenJDK 21 the old count came out 112269, which is how the first round of this PR still failed-checkacross JVMs; caught by Devin Review) are no longer counted; the record's stale figure for this count is corrected alongside. Per root the 514 are training 62, pilot-examples 172, pilot-validation 66, kerml-examples 9, spec-examples 7, examples 162, manual-examples 36 (testdata and probes 0). Which side is right: the metamodel (KerML 1.1 Beta 2 §8.3.3.3.4,deriveFeatureFeaturingType) derivesfeaturingTypefrom the feature'stypeFeaturings and its first chaining feature, which these expressions have neither of, so the stable answer is none — what this repository's writer states; the pilot's other answer is a different run, not a different fact, and the oracle is not the authority.Specification basis
Tooling change; no runtime behaviour moves. The adjudication above relies on KerML 1.1 Beta 2 §8.3.3.3.4 (
Feature::featuringType : Type [0..*] {ordered},deriveFeatureFeaturingType) and §8.3.4.8.4 (FeatureChainExpression). The api-json row ofdocs/project/spec-compliance.mdkeeps its ✅ status with the declared row added to its text.How it was verified
TestDeclaredNondeterminismScoresTheWholeRow: a declared row takes every comparison (pilot states / ours lacks, both state none, the two state different values) in the seventh column only, never an example; an undeclared property of the same metaclass and the same property on another metaclass are scored as before.TestDeclaredNondeterminismScoresTheWholeRowalso assertsunkeyedReferencesstays 0 for every pilot value shape of a declared row.TestDeclaredNondeterminismIsEvidencedAndRecorded: the committed baseline's declared list is the comparison's, every declared row carries evidence and sits wholly in the seventh column, the headline total is the sum of the declared rows, and no undeclared row has a count there.TestRecordStatesTheBaselinesFiguresties the seven-figure headline in the docs to the baseline.go run -C tools ./cmd/pilot-apijson-diff -checkthree times on the final tree — run 1 under OpenJDK 25, run 2 under OpenJDK 21, run 3 under OpenJDK 25: run 1 ✅ reproduces, run 2 (OpenJDK 21) ✅ reproduces, run 3 ✅ reproduces — the committed baseline reproduces on both JVMs (before the second commit the OpenJDK 21 run stopped attotals.unkeyedReferences: 112272 -> 112269; with it, every total and row holds)go build ./...✅,go vet ./...✅,gofmt -l .empty ✅,go test ./...withOPENSYSML_REQUIRE_TRAINING_CORPUS=1 OPENSYSML_REQUIRE_PILOT_CORPORA=1 OPENSYSML_REQUIRE_SPEC_EXAMPLES=1: every package ✅ except two that hit the 10-minute default timeout while two pilot exports were running beside them (cmd/sysmlinTestExploreTablesTheSpacecraftRaceWithinItsBudget,tests/codegeninTestCompiledStepBudgetMatchesInterpreter, both budgeted perf tests, neither touching this change); re-run alone,cmd/sysml✅ 308s andtests/codegen✅ 340s;go test -C tools ./...✅ on the final head;python3 scripts/changelog.py check✅;mkdocs build --strict✅;make docs-counts✅ ("Documentation counts and refereed figures are current").Coordination with #1529 (pilot pin 2026-09)
Dry-merged both commits onto #1529's current head
9ca600a59in a detached worktree: the comparison code, its tests, the changelog fragment,pilot-differential.mdandspec-compliance.mdmerge clean andgo build,go vetand the comparison tests pass on the merged tree;docs/project/api-json-differential-baseline.json(both PRs re-record every row) and two adjacent hunks ofdocs/project/api-json-differential.md(the headline, and the Results heading's pin beside the new section) conflict, as expected of two re-records. Againstorigin/develop(0286c9845) the branch is a fast-forward. Landing order: this PR first, then #1529 re-merges develop and re-records once on the seven-column scorecard at its pin (the #1529 session reproduced the same flip with the 0.63.0 exporter, so the declared row stays; its evidence text names the pin it was proved at). If #1529 lands first, this PR re-records once more on top of it instead.Checklist
make testandmake lintpass locally (see gates above)changes/unreleased/<slug>.<section>.md, not as an edit toCHANGELOG.mdmake docs-countsrun if a gate count moved (compliance rows need nothing: the census is counted at docs build)F4,K5) in the body, docs, or changelog