Repository navigation
fix(export): own a declaration head's relationships in the order the notation spells them - #1333
Merged
Merged
Conversation
…notation spells them ownedRelationship is ordered (KerML 8.3.2.1.2) and the notation adds an element's owned relationships as it parses each clause (KerML 8.2.1, SysML 8.2), so a usage's typing, specializations and multiplicity are owned in the order written, ahead of its FeatureValue and its body members; the writer seated the materialized relationships last. The reader spells a head back in that order. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…-relationship-order
…tate, and pin the order in goldens The reader writes a declaration head's clauses in the order the graph owns their relationship elements, the multiplicity part where its membership stands, so a round trip keeps the spelling; a graph stating the collapsed properties alone keeps the fixed clause order. Goldens re-recorded for the owned-relationship order, with a fixture for each head form; rdf.Graph.ReorderObjects permutes a property's objects in place. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…e ontology gate 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)".
|
…d relationships in notation order Co-Authored-By: jason.han <hanhuijun@gmail.com>
…braries' into fix/api-json-owned-relationship-order
… the merged tree Co-Authored-By: jason.han <hanhuijun@gmail.com>
6 tasks done
…ace an unplaced multiplicity once Co-Authored-By: jason.han <hanhuijun@gmail.com>
… the reader keeps under any id form Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # docs/project/api-json-differential-baseline.json # docs/project/api-json-differential.md
Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # docs/project/api-json-differential.md # tests/export/testdata/convert/constraints.golden.ttl.sha256 # tests/export/testdata/convert/end_binding_bodies.golden.ttl.sha256 # tests/export/testdata/convert/irregular_layout.golden.ttl.sha256 # tests/export/testdata/convert/result_expressions.golden.ttl.sha256
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…-relationship-order
… with develop and the bridge follow-ups Co-Authored-By: jason.han <hanhuijun@gmail.com>
Merged
2 of 6 tasks
…braries' into fix/api-json-owned-relationship-order Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # docs/project/api-json-differential-baseline.json
… with the bridge's develop merge Co-Authored-By: jason.han <hanhuijun@gmail.com>
Base automatically changed from
feat/apijson-bridge-opensysml-libraries
to
develop
October 22, 2026 03:23
…-relationship-order Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # docs/project/api-json-differential-baseline.json # docs/project/api-json-differential.md
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…he re-recorded baseline Co-Authored-By: jason.han <hanhuijun@gmail.com>
…orded baseline Co-Authored-By: jason.han <hanhuijun@gmail.com>
…-relationship-order Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # docs/project/api-json-differential-baseline.json # docs/project/api-json-differential.md # tests/export/testdata/convert/end_binding_bodies.golden.ttl.sha256
…elop Co-Authored-By: jason.han <hanhuijun@gmail.com>
…-relationship-order Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # docs/project/api-json-differential-baseline.json # docs/project/api-json-differential.md # internal/translate/rdf/term.go
…elop with the derived properties Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…-relationship-order
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
The api-json differential (docs/project/api-json-differential.md, the
AttributeUsageownedRelationshipgap row) found that forattribute a redefines x = expr;the pilot'sownedRelationshipis[Redefinition, FeatureValue]while ours was[FeatureValue, Redefinition]. The cause is wider than that shape: the RDF writer materialized a head's relationship elements (FeatureTyping, Subsetting, Redefinition, ReferenceSubsetting, Subclassification) in a pass after the whole document was encoded, so they were appended toownedRelationshipafter the multiplicity's membership, the FeatureValue and every body member, and in a fixed kind order (typing, specializes, subsets, redefines, references) rather than the order written. The API JSON writer serializesownedRelationshipin graph order, so it showed the same.Now:
ownedRelationship: after the prefix metadata, ahead of the FeatureValue and the body members.ownedSpecialization,ownedTyping,ownedSubsetting,ownedRedefinitionandownedReferenceSubsettingfollow the same order. Covers every head form the grammar orders this way:redefines x = v,:>> x : T = v,: T subsets y,: T = v,:>> x default = v,: T [n] :> y/:> y [n] : T, a definition's:> Qahead of its members,#metaprefixes ahead of the head (internal/translate/export/rdf_out.go,rdf_normative.go,rdf_expr.go;rdf.Graph.ReorderObjectspermutes a property's objects in place, tracking the statements through the Term-keyed index feat(export): owned absence and evaluator-derived properties in API JSON #1232 introduced).snapshot :>> done :> fuelno longer comes back assubsets fuel redefines done;of p[*] ordered : Fuelno longer comes back asof p : Fuel[*] ordered). A graph stating the collapsed properties alone keeps the fixed clause order (rdf_in.gorelationshipWords,spelledHead;end_forms.gopayload).feature f subsets x specializes x;owns two Subsettings ofx;referencesand an end form'ssubsetsboth as ReferenceSubsetting), the writer states each element's keyword assysx:headClauseand the reader keeps the clauses apart and in order by it under either id form; a graph of another writer that states no such fact keeps the fixed order. A multiplicity no membership places (an older graph's) is written once, with the first typing clause. The extension is documented indocs/reference/rdf-mapping.md.sysml:type,sysml:redefinedFeature, …) keep their kind order, so that part of the Turtle is unchanged.Specification basis
KerML 1.1 Beta 2 § 8.3.2.1.2 Element:
ownedRelationship : Relationship [0..*] {subsets relationship, ordered}. KerML § 8.2.1 (Table 3) defines the notation-to-abstract-syntax mapping:p += Elementadds the result of parsing the concrete syntax Element to the abstract syntax list property p, so an ordered list property collects its elements in parse order. The productions are, in order: KerMLFeature = … FeatureDeclaration? ValuePart? TypeBody,FeatureSpecializationPart = FeatureSpecialization+ MultiplicityPart? FeatureSpecialization* | MultiplicityPart FeatureSpecialization*with everyTypings/Subsettings/Redefinitions/Referencesclause andMultiplicityPartstatingownedRelationship += …, thenValuePart = ownedRelationship += FeatureValue, then the body's members; SysML v2.1 Beta 2 § 8.2Usage = UsageDeclaration? UsageCompletion,UsageDeclaration = Identification FeatureSpecializationPart?,UsageCompletion = ValuePart? UsageBody, andDefinitionDeclaration = Identification SubclassificationPart?ahead ofDefinitionBody. The grammar is also what the pinned pilot (build/pilot-grammars/SysML.xtext) parses with.Verdict: the order is required by the normative text, not pilot-only. The ordered property plus the mapping rule fix the order to the order the clauses are written in — typings, specializations and the multiplicity as spelled, then the FeatureValue, then the body. The pilot's order is that order; it is differential evidence, not the basis. No compliance row moves (the mapping is export, not validation); the gap row is re-measured below.
In-flight overlap
feature/api-json-derived-properties-layered), feat(referee): list the api-json matches a run lost and gained, and record why naming-feature keys cost manual-examples 171 #1323, feat(tools): record the API JSON writer's source digest in the differential baseline #1325, feat(referee): load the OpenSysML Libraries into the pilot JSON bridge and re-record the api-json differential #1328, feat(export): own the referent Membership of a FeatureReferenceExpression where the notation places it #1331, feat(identity): fix ids for OpenSysML's own library elements so references link by id #1332, fix(semantics): conform to the type a filter names by element, not by name #1365 and the PR-less remote branches touchinginternal/translate/exportorinternal/translate/rdf(feature/api-json-derived-properties,fix/651-…,fix/652-…,fix/653-…,fix/654-…,fix/accept-action-usage,fix/guarded-succession-transition-usage,fix/include-use-case-reference-subsetting,fix/send-action-usage): none changes the order owned relationships are emitted (materializeRelationships,relationships,relationshipOrderor theownedRelationshipwrites) or the reader's clause order. No code overlap.docs/project/api-json-differential-baseline.jsonand editeddocs/project/api-json-differential.md; all four have landed ondevelop. The conflicts their re-records raised against this branch were resolved by regenerating the baseline, the report figures and the fourtests/export/testdata/convert/*.golden.ttl.sha256digests from the merged tree, never by taking a side.Base
develop. The branch was first based on PR #1328'sfeat/apijson-bridge-opensysml-libraries(the referee re-recorded with the OpenSysML Libraries loaded into the pilot bridge is the baseline this change is measured against) via merge commits of its heads, and retargeted todeveloponce #1328 merged;origin/developis merged in as merge commits (0a5fa2d94,5cd37f288, then4196792dfwith #1232, #1388 and #1389) and the baseline re-recorded on that tree each time. With #1232 in,rdf.Graph.ReorderObjectsworks on its Term-keyedsubjectIndex: it detaches a subject's index entry the overlay graph shares with its base before touching it, and finds the statements to permute through a per-predicate position cache built on first use and kept current byAddTriple(reset byRewriteTriples), so a head costs its own statements, not a scan of the graph.api-json referee: before and after
Fresh
XDG_CACHE_HOMEruns, pilot2026-08(0.62.0).fde7c11c6, before and after the change): 89957 elements matched; properties 618674 → 623436 present-equal (+4762), 50027 → 45265 present-different (−4762), every other bucket and count unchanged, matches lost 0 / gained 0; 101 rows moved, all present-different → present-equal: 67ownedRelationship, 22ownedSpecialization, 12ownedSubsetting. The before run showed the family beyondredefines … = …: a usage'sFeatureTypingafter its body'sFeatureMemberships (part camera : Camera { … }), aPartDefinition'sSubclassificationafter its members, aPortUsage'sRedefinitionafter its members,:>> x : T = vas[FeatureValue, FeatureTyping, Redefinition].develop(this head,origin/develop4196792dfmerged, measured againstdevelop's own committed baseline, re-recorded there by feat(export): owned absence and evaluator-derived properties in API JSON #1232): 924 files; 91721 elements matched (18392 ours-only, 37335 pilot-only, 1729 type-mismatch — unchanged); properties 644960 → 649821 present-equal (+4861), 31668 → 26807 present-different (−4861); ours-missing 1079787, pilot-missing 66545, absent-both 2406377, indeterminate 26031 unchanged; refused/unconvertible/colliding/pilot-failed unchanged. Every moved scorecard row: the same 101 rows (67ownedRelationship, 22ownedSpecialization, 12ownedSubsetting), each one present-different → present-equal by the same count with its other four buckets unchanged; no row moved the other way and no other row moved. Largest:AttributeUsage.ownedRelationship2332 → 1197,PartUsage.ownedRelationship1554 → 1004,Feature.ownedRelationship1802 → 1401,ReferenceUsage.ownedRelationship852 → 96,PartDefinition.ownedRelationship215 → 20,RenderingUsage.ownedRelationship33 → 30. Per root (+present-equal = −present-different): training +325, pilot-examples +1533, pilot-validation +513, kerml-examples +530, spec-examples +248, testdata +58, examples +1329, probes +2, manual-examples +323; file counts and matched elements unchanged in every root. The 99 sites over the first measurement are heads feat(export): own the referent Membership of a FeatureReferenceExpression where the notation places it #1331/feat(identity): fix ids for OpenSysML's own library elements so references link by id #1332 and the develop merges (feat(export): owned absence and evaluator-derived properties in API JSON #1232's derived properties included) brought into the match.develop5cd37f288) anddevelop's current one, 3335 further rows move (feat(export): owned absence and evaluator-derived properties in API JSON #1232's derived properties —qualifiedName,owner,memberElement,isLibraryElement, … now stated — with their new matches); those aredevelop's own (feat(export): owned absence and evaluator-derived properties in API JSON #1232, fix(runtime): send via a state definition's own port through what binds or connects it #1388, fix(runtime): read a step's restated parameter as the redefinition it is #1389, adjudicated in their bodies), already indevelop's committed baseline and unchanged by this change. The writer digest moves with the writer.AttributeUsage.ownedRelationship(1197) is a different shape, checked on the pilot's export ofattribute cargoMass : MassValue;(training 33): the pilot owns, after theFeatureTyping, anOwningMembershipof aMultiplicity(not implied) on a usage that writes no multiplicity part; ours states none. Recorded in the gap row.-updateon the merged tree, a fresh-cache-checkreproduces it,make docs-countsgreen; gap row 42, the headline figures and the per-root, present-different and pilot-missing tables refreshed from it.How it was verified
TestCorpusRoundTripwithOPENSYSML_REQUIRE_TRAINING_CORPUS=1 OPENSYSML_REQUIRE_PILOT_CORPORA=1 OPENSYSML_REQUIRE_SPEC_EXAMPLES=1: 876 files, 830 stable, 7 whitespace-only, 0 graph-diff, 1 unwritable, 0 unparseable, 38 refused — no movement against the committed expectation.TestCorpusAPIJSONRoundTriplikewise passes with no movement. Both re-run on the mergeddeveloptree.go test ./internal/translate/... ./tests/export/green on the merged tree. Export goldens re-recorded (36 files): every moved line is anownedRelationship/ownedSpecialization/ownedTyping/ownedSubsetting/ownedRedefinitionorder, a relationship-element block moving with it, or a.golden.sysmlspelling that now keeps the written clause order. New fixturetests/export/testdata/convert/declaration_head_order.sysmlpins every head form above;rdf.Graph.ReorderObjectshas a unit test;TestSameTargetSpecializesAndSubsetsKeepTheirSpelledOrder(both orders,IDQualifiedNameandIDUUID) andTestUnplacedMultiplicityIsWrittenOnceAcrossSplitTypingspin the two review findings.TestAnonymousKeywordsComeBackFromTheTypedFactsAlone,TestLinkedReferencesCarryTheRoundTripWithoutSourceText,TestSelfNamedRedefinitionTargetSurvivesTheGraphAlone,TestPayloadMultiplicityPartBeforeTheTyping(a head comes back in its written clause order instead of the fixed one),TestExpressionBodyParameterIsDeclaredOutsideTheBody(: Gauge [1..upper]owns the FeatureTyping before the multiplicity's membership),TestToolkitAPIGoldenNotationunchanged (the toolkit's JSON states no derivedtarget, so the reader resolves a relationship's end by its specific property). The ontology gate's known-violation list gains the pre-existingisDefault-on-the-usage collapse the new fixture'sdefault = vexercises.go build ./...,go vet ./...,gofmt -l .(empty),go test -C tools ./...(the provenance tests included),make lint,make docs-counts,python3 scripts/changelog.py checkgreen;go test ./...green (heavy packages with-timeout 45m, the Makefile's).Checklist
make testandmake lintpass locallychanges/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 changelogLink to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/3e3f2a6554334f64b826404b21c268fa
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/3e3f2a6554334f64b826404b21c268fa?variant=devin
Requested by: @HuiJun