Make participant ports and hierarchical model navigation discoverable
Add focused containment browsing, contextual paged search, clear outline depth and direct component-port creation and connection actions. Share exact boundary feasibility checks to avoid whole-project validation for each picker candidate. Preserve source/property drafts and interrupted-save recovery state, document source-project behavior, and record Windows/Linux native verification and independent review fixes.
This commit is contained in:
+328
-40
@@ -623,7 +623,7 @@ a { text-decoration: none; }
|
||||
<h1 class="title">Arcadia Studio OA / SA Language and Editing Contract</h1>
|
||||
<dl class="docinfo simple">
|
||||
<dt class="version">Version<span class="colon">:</span></dt>
|
||||
<dd class="version">2</dd>
|
||||
<dd class="version">3</dd>
|
||||
<dt class="status">Status<span class="colon">:</span></dt>
|
||||
<dd class="status">Normative current implementation contract; first-release integration</dd>
|
||||
<dt class="core-implementation">Core implementation<span class="colon">:</span></dt>
|
||||
@@ -637,16 +637,14 @@ a { text-decoration: none; }
|
||||
<h2>1. Scope and conformance</h2>
|
||||
<p>This specification defines the shared Operational Analysis (OA) and System
|
||||
Analysis (SA) model, its textual language, graphical editing obligations,
|
||||
validation, persistence, and explicit migration from version 1. MUST, MUST NOT,
|
||||
validation, persistence, and explicit migration from versions 1 and 2. MUST, MUST NOT,
|
||||
and MAY indicate requirements, prohibitions, and permitted choices.</p>
|
||||
<p>The first-release capability/mission, contextual process/chain, typed scenario
|
||||
and state/event additions
|
||||
are temporarily integrated under schema 2. This does not declare the first
|
||||
release complete or waive its remaining scenario, state, data, transition and
|
||||
usability requirements. A distinct release schema and explicit V2 migration
|
||||
will be specified after those interfaces are frozen. This document describes
|
||||
the current implemented records, rather than inventing compatibility rules for
|
||||
that future schema.</p>
|
||||
<p>Schema 3 introduces typed function and component ports, required functional
|
||||
exchange endpoints, independently oriented boundary exchanges, and explicit
|
||||
PortAllocation relations. First-release scenario/state additions remain in
|
||||
scope; this schema change does not declare native acceptance or the wider
|
||||
release complete. The preserved schema-2 reader validates the original
|
||||
contract before migration.</p>
|
||||
<p>OA describes stakeholders, operational work and needs. SA describes the
|
||||
selected system boundary, external actors, functions, services and expected
|
||||
behavior. SA permits at most one System of Interest; its absence is an
|
||||
@@ -664,7 +662,7 @@ Actual verification evidence is separate from this contract.</p>
|
||||
</section>
|
||||
<section id="one-authoritative-model">
|
||||
<h2>2. One authoritative model</h2>
|
||||
<p>A Project stores <span class="docutils literal">schema_version</span> (2), <span class="docutils literal">id</span>, <span class="docutils literal">alias</span>, <span class="docutils literal">name</span>,
|
||||
<p>A Project stores <span class="docutils literal">schema_version</span> (3), <span class="docutils literal">id</span>, <span class="docutils literal">alias</span>, <span class="docutils literal">name</span>,
|
||||
<span class="docutils literal">description</span>, and maps named <span class="docutils literal">elements</span>, <span class="docutils literal">relations</span>, <span class="docutils literal">diagrams</span>,
|
||||
<span class="docutils literal">artifact_links</span>, and <span class="docutils literal">traces</span>. Each map is keyed by the UUID contained in
|
||||
its record. Duplicate map keys and mismatching keys/identities are errors.</p>
|
||||
@@ -738,8 +736,8 @@ lists all additional fields. <span class="docutils literal">ref</span> means <sp
|
||||
<td><p><span class="docutils literal">[]</span></p></td>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">oa_port</span>, <span class="docutils literal">sa_port</span></p></td>
|
||||
<td><p><span class="docutils literal">direction</span>: In, Out, InOut; <span class="docutils literal">interface</span>: ref?</p></td>
|
||||
<td><p>InOut; none</p></td>
|
||||
<td><p><span class="docutils literal">contract</span>: required PortContract; <span class="docutils literal">legacy</span>: optional LegacyPortContract</p></td>
|
||||
<td><p>No implicit contract; <span class="docutils literal">legacy</span> defaults none. OA admits Legacy only.</p></td>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">oa_scenario</span>, <span class="docutils literal">sa_scenario</span></p></td>
|
||||
<td><p><span class="docutils literal">viewpoint</span>: ScenarioViewpoint; <span class="docutils literal">context</span>: ref?; <span class="docutils literal">precondition</span>, <span class="docutils literal">postcondition</span>: strings; <span class="docutils literal">steps</span>: occurrence refs</p></td>
|
||||
@@ -853,7 +851,7 @@ contain activities; functions contain functions. Capability grouping uses
|
||||
same-layer capability parents; it does not mean inheritance or inclusion.
|
||||
Operational and system missions are root semantic records; they do not own
|
||||
capabilities by containment. MissionCapability expresses that association.
|
||||
DataFields belong to ExchangeItems or Record DataTypes. Ports belong to
|
||||
DataFields belong to ExchangeItems or Record DataTypes. Preserved generic ports belong to
|
||||
participants or work. Lifelines belong to scenarios. State-machine ownership
|
||||
uses participant → machine → region → state/mode; a state or mode can contain
|
||||
a nested region. All other state vertices belong to Regions as well. Events
|
||||
@@ -889,11 +887,15 @@ references. Their kind is the declaration keyword:</p>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">functional_exchange</span></p></td>
|
||||
<td><p>SA function → SA function</p></td>
|
||||
<td><p><span class="docutils literal">source_port</span>, <span class="docutils literal">target_port</span> / none; <span class="docutils literal">items</span> / []</p></td>
|
||||
<td><p>Required <span class="docutils literal">source_port</span>, <span class="docutils literal">target_port</span> refs; <span class="docutils literal">items</span> / []</p></td>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">boundary_exchange</span></p></td>
|
||||
<td><p>Participant-owned output-compatible port → input-compatible port</p></td>
|
||||
<td><p><span class="docutils literal">items</span> refs / []</p></td>
|
||||
<td><p>Different participant owners; typed component ports have matching kinds</p></td>
|
||||
<td><p><span class="docutils literal">oriented</span> bool / true; <span class="docutils literal">items</span> refs / []</p></td>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">port_allocation</span></p></td>
|
||||
<td><p>SA Component port → SA FunctionInput/FunctionOutput port</p></td>
|
||||
<td><p>Requires the function's actual work Allocation to that component</p></td>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">capability_involvement</span></p></td>
|
||||
<td><p>Participant, activity/function, or OA role → capability</p></td>
|
||||
@@ -967,12 +969,68 @@ advisory warning; it does not prevent saving the model. Shared roles do not
|
||||
imply a unique performer.
|
||||
Allocation of a non-leaf work element is invalid. A computed graphical summary
|
||||
of its allocated leaves MUST NOT create an extra semantic allocation.</p>
|
||||
<p>Functional ports, when selected, belong to the corresponding endpoint function
|
||||
and have compatible direction. Boundary ports belong to participants and have
|
||||
compatible direction. An interface groups ExchangeItems; an exchange using
|
||||
that port interface must carry items supported by it. Studio's OA boundary
|
||||
exchange is a simplified representation of operational communication; it is
|
||||
not a claim of complete Capella CommunicationMean equivalence.</p>
|
||||
<p>Typed function ports belong directly to SA Functions. <span class="docutils literal">FunctionOutput</span>
|
||||
declares <span class="docutils literal">outgoing_items</span>; <span class="docutils literal">FunctionInput</span> declares <span class="docutils literal">incoming_items</span>.
|
||||
The lists contain distinct same-layer ExchangeItem references. A functional
|
||||
exchange MUST reference output/input ports owned by its respective functions,
|
||||
and each carried item MUST fit both declarations. Empty declarations accept
|
||||
no items. Item compatibility is identity equality; future specialization is
|
||||
not inferred from names. Port declarations remain independent of incident
|
||||
exchanges after creation.</p>
|
||||
<p>A <span class="docutils literal">Component</span> contract belongs to an SA System or SystemActor and stores
|
||||
<span class="docutils literal">kind</span> (Standard or Flow) and <span class="docutils literal">orientation</span> (Unset, In, Out, InOut).
|
||||
Standard requires Unset. Flow Unset is an incomplete draft, not InOut. Typed
|
||||
component connections require matching kinds: Standard/Flow mismatch is an
|
||||
error. Standard connections normally use <span class="docutils literal">oriented false</span>; directional Flow
|
||||
connections use true. Boundary orientation is separate from endpoint kind and
|
||||
orientation. Oriented Flow endpoints permit Out at source and In at target;
|
||||
unoriented Flow endpoints must permit at least one communication direction.</p>
|
||||
<p>Provided/required interfaces are separate identified relations. A Standard
|
||||
partner satisfies a requirement by providing the identical interface; stored
|
||||
source/target order does not infer service roles. Component carried items must
|
||||
fit the declared interface-item union when explicit declarations exist. An
|
||||
explicitly empty interface is not a wildcard. Missing declarations and
|
||||
unsatisfied required interfaces produce located completeness warnings.</p>
|
||||
<p><span class="docutils literal">PortAllocation</span> relates a Component port to a typed function port only when
|
||||
that function has an actual Allocation to the component owner. Standard may
|
||||
allocate either function direction; Flow directions must agree. A typed
|
||||
ExchangeAllocation requires both corresponding PortAllocations and compatible
|
||||
carried items. Unoriented boundary exchanges allow reversed correspondence.
|
||||
Visual allocation nesting is never evidence of a stored allocation relation.</p>
|
||||
<p><span class="docutils literal">Legacy</span> requires <span class="docutils literal">legacy { direction <span class="pre">...;</span> interface <span class="pre">...;</span> }</span>. It preserves
|
||||
generic direction/interface data and emits a located compatibility warning.
|
||||
It is an explicit compatibility constructor in JSON/source; ordinary creation
|
||||
pickers do not offer it. Resolution to a typed SA contract retains this record
|
||||
without treating it as another active constraint. OA generic ports remain
|
||||
Legacy; OA Interactions stay activity-to-activity without function ports.
|
||||
Deleting a referenced legacy interface clears that optional live reference.</p>
|
||||
<p>A source-3 functional exchange MUST specify both port aliases; the parser does
|
||||
not create endpoints. Graphical/command FE creation plans ports atomically,
|
||||
using unique compatible typed-port reuse or deterministic new endpoints.
|
||||
Port deletion cascades to incident FEs; FE deletion retains independent ports.</p>
|
||||
<p>For example:</p>
|
||||
<pre class="literal-block">arcadia 3;
|
||||
project ports_example "Typed function contract" {
|
||||
sa_function send "Send" {}
|
||||
sa_function receive "Receive" {}
|
||||
sa_exchange_item payload "Payload" {}
|
||||
sa_interface old_service "Preserved service" { items [@payload]; }
|
||||
sa_port output "Output" {
|
||||
parent @send;
|
||||
contract { FunctionOutput { outgoing_items [@payload]; }; };
|
||||
}
|
||||
sa_port input "Input" {
|
||||
parent @receive;
|
||||
contract { FunctionInput { incoming_items [@payload]; }; };
|
||||
}
|
||||
functional_exchange message "Message" {
|
||||
source @send; target @receive;
|
||||
source_port @output; target_port @input; items [@payload];
|
||||
}
|
||||
sa_port preserved "Unresolved original" {
|
||||
parent @send; contract Legacy;
|
||||
legacy { direction InOut; interface @old_service; };
|
||||
}</pre>
|
||||
<p>An exclusive region has at most one initial state. Missing initial state is
|
||||
a completeness warning. Initial states have no incoming transitions and at
|
||||
most one outgoing transition; their outgoing transition has no trigger/guard.
|
||||
@@ -1224,9 +1282,24 @@ Studio profile; no running history state is persisted or synthesized.</p>
|
||||
<section id="diagrams-artifacts-and-cross-layer-traceability">
|
||||
<h2>5. Diagrams, artifacts, and cross-layer traceability</h2>
|
||||
<p><span class="docutils literal">diagram</span> has name, identity, alias, description, <span class="docutils literal">layer</span> (Oa by default),
|
||||
and <span class="docutils literal">projection</span> (Overview by default). Other projections are Decomposition,
|
||||
Allocation, and Traceability. Traceability diagrams can show both layers;
|
||||
<span class="docutils literal">projection</span> (Overview by default), and <span class="docutils literal">routes</span> (empty list by default).
|
||||
Other projections are Decomposition,
|
||||
Allocation, FunctionalDataflow, Capabilities, and Traceability. Traceability diagrams can show both layers;
|
||||
other diagrams show their chosen layer.</p>
|
||||
<p>Allocation is an architecture view: it shows participants and work, nests
|
||||
allocated work under its performer, and displays interactions, functional
|
||||
exchanges and boundary exchanges. FunctionalDataflow shows the work hierarchy
|
||||
and its exchanges. Capabilities shows participants, roles, missions and
|
||||
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
|
||||
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
|
||||
no separate placement. Collapsing an owner hides its interior; projected links
|
||||
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
|
||||
@@ -1237,6 +1310,50 @@ 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>
|
||||
<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
|
||||
at most once in a diagram's route list; different diagrams MAY store independent
|
||||
routes for the same edge. List order and explicit empty entries are retained by
|
||||
source and JSON round trips, although list order has no routing meaning. Edges
|
||||
need not currently be visible in their diagram.</p>
|
||||
<pre class="code text literal-block"><code>routes [
|
||||
{ edge @report_exchange;
|
||||
waypoints [{ x 420; y 260; }, { x 690; y 260; }];
|
||||
label { fraction 0.55; offset { x 0; y -16; }; };
|
||||
}
|
||||
];</code></pre>
|
||||
<p>Waypoints are pinned absolute diagram positions in source-to-target traversal
|
||||
order; at most 128 are allowed per edge. Computed endpoints and automatic elbows
|
||||
MUST NOT be persisted as authored waypoints. A label record requires both
|
||||
<span class="docutils literal">fraction</span> (finite binary32 from 0 through 1, measured along the computed
|
||||
polyline's arc length) and <span class="docutils literal">offset</span> (a relative x/y diagram displacement).
|
||||
All position/displacement components obey the coordinate bounds in section 2.
|
||||
An absent label uses automatic placement. Unknown fields, missing required
|
||||
nested fields, duplicate route edges, non-edge references and invalid numbers
|
||||
are structural errors. A pinned point that obstructs routing remains stored;
|
||||
geometric routing difficulty is reported separately from structural validity.
|
||||
Each EdgeRoute counts as one record against <span class="docutils literal">ParseLimits.max_records</span>; pinned
|
||||
points are bounded by the per-route limit and aggregate input byte limits.</p>
|
||||
<p><span class="docutils literal">SetEdgeRoute { diagram, route }</span> upserts an entry by edge identity, retaining
|
||||
the order and contents of unrelated entries. <span class="docutils literal">RemoveEdgeRoute { diagram, edge }</span>
|
||||
removes it; removing an absent entry is a no-op for an existing diagram and edge.
|
||||
The latter is the Reset routing operation. Either command participates in the
|
||||
same atomic transactions, validation and undo as other model edits. Deleting a
|
||||
relation or trace removes its routes in every diagram; reidentifying it updates
|
||||
route references without changing geometry. Folding, hiding, changing projection
|
||||
or relocating placements MUST NOT erase routing metadata. Group movement
|
||||
translates pins when both actual endpoint owners move by the same delta; label
|
||||
offsets remain relative. Raw <span class="docutils literal">EditNode</span> and source position edits are exact
|
||||
record edits and do not implicitly translate pins.</p>
|
||||
<p>This is an additive schema-3 field. Earlier schema-3 JSON/source that omits
|
||||
<span class="docutils literal">routes</span> loads as an empty list. Frozen schema-1 and schema-2 readers do not
|
||||
accept this new field; migration creates empty route lists. Source projects keep
|
||||
routes in their owning diagram declaration/file, resolve <span class="docutils literal">edge @alias</span> across
|
||||
files, and retain route-entry comments by referenced edge identity when entries
|
||||
are reordered. The existing REST transaction endpoint accepts the same externally
|
||||
tagged command records with UUID references and conditional ETags; no separate
|
||||
routing endpoint or UI-only routing model exists.</p>
|
||||
<p><span class="docutils literal">artifact</span> has name, identity, alias, description, required <span class="docutils literal">owner</span> ref,
|
||||
<span class="docutils literal">relation</span> (References, Satisfies, Verifies, Implements, DerivedFrom;
|
||||
default References), <span class="docutils literal">uri</span> (default empty), <span class="docutils literal">revision</span> (optional string),
|
||||
@@ -1335,7 +1452,7 @@ spellings can be used in alias positions because references begin with <span cla
|
||||
<p>The grammar below uses <span class="docutils literal">*</span> for repetition and <span class="docutils literal">?</span> for optional syntax.
|
||||
<span class="docutils literal">kind</span> is exactly an element/relation keyword listed above. Typed field
|
||||
sets and enum constructors are closed by sections 3–5.</p>
|
||||
<pre class="code text literal-block"><code>document = "arcadia" "2" ";" project
|
||||
<pre class="code text literal-block"><code>document = "arcadia" "3" ";" project
|
||||
project = "project" alias string identity? "{" project-entry* "}"
|
||||
project-entry = "description" string ";" | declaration
|
||||
declaration = (kind | "diagram" | "artifact" | "trace")
|
||||
@@ -1369,6 +1486,77 @@ Ordinary string fields require quoted strings and cannot contain an unquoted
|
||||
<span class="docutils literal">@alias</span> reference. Enum fields require unquoted named values or their typed
|
||||
constructor records. Typed values MUST NOT nest more than 64 levels; malformed
|
||||
deeply nested drafts produce a diagnostic instead of exhausting the parser stack.</p>
|
||||
<section id="modular-source3-projects">
|
||||
<h3>6.1. Modular source3 projects</h3>
|
||||
<p>The pure <span class="docutils literal">source_project</span> core API compiles a virtual source bundle, containing
|
||||
<span class="docutils literal">entry</span> and a <span class="docutils literal">files</span> map from logical paths to UTF-8 strings. Its entry is a
|
||||
root-level <span class="docutils literal">.arcadia</span> file with the source3 project header above. A project entry
|
||||
MAY also be <span class="docutils literal">include string ";"</span>. An included fragment consists only of ordinary
|
||||
declarations and include statements; it MUST NOT contain another version header,
|
||||
project wrapper, or project description. Includes MUST occur between declarations,
|
||||
never inside a typed field value. For example:</p>
|
||||
<pre class="literal-block">arcadia 3;
|
||||
project rescue "Rescue" id "00000000-0000-4000-8000-000000000001" {
|
||||
description "Operational model";
|
||||
include "oa/participants.arcadia";
|
||||
include "oa/activities/activity_respond.arcadia";
|
||||
include "views/diagram_operational.arcadia";
|
||||
}</pre>
|
||||
<p>An include path is relative to its containing file. <span class="docutils literal">.</span> and <span class="docutils literal">..</span> segments
|
||||
normalize within the virtual project root; escaping that root is an error. Bundle
|
||||
keys MUST already be normalized, use forward slashes and the lowercase
|
||||
<span class="docutils literal">.arcadia</span> suffix, and contain no empty path segments. Absolute, drive, UNC,
|
||||
URL, backslash, control-character and non-portable Windows device paths are
|
||||
rejected. Paths ending a segment in dot or space are rejected. Keys that collide
|
||||
after Unicode lowercasing are rejected. References use the exact normalized
|
||||
spelling; filesystems do not participate in resolution.</p>
|
||||
<p>Every reachable file is compiled once, including through repeated or diamond
|
||||
includes. Include cycles are errors with their chain and including location.
|
||||
Missing files, duplicate JSON file keys and supplied unreachable files are
|
||||
errors. The compiler MUST NOT read local files, network resources, environment
|
||||
variables or the process working directory. A future native loader is responsible
|
||||
for translating a directory into this explicit bundle and enforcing physical
|
||||
path ownership; the pure compiler grants no filesystem access.</p>
|
||||
<p><span class="docutils literal">inspect_includes(path, source, is_entry, limits)</span> supports native discovery
|
||||
before all included documents are available. It uses the same strict entry or
|
||||
fragment syntax parser, applies document byte/record and local include-edge
|
||||
budgets, and returns normalized targets with exact directive spans. Comments and
|
||||
strings that mention include syntax are not directives. A syntax failure anywhere
|
||||
in the document returns located errors and no partial include list; it does not
|
||||
scan arbitrary token strings after failure. Global references and engineering
|
||||
validation are deferred to bundle compilation. A native loader MUST retain the
|
||||
unparsed draft on failure and enforce aggregate bytes/files/depth/edges while
|
||||
loading; this inspection call does not own or inspect a directory.</p>
|
||||
<p>All files share the existing global alias/UUID namespace. Files add no semantic
|
||||
namespace, implicit parent, allocation or port contract. Forward references work
|
||||
across files. Duplicate aliases and identities report the offending declaration
|
||||
and the previous declaration location, including collisions with the project.
|
||||
Moving a declaration between files MUST preserve the resulting model and UUIDs.</p>
|
||||
<p><span class="docutils literal">ProjectLimits</span> adds file, include-depth and include-edge budgets to the existing
|
||||
<span class="docutils literal"><span class="pre">language::ParseLimits</span></span>. Model bytes, graph objects, records and ordered
|
||||
references are counted across the complete bundle, never reset per file. The
|
||||
default candidate policy is 256 files, depth 32 (entry depth zero), 1,024 include
|
||||
edges and 64 MiB combined UTF-8 source. Other model counts remain caller policy.
|
||||
Repeated include edges count toward the edge budget; file contents count once.
|
||||
The compiler admits input and stabilized output against the same limits.</p>
|
||||
<p><span class="docutils literal">compile_bundle</span> returns either located errors and no candidate, or a
|
||||
<span class="docutils literal">CompiledSourceProject</span> with the validated <span class="docutils literal">DecodeResult</span>, stabilized bundle,
|
||||
derived <span class="docutils literal">SourceIndex</span> and located engineering warnings. It inserts explicit
|
||||
UUID clauses into headers that omitted them without otherwise reformatting the
|
||||
input. The returned source index and diagnostics address the returned stabilized
|
||||
bytes. Clients MUST retain that bundle after successful Apply; recompiling the
|
||||
original buffers with missing identities would generate fresh identities.</p>
|
||||
<p>Bundle diagnostics wrap the existing Diagnostic with a logical path and optional
|
||||
related locations. Declaration spans, top-level field value spans, project
|
||||
header/body/description spans and resolved include locations are available in
|
||||
the source index. Columns remain one-based Unicode scalars within the real file;
|
||||
spans never refer to concatenated or synthetic source.</p>
|
||||
<p>Single-string parse/lint APIs remain filesystem-free and reject include
|
||||
statements with an explicit source-bundle requirement. V1/V2 single-file imports
|
||||
continue through their existing migration readers and reports. Modular projects
|
||||
require source3; migration is performed before modular export, not independently
|
||||
on included fragments. Modular source does not change the semantic JSON schema.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="canonical-output-and-source-tooling">
|
||||
<h2>7. Canonical output and source tooling</h2>
|
||||
@@ -1385,10 +1573,73 @@ defaults, and JSON-escaped strings. Elements are emitted in UUID order, then
|
||||
relations; diagrams and their nodes follow, then artifacts, then traces.
|
||||
Fields use deterministic name order. Output ends with LF. Alias values come
|
||||
from the model, never from regenerating display names.</p>
|
||||
<p>Comments and input whitespace are lexical trivia. Canonicalizing or applying
|
||||
source does not preserve them; the editor MUST explain that behavior.
|
||||
<p>Comments and input whitespace are lexical trivia to the canonical writer.
|
||||
Canonical export and the current desktop single-document Apply path do not
|
||||
preserve them; the editor MUST explain that behavior. This existing path does not
|
||||
define an acceptable lossless authoring policy for a future project editor.
|
||||
The pure project compiler in section 6.1 preserves them while inserting missing
|
||||
identities. 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>
|
||||
<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
|
||||
placements. Ports follow their owner; relations follow their source/context.
|
||||
Module names derive from persistent aliases, not display names or UUID chunks.
|
||||
Declarations are ordered by semantic ancestry and alias, with owners before
|
||||
descendants. Case-colliding generated file names receive deterministic numeric
|
||||
suffixes. When more than 240 distinct modules would be produced, aggregate
|
||||
folders consolidate into category modules to avoid thousands of tiny files.
|
||||
For every valid P, <span class="docutils literal"><span class="pre">compile_bundle(format_bundle(P)).decoded.project</span> == P</span>
|
||||
when the caller supplies sufficient admission budgets.</p>
|
||||
<p><span class="docutils literal">update_bundle(compiled, P, limits)</span> is a core source update facility. It
|
||||
checks that the compiled document/index/model snapshot still agrees, preserves
|
||||
existing declaration file ownership and all untouched document bytes, and
|
||||
recompiles the result before returning it. New children inherit their owner's
|
||||
file; new roots use canonical module rules and add an explicit entry include.
|
||||
Removed declarations do not delete source files. Alias changes also update
|
||||
declarations containing references to that alias. Invalid or stale updates
|
||||
return errors without mutating the input workspace.</p>
|
||||
<p>Updates MUST NOT canonicalize surviving declarations in full. Header, field and
|
||||
nested value positions are derived from the existing syntax parser. Unchanged
|
||||
fields retain their exact bytes, including field order, omitted defaults, number
|
||||
and string spelling, comments, indentation and line endings. Changed literals and
|
||||
references replace only the required tokens; a reference with comments between
|
||||
<span class="docutils literal">@</span> and its alias retains those comments. A previously omitted default is
|
||||
inserted only if its semantic value changes. New fields use the existing record's
|
||||
indentation and line-ending style without reformatting its other fields.</p>
|
||||
<p>A constructor tag change retains shared nested fields in place. Removed fields,
|
||||
constructors and declarations remove syntax tokens, retaining their comments
|
||||
and whitespace as annotations in the enclosing record or file. A complete value
|
||||
shape replacement likewise retains the old value's comments beside the new value.
|
||||
The updater does not invent an engineering interpretation for orphaned comments.</p>
|
||||
<p>List entries use stable referenced UUIDs, message-value <span class="docutils literal">field</span> references or
|
||||
lifeline-binding <span class="docutils literal">referenced</span> identities when these keys are unique. Literal
|
||||
entries use their literal value. Retained entries carry their authored value
|
||||
text and inter-separator comments when reordered. Trivia after a preceding comma
|
||||
belongs to the following entry; trivia before the next comma belongs to the
|
||||
preceding entry. Separators are reconstructed before trailing line comments so
|
||||
that the result remains valid syntax. Unkeyed or duplicate-key lists use source
|
||||
positions. Removed-entry comments remain as annotations in the list; newly added
|
||||
entries receive formatted syntax. These rules preserve comments without silently
|
||||
attaching new semantic identity to an ambiguous list entry.</p>
|
||||
<p>Retained declaration UUIDs and source ownership remain unchanged. Records match
|
||||
by UUID, not display name or alias. The model-only <span class="docutils literal">update_bundle</span> treats an
|
||||
explicit UUID replacement as removal and creation. The desktop instead uses
|
||||
<span class="docutils literal">update_bundle_with_identity_map</span> with the surviving-record provenance from
|
||||
<span class="docutils literal">prepare_command</span>: explicit identity edits and sequential identity swaps MUST
|
||||
preserve each original declaration's owning file and attached source trivia.
|
||||
New records have no original identity mapping. The mapping MUST be injective,
|
||||
refer to existing records and preserve record classes. The
|
||||
result is recompiled, reindexed and checked for equality with the requested
|
||||
model before return. Source changes needed for undo are workspace history data;
|
||||
callers should retain complete compiled workspace snapshots rather than infer
|
||||
past omission/layout choices from a model-only undo.</p>
|
||||
<p>Canonical modular export is a distinct, explicit operation and does not promise
|
||||
original comment/layout preservation. The native editor integrates per-file
|
||||
drafts and source-project saves as specified below. The pure compiler performs
|
||||
no filesystem access. REST source endpoints currently exchange a canonical
|
||||
model; they do not yet exchange the multi-file source bundle.</p>
|
||||
<p><span class="docutils literal">parse</span> returns a complete structurally validated candidate or error
|
||||
diagnostics and no model. Engineering warnings alone MUST NOT reject a valid
|
||||
candidate. Parsing may stop at the first syntax/conversion error. Diagnostics
|
||||
@@ -1431,8 +1682,9 @@ placement move are different transactions. The UI MUST identify which operation
|
||||
will occur. Reparenting work must not silently change its performer. A computed
|
||||
parent summary must remain distinguishable from direct allocation. A collapse
|
||||
operation hides presentation detail without deleting the children.</p>
|
||||
<p>Applying complete source is one model transaction. Graphical edits regenerate
|
||||
the matching canonical source. Both paths validate their candidate before
|
||||
<p>Applying a reachable source bundle is one model transaction. Graphical edits
|
||||
update its owning declarations through the source-preserving updater. Both
|
||||
paths validate their candidate and model/source equality before
|
||||
adoption; failure preserves the committed model, save baseline, and history.
|
||||
Incomplete but structurally safe references and coverage gaps produce warnings
|
||||
that allow continued authoring and saving.</p>
|
||||
@@ -1440,7 +1692,11 @@ that allow continued authoring and saving.</p>
|
||||
MUST NOT be replaced by generated text or lost on ordinary navigation. Undoing
|
||||
source-buffer edits and undoing committed model changes are distinct operations.
|
||||
Successful source Apply creates one model-history entry. Undo/redo restores
|
||||
the full stored model, including aliases, trace links, and occurrence identity.</p>
|
||||
the full stored model and exact accepted source bundle, including aliases,
|
||||
trace links, occurrence identity, comments and file ownership. Each open file
|
||||
retains its own unapplied draft across file navigation. Located lint diagnostics
|
||||
refer to the raw draft bytes rather than an identity-stabilized intermediate.
|
||||
Property editing MUST NOT silently discard a pending source draft.</p>
|
||||
<p>Changing a graphical UUID must atomically update map keys and every reference.
|
||||
Alias changes preserve UUID identity. Deletion must account for owned elements,
|
||||
incident relationships, ordered occurrences, and diagram placements without
|
||||
@@ -1449,14 +1705,24 @@ exchanges it references. Cross-layer counterparts are not owned descendants.
|
||||
Text edits describe a complete candidate and must remove or repair dependencies
|
||||
explicitly before Apply succeeds.</p>
|
||||
</section>
|
||||
<section id="persistence-and-v1-migration">
|
||||
<h2>9. Persistence and V1 migration</h2>
|
||||
<section id="persistence-and-explicit-migration">
|
||||
<h2>9. Persistence and explicit migration</h2>
|
||||
<p>Loading detects JSON from its first non-whitespace <span class="docutils literal">{</span>; other input is parsed
|
||||
as Arcadia source regardless of filename. Saving an <span class="docutils literal">.arcadia</span> suffix uses
|
||||
canonical V2 text; other suffixes use V2 JSON. Both forms preserve the same
|
||||
the accepted V3 source bundle (<span class="docutils literal">arcadia 3</span>); other suffixes use V3 JSON. Both forms preserve the same
|
||||
complete model. JSON rejects unknown fields throughout typed payloads,
|
||||
duplicate maps, unsupported versions, and structural errors.</p>
|
||||
<p>During first-release schema-2 integration, old Scenario bodies without a
|
||||
<p>Native source Save All checks the original contents of observed dependencies
|
||||
before staging writes. Existing target files are replaced individually and the
|
||||
entry is installed last. A transaction journal records originals and intended
|
||||
writes; explicit recovery restores originals only when current bytes match a
|
||||
known transaction state. Unrelated external contents MUST NOT be overwritten
|
||||
by recovery. Missing entry files and lint updates MUST NOT hide a detected
|
||||
pending-recovery action. This is not cross-process compare-and-swap or atomic
|
||||
multi-file visibility. Save failures retain the accepted model and drafts.
|
||||
Detached dirty buffers MUST be reattached or reverted before source saving;
|
||||
JSON export does not replace the source project's saved baseline or location.</p>
|
||||
<p>The frozen schema-2 reader retains staged compatibility defaults. Old Scenario bodies without a
|
||||
<span class="docutils literal">viewpoint</span> retain MixedLegacy, and old Exchange occurrence bodies without
|
||||
<span class="docutils literal">message_kind</span>, <span class="docutils literal">reply_to</span> or <span class="docutils literal">values</span> retain Asynchronous, none and [].
|
||||
Old StateTransition bodies without <span class="docutils literal">transition_kind</span>, <span class="docutils literal">triggers</span> or
|
||||
@@ -1469,8 +1735,30 @@ defaults without changing any prior identity, name, reference, order, geometry,
|
||||
artifact or trace field. The original V2 golden source/JSON in
|
||||
<span class="docutils literal"><span class="pre">crates/oa-core/tests/fixtures</span></span> MUST NOT be regenerated from the newer demo;
|
||||
they verify that every old persistent field survives. Canonical output writes
|
||||
the added defaults. A future schema-3 adapter remains a separate required
|
||||
migration and is not implied by this temporary compatibility behavior.</p>
|
||||
the added defaults through the explicit schema-3 migration.</p>
|
||||
<p>The V2 adapter preserves every original identity, alias, prose, parent,
|
||||
placement, trace and artifact. Generic ports become Legacy with their original
|
||||
direction/interface record. Existing FE endpoint IDs remain unchanged. For
|
||||
only a missing endpoint it creates an item-bearing FunctionOutput/Input owned
|
||||
by the already specified function, using UUID v5 in the project namespace
|
||||
with <span class="docutils literal"><span class="pre">v2-fe-port:<fe-id>:source</span></span> or <span class="docutils literal"><span class="pre">v2-fe-port:<fe-id>:target</span></span>. Every
|
||||
identity category is checked for collision; collisions are located errors,
|
||||
never overwrites. New aliases follow the deterministic collision-free alias
|
||||
convention. Every old boundary exchange receives <span class="docutils literal">oriented true</span>; no
|
||||
PortAllocation is inferred.</p>
|
||||
<p><span class="docutils literal">decode_with_report</span>, <span class="docutils literal">load_with_report</span> and their limited/source variants
|
||||
return the model plus a migration report containing original unresolved port
|
||||
IDs, required resolutions, generated endpoint IDs/aliases/owners, and boundary
|
||||
orientation defaults. REST import, replacement, candidate validation and
|
||||
project snapshots surface the same report. Opening an old server envelope
|
||||
preserves its resource ID/revision and bytes; the next explicit edit writes
|
||||
schema 3. Model/source exports contain only the canonical model. Migration
|
||||
reports are transient response metadata, not persisted model facts.</p>
|
||||
<p>Admission checks account for generated objects and their references before
|
||||
construction. Both the old V2 contract and the resulting V3 graph are
|
||||
validated. Migration itself does not save or increase a stored revision.
|
||||
Canonical second saves are stable. V1 normalization produces the frozen V2
|
||||
model and then uses this same V2-to-3 stage.</p>
|
||||
<p>Save validates a snapshot, writes a sibling temporary file, flushes it, and
|
||||
atomically replaces the destination. Failed serialization or validation must
|
||||
not truncate a previous file. External concurrent-writer conflict resolution
|
||||
@@ -1486,20 +1774,20 @@ step becomes a distinct occurrence element owned by its process. Generated
|
||||
diagram, node, and occurrence identities use UUID v5 with the old Project ID
|
||||
as namespace and deterministic role/index names. If such an identity collides,
|
||||
a deterministic suffix is tried. Reimporting the same fully identified V1
|
||||
input therefore yields the same V2 result, including repeated occurrences.
|
||||
input therefore yields the same V3 result, including repeated occurrences.
|
||||
No System or SA content is invented during an OA-only migration.</p>
|
||||
<p>V1 source aliases are retained when valid in V2. JSON imports generate the old
|
||||
canonical aliases deterministically. Any alias newly reserved in V2 is changed
|
||||
by a deterministic suffix; aliases were not persistent V1 semantic data.
|
||||
A project alias and aliases for new records are generated without colliding
|
||||
with retained aliases. The existing bundled V1 text and JSON migrate to equal
|
||||
V2 projects. Future versions remain errors until a separate migration exists.</p>
|
||||
V3 projects. Future versions remain errors until a separate migration exists.</p>
|
||||
</section>
|
||||
<section id="complete-authoring-example">
|
||||
<h2>10. Complete authoring example</h2>
|
||||
<p>This document intentionally omits IDs for new authoring. Apply and Save write
|
||||
the assigned UUIDs explicitly.</p>
|
||||
<pre class="code text literal-block"><code>arcadia 2;
|
||||
<pre class="code text literal-block"><code>arcadia 3;
|
||||
project harbor "Harbor assistance" {
|
||||
oa_entity control "Harbor control" {}
|
||||
oa_activity assess "Assess assistance" {}
|
||||
|
||||
Reference in New Issue
Block a user