Controller ownership and lifetime
Create one DiagramController per editor. DiagramController(document:, configuration: DiagramConfiguration(extensions:)) creates and owns a Diagram; other actors, such as an agent or a second canvas, join it with DiagramController(diagram: controller.diagram, participant: DiagramParticipant.agent(id: ..., name: ...)). Mount a DiagramCanvas with a controller; it edits when an editable extension such as EditorExtension is installed; only one canvas may own a controller at a time. Unmounting the canvas preserves the document.
Dispose each controller when its host is disposed. Disposing a controller that joined a diagram releases only its selection, previews and listeners. Disposing the controller that created the diagram disposes the diagram and every controller on it, so dispose the joined controllers and unmount their canvases first.
Content verbs work without a mounted canvas. Camera, coordinate conversion and animation operations require a mounted presentation. Capture controller.diagram.snapshot before disposal when retaining the committed document and resolved geometry.
Core owns headless editing; Flutter supplies the public canvas and platform input. Optional UI supplies DiagramInspector and ready-made controls. Portable and Flutter extensions are installed in the configuration's one extensions list. See controller, extensions and options and writing extensions.
Extensions own their elements end to end
An extension that introduces an element owns all of it in its own package: the model and its persistence codec, layout and paint contributions, verbs and properties, on-canvas affordances, icons and any Flutter UI. Rich text owns its paragraph and run attributes and RichTextCodec; connectors own the orthogonal, quadratic and bezier route identities (ConnectorRoutes); snap guides own alignment snapping.
A package is split only by platform: x holds the pure Dart extension and x_flutter its widgets, as with vyuh_diagram_extension_table and vyuh_diagram_extension_table_flutter. Behaviour that the core extension points can express stays pure Dart, so most extensions need no Flutter package.
Core, Flutter, the codecs and the editor only define extension points, such as TextParagraphAttributes, DiagramTextCodec, DiagramConnectorRouteProvider, DiagramMoveAdjuster, ShapeDefinition.affordances and DiagramIcon. They never depend on an extension, not even for tests. Test an extension in its own package with package:vyuh_diagram_core/testing.dart, whose testRegistry(...) assembles a grammar from test contributions. See extensions.