Repository navigation
feat(export): own the referent Membership of a FeatureReferenceExpression where the notation places it - #1331
Merged
Merged
Conversation
…' into feat/apijson-bridge-opensysml-libraries
…e as explicit extension libraries The bridge takes --extension-library <dir> (repeatable; .kerml then .sysml, read as library resources after the pinned standard library, as the two validator bridges do). The api-json referee passes the directory the pilot differential already hands its validators (diff.LibrariesHandedOver) and records it in the baseline as the opensysml-libraries input. Co-Authored-By: jason.han <hanhuijun@gmail.com>
… Libraries loaded 2983 elements move from unmatched to matched and none is lost: the 357 library-named members of docs/manual/examples and 2626 in examples, 1712 of them in the two files the pilot could not export while MOSA and OOSEM were unloaded. The newly resolved comparisons differ in three shapes the scorecard already carried (a library target spelled as a name, the order of a usage's Redefinition and FeatureValue, the referent Membership of a FeatureReferenceExpression), recorded as launch-ready gap rows 41-43. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…sion where the notation places it A FeatureReferenceExpression owns a Membership whose memberElement is the referenced Feature (KerML 8.2.5.8.3 FeatureReferenceMember); referent is derived from it (8.3.4.8.5 deriveFeatureReferenceExpressionReferent). The writer now emits that Membership before the result parameter and lists it under ownedMembership too, instead of restating referent after the fact at the end of ownedRelationship. A Membership an expression owns to the element it names (metadata access, invocation callee) is an ownedMembership as well. 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)".
|
…ences link by id
A reference into one of the bundled extension libraries (DocumentQueries,
MOSA, OOSEM, ...) was written as a {"@ref": name} name reference, because
libraryElement gave an id only to symbols the norm identifies. The
extension libraries now carry fixed, deterministic ids derived as the
normative ones are, under the libraries' upstream URL (identity.OpenSysML,
SourceExtension), so the writer links them by id and names them with a
library stub, hover reports them as (extension, OpenSysML), and the
identity gate checks they collide with nothing in the pilot's XMI.
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…p where the notation places it A FeatureChainExpression names its target through a Membership it owns (KerML 8.2.5.8.3 FeatureChainMember), from which targetFeature is derived (8.3.4.8.4 deriveFeatureChainExpressionTargetFeature). The writer now emits that Membership between the operand and the result parameter and lists it under ownedMembership, which retires the pass that restated referent and targetFeature Memberships at the end of ownedRelationship. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ridge-opensysml-libraries The api-json provenance now carries both the writer's source digest and the opensysml-libraries input.
…-provenance tree Same counts, scorecard and matches as before the merge (0 lost, 0 gained against the previous run); the provenance now names the writer digest and the opensysml-libraries input together. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ridge-opensysml-libraries Brings the referee's -trimpath refusal and develop with #1323 merged; the api-json provenance keeps the writer digest and the opensysml-libraries input.
…to OpenSysML's libraries linked by id The writer now links every reference into this repository's own libraries by the element's fixed id, so the baseline moves present-different 50027 -> 45688 and indeterminate 21034 -> 25703 on the same 920 files; the record adjudicates every row that moved and closes gap row 41 for those libraries. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…erent Memberships FeatureReferenceExpression ownedRelationship/ownedMembership move from 38 equal / 2110 different to 2141 / 7, FeatureChainExpression from 0 / 504 to 415 / 89, InvocationExpression ownedMembership from 0 / 468 to 439 / 29, MetadataAccessExpression ownedMembership from 6 ours-missing to 6 equal; gap row 43 records what the 7 remaining elements are. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…sml-libraries The referee is handed its build checkout for the writer digest; the provenance keeps the opensysml-libraries input beside it. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…sml-libraries Co-Authored-By: jason.han <hanhuijun@gmail.com>
…braries' into feat/extension-library-identity
…library identity change The base branch now records the writer's source digest in the baseline; a full -update over the merged tree moves only that digest, every count being the one already recorded. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…mbership Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # docs/project/api-json-differential-baseline.json # docs/project/api-json-differential.md
…ed with the extension-library identity change Re-run from the merged tree rather than taking a side: against the baseline the identity change recorded, only the owned-Membership rows move (FeatureReferenceExpression 38/2110 -> 2141/7, FeatureChainExpression 0/504 -> 415/89, InvocationExpression ownedMembership 0/468 -> 439/29, ConstructorExpression ownedMembership 0/57 -> 3/54, MetadataAccessExpression ownedMembership 6 ours-missing -> 6 equal) and the writer digest. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Merged
2 of 6 tasks
…ence-membership Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # docs/project/api-json-differential-baseline.json
No scorecard row moves; the writer digest, one spec-examples type mismatch and three extension properties move with develop. Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration
Bot
changed the base branch from
feat/apijson-bridge-opensysml-libraries
to
develop
October 21, 2026 23:55
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
A
FeatureReferenceExpressionowns aMembershipwhosememberElementis the referenced Feature, andreferentis derived from it. The writer collapsed the reference to thereferentedge and a later pass (materializeReferentMemberships) restated it as a Membership appended after the result parameter and absent fromownedMembership, soownedRelationshipandownedMembershipdiffered from the pilot on every feature reference expression (api-json differential gap row 43). AFeatureChainExpression's target feature had the same shape.Now the writer owns the Membership itself, where the notation places it:
FeatureReferenceExpression:[Membership(referent), ReturnParameterMembership](featureReferentinrdf_expr.go), with the same ids the restating pass minted (<node>_preferentunder an expression node,<element>_referentbeside an expression element, claimed against declared ids);FeatureChainExpressionnaming a plain member:[ParameterMembership(operand), Membership(targetFeature), ReturnParameterMembership]; a chained member keeps itsOwningMembershipof the owned chain feature;MetadataAccessExpression's referenced element, an invocation's callee) is listed underownedMembershipas well asownedRelationship(Namespace::ownedMembership = ownedRelationship->selectByKind(Membership)).The restating pass is removed;
materializeNormativekeeps its other work.Targets
develop. The branch was cut on #1328's branch and lands after #1332 in the bridge follow-up order, so #1328's head (97f8c58, which mergesdevelopwith #1325) and #1332's head (63cb7b2) are merged in as merge commits, and the baseline and report are re-recorded from the combined tree rather than resolved by picking a side.origin/develop(5db0f74) is merged in as well, with the baseline re-recorded from the merged tree (no scorecard row moved; the writer digest and spec-examples' type-mismatch count moved with develop).Specification basis
KerML 1.1 Beta 2:
FeatureReferenceExpression : ownedRelationship += FeatureReferenceMember,FeatureReferenceMember : Membership = memberElement = FeatureReference;FeatureChainExpression … '.' ownedRelationship += FeatureChainMember,FeatureChainMember : Membership = FeatureReferenceMember | OwnedFeatureChainMember.deriveFeatureReferenceExpressionReferent: the referent is thememberElementof the firstownedMembershipthat is not aParameterMembership; § 8.3.4.8.4deriveFeatureChainExpressionTargetFeaturelikewise for the target feature.The owned Membership is the abstract-syntax mapping of the notation, not a pilot habit; the pilot agrees. Moves the
referent/targetFeaturerow ofdocs/project/spec-compliance.mdto its new locus (still ✅).In-flight overlap
feature/api-json-derived-properties-layered): touchesapi_json_*.goonly, nordf_expr.go/rdf_normative.gochange and noreferent/FeatureReferenceExpressionrow among its derived properties; no overlap.feat/extension-library-identity): merged in; it changes which references link by id, not the owned Memberships — against its baseline only the rows below move.feature/api-json-derived-properties(predecessor of feat(export): owned absence and evaluator-derived properties in API JSON #1232, 9 commits ahead of its merge-base, not in feat(export): owned absence and evaluator-derived properties in API JSON #1232): touchesrdf_expr.gofor argument/body minting, not the referent Membership. Other PR-less branches touchinginternal/translate/export(fix/651-…,fix/652-…,fix/653-…,fix/654-…,fix/accept-action-usage,fix/include-use-case-reference-subsetting,fix/send-action-usage) do not touch the referent, target-feature or callee Memberships.Counter movements (api-json referee, fresh
XDG_CACHE_HOME)Against #1332's baseline (the state this PR lands on): present-equal 619268 → 624752 (+5484), present-different 45688 → 40210 (−5478), ours-missing 1058259 → 1058253 (−6); matched 90023, ours-only, pilot-only, pilot-missing, absent-both and indeterminate unchanged; provenance differs in the
api-json-writersource digest and the date only. A fresh-cache-checkon the combined tree reproduces the recorded baseline.Before this PR was combined, the same deltas were measured against #1328's baseline (
-checkon #1328's then head 3d8d957 in a separate worktree reproduced it exactly): 618674 → 624158, 50027 → 44549, 1058325 → 1058319.FeatureReferenceExpression.ownedRelationship,.ownedMembershipownedMembership; the 7 left are a function named as an argument (->reduce '+'inSimple Tests/Expressions.kerml), which the pilot owns as aFeatureMembershipof anExpressiontyped by the function (§ 8.2.5.8.3FunctionReferenceMember) where ours writes aMembershipof the function — a different mapping, recorded in gap row 43FeatureChainExpression.ownedRelationship,.ownedMembershipFeatureChainthrough anOwningMembershipwhere ours resolves the member to aMembershipof the named feature (Control Structures Example.sysml)InvocationExpression.ownedMembershipownedMembership; the 29 left are receiver-first invocations (s.f(x)), where the pilot orders[ParameterMembership, Membership, …]and ours the callee first — the same 29 theownedRelationshiprow already carriedConstructorExpression.ownedMembershipParameterMembershipper argument where the pilot owns none (ActionTest.sysml) — theownedRelationshiprow's existing 54MetadataAccessExpression.ownedMembershipownedMembershipPer root, present-equal rises and present-different falls by the same amount (training +563, sysml-examples +1897, sysml-validation +665, kerml-examples +182, spec-examples +145/−144 with one ours-missing closed, tests/testdata +17, examples +1403 with five ours-missing closed, probes +2, manual-examples +610). No other scorecard row moved.
How it was verified
tests/exportgoldens: 33 files move. By category: everyFeatureReferenceExpressionnode gainsownedMembershipof its referent Membership and lists it before_pout_om(88 nodes), the 11 expression-element feature references (constraint { x }) keep their<element>_referentid and lose the trailing position,FeatureChainExpression/MetadataAccessExpression/invocation nodes list their Membership underownedMembership(19 nodes reordered); no triple other thanownedRelationship/ownedMembershiplists and the moved Membership nodes changes. On the combined treetests/exportandtests/identitypass without further golden movement.tests/export/result_expression_test.goTestExpressionBodyParameterIsDeclaredOutsideTheBodypins the new shape;TestReferentMembershipIDCollisionIsRefusedpins the id claim at its new locus.TestCorpusRoundTrip,TestCorpusAPIJSONRoundTrip,TestSameTriples,TestRefusalClasswithOPENSYSML_REQUIRE_TRAINING_CORPUS=1 OPENSYSML_REQUIRE_PILOT_CORPORA=1 OPENSYSML_REQUIRE_SPEC_EXAMPLES=1: pass on the combined tree, no ratchet movement.go run -C tools ./cmd/pilot-apijson-diff -updatefrom the combined tree with a freshXDG_CACHE_HOME, then-checkwith another fresh cache: reproduces;make docs-countscurrent.go build ./...,go vet ./...,gofmt -l .(empty),go test ./...(119 packages ok),go test -C tools ./...,make lint,python3 scripts/changelog.py check: pass.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/08dcd1a81c9f4d8881aa21febe894183
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/08dcd1a81c9f4d8881aa21febe894183?variant=devin
Requested by: @HuiJun