Add direct diagram connections, movable ports, and contextual authoring

This commit is contained in:
2026-09-06 02:13:49 +03:00
parent 35133de650
commit fef2e0dbce
39 changed files with 7076 additions and 499 deletions
+38 -5
View File
@@ -1296,7 +1296,7 @@ capabilities with their involvement, exploitation, include, extend and
generalization links. Decomposition and Overview retain general containment;
Overview also exposes all relationships. Changing the projection hides
inapplicable placements without deleting them or changing semantic records.</p>
<p>Ports are calculated boundary anchors of visible owners, with their existing
<p>Ports are boundary anchors of visible owners, with their existing
semantic identity. An explicitly placed port is not rendered as a separate
large node. Functional exchanges use their declared source/target ports;
boundary exchanges attach to their participant ports even if those ports have
@@ -1305,13 +1305,45 @@ may terminate at a visible ancestor without creating a new port or exchange.</p>
<p><span class="docutils literal">node</span> has an alias and identity but no display-name string. Required fields
are <span class="docutils literal">diagram</span> and <span class="docutils literal">element</span> references. Optional fields are <span class="docutils literal">position</span>
(record with x/y, default 0/0), <span class="docutils literal">size</span> (width/height, default 224/94), and
<span class="docutils literal">collapsed</span> (false). Node identity is independent of its semantic element.
<span class="docutils literal">collapsed</span> (false), and <span class="docutils literal">port_anchors</span> (empty list). Node identity is
independent of its semantic element.
Coordinates are absolute diagram coordinates. Placement does not alter parent,
allocation, or realization. Hiding an element from a diagram must remain
distinguishable from deleting it from the model.
Changing a node's diagram preserves the placement identity, alias, coordinates,
size, collapse state, and attached artifacts. The destination must accept the
element's layer and must not already contain another placement of that element.</p>
size, collapse state, manual port anchors, and attached artifacts. The destination
must accept the element's layer and must not already contain another placement
of that element.</p>
<p>Each <span class="docutils literal">port_anchors</span> entry is a PortAnchor record with required <span class="docutils literal">port</span>
reference, <span class="docutils literal">side</span> (Left, Right, Top, or Bottom), and <span class="docutils literal">offset</span> (finite
binary32 from 0 through 1). It has no separate identity or alias. The port MUST
be an existing Port directly owned by the placement's <span class="docutils literal">element</span>. A port MAY
have one manual anchor per placement; different diagrams MAY position it
independently. List order is preserved but has no positional meaning.</p>
<p><span class="docutils literal">offset</span> measures a fraction of the complete projected owner edge, from top
on Left/Right or from left on Top/Bottom. Zero and one denote its corners.
The side is presentation data and MUST NOT change the port's contract,
orientation, ownership, allocations, or connected exchanges. Absent anchors use
automatic positioning. Empty lists are omitted in canonical JSON/source;
earlier schema-3 input without this field hydrates as <span class="docutils literal">[]</span>.</p>
<pre class="code text literal-block"><code>node actor_view {
diagram &#64;architecture; element &#64;vessel;
port_anchors [{ port &#64;communication; side Top; offset 0.25; }];
}</code></pre>
<p><span class="docutils literal">SetPortAnchor { diagram, node, anchor }</span> upserts by port identity and retains
unrelated entries. <span class="docutils literal">RemovePortAnchor { diagram, node, port }</span> restores
automatic positioning; it is a no-op only for an existing direct child port
of that placement. Unknown fields, duplicate port references, non-port or
foreign-owner references, and invalid offsets are structural errors. Each
anchor counts as one record against <span class="docutils literal">ParseLimits.max_records</span>.</p>
<p>These commands use the same atomic history, conditional REST transactions, and
source writeback as other presentation edits. Source references resolve across
files, and anchor comments follow port identity. Reidentifying a port updates
anchor references; deleting it removes its anchors. Reparenting MUST repair
old-owner anchors in the same transaction, for example by removing them before
the Reparent command. Moving, resizing, arranging, or folding an owner retains
its authored sides and fractions. Frozen schema-1/schema-2 readers do not accept
<span class="docutils literal">port_anchors</span>; their explicit migration supplies an empty list.</p>
<p>Each <span class="docutils literal">routes</span> entry is an EdgeRoute record with a required <span class="docutils literal">edge</span> reference
to an existing Relation or Trace, <span class="docutils literal">waypoints</span> (default <span class="docutils literal">[]</span>), and <span class="docutils literal">label</span>
(default <span class="docutils literal">none</span>). Route records have no separate UUID or alias. An edge occurs
@@ -1615,7 +1647,8 @@ preserve authored comments and whitespace on Apply while inserting missing
identities. Explicit canonical export remains a separate operation. Project
update/export distinctions are described below.
Camera position, selection, source cursor, and undo history are not stored
model fields. Layout and collapse state inside NodePlacement are model data.</p>
model fields. Layout, collapse state, and manual port anchors inside
NodePlacement are model data.</p>
<p>The pure <span class="docutils literal">format_bundle</span> exporter uses the same typed declaration writer as
<span class="docutils literal">format</span>. It creates a small entry file, layer/category modules, separate
activity/function roots and behavior contexts, and separate diagrams with their