Skip to content

Refactor GeneralViewLayoutStrategy to use LayoutGraph and LayoutEngine - #15

Merged
Malcolmnixon merged 7 commits into
mainfrom
phaseb-rendering-graph-migration
Jul 6, 2026
Merged

Refactor GeneralViewLayoutStrategy to use LayoutGraph and LayoutEngine#15
Malcolmnixon merged 7 commits into
mainfrom
phaseb-rendering-graph-migration

Conversation

@Malcolmnixon

Copy link
Copy Markdown
Member

This pull request updates documentation to reflect recent architectural changes and improvements in the SysML2Tools project, particularly in how the standard library is pre-compiled and how general view layout is structured and described. The most important changes clarify the build process, update design documentation to match implementation, and provide a more accurate and detailed explanation of the general view layout strategy.

Build & Tooling Documentation:

  • Updated build.ps1 to always regenerate the stdlib.json.gz resource before building, ensuring the pre-compiled standard library never goes stale. This is now a sequential step outside the MSBuild graph for reliability and simplicity.
  • Updated references throughout the documentation to reflect that the standard library is now serialized as stdlib.json.gz (not stdlib.bin), and that StdlibGen is a standalone tool invoked by build.ps1 rather than part of the MSBuild graph. [1] [2]

General View Layout Strategy Documentation:

  • Rewrote the description of the general view layout process to clarify that all package folders and definitions are now handled as a single LayoutGraph and placed with one call to HierarchicalLayoutAlgorithm.Apply, with explicit separation of responsibilities for box sizing and placement.
  • Refactored and clarified the internal data model and key methods in the layout strategy documentation, including the introduction of ModelEdge, Location, and TruncatedFolder records, and a new explanation of how edges and nodes are resolved, placed, and decorated. The documentation now matches the latest code structure and algorithms. [1] [2]

Roadmap Updates:

  • Updated the roadmap to reflect that model query and analysis capabilities now extend beyond the query command, with a focus on dynamic (ad-hoc) views and further AI-analysis options, and trimmed implementation details from the roadmap to keep it forward-looking. [1] [2]

Malcolm Nixon and others added 7 commits July 4, 2026 20:30
…raph

Phase B of the Rendering migration: GeneralViewLayoutStrategy no longer
hand-rolls its own placement pipeline (PlaceGroups/LayoutGroup/BuildEdges/
RouteEdges/ComputeCanvasWidth). Instead it expresses the whole General View
as one DemaConsulting.Rendering LayoutGraph - package folders as Folder-shaped
container nodes, definitions as leaf nodes carrying Shape/Keyword/Compartments
- and places it with a single HierarchicalLayoutAlgorithm.Apply call:

- Root scope packs package folders and top-level definitions by reading order
  (ContainmentLayoutAlgorithm), selected via LayoutOptions.ForAlgorithm so a
  future LayoutEngine.Layout(graph) caller is never misled into skipping the
  hierarchical engine.
- Each folder own contents are ordered by their intra-package edges with the
  bundled layered algorithm (LayeredLayoutAlgorithm), selected per-node via
  CoreOptions.Algorithm on the folder container itself.
- Folder TitleHeight is set from BoxMetrics.TitleAreaHeight so the engine
  reserves the exact title band the renderer draws (uses the new
  LayoutGraphNode.TitleHeight override).
- Depth-truncated folders are never expanded into individual boxes at all:
  the folder becomes a single leaf node sized like the previous ellipsis
  indicator (its Children graph is never touched, so the engine keeps the
  caller-computed size instead of auto-sizing it as a container), and its
  "+N more..." label is stamped onto the placed box once layout is known.
- Model edges are resolved by qualified name once, then scoped per the
  graph's lowest-common-ancestor convention: same-package edges go into that
  folder's own Children scope, everything else goes to the root graph
  referencing descendant nodes directly. An edge touching a depth-truncated
  definition has no node to reference and is dropped, exactly as before.

This removes SysML2Tools's hand-rolled box-placement/edge-routing logic in
favor of Rendering's own engine, including its anchor-coordination fix for
connectors converging on a shared box face. Regenerated
DictionaryMarkSystemView confirms the original 6-way connector collision no
longer reproduces.

Test updates: intra-package edges are now routed within their folder's own
coordinate space by the hierarchical engine, so they appear nested inside
that folder box's Children rather than at the top level of the LayoutTree.
Added a recursive CollectLines test helper (mirroring the existing
CollectBoxes helper) and switched every edge-presence assertion to use it.
All existing GeneralViewLayoutStrategy behavioral tests continue to pass
unchanged in intent.

Note: DemaConsulting.SysML2Tools.Core and .Tool still reference the local
Rendering checkout via ProjectReference (TitleHeight/Shape/Keyword/
Compartments are not yet in a published Rendering package). Revert to
PackageReference once Rendering ships a release containing them.

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

Reverts the temporary ProjectReferences to the local Rendering repo
(used for testing against unreleased fixes) back to PackageReference,
now that DemaConsulting.Rendering.Layout/.Svg/.Skia 0.1.0-beta.4 is
published on nuget.org. Also bumps the test project's existing package
references from the stale 0.1.0-beta.2 pin to 0.1.0-beta.4.

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

LayeredPlacement now delegates to the DemaConsulting.Rendering.Layout
package's public LayoutEngine.Layout(LayoutGraph) facade rather than
instantiating LayeredLayoutAlgorithm directly. Since LayeredPlacement's
graphs are always flat (no container nodes), the facade's default
hierarchical algorithm is guaranteed byte-for-byte identical to the
layered algorithm applied directly. The requested flow direction now
sets CoreOptions.Direction on the graph itself (via IPropertyHolder.Set)
rather than on a LayoutOptions instance, since the facade always seeds
its internal cascade with empty options and only honors settings
declared directly on the graph.

Also corrects the LayeredPlacement design doc and reqstream
justification text, which still listed GeneralViewLayoutStrategy as a
caller — that strategy now builds and places its own nested LayoutGraph
directly via HierarchicalLayoutAlgorithm and no longer goes through
this helper.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Regenerated all 8 gallery models (SVG + PNG) to confirm the
LayeredPlacement change (LayoutEngine.Layout facade instead of direct
LayeredLayoutAlgorithm.Apply) produces byte-identical layouts for the
ActionFlow, Interconnection, and StateTransition gallery examples.

DroneGeneralView.svg/.png also updated: unrelated to this change, its
committed gallery images were stale from before the earlier Phase B
GeneralViewLayoutStrategy rewrite (the container is now taller/wider
per the current HierarchicalLayoutAlgorithm sizing) and had never been
regenerated since.

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

- Stdlib.csproj's GenerateStdlibBin target previously used <Exec> to spawn a
  separate, uncoordinated 'dotnet build StdlibGen.csproj' process. Since
  StdlibGen.csproj ProjectReferences Language.csproj, that second process could
  race the outer solution build's own build of Language.csproj for the same
  net10.0 output, intermittently failing CI with CS2012 (DLL in use by another
  process).
- Replaced the nested Exec 'dotnet build' with an in-process MSBuild task call
  (Targets="Restore;Build"), so StdlibGen is built within the same MSBuild
  engine/BuildManager session as the outer build. Deliberately not exposed as
  a ProjectReference item, since that made StdlibGen discoverable by other
  multi-targeted projects' own TFM-negotiation evaluations, which build
  referenced projects with a default Debug configuration independent of this
  target's guard.
- Added a BuildingProject guard to the target, since BeforeTargets=PrepareForBuild
  also fires during lightweight non-build MSBuild evaluations (e.g. other
  projects' GetTargetFrameworks-style calls).
- Fixed a related latent bug in StdlibGen's Program.cs: File.WriteAllBytesAsync
  writes in place (FileMode.Create, FileShare.Read), which does not tolerate a
  second concurrent writer to the same output path - exactly the scenario the
  solution's multi-project build graph can trigger. StdlibGen now writes to a
  uniquely-named temp file and atomically renames it onto the destination.
- Verified via repeated clean rebuilds (plain and --graphBuild) and the full
  build.ps1 suite (0 warnings, 0 errors, all 441 tests x 3 TFMs passing).
- Trimmed ROADMAP.md: removed the fully-implemented per-verb CLI architecture
  and query command sections (already documented in the User Guide and design
  docs), and removed all other completed-work summaries/callouts per the
  policy that ROADMAP.md contains only future/planned work.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Eliminates the recurring CS2012 file-in-use races and NETSDK1005 restore-corruption
errors caused by Stdlib.csproj invoking StdlibGen via nested MSBuild/Exec tasks
during the multi-targeted (net8.0/net9.0/net10.0) solution build.

- StdlibGen now writes a gzip-compressed UTF-8 JSON artifact (stdlib.json.gz,
  ~463 KB) instead of an uncompressed stdlib.bin, and only overwrites its output
  when content actually changed (temp-file + binary compare), so it is safe and
  cheap to run on every build.
- Diagnostic file paths embedded in the artifact are now normalized relative to
  --stdlib-dir, making the output byte-for-byte reproducible regardless of
  machine, checkout path, or absolute/relative invocation style.
- stdlib.json.gz is committed to source control and embedded via a plain
  EmbeddedResource item in Stdlib.csproj - no MSBuild target, no ProjectReference
  to StdlibGen, no build-time generation step at all.
- Fixed a related MSBuild culture-detection bug: naming the file stdlib.bin.gz
  caused AssignCulture to treat 'bin' as an ISO 639 culture code and silently
  route the resource into a satellite culture assembly. Renamed to stdlib.json.gz
  (accurately reflecting its content) and set WithCulture=false defensively.
- build.ps1 now regenerates stdlib.json.gz as a plain sequential pre-build step
  (dotnet run StdlibGen) so it can never be forgotten after editing stdlib
  sources, instead of relying on a separate manually-run script.
- StdlibProvider.LoadFromResource decompresses via GZipStream before
  deserializing.
- Updated design docs (introduction.md, sysml2-tools-stdlib.md and subdocs,
  ast-serializer.md, ast-deserializer.md, reqstream yaml) to describe the new
  architecture and remove references to the old GenerateStdlibBin/EmbedStdlibBin
  MSBuild targets.

Verified: full clean build.ps1 run passes (441 tests x3 TFMs), stdlib.json.gz
regeneration is confirmed byte-identical across absolute/relative invocation
styles (SHA256 match), and the skip-if-unchanged no-op path is confirmed working.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Malcolmnixon
Malcolmnixon merged commit 6ca0a07 into main Jul 6, 2026
15 checks passed
@Malcolmnixon
Malcolmnixon deleted the phaseb-rendering-graph-migration branch July 6, 2026 02:50
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