Skip to content

fix(semantics): an implied conjugated port definition is named only by its original's name and never has a short name - #1812

Merged
HuiJun merged 24 commits into
developfrom
fix/conjugated-port-definition-names
Nov 1, 2026
Merged

HuiJun merged 24 commits into
developfrom
fix/conjugated-port-definition-names

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

What and why

Follow-up to #1807 (merged); originally stacked on it, now merged with develop and targeting develop.

#1807 gives a port definition's implied ConjugatedPortDefinition a native element. For a port definition with a short name, the conjugate was named after the short name in three places that agreed with each other but not with the specification: native Name/ShortName ~s/~q, RDF declaredShortName "~s"/"~q" and an invented address segment P::@0::'~s', and a reverse converter that required them. (The ~q short name for port def <q> Q; is also present on develop, and develop could not round-trip port def <s>; through RDF.)

Now the conjugate is named ~ plus the original's name when the original has a name and is otherwise anonymous. It never has a short name:

  • native (symbols/implied.go buildConjugatedPortDefinition): the conjugate's identification has Name ~Name only for a named original and never has a ShortName. The conjugate is still built for a short-name-only port. Its ids, OwningMembership and PortConjugation from fix(semantics): a port definition owns the ConjugatedPortDefinition it implies — its OwningMembership and PortConjugation read natively as the conversion writes them #1807 are unchanged. port x : ~s; still resolves, because the ~ typing resolves the original s and then conjugates it, so it never looks up the conjugate's own name. A test covers this case.
  • positional identities (export/positional.go): an implied symbol's declaration span is its original's span, so an anonymous conjugate would have claimed its original's positional name (P::@0). positionalSymbol now skips implied symbols, which get their ids from ElementIDs.conjugateOf.
  • RDF writer (export/rdf_normative.go conjugatedPortDefinition): writes no declaredShortName. It writes declaredName "~P" and sysml:qualifiedName <owner>::'~P' only for a named original. An anonymous conjugate gets no declared name and the address sysx:positionalName <owner>::@conjugated. That address follows the minted-segment form fix(export): an unnamed element's address is sysx:positionalName; sysml:qualifiedName states only the qualified name the metamodel derives #1805 documents in address.go for implied elements without a name (@trigger for a transition's trigger action). The unnamed-member form @N does not fit, because P::@0::@0 already names the first unnamed member of <s>'s own body.
  • reverse converter (export/rdf_in_normative.go verifyConjugated): requires declaredName "~"+original name when the original is named, through its declaredName or a named address segment. It requires no declaredName when the original is unnamed. It accepts an absent declaredShortName, or exactly ~<original short> (the legacy value earlier writers emitted). It rejects anything else.

TestConversionNamesAShortNamedPortsConjugateByItsShortName asserted declaredShortName "~s" and an address ending ::'~s', which is the non-conformant behavior. It is replaced by TestConversionNamesConjugatesFromOriginalDeclaredNames, which asserts the spec behavior for all three originals. The ~q/~s expectations in TestPortDefinitionOwnsItsConjugate change for the same reason.

Specification basis

  • SysML v2.1 Beta 2 §8.3.12.2 ConjugatedPortDefinition::effectiveName(): let originalName : String = originalPortDefinition.name in if originalName = null then null else '~' + originalName endif.
  • KerML Element::shortName is derived by effectiveShortName(), whose default body is declaredShortName. ConjugatedPortDefinition does not redefine it, and the implied conjugate declares nothing, so its shortName is null in every case.
  • KerML Element::qualifiedName is null if there is not a complete ownership chain of named Namespaces. The original <s> is unnamed.

The pinned pilot agrees. For package P { port def <s>; port def <q> Q; } its api-json exporter gives: the conjugate of <q> Q has name ~Q, shortName null, qualifiedName P::Q::'~Q' and declaredName/declaredShortName null; the conjugate of <s> has name, shortName and qualifiedName all null.

No docs/project/spec-compliance.md row moves.

How it was verified

  • TestConjugatedPortDefinitionNamesFollowTheOriginalName (semantics) runs over <s>, <q> Q and R and a part typing ~s/~Q/~R. It checks the reflective name/declaredName/shortName/declaredShortName/qualifiedName of each conjugate and that each port's ConjugatedPortTyping reaches its original with no resolver diagnostics. A metamodel-evaluator test checks the derived Element::qualifiedName against the pilot's P::Q::'~Q'.
  • TestConversionNamesConjugatesFromOriginalDeclaredNames checks the RDF properties and address for each original. TestElementIDReaderSeparatesShortPortAndAnonymousConjugate and TestPositionalIdentityIgnoresImpliedConjugate check that <s> and its conjugate read distinct graph-written ids.
  • TestShortNamedPortDefinitionRoundTripsThroughRDF runs over port def <s>;, port def <q> Q;, port def Q; and the ~s/~Q/~R model. Each does ToRDF → ToSysML with sysx:sourceText stripped, then re-converts, and checks that the graph is identical. Reverse-converter tests cover the legacy declaredShortName "~q" (accepted), a wrong declaredName/declaredShortName (rejected) and a declaredName on the anonymous conjugate (rejected).
  • Generated artifacts compared with the base: pilot-apijson-diff -update moved only the writer sourceDigest in docs/project/api-json-differential-baseline.json, and the scorecard did not move. make stdlib-snapshot-check is clean, so stdlib.snapshot did not move. Grep shows no port definition with a short name (port def <…>, short-only or name plus short) in examples/, tests/ or the downloaded training, pilot and spec-example corpora. That is why the corpus round-trip and scorecard do not move. TestCorpusRoundTrip passes with OPENSYSML_REQUIRE_TRAINING_CORPUS=1 OPENSYSML_REQUIRE_PILOT_CORPORA=1.
  • go build ./..., go vet ./..., gofmt -l . (empty), go test -count=1 ./internal/semantic/... ./internal/translate/... ./tests/export/... ./tests/corpus/... ./internal/check/... ./internal/doc/queryexec/... ./internal/frontend/repl/... ./internal/workspace/libs/..., go -C tools test -count=1 ./referee/apijson/... ./oracle/baseline/....

Known difference not changed here: the semantics reflective qualifiedName feature joins raw names for every element (P::Q::~Q, as it would P::a b), while the metamodel evaluator escapes segments as the pilot does.

Checklist

  • make test and make lint pass locally (the targeted gate above)
  • Tests added or updated for the change
  • Documentation extended where it already covers the surface (docs/reference/rdf-mapping.md)
  • Changelog entry added as changes/unreleased/conjugated-port-definition-names.fixed.md
  • baselines regenerated (pilot-apijson-diff -update: writer digest only)
  • No internal work-item labels in the body, docs, or changelog

Link to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/0e3626a6a66d49e49fc83db32d479123
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/0e3626a6a66d49e49fc83db32d479123?variant=devin
Requested by: @HuiJun

devin-ai-integration Bot and others added 19 commits October 31, 2026 12:52
…rtDefinition it implies (ImpliedDecl)

Co-Authored-By: Nicolas Rouquette <nicolas.f.rouquette@jpl.nasa.gov>
Co-Authored-By: Nicolas Rouquette <nicolas.f.rouquette@jpl.nasa.gov>
…t implies, with its OwningMembership and PortConjugation, as the conversion writes them

Co-Authored-By: Nicolas Rouquette <nicolas.f.rouquette@jpl.nasa.gov>
…gest

Co-Authored-By: Nicolas Rouquette <nicolas.f.rouquette@jpl.nasa.gov>
…erting it

Co-Authored-By: Nicolas Rouquette <nicolas.f.rouquette@jpl.nasa.gov>
…tion, its PortConjugation reads as ownedConjugator/isConjugated, and the snapshot decoder interns ImpliedDecls under a mutex

Co-Authored-By: Nicolas Rouquette <nicolas.f.rouquette@jpl.nasa.gov>
…t-definition-member

Co-Authored-By: Nicolas Rouquette <nicolas.f.rouquette@jpl.nasa.gov>

# Conflicts:
#	docs/project/api-json-differential-baseline.json
#	internal/semantic/symbols/facts.go
#	internal/translate/export/element_ids.go
#	internal/workspace/libs/stdlib.snapshot
Co-Authored-By: Nicolas Rouquette <nicolas.f.rouquette@jpl.nasa.gov>
…s its conjugate too

Co-Authored-By: Nicolas Rouquette <nicolas.f.rouquette@jpl.nasa.gov>
…s short name, not an empty declared name

Co-Authored-By: Nicolas Rouquette <nicolas.f.rouquette@jpl.nasa.gov>
…gest

Co-Authored-By: Nicolas Rouquette <nicolas.f.rouquette@jpl.nasa.gov>
…ion's conjugate by its short name

Co-Authored-By: Nicolas Rouquette <nicolas.f.rouquette@jpl.nasa.gov>
…gest over the reverse-converter fix

Co-Authored-By: Nicolas Rouquette <nicolas.f.rouquette@jpl.nasa.gov>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ember' into fix/conjugated-port-definition-names

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	docs/project/api-json-differential-baseline.json
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

Base automatically changed from fix/conjugated-port-definition-member to develop October 31, 2026 19:41
@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review October 31, 2026 20:19
devin-ai-integration Bot and others added 4 commits November 1, 2026 02:06
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
@HuiJun
HuiJun merged commit 5edbe66 into develop Nov 1, 2026
30 checks passed
@HuiJun
HuiJun deleted the fix/conjugated-port-definition-names branch November 1, 2026 05:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant