Labels. This record cross-references the other conformance records under docs/project/ by
their private labels — derive* names the metamodel's derivation constraints as
docs/project/constraint-manifest.json lists them (deriveElementQualifiedName, …), and OMG issue
keys (KERML11-191, SYSML21-419) name the Beta 2 corrections the referee can adjudicate. A
reader outside the records needs none of them.
What it is. An advisory referee, in the shape of the pilot differential
and the execution referee: every model file under the corpus roots is
exported as the SysML v2 API's element JSON twice — by this repository's writer
(sysml -convert api-json, internal/translate/export) and by the pinned OMG pilot
implementation — the elements are matched by a stable key, and every property of every matched
element is bucketed. Bucketed per (metaclass, property), the counts read as a scorecard of the
metamodel's derived properties: SysML v2's abstract syntax is mostly derivation (235 derive*
constraints in the manifest, nearly all of status unknown before this referee), and the pilot's
export is the only reference for what each derived property should hold. The referee never
decides a pass; it measures.
The pinned pilot is 2026-08 (jupyter-sysml-kernel 0.62.0), the artifact the reference
validators use (scripts/pilot-pin.sh).
./scripts/download-pilot-json-exporter.sh # builds build/pilot-json-exporter/export-json
./scripts/download-training-examples.sh && ./scripts/download-pilot-corpora.sh
go run -C tools ./cmd/pilot-apijson-diff # writes build/pilot-apijson-diff/
go run -C tools ./cmd/pilot-apijson-diff -check # fails unless the committed baseline reproduces
go run -C tools ./cmd/pilot-apijson-diff -update # re-records docs/project/api-json-differential-baseline.json-roots training,probes restricts a run to named roots (never with -update); -exporter, -out
and -timeout override the launcher, the output directory and the per-root time allowed to the
pilot. A run writes pilot-apijson-diff.json (the baseline's shape), pilot-apijson-diff.txt
(the ranked scorecard with one concrete example per differing row, the unmatched elements by
metaclass and the pilot's diagnostics), pilot-apijson-diff-examples.json and
pilot-apijson-diff-matches.json, the run's inventory of every key per root under the fate the
matching gave it (matched, ours-only, pilot-only). -lost-against <earlier run>/pilot-apijson-diff-matches.json
then names, in pilot-apijson-diff-movements.txt and .json, each element the earlier run matched
and this one does not (lost) and the reverse (gained), grouped by root and metaclass, each with
the key's fate in the run that does not match it; a change to either side's naming is read from
that list rather than from a moved total.
scripts/download-pilot-json-exporter.sh shares scripts/pilot-pin.sh with the validators,
compiles scripts/pilot-json-exporter/ExportJSON.java against the pinned shaded jar and writes the
launcher build/pilot-json-exporter/export-json --library <sysml.library> --root <dir> --out <dir> [--extension-library <dir>]... <files> (the library defaults to the pinned one). The bridge is the
pilot's own export path, the one the Jupyter kernel's %export magic runs
(SysMLInteractive.export):
- the standard library is read first, as
SysMLInteractive.loadLibraryreads it (Kernel Librariesas KerML, thenSystems LibraryandDomain Librariesas SysML, all as library resources); then each--extension-librarydirectory is read the same way — its.kermlfiles, then its.sysmlfiles, as library resources — which is how the pilot's command-line utilities read the library paths that follow their input. The referee passes this repository's own libraries,internal/workspace/libs/stdlib/OpenSysML Libraries/, the directory the pilot differential hands its validators: the one inside the standard-library root OpenSysML itself loads (the bundled tree unlessOPENSYSML_LIBRARY_PATHnames another), never a free command-line choice, so both sides resolve the same library text; the baseline records it as theopensysml-librariesinput. A member whose naming feature, type or redefined feature lives inDocumentQueries,AnalysisRecordsorOpenSysMLRenderingsthus resolves on the pilot's side as it does on ours; - the files of one corpus root are read into one resource set with those libraries
(
org.omg.sysml.io.SysMLUtil, the KerML and SysML Xtext setups both registered, so.kermland.sysmlinputs alike resolve), thentransformAll(false)runs the pilot's model transformation as its validation does before an export, without adding the implied relationships as elements (the traversal otherwise adds them while it iterates); - each input resource's root elements are visited by
org.omg.sysml.util.traversal.facade.impl.JsonElementProcessingFacadewithsetIsIncludeDerived(true)throughorg.omg.sysml.util.traversal.Traversal, and the tree istoJsonTree(true)— the exact callsSysMLInteractive.exportmakes; standard-library elements are referenced, never written, as in the pilot, and the elements of this repository's libraries are written as library elements (isLibraryElementtrue, thelibrary packagekeyword deciding it) and left out of the comparison like the standard library's; - one document per input file is written under
--out, mirroring the file's path:{"file", "elements": [{"payload": {…}, "identity": {"@id"}}], "keys": {"<elementId>": "<key>"}},keysresolving every id the elements mention, library elements included, to the stable key described below; nulls are serialized as the facade emits them (Gson.serializeNulls).
The pilot mints a fresh random UUID for every user-model element on each run (library elements keep their name-based ones), so the export is never byte-identical twice; the keys are what make it comparable.
Each root's files are parsed and converted together (export.ModelToRDFWith with qualified-name
ids, then export.WriteAPIJSON), so cross-file imports resolve as they do for the pilot. A file the
parser cannot read whole is refused and counted (oursRefused), as sysml -convert refuses it; a
file the pilot failed on is left out (pilotFailed), so that its elements do not count as
ours-only against an export that never existed. Two documents that declare the same element
(tests/testdata holds two versions of one library package; the interchange fixtures redeclare
their packages) cannot share one graph, since the qualified-name ids collide: each document is
first converted alone, the documents whose ids collide stay converted alone (oursColliding),
and the rest are converted together. Only if the rest still do not convert as one model is every
document kept alone (oursSeparate); a document the writer refuses alone is counted under
oursUnconvertible. Cross-file references out of a document converted alone stay unresolved and
are measured as such.
Elements are matched by a stable key, computed identically on both sides:
- a named element by its
qualifiedName, spelled with every segment unquoted ('Derived Probe'::VehicleandDerived Probe::Vehicleare one key; thequalifiedNameproperty is still compared as written, so the quoting difference is measured); - an unnamed element by its owner:
<ownerKey>/<metaclass>[i],icounting the owner's preceding owned relationships (for a relationship — the owner is itsowningRelatedElement) or owned elements (otherwise) of the same metaclass; the owned elements are the owned relationships' owned related elements, in order, which is how the metamodel derivesownedElement; - a document's root elements by the document:
/<file>/<metaclass>#i.
A positional name this repository's writer spells for an unnamed element (Demo::@1,
Legacy::@4::@trigger) is not a name — the metamodel derives no qualifiedName for an unnamed
element — so such an element is keyed structurally and its stated qualifiedName is measured
against the pilot's null. Identical copies of one element on a side are one element (the pilot
writes an element in every file whose traversal reaches it; duplicateElements); elements two of
which compute one key but differ are dropped from matching (ambiguousKeys); elements no key
addresses (unkeyableElements: on the pilot's side the ownerless connectors it synthesizes and
what they own) are counted and left out.
Every normalization equates representations of one fact, never two facts; the list is written into
every report (normalizations):
- the pilot's
{payload, identity}envelope is unwrapped; - every
{"@id": x}reference compares as the key ofx, the pilot's key table covering library elements; a reference no key addresses is counted (unkeyedReferences) and makes the comparison indeterminate (two unknown targets are not known equal, nor different), a bucket kept apart from the four the scorecard ranks; elementId,memberElementIdandownedMemberElementIdhold ids as strings and are mapped through the same keys;elementIdis identity, not derivation, and is not bucketed;- JSON null, a missing property and an empty collection all state nothing — absent;
- a Boolean attribute written at its metamodel default (
model/kerml.ecoreandmodel/SysML.ecorein the pinned jar:isUniquedefaults totrue, every other defaulted Boolean tofalse) against a side that leaves it out is absent on both sides, since leaving it out states the default; a value the other side lacks is missing; the derived Booleans (isConjugated,isLibraryElement,isModelLevelEvaluable,isReference,mayTimeVary),isVariationand aLiteralBoolean'svaluehave no default, so leaving one out states nothing; - property order and object-key order are ignored; the order of collections is compared;
- properties outside the metamodel (this repository's
sysx:annotations) are left out and counted (extensionProperties); - the pilot's implied relationships (
isImplied) have no counterpart in the notation; those the writer does not emit are counted underpilotOnlyImplied; - standard-library elements the pilot writes (
isLibraryElement, one copy per file that refers to them) are left out and counted (pilotLibraryElements); this repository's writer refers to library elements and never writes them.
Each property of each matched pair lands in one bucket: present-equal, present-different,
ours-missing (the pilot states a value, we state nothing), pilot-missing (the reverse), or
absent-both (neither states anything — agreement, but not evidence that either side derives the
property, so it is kept apart from the four the scorecard ranks). The row is named by the pilot's
metaclass when the two sides disagree on the metaclass (typeMismatch).
- Determinism. The report is sorted throughout (roots in order, elements by key, properties by
name, rows by differing count then name); two runs over one checkout write byte-identical reports
but for the recording date, which is what
-checkverifies in the oracle-reproduction workflow and whatTestReportIsDeterministicpins without Java. - Disagreement.
TestDisagreementDetectorIsLivecompares the committed pilot export oftools/referee/apijson/testdata/probe.sysmlwith itself (no row differs), then with a scratch copy in which one derived collection ofDerived Probe::Vehicleis emptied (ownedUsage→ exactly one ours-missing in that row, nowhere else) and one in which one attribute is flipped (isAbstract→ exactly one present-different), each with one example naming the element. - Provenance. The baseline's
provenanceblock names both sides of the comparison: the pilot pin (pilotTag,pilotCommit,pilotArtifact), the errata-registry digest, onetoolsentry per side, every root's file digest and, as theopensysml-librariesinput, the digest of the library directory the bridge reads beside the standard library.pilot-json-exporterdigests the bridge sourcescripts/pilot-json-exporter/ExportJSON.javaagainst the pinned release;api-json-writerdigests this repository's writer,internal/translate/export: its non-test.gofiles, sorted by file name, each hashed by name and content, so the digest is the same on any machine and in any checkout path. It moves on any edit to a production source of the package (a renamed member, a dropped property, a reordered emission) and stays put on edits to its tests, fixtures or prose. It does not cover what the writer consumes — the parser, name resolution, the metamodel or the library — so a semantic change upstream still surfaces as count movement with no named cause; it names writer changes only.TestCommittedBaselineStatesThisRepositorysProvenancechecks, without Java, that every one of those fields is this checkout's;-checkholds the same block to the baseline before the counts, so a writer edit stops it atprovenance.tools[api-json-writer].sourceDigest: baseline records …, repository now has …rather than at bare count drift (the fresh report it wrote still holds the moved buckets). The writer digested is the one linked into the referee — the checkout it was built from — which-repopointing elsewhere does not change; a-trimpathbuild keeps no record of that checkout and is refused rather than guessed at.TestProvenanceGuardFailsOnAMovedPinandTestProvenanceGuardFailsOnAnEditedWriterpin that a moved pin and an edited writer are each named with the refresh command.TestRecordStatesTheBaselinesFigures(make docs-counts) ties this record's figures to the baseline.
The pinned pilot's verdict on the probe (validate-sysml-batch): clean.
Scorecard: 924 files; 90265 elements matched (28431 ours-only, 38776 pilot-only, 0 of them implied); properties: 626193 present-equal, 40479 present-different, 1060910 ours-missing, 68760 pilot-missing, 2108306 absent-both, 25713 indeterminate.
The pilot's export failed on 56 files (pilotFailed: its own export throws on an element without a resource, 52 of them specification examples and 4 test fixtures; the files are named in the run's text report), ours refused 36 (all of them specification examples the parser could not read whole), left the pilot's 56 failed files out and converted 26 documents alone for declaring an element another document of their root declares (oursColliding); no root fell back to per-document conversion. 11311 (metaclass, property) rows carry a comparison; 108553 references compared through the unkeyed sentinel, 147292 of our sysx: annotations were left out, and 293/347 elements (ours/pilot) were dropped for ambiguous keys, 8210/31316 for having none.
| root | files | matched | ours-only | pilot-only | present-equal | present-different | ours-missing | pilot-missing |
|---|---|---|---|---|---|---|---|---|
examples/sysml-v2-training |
100 | 7287 | 2131 | 2873 | 50698 | 3608 | 86942 | 5306 |
examples/pilot-corpora/sysml-examples |
99 | 25864 | 9952 | 10402 | 182942 | 10084 | 309788 | 19572 |
examples/pilot-corpora/sysml-validation |
56 | 9246 | 2967 | 3341 | 63665 | 5435 | 108814 | 7092 |
examples/pilot-corpora/kerml-examples |
58 | 6387 | 1637 | 1854 | 43853 | 3110 | 63793 | 5268 |
examples/spec-examples |
511 | 6980 | 1966 | 2728 | 44427 | 5885 | 71585 | 5182 |
tests/testdata |
36 | 1357 | 97 | 552 | 8800 | 485 | 14752 | 1015 |
examples |
52 | 26071 | 8734 | 14944 | 183276 | 9550 | 316321 | 20333 |
tools/referee/diff/testdata |
4 | 53 | 0 | 0 | 348 | 15 | 462 | 43 |
docs/manual/examples |
8 | 7020 | 947 | 2082 | 48184 | 2307 | 88453 | 4949 |
The scorecard is mostly ours-missing: this repository's writer emits a subset of the metamodel's properties, and the referee now measures which, per metaclass. The full ranked scorecard with one concrete example per differing row is build/pilot-apijson-diff/pilot-apijson-diff.txt after a run; the baseline keeps every row's five counts.
The largest present-different rows, with the reading the examples support:
| metaclass | property | present-equal | present-different |
|---|---|---|---|
AttributeUsage |
ownedRelationship |
113 | 2323 |
Feature |
ownedRelationship |
3670 | 1781 |
PartUsage |
ownedRelationship |
309 | 1551 |
ReferenceUsage |
qualifiedName |
983 | 882 |
ReferenceUsage |
ownedRelationship |
1255 | 838 |
PartUsage |
qualifiedName |
1119 | 830 |
Package |
qualifiedName |
460 | 723 |
PartUsage |
ownedMember |
362 | 702 |
PartUsage |
ownedMembership |
716 | 634 |
AttributeUsage |
ownedMembership |
1178 | 622 |
| metaclass | property | pilot-missing | clause |
|---|---|---|---|
FeatureMembership |
owner |
10630 | Element::owner = owningRelationship.owningRelatedElement, and Relationship::owner = owningRelatedElement (KerML 8.3.2.1, 8.3.2.5.2) |
OwningMembership |
owner |
9518 | Element::owner = owningRelationship.owningRelatedElement, and Relationship::owner = owningRelatedElement (KerML 8.3.2.1, 8.3.2.5.2) |
FeatureValue |
owner |
7048 | Element::owner = owningRelationship.owningRelatedElement, and Relationship::owner = owningRelatedElement (KerML 8.3.2.1, 8.3.2.5.2) |
FeatureTyping |
owner |
5908 | Element::owner = owningRelationship.owningRelatedElement, and Relationship::owner = owningRelatedElement (KerML 8.3.2.1, 8.3.2.5.2) |
ReturnParameterMembership |
owner |
4735 | Element::owner = owningRelationship.owningRelatedElement, and Relationship::owner = owningRelatedElement (KerML 8.3.2.1, 8.3.2.5.2) |
ParameterMembership |
owner |
4376 | Element::owner = owningRelationship.owningRelatedElement, and Relationship::owner = owningRelatedElement (KerML 8.3.2.1, 8.3.2.5.2) |
Membership |
owner |
3144 | Element::owner = owningRelationship.owningRelatedElement, and Relationship::owner = owningRelatedElement (KerML 8.3.2.1, 8.3.2.5.2) |
AttributeUsage |
value |
1650 | see the derive* row for this property in docs/project/constraint-manifest.json |
owner on every relationship is the pilot leaving Relationship::owner null where the metamodel derives owningRelatedElement; ours states it. The remaining pilot-missing rows are properties this repository writes outside the metamodel's spelling (value on usages) or states for unnamed elements the metamodel leaves null (qualifiedName).
A member that takes its name from a naming feature is keyed by that name on both sides: KerML
Feature::effectiveName is the effective name of namingFeature() when nothing is declared
(8.3.3.3.4 Feature, body: if declaredShortName <> null or declaredName <> null then declaredName else … namingFeature.effectiveName()), and the default namingFeature() is
ownedRedefinition->at(1).redefinedFeature; SysML redefines it for a variant (8.3.6.4 Usage,
ownedReferenceSubsetting.referencedFeature), a transition payload (8.3.6.3 ReferenceUsage), a
performed action (8.3.17.14 PerformActionUsage, performedAction), a requirement constraint
(8.3.20.4 ConstraintUsage) and a view rendering (8.3.26.6 RenderingUsage). The pilot derives the
same name when it resolves the naming feature, which is why the bridge reads this repository's
own libraries beside the standard one: attribute redefines title = "…"; in a Section names
DocumentQueries::Section::title on both sides and is keyed …::coverage::title on both.
Reading those libraries moved 2983 elements from unmatched to matched and lost none:
docs/manual/examples from 6663 to 7020 (87 members — 84 AttributeUsage and 3 ReferenceUsage,
each an attribute redefines caption|title|text|term|description|kind|direction|style|groupBy = …
or ref redefines source|target = … of a DocumentQueries feature — with the 270 elements they
own) and examples from 23379 to 26005: 914 such members and owned elements of DocumentQueries
and AnalysisRecords features, with the two render members of OpenSysMLRenderings renderings,
in six files the pilot already exported, and the 1712 elements of mosa-demo/mosa-demo.sysml and
oosem-demo/oosem-demo.sysml, whose export the pilot had abandoned (pilotFailed, an element
without a resource) while MOSA and OOSEM were unloaded. tests/testdata matched the same 1201
elements with two more properties present-equal; no other root moved, and the pilot reported no
diagnostic on any library file (its batch validator reads the sixteen as one resource set without
an error). The members that gained a match disagreed with the pilot in three shapes when the libraries were
first loaded, none of them a derivation this repository gets wrong and none new — each a shape the
scorecard already carried for the standard library or for members the model declares itself, now
measured on library-backed members too. The first and the third are closed (the first in the next section, the third by the writer owning the referent Membership, below); the second remains:
- a reference to an element of this repository's libraries was spelled as a name,
{"@ref": "caption"}, where the pilot writes the element:Redefinition::redefinedFeature(KerML 8.3.3.3.8) on all 327 of those redefinitions,FeatureTyping::type(8.3.3.3.7) on 157, thetypeof 123MetadataUsageand 16ViewUsagetyped byMOSAandOOSEMmetadata and view definitions,FeatureReferenceExpression::referent(8.3.4.8.5) and thememberElementof itsMembershipon 28 enumeration literals, andReferenceSubsetting::referencedFeatureon the tworendermembers. The writer gave a library element an id only where the pilot's XMI of the standard library fixes one; this repository's libraries have no such norm, so a reference to one of their elements fell back to the name as written, and the library element itself was not stated. EveryElementhas anelementId(KerML 8.3.2.1.2) and the API's JSON refers to an element by it, so the pilot's reading is the metamodel's — the writer now fixes an id for these elements too; - the order of
ownedRelationshipon a usage that both redefines and has a value: the pilot lists theRedefinitionbefore theFeatureValue, in the order the notation declares them; ours lists the value first (275AttributeUsage, 97ReferenceUsage, 2RenderingUsage).ownedRelationshipis ordered (KerML 8.3.2.1.2 Element,ownedRelationship : Relationship [0..*] {ordered}), and the textual notation adds an element's owned relationships as it parses them, so the pilot's order is the notation's, a shape theAttributeUsageownedRelationshiprow already carried; - a
FeatureReferenceExpressionowns aMembershipof its referent, which both sides now write:referentis derived as thememberElementof the firstownedMembershipthat is not aParameterMembership(KerML 8.3.4.8.5, deriveFeatureReferenceExpressionReferent), and the notation maps the reference to that ownedMembership(8.2.5.8.3,FeatureReferenceMember), so theMembershipis part of the abstract syntax; the writer owns it before the result parameter and lists it underownedMembership, as it does the target-featureMembershipof aFeatureChainExpression(8.3.4.8.4) and the calleeMembershipof an invocation. TheFeatureReferenceExpressionownedMembershiprow keeps 7 differing elements, all of them a function named as an argument (->reduce '+'), which the pilot owns as aFeatureMembershipof anExpressiontyped by the function (8.2.5.8.3,FunctionReferenceMember) where ours writes aMembershipof the function itself.
The two files the pilot now exports add, besides those three shapes, every shape the scorecard
already carries for user models (the pilot quoting a qualifiedName segment that holds a space,
'Modular Ground Vehicle'::vehicle, where ours does not; the structural ordinals of unnamed
members; the naming of connector ends). The other roots' movements under earlier changes to the
keys were of the first kind too: spec-examples names 13 members by a naming feature the pinned
excerpt leaves undeclared (perform VehicleActions::move, individual timeslice redefines preflight, render asMyTreeDiagram under an undefined view definition, …), which the pilot,
resolving nothing, does not name. A run's own list of such movements comes from -lost-against.
Every named element of this repository's own libraries (DocumentQueries, MOSA, OOSEM, …)
now carries a fixed id, derived as a standard library element's normative id is — a library
package's id is uuid5(URL name space, "https://github.com/Open-MBEE/OpenSysML-Extensions-Library/" + package), each named element under it uuid5(package id, escaped qualified name) — so a reference
to one is written by id, {"@id": …}, the element itself named by a library stub in the graph, and
never as {"@ref": "name"} (the RDF mapping).
Those ids are deterministic and the same on every run, but they are not the pilot's: no
specification fixes ids for a non-normative library, and the pilot, reading the same files as a
library directory, hashes every library package under https://www.omg.org/spec/SysML/, so the two
sides' ids for MOSA::ConsensusStandard differ by that prefix alone. The referee cannot therefore
call such a reference equal: our side writes no element for a library target (the element form
carries the model's own elements only, above), so the id has no key and the comparison
is indeterminate — the bucket that already holds references to standard library elements —
rather than equal or different. What this measures is presence and shape: the property is stated,
as an element reference, where it was stated as a name.
Movement on the same 920 files, pilot and keys unchanged (the exact movement a -check after this
change reports): present-different 50027 → 45688 (−4339), indeterminate 21034 → 25703 (+4669),
present-equal 618674 → 619268 (+594), absent-both 2102500 → 2103094 (+594), elements matched 89957
→ 90023 (+66, pilot-only 38863 → 38797), ours-missing 1058325 → 1058259 (−66), pilot-missing
68494 → 68560 (+66); no row's present-equal count fell, and no root but examples/spec-examples
(−5 present-different), tests/testdata (−10), examples (−2875) and docs/manual/examples (−1449)
moved. By row, present-different → indeterminate, one movement per site, the end properties of a
relationship (target, relatedElement, general, subsettedFeature) moving with the end they
restate:
| row | present-different | indeterminate | what moved |
|---|---|---|---|
Redefinition.redefinedFeature (and target, relatedElement, general, subsettedFeature) |
388 → 58 | 542 → 938 | 330 redefinitions of a library feature (attribute redefines caption = …, :>> organization = …), plus 66 redefinitions newly matched (below); the 58 left are redefinitions the writer cannot link inside the model itself (vehicle_b_1::providePower redefining the feature inherited through vehicle_b) |
FeatureTyping.type (and target, relatedElement, general) |
670 → 338 | 1904 → 2236 | 332 features typed by a library definition (item ethernet : ConsensusStandard, metadata typed by MOSA and OOSEM definitions) |
MetadataUsage.type |
147 → 13 | 82 → 216 | 134 metadata usages typed by a library metadata definition (#majorSystemComponent, @MOSAPackage) |
ViewUsage.type |
19 → 3 | 29 → 45 | 16 views typed by a MOSA or OOSEM view definition |
FeatureReferenceExpression.referent |
99 → 71 | 436 → 464 | 28 references to a library enumeration literal (MOSAPillar::openStandards) |
Membership.memberElement |
353 → 99 | 646 → 900 | 254 memberships of a referenced library element, the referent memberships among them |
InvocationExpression.function |
245 → 19 | 107 → 333 | 226 calls of a calculation or function of these libraries |
Subclassification.superclassifier (and target, relatedElement, general) |
126 → 13 | 136 → 249 | 113 definitions specializing a library definition (:> MOSA::Standard) |
PartUsage.type |
235 → 63 | 0 → 172 | 172 parts typed by a definition of these libraries |
Subsetting.subsettedFeature (and target, relatedElement, general) |
44 → 34 | 425 → 435 | 10 features subsetting a library feature |
NamespaceImport.importedNamespace, MembershipImport.importedMembership |
25 → 8, 15 → 13 | 331 → 348, 265 → 267 | 17 imports of a library package, 2 of a library member |
CalculationUsage.type, ItemUsage.type, ReferenceUsage.type, ReferenceSubsetting.referencedFeature (and its ends) |
7 → 3, 20 → 16, 48 → 46, 40 → 38 | 0 → 4, 16 → 20, 501 → 503, 24 → 26 | 4, 4, 2 and 2 references to a library element |
The 66 newly matched elements are Redefinitions: a feature in a metadata usage's body that
binds a feature of the metadata definition by name (@MOSAPackage { pillar = MOSAPillar::openStandards; },
which redefines MOSAPackage::pillar) was written as a
ReferenceUsage with the declared name pillar and a value, because its redefinition reached a
library feature the writer could not link; it is now written as the pilot writes it — unnamed, with
an owned Redefinition of MOSAPackage::pillar — so ReferenceUsage.declaredName falls from 70
to 4 pilot-missing, ReferenceUsage.ownedRedefinition/ownedSpecialization/ownedSubsetting
gain 66 present-equal each, and the 66 Redefinitions match the pilot's, carrying every shape the
Redefinition rows already carry (isLibraryElement, owningType ours-missing; owner
pilot-missing; redefinedFeature indeterminate).
The (metaclass, property) rows ranked by the corpus elements on which the pilot states a value and we state nothing (ours-missing), each with the derivation clause to implement and the in-flight work that already covers it, so that each row can be handed on as it stands. Where a property is an owned attribute with a default rather than a derivation, the row says so: the gap is in the writer, not in a derivation. The missing derivations are not implemented here.
| # | metaclass | property | ours-missing | present-different | in-flight overlap | derivation clause |
|---|---|---|---|---|---|---|
| 1 | FeatureMembership |
isLibraryElement |
10632 | 0 | PR #1232 (feature/api-json-derived-properties-layered; writes true on library elements only, never false) |
Element::isLibraryElement = libraryNamespace() <> null (KerML 8.3.2.1, deriveElementIsLibraryElement); the pilot writes false on every user element |
| 2 | FeatureMembership |
memberElementId |
10632 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Membership::memberElementId = memberElement.elementId (KerML 8.3.2.3.5, deriveMembershipMemberElementId) |
| 3 | FeatureMembership |
ownedMemberElementId |
10632 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
OwningMembership::ownedMemberElementId = ownedMemberElement.elementId (KerML 8.3.2.3.6) |
| 4 | FeatureMembership |
relatedElement |
10632 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Relationship::relatedElement = source->union(target), ordered (KerML 8.3.2.5.2, deriveRelationshipRelatedElement) |
| 5 | FeatureMembership |
source |
10632 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Relationship::source, which Membership redefines as [membershipOwningNamespace] (KerML 8.3.2.3.5) |
| 6 | FeatureMembership |
target |
10632 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Relationship::target, which Membership redefines as [memberElement] (KerML 8.3.2.3.5) |
| 7 | FeatureMembership |
visibility |
10568 | 1 | PR #1232 (feature/api-json-derived-properties-layered) |
owned attribute Membership::visibility : VisibilityKind, default public (KerML 8.3.2.3.5); not derived |
| 8 | Feature |
featureTarget |
10046 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Feature::featureTarget: the last chainingFeature, else the feature itself (KerML 8.3.3.3, deriveFeatureFeatureTarget; KERML11-1 crossFeature) |
| 9 | Feature |
inheritedFeature |
10046 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Type::inheritedFeature = inheritedMembership.memberElement->selectByKind(Feature) (KerML 8.3.3.1, deriveTypeInheritedFeature) |
| 10 | Feature |
inheritedMembership |
10046 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Type::inheritedMembership = inheritedMemberships(excluded) over the supertypes (KerML 8.3.3.1, deriveTypeInheritedMembership) |
| 11 | Feature |
isConjugated |
10046 | 0 | none found | Type::isConjugated = ownedConjugator <> null (KerML 8.3.3.1 Type; a derived attribute without a named derive constraint); the pilot writes false on every type |
| 12 | Feature |
isLibraryElement |
10046 | 0 | PR #1232 (feature/api-json-derived-properties-layered; writes true on library elements only, never false) |
Element::isLibraryElement = libraryNamespace() <> null (KerML 8.3.2.1, deriveElementIsLibraryElement); the pilot writes false on every user element |
| 13 | Feature |
member |
10046 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Namespace::member = membership.memberElement (KerML 8.3.2.4, deriveNamespaceMember) |
| 14 | Feature |
membership |
10046 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Namespace::membership = ownedMembership->union(importedMembership), and for a Type also inheritedMembership (KerML 8.3.2.4, 8.3.3.1) |
| 15 | Feature |
feature |
10040 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Type::feature = featureMembership.ownedMemberFeature (KerML 8.3.3.1, deriveTypeFeature) |
| 16 | Feature |
featureMembership |
10040 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Type::featureMembership = ownedFeatureMembership->union(inheritedMembership->selectByKind(FeatureMembership)) (KerML 8.3.3.1; KERML11-191 restricts the inherited part to the supertypes) |
| 17 | Feature |
featuringType |
9762 | 2 | PR #1232 (feature/api-json-derived-properties-layered) |
Feature::featuringType = typeFeaturing.featuringType, plus the owning type of an owned feature (KerML 8.3.3.3, deriveFeatureFeaturingType; KERML11-3/4 multiplicity featuring) |
| 18 | Feature |
owningFeatureMembership |
9473 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Feature::owningFeatureMembership = owningMembership->selectByKind(FeatureMembership) (KerML 8.3.3.3) |
| 19 | Feature |
owningType |
9473 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Feature::owningType = owningFeatureMembership.owningType (KerML 8.3.3.3, deriveFeatureOwningType) |
| 20 | Feature |
type |
9407 | 120 | PR #1232 (feature/api-json-derived-properties-layered) |
Feature::type = typing.type with the types inherited through chaining and redefinition (KerML 8.3.3.3, deriveFeatureType) |
| 21 | OwningMembership |
isLibraryElement |
9560 | 0 | PR #1232 (feature/api-json-derived-properties-layered; writes true on library elements only, never false) |
Element::isLibraryElement = libraryNamespace() <> null (KerML 8.3.2.1, deriveElementIsLibraryElement); the pilot writes false on every user element |
| 22 | OwningMembership |
relatedElement |
9560 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Relationship::relatedElement = source->union(target), ordered (KerML 8.3.2.5.2, deriveRelationshipRelatedElement) |
| 23 | OwningMembership |
source |
9560 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Relationship::source, which Membership redefines as [membershipOwningNamespace] (KerML 8.3.2.3.5) |
| 24 | OwningMembership |
memberElementId |
9557 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Membership::memberElementId = memberElement.elementId (KerML 8.3.2.3.5, deriveMembershipMemberElementId) |
| 25 | OwningMembership |
ownedMemberElementId |
9557 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
OwningMembership::ownedMemberElementId = ownedMemberElement.elementId (KerML 8.3.2.3.6) |
| 26 | OwningMembership |
target |
9557 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Relationship::target, which Membership redefines as [memberElement] (KerML 8.3.2.3.5) |
| 27 | OwningMembership |
visibility |
9535 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
owned attribute Membership::visibility : VisibilityKind, default public (KerML 8.3.2.3.5); not derived |
| 28 | Feature |
name |
9518 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Element::name = effectiveName(): the declared name, or for a feature the name of the feature it redefines (KerML 8.3.2.1, deriveElementName) |
| 29 | FeatureMembership |
memberName |
9150 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Membership::memberName = memberElement.name (KerML 8.3.2.3.5, deriveMembershipMemberName) |
| 30 | FeatureMembership |
ownedMemberName |
9150 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
OwningMembership::ownedMemberName = ownedMemberElement.name (KerML 8.3.2.3.6) |
| 31 | Feature |
owningNamespace |
8727 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Element::owningNamespace = owningMembership.membershipOwningNamespace (KerML 8.3.2.1, deriveElementOwningNamespace) |
| 32 | FeatureValue |
isLibraryElement |
7066 | 0 | PR #1232 (feature/api-json-derived-properties-layered; writes true on library elements only, never false) |
Element::isLibraryElement = libraryNamespace() <> null (KerML 8.3.2.1, deriveElementIsLibraryElement); the pilot writes false on every user element |
| 33 | FeatureValue |
memberElementId |
7066 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Membership::memberElementId = memberElement.elementId (KerML 8.3.2.3.5, deriveMembershipMemberElementId) |
| 34 | FeatureValue |
ownedMemberElementId |
7066 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
OwningMembership::ownedMemberElementId = ownedMemberElement.elementId (KerML 8.3.2.3.6) |
| 35 | FeatureValue |
relatedElement |
7066 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Relationship::relatedElement = source->union(target), ordered (KerML 8.3.2.5.2, deriveRelationshipRelatedElement) |
| 36 | FeatureValue |
source |
7066 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Relationship::source, which Membership redefines as [membershipOwningNamespace] (KerML 8.3.2.3.5) |
| 37 | FeatureValue |
target |
7066 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Relationship::target, which Membership redefines as [memberElement] (KerML 8.3.2.3.5) |
| 38 | FeatureValue |
visibility |
7066 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
owned attribute Membership::visibility : VisibilityKind, default public (KerML 8.3.2.3.5); not derived |
| 39 | FeatureTyping |
isLibraryElement |
5919 | 0 | PR #1232 (feature/api-json-derived-properties-layered; writes true on library elements only, never false) |
Element::isLibraryElement = libraryNamespace() <> null (KerML 8.3.2.1, deriveElementIsLibraryElement); the pilot writes false on every user element |
| 40 | FeatureTyping |
owningType |
5915 | 0 | PR #1232 (feature/api-json-derived-properties-layered) |
Feature::owningType = owningFeatureMembership.owningType (KerML 8.3.3.3, deriveFeatureOwningType) |
| 41 | Redefinition |
redefinedFeature |
0 | 58 | closed for this repository's libraries (above) | Redefinition::redefinedFeature : Feature (KerML 8.3.3.3.8) is an element reference, and every Element carries an elementId (KerML 8.3.2.1.2) the API's JSON refers to it by; the 330 redefinitions of a feature of this repository's libraries once spelled as a name, {"@ref": "caption"}, now link by the element's fixed id — the same movement for FeatureTyping::type, MetadataUsage::type, FeatureReferenceExpression::referent and ReferenceSubsetting::referencedFeature into those libraries — and the 58 left are redefinitions of a feature inherited within the model itself that the writer spells as a name (vehicle_b_1::providePower) |
| 42 | AttributeUsage |
ownedRelationship |
36 | 2325 | none found | Element::ownedRelationship : Relationship [0..*] {ordered} (KerML 8.3.2.1.2) in the order the notation declares them: a usage's Redefinition (redefines x) before its FeatureValue (= …); ours lists the value first |
| 43 | FeatureReferenceExpression |
ownedMembership |
0 | 7 | the writer owns the Membership (export/rdf_expr.go featureReferent); the 7 left are the FunctionReferenceMember shape, a FeatureMembership owning an Expression typed by the named function (KerML 8.2.5.8.3), which ours writes as a Membership of the function |
FeatureReferenceExpression::referent is the memberElement of the first ownedMembership that is not a ParameterMembership (KerML 8.3.4.8.5, deriveFeatureReferenceExpressionReferent); the notation maps a feature reference to that owned Membership (8.2.5.8.3, FeatureReferenceMember) |
Rows an evaluator rule in PR #1232 (internal/semantic/metamodel/rules.go) already names are marked; that PR adds a lazy metamodel evaluator and layers its derived values into the API-JSON writer, so its merge is expected to move those rows from ours-missing to present-equal or present-different, and this referee is how that movement is measured.