Skip to content

Enhance SysML v2 support with Dependency, Binding, and layout fixes#29

Merged
Malcolmnixon merged 21 commits into
mainfrom
feature/general-view-relationship-edges
Jul 12, 2026
Merged

Enhance SysML v2 support with Dependency, Binding, and layout fixes#29
Malcolmnixon merged 21 commits into
mainfrom
feature/general-view-relationship-edges

Conversation

@Malcolmnixon

Copy link
Copy Markdown
Member

This pull request introduces significant improvements and corrections to the documentation and configuration for SysML v2 diagram rendering, focusing on relationship edge handling, terminology, and notation accuracy. The main updates clarify and extend how various relationship types (including subsetting, dependency, allocation, binding, and connect) are represented and described in the codebase and documentation, aligning them with the latest SysML v2 specifications.

General View Relationship Edge Handling:

  • Updated the documentation to include and explain new edge kinds (subsetting, connect, allocate, dependency, binding) in GeneralViewLayoutStrategy, detailing how each is resolved and rendered, and clarifying the removal of the obsolete hollow-diamond membership for ref usages. [1] [2] [3] [4]
  • Added detailed explanations of how dropped edges are handled and surfaced as warnings, improving diagnostic visibility for unresolved or self-referential edges. [1] [2]

SysML v2 Notation and Relationship Corrections:

  • Updated the roadmap to clarify correct rendering for ref usages (now dependency-style, not hollow-diamond membership), and corrected previous misconceptions about containment and compartment rendering for certain usages.
  • Added an explicit section describing the handling of implied-source (initial-pseudostate) transitions in state machine diagrams, including the required changes for correct graphical rendering.

AST and Semantic Model Alignment:

  • Documented new AST nodes and visitor methods for dependency and binding connectors, ensuring the semantic model supports the expanded set of relationships.

Configuration and Spelling:

  • Added "subsetted" and "Subsetted" to the spelling dictionary to support the new terminology used in documentation and code comments.

These changes collectively improve the accuracy, completeness, and maintainability of the SysML v2 rendering subsystem and its documentation, ensuring closer alignment with the standard and better diagnostics for edge-case scenarios.

Malcolm Nixon and others added 21 commits July 11, 2026 22:24
…arch

Per OMG SysML v2 spec section 8.2.3, item/occurrence/action/state/requirement
usages render as compartment rows (already handled generically), not as
diamond-edge-connected boxes. Removes 'containment' from the edge-kind list,
adds a ref-to-dependency-style-edge fix (shared aggregation removed in v2).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add SysmlEdgeKind.Dependency and .Binding
- Add SysmlDependencyNode AST node for standalone dependency statements
- Add AstBuilder.VisitDependency and VisitBindingConnectorAsUsage
- Add ReferenceResolver support: Dependency cross-product resolution (pass 1),
  Binding dotted feature-chain resolution (pass 2)
…GeneralViewLayoutStrategy

- Fix ref keyword bug: remove obsolete hollow-diamond marker, render ref as
  a Dependency-shaped edge (dashed, open chevron) instead
- Add ResolveOwningBox helper for Connect/Binding feature-chain endpoint
  resolution (shortest-typed-feature-prefix walk, avoids self-loop edges)
- Add Subsetting as a private view-layer EdgeKind (not a new SysmlEdgeKind),
  reusing ResolveRedefinitionOwner and SysmlFeatureNode.SupertypeNames
- Add ModelEdge.Label and wire it through BuildGraph for allocate/binding
  midpoint labels (allocate guillemets, equals sign)
- BuildModelEdges now takes the SysmlWorkspace to read workspace.Index.AllEdges
  for Connect/Allocate/Dependency/Binding edges
…rpus tests

Adds parse/resolve unit tests for Dependency (binary + comma-list cross product + unresolved-end) and Binding (dotted-chain + unresolved-end) in WorkspaceLoaderTests.cs. Adds OMG corpus regression tests validating the 7 expected Dependency edges from DependencyExample.sysml/12a-Dependency.sysml, and documents a pre-existing gap (BuildUsageNode has no name fallback for bare 'redefines' targets) that prevents Binding resolution in BindingConnectorsExample-1.sysml.
Documents the new SysmlEdgeKind.Dependency/Binding values, SysmlDependencyNode,
AstBuilder.VisitDependency/VisitBindingConnectorAsUsage, ReferenceResolver's
Dependency cross-product and Binding feature-chain resolution passes, and
GeneralViewLayoutStrategy's ref-fix, ResolveOwningBox endpoint-resolution
algorithm, and the private view-layer Subsetting classification.
…onnect/Allocate/Dependency/Binding/Subsetting

Adds reqstream requirements and matching verification entries for:
- AstBuilder.VisitDependency / VisitBindingConnectorAsUsage
- ReferenceResolver's Dependency cross-product resolution and Binding
  feature-chain resolution
- GeneralViewLayoutStrategy's Connect/Allocate/Dependency/Binding rendering,
  the private Subsetting classification, and the ref-fix (updates the
  existing ReferenceMembership requirement, which previously described the
  now-removed obsolete hollow-diamond notation).

All test-name references were checked against the actual xUnit fact names in
GeneralViewLayoutStrategyTests.cs, WorkspaceLoaderTests.cs, and
OmgModelsTests.cs.
… drone gallery

- Extend docs/gallery/models/01-drone-general.sysml with a connect edge
  (controller.power to battery.output, using inline nested port redeclarations
  so the dotted chain resolves through the instance features rather than the
  shared PowerPort type, avoiding a ResolveOwningBox self-loop), an allocate
  edge (FlightTimeRequirement to Battery), a standalone dependency edge
  (FlightController to Battery), and a RacingDrone part def demonstrating
  subsets (frontMotors subsets motors).
- Regenerate docs/gallery/svg/DroneGeneralView.svg and docs/gallery/png/*.png
  via the sysml2tools render CLI to visually confirm the new edge kinds
  render with distinct, correctly-headed styles.
- Update docs/gallery/README.md with one sentence per new relationship kind.
…, subsetted vocabulary)

- Replace unicode escape \u00ab/\u00bb with literal guillemet characters in
  the allocate label string literal (cspell was tokenizing the escape plus
  following word as a single false-positive 'aballocate' token).
- Shorten the VisitBindingConnectorAsUsage table row in ast-builder.md to
  fit the 120-character line-length limit.
- Add 'subsetted'/'Subsetted' to .cspell.yaml's project words list (paired
  with the already-whitelisted 'Subsetting'/'subsettings' terms) since this
  is genuine SysML/technical vocabulary introduced by this feature.
…gnostic

Root-cause fix: TryResolveFeatureChain now tracks a parallel instancePath
accumulator, and FindFeatureMember reports whether a segment was resolved via
the type-hierarchy fallback branch. When it was, the returned qualified name
preserves the instance-relative path (e.g. Drone::controller::power) instead
of collapsing to the type's own declared path (e.g. FlightController::power).
This fixes the ResolveOwningBox self-loop for the dominant real-world
connect/bind shape (two sibling features declared directly in their owning
part defs, no per-instance nested redeclaration).

Defense-in-depth: BuildModelEdges now also reports any Connect/Allocate/
Dependency/Binding edge dropped because an endpoint failed to resolve to a
box, or because both endpoints collapsed to the same box, via the new
LayoutWarnings.ForDroppedRelationshipEdges warning, threaded into
BuildLayout's existing warnings list.

Tests: updated the 3 typing-fallback qualified-name assertions in
WorkspaceLoaderTests.cs affected by the resolver change, updated
QueryVerbsTests.cs's Connections_ReportsResolvedEndpointsIncludingFeatureChain
test (query element/assertion now use the instance-relative path; the query
--element option requires a declared node, so the element is now the engine
part usage rather than the port itself), added a new dominant-shape test to
WorkspaceLoaderTests.cs, and added an end-to-end GeneralViewLayoutStrategyTests
test that runs the real WorkspaceLoader + BuildLayout (no synthetic edges) plus
a warning assertion on the existing self-loop test proving the new diagnostic
fires.
WorkspaceLoader_LoadAsync_BindingDottedChain_RecordsBindingEdge asserts a
Binding edge produced via the same type-hierarchy fallback branch as the
3 already-enumerated Connect tests (bind a.x = b.y inside part def Q, both
a and b typed by definitions declared elsewhere) — the fix plan's blast-radius
table did not enumerate this test. Full 3-TFM test suite is green with this
5th update; no other assertion in the 764-test suite needed changing.
…expose noise

docs/gallery/models/01-drone-general.sysml: remove the now-unneeded inline
nested port redeclarations under battery/controller — the ReferenceResolver
root-cause fix means the natural, bare part declarations now resolve the
'connect controller.power to battery.output;' statement correctly. Regenerated
DroneGeneralView/BatterySubsystemView SVG+PNG: byte-identical to the
already-committed images, confirming the fix reproduces the exact same
(correct) rendering the workaround previously forced.

GeneralViewLayoutStrategy.cs: refined the dropped-relationship-edge diagnostic
added in the previous commit so it only reports an unresolved-endpoint drop
when the view is not expose-scoped; a genuine self-loop (both endpoints
resolve, to the same box) is still always reported regardless of scoping.
Without this, every expose-narrowed view legitimately produces
Allocate/Dependency/Connect drops for relationships crossing the exposed
boundary by design (confirmed while regenerating BatterySubsystemView, an
expose-scoped gallery view, which surfaced 3 such warnings before this
refinement and 0 after) -- noise unrelated to the quality report's actual
concern (silent self-loop collapse).
…stic

- design/.../general-view-layout-strategy.md: correct the self-loop
  mischaracterization (the dominant real-world connect shape resolves to two
  distinct boxes, not a self-loop, once ReferenceResolver preserves the
  instance-relative path); document BuildModelEdges's new isScoped parameter,
  DroppedRelationshipEdge record, and the dropped-edge diagnostic threaded
  into BuildLayout's warnings, including the expose-scope exclusion rule.
- design/.../reference-resolver.md: document the instancePath accumulator and
  viaTypeFallback distinction in TryResolveFeatureChain/FindFeatureMember.
- verification/.../reference-resolver.md: add acceptance criterion and Test
  Scenario rows for dotted feature-chain resolution (previously undocumented
  entirely), covering direct-child, type-hierarchy-fallback, mixed, inherited,
  dominant-shape, and unresolved-endpoint cases.
- verification/.../general-view-layout-strategy.md: correct the self-loop
  wording, add the new dropped-edge-diagnostic acceptance criterion and Test
  Scenario rows for the self-loop warning and the new end-to-end test.
- reqstream/sysml2-tools-language.yaml: add the new dominant-shape test to the
  existing FeatureChainResolution requirement's test list; clarify its title
  to mention instance-relative-path preservation (bug fix to already-specified
  behavior, no new requirement ID).
- reqstream/.../general-view-layout-strategy.yaml: correct the Connect
  requirement's self-loop justification; add the new end-to-end test; add a
  new DroppedRelationshipEdgeWarning requirement for the diagnostic.

All docs verified against pwsh ./lint.ps1 (exit code 0) and pwsh ./fix.ps1.
Gzip re-compression produces different bytes for identical content
(non-deterministic header), unrelated to this branch's actual scope.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…a fallback hop

TryResolveFeatureChain reset the instance-relative accumulator to a member's
raw QualifiedName whenever a segment was found via FindFeatureMember's
direct-child branch. That is only correct while every prior segment was
also a direct child of a true instance node. Once an earlier segment
resolves via the type-hierarchy fallback branch, 'current' refers to the
type's own declared path rather than the instance, so a later 'direct
child' match is still only reachable relative to that type — and the old
code incorrectly collapsed the accumulated instance path back to the
type-declared path in that case.

Fixed by latching an 'in type context' flag on the first fallback hop and
keeping every subsequent segment in instance-relative-append mode once
that flag is set, regardless of whether later segments individually
resolve via direct-child or fallback.

Found by code-review agent during this branch's automated review pass;
added a regression test mirroring the existing
ConnectionThreeSegmentChain_MixesDirectChildAndTypingFallback test but
with the fallback/direct-child hop order reversed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
F2 (Medium): assert the Warning diagnostic in
WorkspaceLoader_LoadAsync_BindingUnresolvedEnd_ProducesWarningNoEdge, matching
its own doc summary and the parallel Dependency test.

F1 (Low): sysml-edge.md said 'twelve members' and omitted MetadataType from
the bulleted list; corrected to thirteen and added the missing bullet.

F3 (Low): SysmlConnectionNode.ConnectionKeyword XML doc now lists 'binding'
alongside connection/message/allocation.

F4 (Low): SysmlDependencyNode.FromNames XML doc corrected — the implicit-from
shape (dependency z to x;) still populates FromNames; it is only empty when
no qualified name precedes 'to' at all.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…pseudostate) gap

Documents a separate, harder limitation than the Binding/item implicit-name
gap fixed in the next commit: SysML v2 allows a transition with no explicit
source (then TargetState;), an initial-pseudostate semantic that today
produces no Transition edge at all. Closing it requires distinguishing
"no source" from "unresolved source" plus new marker rendering, so it is
tracked as its own roadmap item rather than folded into this branch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…lared name

SysML v2 allows a redefining usage to omit its own declared name, taking the
redefined feature's name instead (e.g. `port redefines fuelTankPort { item
redefines fuelSupply; }` is named `fuelTankPort`). AstBuilder.BuildUsageNode
previously only used the explicit declared name, so such usages were built
as anonymous nodes never registered in the symbol table -- any subsequent
reference to them (including `bind` connector ends) failed to resolve.

Adds SimpleNameFromReference to derive the trailing ::-segment of a
redefined-feature reference, and uses it as an effectiveName fallback
throughout BuildUsageNode (namespace stack, QualifiedName, Name) whenever no
explicit name is declared.

Rewrites the OMG binding corpus regression test to assert the two Binding
edges now resolve correctly (previously asserted only "parses without
crashing" against 0 resolved edges), adds a focused
WorkspaceLoaderTests regression test mirroring the fixture shape in
isolation, and updates the ast-builder design/verification docs and
reqstream requirement to document the new fallback behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… naming

Code review of the prior commit found that SimpleNameFromReference only
stripped a trailing "::" segment, but ownedRedefinition is grammatically
qualifiedName ( DOT qualifiedName )*, so a redefinition reference can be a
dotted feature-chain path (e.g. tank.fuelTankPort), not just a ::-qualified
name. The old logic would have assigned a bogus dotted name (e.g.
"tank.fuelTankPort") instead of the correct trailing simple name
("fuelTankPort") for such usages.

Fixes SimpleNameFromReference to take whichever of the last "::" or last "."
separator occurs furthest to the right. Adds a regression test
(WorkspaceLoader_LoadAsync_ImplicitNameFromDottedRedefinitionChain_UsesTrailingSegment)
and updates the ast-builder design/verification docs and reqstream
requirement accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rename

The Binding OMG corpus test was renamed from
Binding_OmgCorpusFixture_ParsesAndResolvesWithoutCrashing to
Binding_OmgCorpusFixture_ResolvesBindingEdgesViaImplicitRedefinitionNames in
commit b5eea86, but two other reqstream requirements
(AstBuilder-BindingConnector, ReferenceResolver-BindingFeatureChain) and the
reference-resolver verification doc still referenced the old test name,
leaving them without a satisfying test per the reqstream tool.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Malcolmnixon
Malcolmnixon merged commit 6cb5e15 into main Jul 12, 2026
15 checks passed
@Malcolmnixon
Malcolmnixon deleted the feature/general-view-relationship-edges branch July 12, 2026 15:36
Malcolmnixon pushed a commit that referenced this pull request Jul 12, 2026
The drone gallery model (docs/gallery/models/01-drone-general.sysml)
already has real connect/allocate/dependency/subsets usages from the
merged PR #29 work; the roadmap entry was never tagged done.
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