1548 lines
86 KiB
ReStructuredText
1548 lines
86 KiB
ReStructuredText
Arcadia Studio OA / SA Language and Editing Contract
|
||
====================================================
|
||
|
||
:Version: 4
|
||
:Status: Normative current implementation contract; first-release integration
|
||
:Core implementation: ``crates/oa-core``
|
||
:Text suffix: ``.arcadia``
|
||
|
||
1. Scope and conformance
|
||
------------------------
|
||
|
||
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 versions 1, 2 and 3. MUST, MUST NOT,
|
||
and MAY indicate requirements, prohibitions, and permitted choices.
|
||
|
||
Schema 4 adds bounded reusable data types, typed scalar defaults, exchange
|
||
mechanisms, qualified message values, specialization, identified interface
|
||
allocations and reference associations. It retains schema 3 typed ports and
|
||
state views. Explicit older readers preserve existing meanings and identities.
|
||
This contract does not by itself establish native acceptance or release completion.
|
||
|
||
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
|
||
incomplete-model warning when other SA elements exist. The SA System MUST NOT
|
||
contain internal components. Functional decomposition is independent of that
|
||
structural boundary. Logical Architecture, Physical Architecture, deployment,
|
||
Capella file interchange, and executable behavioral simulation are outside
|
||
this specification. This independent language does not claim complete Arcadia,
|
||
Eclipse Capella, or SysML conformance.
|
||
|
||
An implementation conforms only when each supported field and relationship is
|
||
reachable in both graphical and textual editing, preserves identity through
|
||
save/open and undo, and uses the same structural validation. Merely displaying
|
||
a name or storing an opaque payload does not establish graphical support.
|
||
Actual verification evidence is separate from this contract.
|
||
|
||
2. One authoritative model
|
||
--------------------------
|
||
|
||
A Project stores ``schema_version`` (4), ``id``, ``alias``, ``name``,
|
||
``description``, and maps named ``elements``, ``relations``, ``diagrams``,
|
||
``artifact_links``, and ``traces``. Each map is keyed by the UUID contained in
|
||
its record. Duplicate map keys and mismatching keys/identities are errors.
|
||
|
||
All objects share one UUID and alias namespace: Project, Element, Relation,
|
||
Diagram, NodePlacement, ArtifactLink, and Trace. UUIDs are durable identity;
|
||
aliases are durable, editable source labels. Display-name changes MUST NOT
|
||
regenerate existing aliases. Different objects MAY have the same display name.
|
||
|
||
Every Element has ``id``, ``alias``, ``name``, ``description``, ``parent``
|
||
(optional element reference), and a typed ``body``. Its kind and OA/SA layer
|
||
are derived from its body. A Relation has ``id``, ``alias``, ``name``,
|
||
``description``, and a typed body; it has no independently editable kind tag
|
||
that can disagree with its payload.
|
||
|
||
Diagram placement does not determine semantic ownership. NodePlacement
|
||
records belong to diagrams and reference semantic elements. Multiple diagrams
|
||
can show the same element with independent placement and collapse state.
|
||
Within one diagram, each element appears at most once.
|
||
|
||
All stored strings MUST contain only XML 1.0 characters: U+0009, U+000A,
|
||
U+000D, U+0020–U+D7FF, U+E000–U+FFFD, or U+10000–U+10FFFF. Strings are not
|
||
trimmed or Unicode-normalized. Escaping a forbidden character does not permit
|
||
it. Coordinates and sizes are finite IEEE-754 binary32 values with absolute
|
||
value at most 1000000. Width and height MUST be positive. Signed zero and
|
||
subnormal coordinates are retained.
|
||
|
||
3. Element declarations and typed fields
|
||
----------------------------------------
|
||
|
||
Each element declaration starts with its layer and kind, for example
|
||
``oa_activity`` or ``sa_function``. Every element body accepts
|
||
``description`` (default ``""``) and ``parent`` (default ``none`` for a
|
||
document-level declaration, or its lexical element owner when nested; section
|
||
6.2). The table
|
||
lists all additional fields. ``ref`` means ``@alias``; ``ref?`` also accepts
|
||
``none``. Lists preserve order. Unknown or duplicate fields are errors.
|
||
|
||
.. list-table:: Element body field catalog
|
||
:header-rows: 1
|
||
:widths: 27 43 30
|
||
|
||
* - Declarations
|
||
- Additional fields
|
||
- Defaults
|
||
* - ``oa_entity``, ``oa_actor``, ``oa_role``, ``oa_activity``, ``oa_capability``, ``oa_mission``
|
||
- None
|
||
- Empty body
|
||
* - ``sa_system``, ``sa_actor``, ``sa_function``, ``sa_capability``, ``sa_mission``
|
||
- None
|
||
- Empty body
|
||
* - ``oa_process``, ``sa_functional_chain``
|
||
- ``steps``: occurrence refs
|
||
- ``[]``
|
||
* - ``oa_exchange_item``, ``sa_exchange_item``
|
||
- ``kind``: Information, Material, Energy; ``mechanism``: ExchangeMechanism; ``supertype``: item ref?
|
||
- Information; Unspecified; none
|
||
* - ``oa_data_type``, ``sa_data_type``
|
||
- ``definition``: DataTypeDefinition; ``default``: DataValue?; ``unit``: string
|
||
- String with minimum_length 0 / maximum_length none; none; ``""``
|
||
* - ``oa_data_field``, ``sa_data_field``
|
||
- ``type_ref``; ``minimum``: u32; ``maximum``: optional u32; ``unit``: string; ``direction``: ParameterDirection; ``storage``: FieldStorage; ``default``: DataValue list?
|
||
- String; 1; 1; ``""``; Unspecified; Value; none
|
||
* - ``oa_interface``, ``sa_interface``
|
||
- ``supertype``: interface ref?
|
||
- none; membership is an identified interface_item_allocation relation
|
||
* - ``oa_port``, ``sa_port``
|
||
- ``contract``: required PortContract; ``legacy``: optional LegacyPortContract
|
||
- No implicit contract; ``legacy`` defaults none. OA admits Legacy only.
|
||
* - ``oa_scenario``, ``sa_scenario``
|
||
- ``viewpoint``: ScenarioViewpoint; ``context``: ref?; ``precondition``, ``postcondition``: strings; ``steps``: occurrence refs
|
||
- MixedLegacy for omitted schema-2 source; none; ``""``; ``""``; ``[]``
|
||
* - ``oa_lifeline``, ``sa_lifeline``
|
||
- ``represented``: participant, work, or role ref?
|
||
- none
|
||
* - ``oa_occurrence``, ``sa_occurrence``
|
||
- ``body``: occurrence constructor; ``precondition``, ``postcondition``: strings
|
||
- Exchange with none references, Asynchronous message kind and no values; two empty strings
|
||
* - ``oa_state_machine``, ``sa_state_machine``, ``oa_region``, ``sa_region``
|
||
- None
|
||
- Empty body
|
||
* - ``oa_state``, ``sa_state``, ``oa_mode``, ``sa_mode``, ``oa_initial``, ``sa_initial``, ``oa_final``, ``sa_final``
|
||
- ``kind``: StateKind; ``entry``, ``exit``, ``do_activity``: strings
|
||
- Kind selected by declaration; three empty strings
|
||
* - ``oa_choice``, ``oa_junction``, ``oa_fork``, ``oa_join``, ``oa_shallow_history``, ``oa_deep_history``, ``oa_entry_point``, ``oa_exit_point``, ``oa_terminate`` and corresponding ``sa_`` declarations
|
||
- Same State body; StateKind is Choice, Junction, Fork, Join, ShallowHistory, DeepHistory, EntryPoint, ExitPoint or Terminate
|
||
- Kind selected by declaration; three empty strings
|
||
* - ``oa_event``, ``sa_event``
|
||
- ``body``: Signal, Time or Change constructor
|
||
- Signal with ``items []``
|
||
* - ``oa_constraint``, ``sa_constraint``
|
||
- ``expression``: string; ``constrained``: semantic record refs
|
||
- ``""``; ``[]``
|
||
|
||
The explicit state ``kind`` field MUST agree with its declaration keyword.
|
||
``u32`` is an integer from 0 through 4294967295. A DataField's maximum MUST
|
||
be at least its minimum; ``none`` means unbounded. Primitive TypeRefs are
|
||
Boolean, Integer, Real, and String. A named TypeRef uses a DataType reference.
|
||
An Enumeration contains unique string literals. For example:
|
||
|
||
.. code-block:: text
|
||
|
||
definition { Enumeration { literals ["Clear", "Fog"]; }; };
|
||
type_ref { Named @weather_classification; };
|
||
|
||
These are typed constructors with named fields, not embedded JSON documents.
|
||
Constructor field names and enum spellings are case-sensitive. When replacing
|
||
a constructor, all of its fields MUST be supplied; the containing declaration
|
||
defaults do not silently fill a different constructor's missing fields.
|
||
During schema-2 compatibility, the new Exchange fields ``message_kind``,
|
||
``reply_to`` and ``values`` are exceptions: omitted values hydrate as
|
||
Asynchronous, none and [] respectively. Canonical output writes them explicitly.
|
||
This preserves older schema-2 source/JSON without inventing call correlation or
|
||
value annotations. It is not a rule for an unspecified future schema.
|
||
|
||
.. list-table:: Occurrence body constructors
|
||
:header-rows: 1
|
||
:widths: 22 78
|
||
|
||
* - Constructor
|
||
- Required fields
|
||
* - Exchange
|
||
- ``exchange``: exchange relation ref?; ``sender``, ``receiver``: lifeline refs?; ``message_kind``: MessageKind; ``reply_to``: occurrence ref?; ``values``: MessageValue records
|
||
* - Action
|
||
- ``action``: activity/function ref?; ``lifeline``: ref?
|
||
* - Control
|
||
- ``kind``: Choice, Merge, Fork, Join, Loop
|
||
* - SequenceReference
|
||
- ``sequence``: process/functional-chain ref?
|
||
* - ScenarioUse
|
||
- ``scenario``: scenario ref?; ``bindings``: LifelineBinding records
|
||
* - State
|
||
- ``state``: state/mode ref?; ``lifeline``: ref?
|
||
* - Fragment
|
||
- ``operator``: Alternative, Parallel, Loop, Optional; ``branches``: branch occurrence refs
|
||
* - Branch
|
||
- ``guard``: string; ``occurrences``: occurrence refs
|
||
|
||
For example, ``body { Action { action @assess; lifeline @operator_line; }; };``
|
||
selects an Action occurrence. Processes and functional chains contain Exchange,
|
||
Action, Control and SequenceReference occurrences. Process/chain Actions are
|
||
contextual work contributions and MUST have ``lifeline none``. A Control or
|
||
SequenceReference MUST belong directly to a Process or FunctionalChain, not a
|
||
Scenario. Scenarios contain Exchange, Action, State, Fragment, Branch and ScenarioUse
|
||
occurrences according to their enclosing ownership rules. Each
|
||
listed occurrence belongs to its enclosing sequence or branch through
|
||
``parent``. A Branch belongs to a Fragment; the Fragment's ``branches`` list
|
||
references the branches it owns.
|
||
|
||
An exchange and an occurrence of that exchange have different identities.
|
||
Repeating an exchange requires distinct occurrence records. Repeating one
|
||
occurrence identity within an ordered list is invalid. Conditions, guards,
|
||
entry/exit/do text, and constraint expressions are descriptive strings; this
|
||
version does not parse or execute them as a programming language.
|
||
|
||
4. Containment, allocation, and relationships
|
||
---------------------------------------------
|
||
|
||
Containment MUST be acyclic and stay within one layer. Entities may contain
|
||
entities, actors, and roles. Actors are not structural containers. Activities
|
||
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. 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
|
||
are root semantic records and do not acquire a machine owner when referenced.
|
||
|
||
DataFields, ports, lifelines, occurrences, Regions and all state vertices
|
||
require an owner. An unowned StateMachine can be saved as incomplete
|
||
work and produces a warning. The System cannot own internal components.
|
||
The present Studio profile does not decompose SA Actors.
|
||
|
||
All relations have a header identity, alias, display name, optional
|
||
``description`` (default ``""``), and required ``source`` and ``target``
|
||
references. Their kind is the declaration keyword:
|
||
|
||
.. list-table:: Relation catalog
|
||
:header-rows: 1
|
||
:widths: 24 49 27
|
||
|
||
* - Declaration
|
||
- Endpoint meaning
|
||
- Additional fields / defaults
|
||
* - ``allocation``
|
||
- Same-layer participant → leaf activity/function
|
||
- None
|
||
* - ``interface_item_allocation``
|
||
- Same-layer Interface → ExchangeItem
|
||
- ``order`` u32 / 0; ``transmission`` TransmissionProtocol / Unspecified; ``acquisition`` AcquisitionProtocol / Unspecified
|
||
* - ``data_association``
|
||
- Same-layer Record DataType → Record DataType
|
||
- ``source_role``, ``target_role`` / ""; ``source_minimum``, ``target_minimum`` / 0; ``source_maximum``, ``target_maximum`` / none; ``source_navigable``, ``target_navigable`` / false
|
||
* - ``interaction``
|
||
- OA activity → OA activity
|
||
- ``items`` refs / []
|
||
* - ``functional_exchange``
|
||
- SA function → SA function
|
||
- Required ``source_port``, ``target_port`` refs; ``items`` / []
|
||
* - ``boundary_exchange``
|
||
- Different participant owners; typed component ports have matching kinds
|
||
- ``oriented`` bool / true; ``items`` refs / []
|
||
* - ``port_allocation``
|
||
- SA Component port → SA FunctionInput/FunctionOutput port
|
||
- Requires the function's actual work Allocation to that component
|
||
* - ``capability_involvement``
|
||
- Participant, activity/function, or OA role → capability
|
||
- None
|
||
* - ``chain_involvement``
|
||
- Process/functional chain → capability
|
||
- None
|
||
* - ``role_realization``
|
||
- OA entity/actor → OA role
|
||
- None
|
||
* - ``role_assignment``
|
||
- OA role → leaf OA activity
|
||
- None
|
||
* - ``mission_capability``
|
||
- OA mission → OA capability, or SA mission → SA capability
|
||
- None
|
||
* - ``mission_involvement``
|
||
- OA entity/actor → OA mission, or SA System/Actor → SA mission
|
||
- None
|
||
* - ``capability_include``
|
||
- Including capability → included capability in one layer
|
||
- None
|
||
* - ``capability_extend``
|
||
- Extending capability → extended capability in one layer
|
||
- ``condition`` string / ""
|
||
* - ``capability_generalization``
|
||
- Specific capability → general capability in one layer
|
||
- None
|
||
* - ``sequence_link``
|
||
- Preceding contribution → following contribution in one process/chain
|
||
- ``guard`` string / ""
|
||
* - ``state_transition``
|
||
- State vertices in one machine, subject to section 4.4
|
||
- ``trigger``, ``guard``, ``effect`` strings / ""; ``transition_kind`` External; ``triggers``, ``effects`` reference lists / []
|
||
* - ``availability``
|
||
- Work, participant, capability, or process/chain → state/mode
|
||
- None
|
||
* - ``exchange_allocation``
|
||
- Boundary-exchange relation → SA functional-exchange relation
|
||
- None
|
||
* - ``interface_provision``, ``interface_requirement``
|
||
- Participant/port → provided/required interface
|
||
- None
|
||
* - ``state_action``
|
||
- State/mode → activity/function
|
||
- ``phase``: Entry, Do, Exit / Do
|
||
|
||
Relation endpoints and carried ExchangeItems stay in the same layer. Parallel
|
||
exchanges with distinct identities are permitted. Self-relations are invalid
|
||
except for a state transition that returns to its source state or an explicit
|
||
DataAssociation between two ends of the same Record type.
|
||
|
||
Direct Allocation has at most one performer per leaf. Role sharing is a
|
||
different relationship: several OA participants can realize a Role. A direct
|
||
allocation inconsistent with its role's realized performers produces an
|
||
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.
|
||
|
||
Typed function ports belong directly to SA Functions. ``FunctionOutput``
|
||
declares ``outgoing_items``; ``FunctionInput`` declares ``incoming_items``.
|
||
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.
|
||
|
||
A ``Component`` contract belongs to an SA System or SystemActor and stores
|
||
``kind`` (Standard or Flow) and ``orientation`` (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 ``oriented false``; 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.
|
||
|
||
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.
|
||
|
||
``PortAllocation`` 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.
|
||
|
||
``Legacy`` requires ``legacy { direction ...; interface ...; }``. 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.
|
||
|
||
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.
|
||
|
||
For example::
|
||
|
||
arcadia 4;
|
||
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" {}
|
||
interface_item_allocation service_payload "Service payload" { source @old_service; target @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; };
|
||
}
|
||
|
||
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.
|
||
Final states have no outgoing transitions. Mixing State and Mode entries is
|
||
permitted by this Studio profile. StateAction links provide typed work
|
||
references alongside the descriptive entry/exit/do strings.
|
||
|
||
4.1. Capabilities and missions
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
Include means the including capability requires the included capability's
|
||
behavior. Extend means the source capability adds conditional behavior to the
|
||
target; its ``condition`` records when that behavior applies. Generalization
|
||
means a specific source capability specializes a general target capability.
|
||
Each relationship stays within OA capabilities or within SA capabilities.
|
||
Include and Generalization graphs MUST each be acyclic, including transitive
|
||
cycles. Extend does not introduce an additional cycle restriction; the ordinary
|
||
no-self rule still applies. An empty Extend condition is an engineering warning
|
||
so an incomplete capability map can be authored and saved.
|
||
|
||
MissionCapability and MissionInvolvement express need and stakeholder/system
|
||
participation. They MUST NOT create a capability parent, a performer allocation,
|
||
or a cross-layer realization. These relationships remain distinct when the
|
||
same objects appear in a diagram or share names.
|
||
|
||
4.2. Contextual process and chain topology
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
A Process or FunctionalChain owns contribution occurrences with stable
|
||
identities. ``steps`` is their persistent membership and presentation order;
|
||
an identity MUST occur at most once in that list. A work contribution points to
|
||
an existing same-layer Activity or Function. Reusing the same work or exchange
|
||
requires separate occurrence identities and MUST NOT duplicate the referenced
|
||
engineering element. A SequenceReference points to another same-layer Process
|
||
or FunctionalChain of the owner's kind. Its target may be ``none`` while the
|
||
draft is incomplete. Direct and transitive recursive sequence reuse are errors.
|
||
|
||
SequenceLinks connect distinct occurrences directly owned by the same process
|
||
or chain. Their source is the predecessor and target is the successor. A link
|
||
from work to an exchange requires that work to be the referenced exchange's
|
||
source; an exchange-to-work link requires the target work to be its endpoint.
|
||
Two adjacent exchange contributions require the first exchange's target to
|
||
match the second exchange's source. A mismatch is a structural error. Other
|
||
links express contextual precedence without manufacturing a global exchange.
|
||
|
||
When links or work/control/reuse contributions exist, topology is explicit.
|
||
Reordering ``steps`` MUST NOT add, remove or reorder SequenceLinks. The editor
|
||
MUST retain the difference between alternative Choice/Merge and parallel
|
||
Fork/Join contributions. Choice/Fork expect one incoming and at least two
|
||
outgoing links; Merge/Join expect at least two incoming and one outgoing link.
|
||
Loop expects at least one incoming and two outgoing links for repetition and
|
||
exit. These cardinalities are completeness warnings, not barriers to building
|
||
an incomplete flow. Choice and Loop outgoing paths with empty guards warn;
|
||
an explicit ``else`` guard is permitted. Guards remain descriptive strings.
|
||
|
||
Validation warns about missing/ambiguous entry and exit, isolated or unreachable
|
||
contributions, contributions with no reachable exit, and splits/merges that
|
||
lack explicit controls. Topology cycles are permitted for loops; the recursive
|
||
SequenceReference prohibition is a different rule. A legacy exchange-only
|
||
sequence without explicit links retains its ordered linear meaning and
|
||
adjacent-exchange gap diagnostics. Implementations MUST NOT silently invent
|
||
topology links when loading or reordering such a sequence.
|
||
|
||
4.3. Typed scenarios and reusable behavior
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
ScenarioViewpoint is one of OperationalActivity (OA activity lifelines),
|
||
ParticipantInteraction (OA entity/actor/role lifelines), Functional (SA function
|
||
lifelines), BoundaryInterface (SA System/Actor lifelines), or MixedLegacy.
|
||
The first two are OA viewpoints; the next two are SA viewpoints. Lifeline
|
||
references MUST agree with that perspective. OperationalActivity messages use
|
||
Interactions; Functional messages use FunctionalExchanges. Participant views
|
||
may use their layer's work exchanges through effective performer allocation,
|
||
or participant boundary exchanges through the relevant ports. Corresponding
|
||
lifelines and endpoints MUST agree; a viewpoint is not a label that suppresses
|
||
reference checks.
|
||
|
||
Omitted schema-2 viewpoints hydrate as MixedLegacy in both source and JSON.
|
||
This preserves pre-extension mixed work/participant scenes without discarding
|
||
their lifelines or silently assigning a stricter meaning. MixedLegacy emits a
|
||
review warning. New graphical factories explicitly select OperationalActivity
|
||
or Functional by layer. Authors can select a strict viewpoint after reviewing
|
||
the legacy scene; canonical source then records that choice.
|
||
|
||
MessageKind is Asynchronous, Call, Reply, Create, Delete, or
|
||
``{ Timer { expression "after 5 s"; }; }``. A process/chain exchange
|
||
contribution MUST remain Asynchronous with no reply correlation. Call/reply,
|
||
creation/deletion and timer semantics belong to scenarios. Reply's ``reply_to``
|
||
references a Call occurrence in the same scenario. The call MUST precede the
|
||
reply on a guaranteed common sequence/enclosing branch path. Reply lifelines
|
||
reverse the call's sender/receiver; it may reuse the call's exchange in reverse
|
||
or use an explicit reverse-direction exchange. A second reply to the same call
|
||
on that guaranteed path is an error. Missing reply correlation is a draft
|
||
warning; non-Reply messages MUST NOT have ``reply_to``.
|
||
|
||
Create identifies the receiver lifeline's creation. An earlier guaranteed use
|
||
of that lifeline is an error. Delete identifies its destruction; a later
|
||
guaranteed use is an error. Ordering checks respect branch ownership; they MUST
|
||
NOT flatten alternative branches into a false unconditional order. A Timer is
|
||
local to its sender lifeline, has no global exchange or values, and has either
|
||
no receiver or the same receiver as sender. Its nonempty expression describes
|
||
the delay/deadline; an empty expression warns. Conditions and expressions are
|
||
stored engineering annotations, not an executable simulation language.
|
||
|
||
Each MessageValue is ``{ path [@parameter]; field @data_field; expression "value expression"; }``.
|
||
Its identity is the pair (path, field), so two uses of one Record can have
|
||
different values for the same terminal field. Path contains enclosing DataField
|
||
references, excluding the terminal field; direct parameters use ``[]``. Every
|
||
hop MUST follow Value storage through a named Record's effective fields. Reference
|
||
storage stops traversal. Operation Call accepts In/InOut and Reply accepts
|
||
Out/InOut/Return, interpreted from the provider's perspective. Nested field paths
|
||
inherit their direct parameter's direction. Unspecified direction warns.
|
||
At most one annotation for a pair is allowed. Omitted path defaults to ``[]``;
|
||
an ambiguous preserved legacy nested annotation warns ``message_value_ambiguous_path``
|
||
until an explicit path is selected. New graphical choices always identify a path.
|
||
Values never overwrite types or items. Expression text is descriptive, preserved
|
||
exactly and not evaluated; an empty expression warns.
|
||
|
||
ScenarioUse references an existing same-layer scenario and maps its lifelines
|
||
with ``bindings [ { referenced @callee_line; local @caller_line; } ];``.
|
||
Each binding is one-to-one and references a direct lifeline of the appropriate
|
||
scenario. Bound lifelines represent the same semantic object, or an explicitly
|
||
realized operational role. Strict viewpoints MUST agree; MixedLegacy retains
|
||
the compatibility case until reviewed. Missing bindings produce warnings.
|
||
Direct/transitive recursive scenario use is invalid; repetition uses a Loop
|
||
fragment instead. ScenarioUse owns neither its referenced scenario nor its
|
||
lifelines; deleting a use does not delete the reusable definition.
|
||
|
||
4.4. State vertices, events and transition contracts
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
StateKind comprises State, Mode, Initial, Final, Choice, Junction, Fork, Join,
|
||
ShallowHistory, DeepHistory, EntryPoint, ExitPoint and Terminate. Every vertex
|
||
belongs to a Region. Only State and Mode are stable states: only these may own
|
||
nested Regions, typed StateAction links, availability and scenario state
|
||
observations. Multiple sibling Regions describe orthogonal configurations.
|
||
EntryPoint and ExitPoint retain Region ownership; their boundary is that
|
||
Region's owning State/Mode or StateMachine. Their graphical symbols belong on
|
||
that boundary. This is Studio's explicit containment encoding.
|
||
|
||
Events are ordinary same-layer semantic elements, independent of diagram
|
||
placements. EventBody has exactly these constructors:
|
||
|
||
.. list-table:: Event definitions
|
||
:header-rows: 1
|
||
|
||
* - Constructor
|
||
- Fields and meaning
|
||
* - Signal
|
||
- ``items`` is a unique list of same-layer ExchangeItem references; empty is valid
|
||
* - Time
|
||
- ``kind`` is After or At; ``expression`` is descriptive time text
|
||
* - Change
|
||
- ``expression`` describes the Boolean condition becoming true
|
||
|
||
After measures relative time from activation of a transition's source state;
|
||
At describes an absolute instant. Empty Time/Change expressions are located
|
||
completeness warnings. The application does not execute expressions, fire
|
||
timers or transport signals. For example::
|
||
|
||
sa_event timeout "Recovery timeout" {
|
||
body { Time { kind After; expression "30 s"; }; };
|
||
}
|
||
sa_event recovered "Pressure recovered" {
|
||
body { Change { expression "pressure > 4 && status == \"Ready\""; }; };
|
||
}
|
||
|
||
StateTransition's ``triggers`` references Events or layer-appropriate work
|
||
(OA Activity / SA Function). Referenced work need not have the machine owner's
|
||
performer: external work can cause the observed transition. Multiple triggers
|
||
are alternatives. ``effects`` references work describing effects, without
|
||
executing it. Duplicate, missing, wrong-layer or wrong-kind references are
|
||
errors. The existing ``trigger``, ``guard`` and ``effect`` strings remain
|
||
authored prose; they MUST NOT be renamed, parsed as UUIDs or inferred by name.
|
||
|
||
With typed triggers, ``trigger`` adds descriptive information. With no typed
|
||
triggers and nonblank trigger prose, the transition has an unresolved
|
||
descriptive trigger and emits a warning. Both empty denotes completion from
|
||
a stable state or transient routing from a pseudostate. Deleting the final
|
||
typed trigger when prose is empty MUST leave an explicit descriptive reminder;
|
||
it MUST NOT silently create a completion transition. Guards/effect prose remain
|
||
unchanged. Signal payload references and typed effect references are pruned
|
||
when their targets are removed.
|
||
|
||
TransitionKind is External, Local or Internal. External leaves/re-enters the
|
||
affected configuration; a stable self-transition includes exit and entry
|
||
behavior. Internal requires the same stable source and target, preserves nested
|
||
configuration, and does not imply entry/exit. Local requires a composite stable
|
||
source and proper descendant target, preserving the source activation; an
|
||
EntryPoint also routes locally into its boundary. Local self/outside targets
|
||
are invalid. Other pseudostates route externally. Endpoints MUST share a layer
|
||
and StateMachine; crossing nested Regions within that machine is not generally
|
||
forbidden. A pseudostate self-transition is invalid.
|
||
|
||
A simple state's completion means entry/do behavior is complete. A composite
|
||
completes when its active Regions complete. Final completes its containing
|
||
Region; Terminate ends the containing machine's activation. These are modeling
|
||
meanings, not evidence of a running state-machine engine.
|
||
|
||
Missing connections/guards and unfinished initial/history paths produce
|
||
warnings, so an engineer can insert vertices before wiring them. Contradictory
|
||
upper cardinalities, forbidden directions/kinds and invalid references reject.
|
||
|
||
.. list-table:: Vertex connection constraints
|
||
:header-rows: 1
|
||
|
||
* - Vertex
|
||
- Structural restrictions
|
||
- Incomplete-model warnings
|
||
* - Initial
|
||
- At most one per Region; no incoming; at most one outgoing; no outgoing trigger or guard
|
||
- Missing initial/default entry or outgoing
|
||
* - Final / Terminate
|
||
- No outgoing or nested Region
|
||
- No incoming
|
||
* - Choice
|
||
- At most one incoming; outgoing transient alternatives
|
||
- Missing incoming, fewer than two outgoing, missing guard or else
|
||
* - Junction
|
||
- Transient routing, no implicit concurrency
|
||
- Missing side or ambiguous unguarded alternatives
|
||
* - Fork
|
||
- At most one incoming; outgoing stable targets in distinct orthogonal Regions
|
||
- Missing incoming or fewer than two outgoing
|
||
* - Join
|
||
- At most one outgoing; incoming stable sources in distinct orthogonal Regions
|
||
- Fewer than two incoming or missing outgoing
|
||
* - ShallowHistory
|
||
- At most one per Region; at most one fallback to a direct stable child of that Region; no fallback trigger/guard
|
||
- Missing fallback/default entry
|
||
* - DeepHistory
|
||
- At most one per Region; at most one fallback to a stable descendant of that Region; no fallback trigger/guard
|
||
- Missing fallback/default entry
|
||
* - EntryPoint
|
||
- Incoming from outside boundary, outgoing Local into it; at most one outgoing per destination Region
|
||
- Missing outgoing or incomplete affected-Region entry
|
||
* - ExitPoint
|
||
- Incoming from inside boundary; at most one outgoing External to outside
|
||
- Missing input/output; top-level exit is an exit endpoint, not implicit termination
|
||
|
||
Fork outputs and Join inputs MUST NOT carry guards or typed/descriptive
|
||
triggers. Their distinct orthogonal Regions are the first Regions beneath the
|
||
nearest common composite or machine, not merely each endpoint's immediate
|
||
parent. Choice/Junction routing expresses conditional alternatives. Retained
|
||
pseudostate entry/exit/do prose produces a warning and remains editable; it
|
||
does not become a typed state behavior. StateAction remains the maintained
|
||
reference for entry/do/exit work on stable states.
|
||
|
||
Other pseudostate outgoing segments MUST NOT introduce event/work triggers
|
||
or trigger prose. A Choice has at most one literal ``else`` guard; the tool
|
||
does not prove arbitrary guard expressions disjoint or exhaustive. Choice
|
||
expresses a dynamic decision after incoming effects; Junction expresses a
|
||
compound path selected by guards before traversing it. ShallowHistory remembers
|
||
the immediate state and uses default entry for deeper configuration;
|
||
DeepHistory remembers nested configuration. Fallback applies when no resumable
|
||
history exists. History is per Region, including top-level Regions in this
|
||
Studio profile; no running history state is persisted or synthesized.
|
||
|
||
4.5. Data contracts, specialization and interface allocation
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
ExchangeItem ``kind`` describes nature: Information, Material or Energy.
|
||
``mechanism`` is Unspecified, Flow, Event, Operation or SharedData. Unknown
|
||
mechanisms remain explicit Unspecified drafts with a warning. Material/Energy
|
||
with Event/Operation/SharedData warns for engineering review; it is not silently
|
||
reclassified. Empty Event notifications and void Operations are valid. An empty
|
||
carried/allocated Flow, SharedData or Unspecified item warns.
|
||
|
||
An Operation's directly owned DataFields are parameters. ``direction`` is
|
||
Unspecified, In, Out, InOut or Return, from the provider's perspective. At most
|
||
one effective parameter is Return. Unspecified parameters warn; non-operation
|
||
fields MUST use Unspecified. Nested record fields inherit direction from their
|
||
direct parameter when used in message paths, rather than storing context on a
|
||
shared type. ``storage`` is Value or Reference. Reference requires a named Record,
|
||
has no explicit default, and does not convey ownership or deletion of the type.
|
||
|
||
DataTypeDefinition has exactly the following constructors:
|
||
|
||
.. list-table:: Reusable definitions
|
||
:header-rows: 1
|
||
|
||
* - Constructor
|
||
- Required fields
|
||
* - Boolean
|
||
- None
|
||
* - Integer
|
||
- ``minimum``, ``maximum``: optional signed 64-bit integers
|
||
* - Real
|
||
- ``minimum``, ``maximum``: optional finite IEEE-754 binary64 values
|
||
* - String
|
||
- ``minimum_length``: u32; ``maximum_length``: optional u32
|
||
* - Enumeration
|
||
- ``literals``: unique nonempty, case-sensitive strings
|
||
* - Record
|
||
- ``supertype``: same-layer Record ref?
|
||
|
||
Bounds are inclusive and ordered; an absent bound means unbounded within the
|
||
represented numeric domain. Integer comparisons MUST NOT convert to binary64.
|
||
NaN, infinities, overflow and reversed bounds reject. String length counts Unicode
|
||
scalar values, not UTF-8 bytes or grapheme clusters. Enum defaults match exact
|
||
literals. Empty enum definitions remain incomplete drafts with a warning.
|
||
|
||
DataValue is a tagged scalar: ``{ Boolean true; }``, ``{ Integer 42; }``,
|
||
``{ Real 1.5; }``, ``{ String "value"; }`` or ``{ Enumeration "Ready"; }``.
|
||
There is no implicit numeric or string coercion. A type default is one compatible
|
||
scalar within its bounds. Record type defaults and record/object instance literals
|
||
are unsupported. A field default is absent (``none``) or a list of compatible
|
||
scalars with length inside its multiplicity. ``[]`` explicitly supplies an empty
|
||
collection and requires minimum 0, including Value Record fields; a nonempty
|
||
Record literal rejects. Reference fields MUST use ``none``. A one-valued scalar
|
||
field uses a one-value list. A named type default supplies an individual element's
|
||
default, not a collection or an implicit instance of a mandatory field.
|
||
|
||
Numeric types may carry unit text. Empty field units inherit the named type unit;
|
||
an explicit different unit warns when that type has a unit. Units on nonnumeric
|
||
fields/types warn and remain preserved. Unit strings never convert values or
|
||
establish dimensional compatibility. Expressions are not executed.
|
||
|
||
Record, ExchangeItem and Interface each permit one same-family, same-layer
|
||
supertype. Specialization is acyclic and separate from containment. Effective
|
||
fields are base fields followed by local fields, preserving original field UUIDs
|
||
and owners. Local names MUST NOT shadow inherited names. Item specialization
|
||
preserves base nature and any specified mechanism; an Unspecified base mechanism
|
||
may be refined. Deleting a derived record never deletes its base. Mandatory
|
||
Value-field cycles warn ``record_no_finite_value``; optional or Reference cycles
|
||
are valid without that warning. Traversal is cycle guarded and bounded; a payload
|
||
path budget failure is an explicit diagnostic, not silent truncation.
|
||
|
||
InterfaceItemAllocation is an ordinary identified relation from Interface to
|
||
ExchangeItem. It stores ``order`` and independent transmission/acquisition
|
||
protocols. Transmission is Unspecified, Synchronous, Asynchronous, Unicast,
|
||
Multicast or Broadcast; acquisition is Unspecified, Read or Accept. No protocol
|
||
combination is inferred from mechanism. Effective allocations are base-first,
|
||
then local ordered by (order, alias, UUID). A local item already allocated locally
|
||
or inherited is an error. Removing an allocation keeps its item and other
|
||
allocations; if live boundary compatibility would break, the transaction MUST
|
||
repair the affected contract explicitly or reject atomically. Artifacts can
|
||
reference the allocation identity independently of the global item.
|
||
|
||
An exchange carrying a specialized item satisfies a declaration of its base,
|
||
never the reverse. Standard provided/required compatibility uses explicit
|
||
interface ancestry. Identity/ancestry, not matching names, defines conformance.
|
||
The current typed function/component port contracts remain unchanged.
|
||
|
||
DataAssociation connects Record types without adding fields or transitively
|
||
carrying payload. Each named end has role, multiplicity and navigability. Source
|
||
multiplicity counts source instances per target instance and vice versa; it is
|
||
not a count of model elements. An end's navigable flag permits navigation toward
|
||
that end. Self-associations are valid; if both ends are navigable they require
|
||
distinct nonempty roles. Empty roles and duplicate role contracts warn, whereas
|
||
invalid ranges reject. Composition/shared aggregation, multiple inheritance,
|
||
redefinition, instance literals and arbitrary-precision decimal arithmetic are
|
||
outside this bounded contract.
|
||
|
||
This complete data contract example is also exercised through the REST API:
|
||
|
||
.. code-block:: text
|
||
|
||
arcadia 4;
|
||
project engineering_data "Engineering data" {
|
||
sa_data_type voltage "Voltage" {
|
||
definition { Real { minimum 0.0; maximum 48.0; }; };
|
||
default { Real 24.0; }; unit "V";
|
||
}
|
||
sa_data_type coordinate "Coordinate" {
|
||
definition { Record { supertype none; }; };
|
||
sa_data_field latitude "Latitude" { type_ref Real; }
|
||
}
|
||
sa_data_type located "Located asset" {
|
||
definition { Record { supertype @coordinate; }; };
|
||
sa_data_field supply "Supply" { type_ref { Named @voltage; }; }
|
||
}
|
||
sa_exchange_item navigate "Navigate" {
|
||
mechanism Operation;
|
||
sa_data_field origin "Origin" { type_ref { Named @coordinate; }; direction In; }
|
||
sa_data_field destination "Destination" { type_ref { Named @coordinate; }; direction In; }
|
||
sa_data_field accepted "Accepted" { type_ref Boolean; direction Return; }
|
||
}
|
||
sa_interface navigation "Navigation" {}
|
||
sa_interface monitoring "Monitoring" {}
|
||
interface_item_allocation nav_operation "Navigation operation" {
|
||
source @navigation; target @navigate; transmission Synchronous; acquisition Accept;
|
||
}
|
||
interface_item_allocation monitor_operation "Monitoring operation" {
|
||
source @monitoring; target @navigate; transmission Asynchronous; acquisition Read;
|
||
}
|
||
data_association location_link "Location relationship" {
|
||
source @coordinate; target @located;
|
||
source_role "location"; target_role "assets";
|
||
source_maximum 1;
|
||
}
|
||
}
|
||
|
||
5. Diagrams, artifacts, and cross-layer traceability
|
||
----------------------------------------------------
|
||
|
||
``diagram`` has name, identity, alias, description, ``layer`` (Oa by default),
|
||
``projection`` (Overview by default), and ``routes`` (empty list by default).
|
||
The string projections are Overview, Decomposition, Allocation,
|
||
FunctionalDataflow, Capabilities, and Traceability. StateMachine is a payload
|
||
constructor with one required ``machine`` reference. Traceability diagrams
|
||
can show both layers; other diagrams show their chosen layer.
|
||
|
||
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. These string projections hide
|
||
inapplicable placements without deleting them or changing semantic records.
|
||
|
||
A StateMachine projection MUST reference an existing StateMachine in the
|
||
diagram's layer. Its placements MUST refer to that machine, its Regions, or
|
||
its state vertices, including nested Regions and vertices. Events, other
|
||
machines and their members, and unrelated semantic elements are not valid
|
||
placements in this view. Empty and partial state views are valid; neither
|
||
creating nor reading a view synthesizes semantic elements or placements.
|
||
Changing an existing diagram to StateMachine, or changing its machine, MUST
|
||
remove or relocate incompatible placements in the same transaction. Context
|
||
errors use ``state_diagram_context``; incompatible placements use
|
||
``state_diagram_member``. Neither case silently hides invalid members.
|
||
|
||
This complete source example places one state from an existing machine:
|
||
|
||
.. code-block:: text
|
||
|
||
arcadia 4;
|
||
project operating "Operating modes" {
|
||
oa_entity crew "Crew" {}
|
||
oa_state_machine modes "Modes" { parent @crew; }
|
||
oa_region main "Main region" { parent @modes; }
|
||
oa_state ready "Ready" { parent @main; }
|
||
diagram mode_view "Operating modes" {
|
||
layer Oa;
|
||
projection { StateMachine { machine @modes; }; };
|
||
}
|
||
node ready_view { diagram @mode_view; element @ready; }
|
||
}
|
||
|
||
The JSON projection is
|
||
``{"StateMachine":{"machine":"11111111-1111-4111-8111-111111111111"}}``,
|
||
where the UUID is the referenced machine's identity. A bare ``"StateMachine"``,
|
||
a missing or null ``machine``, an invalid UUID, or additional payload fields
|
||
is malformed. Existing projections retain their string representation, for
|
||
example ``"Overview"`` in JSON and ``projection Overview;`` in source.
|
||
|
||
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
|
||
no separate placement. Collapsing an owner hides its interior; projected links
|
||
may terminate at a visible ancestor without creating a new port or exchange.
|
||
|
||
``node`` has an alias and identity but no display-name string. Required fields
|
||
are ``diagram`` and ``element`` references. Optional fields are ``position``
|
||
(record with x/y, default 0/0), ``size`` (width/height, default 224/94), and
|
||
``collapsed`` (false), and ``port_anchors`` (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, manual port anchors, and attached artifacts. The destination
|
||
must accept the element's layer, satisfy StateMachine membership when applicable,
|
||
and must not already contain another placement of that element.
|
||
|
||
Each ``port_anchors`` entry is a PortAnchor record with required ``port``
|
||
reference, ``side`` (Left, Right, Top, or Bottom), and ``offset`` (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 ``element``. A port MAY
|
||
have one manual anchor per placement; different diagrams MAY position it
|
||
independently. List order is preserved but has no positional meaning.
|
||
|
||
``offset`` 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 ``[]``.
|
||
|
||
.. code-block:: text
|
||
|
||
node actor_view {
|
||
diagram @architecture; element @vessel;
|
||
port_anchors [{ port @communication; side Top; offset 0.25; }];
|
||
}
|
||
|
||
``SetPortAnchor { diagram, node, anchor }`` upserts by port identity and retains
|
||
unrelated entries. ``RemovePortAnchor { diagram, node, port }`` 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 ``ParseLimits.max_records``.
|
||
|
||
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
|
||
``port_anchors``; their explicit migration supplies an empty list.
|
||
|
||
Each ``routes`` entry is an EdgeRoute record with a required ``edge`` reference
|
||
to an existing Relation or Trace, ``waypoints`` (default ``[]``), and ``label``
|
||
(default ``none``). 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.
|
||
|
||
.. code-block:: text
|
||
|
||
routes [
|
||
{ edge @report_exchange;
|
||
waypoints [{ x 420; y 260; }, { x 690; y 260; }];
|
||
label { fraction 0.55; offset { x 0; y -16; }; };
|
||
}
|
||
];
|
||
|
||
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
|
||
``fraction`` (finite binary32 from 0 through 1, measured along the computed
|
||
polyline's arc length) and ``offset`` (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 ``ParseLimits.max_records``; pinned
|
||
points are bounded by the per-route limit and aggregate input byte limits.
|
||
|
||
``SetEdgeRoute { diagram, route }`` upserts an entry by edge identity, retaining
|
||
the order and contents of unrelated entries. ``RemoveEdgeRoute { diagram, edge }``
|
||
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 ``EditNode`` and source position edits are exact
|
||
record edits and do not implicitly translate pins.
|
||
|
||
This is an additive schema-3 field. Earlier schema-3 JSON/source that omits
|
||
``routes`` 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 ``edge @alias`` 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.
|
||
|
||
``artifact`` has name, identity, alias, description, required ``owner`` ref,
|
||
``relation`` (References, Satisfies, Verifies, Implements, DerivedFrom;
|
||
default References), ``uri`` (default empty), ``revision`` (optional string),
|
||
and ``fragment`` (optional string). The two optional strings default to none.
|
||
URI must be nonempty, have no whitespace/backslash/control characters, and
|
||
use valid percent escapes. The owner is another existing model object.
|
||
Validation MUST NOT fetch the URI. Revision and fragment are retained verbatim.
|
||
|
||
``trace`` has name, identity, alias, description, required ``oa`` and ``sa``
|
||
endpoint references, ``kind`` (default Refinement), and ``baseline`` (default
|
||
none). Endpoints are canonical: SA realizes OA, regardless of which side
|
||
initiated creation. Trace does not change endpoint identity or containment.
|
||
Multiple distinct counterparts are permitted; duplicate endpoint/kind triples
|
||
are invalid.
|
||
|
||
.. list-table:: Trace kinds
|
||
:header-rows: 1
|
||
:widths: 23 77
|
||
|
||
* - Kind
|
||
- OA → SA endpoint types
|
||
* - Refinement
|
||
- Activity → Function
|
||
* - Participant
|
||
- Entity/Actor → System/Actor
|
||
* - Capability
|
||
- Operational Capability → System Capability
|
||
* - Mission
|
||
- Operational Mission → System Mission
|
||
* - Exchange
|
||
- Interaction relation → FunctionalExchange relation
|
||
* - Sequence
|
||
- Process → FunctionalChain, or paired occurrence contributions directly owned by Process / FunctionalChain
|
||
* - Item
|
||
- Same shared kind: ExchangeItem, DataType, DataField, Interface, or Port
|
||
* - Scenario
|
||
- Same shared kind: Scenario, Lifeline, or Occurrence
|
||
* - State
|
||
- Same shared kind: StateMachine, Region, any StateKind vertex, or Event
|
||
* - Manual
|
||
- Engineer-defined relationship between OA/SA elements or relations
|
||
|
||
A nonempty baseline is ``{ oa { name "..."; description "..."; };
|
||
sa { name "..."; description "..."; }; }``. It records last-reviewed names
|
||
and descriptions, not a full structural snapshot. Implementations MUST NOT
|
||
present it as structural synchronization or a lossless inverse transition.
|
||
Explicit counterpart creation, linking, comparison, and reviewed property
|
||
update may start in either layer. Ordinary edits MUST NOT automatically
|
||
overwrite the counterpart. Deletion MUST NOT silently cascade across layers.
|
||
|
||
Operational Capability normally creates a System Capability. Operational Mission
|
||
and System Mission are default counterparts in both directions and use Mission
|
||
traces. An explicit Operational Capability ↔ System Mission mapping remains
|
||
supported with a Manual trace; a uniquely linked such counterpart is reused
|
||
instead of silently creating a different mapping. Required/subtree process and
|
||
chain transitions include their contextual links, owned contributions and
|
||
referenced dependencies. New process/chain contribution mappings use Sequence
|
||
traces; older Scenario-kind occurrence mappings remain accepted. The current
|
||
name/description baseline does not reconcile later topology changes.
|
||
|
||
Name and description are compared independently against each endpoint's
|
||
last-reviewed baseline. An unchanged source MUST NOT overwrite an accepted
|
||
different target value. A source-only change proposes an update; different
|
||
changes on both sides require an explicit decision to take the source, keep
|
||
the target, or enter a merged value. An explicit decision records both current
|
||
values as reviewed, even when they differ. A target-only edit is preserved
|
||
without advancing that field's baseline, so it remains eligible to propagate
|
||
in the reverse direction. Equal current values can be recorded as converged.
|
||
|
||
6. Text grammar and resolution
|
||
------------------------------
|
||
|
||
The input is UTF-8 without a byte-order mark. LF, CR, space, and tab separate
|
||
tokens. ``//`` starts a comment through the next LF or end of input. Quoted
|
||
strings use JSON string escaping, including ``\n``, ``\r``, ``\t``, ``\\``,
|
||
and Unicode escapes. Literal unescaped newlines inside strings are invalid.
|
||
Numbers use JSON decimal/exponent syntax; NaN, infinity, hexadecimal numbers,
|
||
leading plus signs, and leading zeroes are invalid.
|
||
|
||
Aliases match ``[A-Za-z_][A-Za-z0-9_]*``. The following aliases are reserved:
|
||
arcadia, project, id, oa, sa, element, relation, diagram, node, artifact,
|
||
trace, body, alias, name, description, parent, from, to, entity, actor,
|
||
activity, capability, process, allocation, interaction, contribution,
|
||
realization, position, steps, true, false, null. Other field/constructor
|
||
spellings can be used in alias positions because references begin with ``@``.
|
||
|
||
The grammar below uses ``*`` for repetition and ``?`` for optional syntax.
|
||
``element-kind`` and ``relation-kind`` are exactly the corresponding declaration
|
||
keywords listed above. Typed field
|
||
sets and enum constructors are closed by sections 3–5.
|
||
|
||
.. code-block:: text
|
||
|
||
document = "arcadia" "4" ";" project
|
||
project = "project" alias string identity? "{" project-entry* "}"
|
||
project-entry = "description" string ";" | declaration
|
||
declaration = element
|
||
| (relation-kind | "diagram" | "artifact" | "trace")
|
||
alias string identity? fields
|
||
| "node" alias identity? fields
|
||
element = element-kind alias string identity? element-body
|
||
element-body = "{" (field-name value ";" | element)* "}"
|
||
identity = "id" uuid-string
|
||
fields = "{" (field-name value ";")* "}"
|
||
value = string | number | "true" | "false" | "none"
|
||
| enum-word | "@" alias | list | fields
|
||
list = "[" (value ("," value)*)? "]"
|
||
|
||
The project description defaults to empty and may appear once. There is no
|
||
semicolon after a declaration or project closing brace. Every field inside a
|
||
record ends with a semicolon, including fields whose values are nested records.
|
||
Trailing list commas are invalid. Fields may appear in any order.
|
||
|
||
UUID strings use 8-4-4-4-12 hexadecimal spelling, with uppercase or lowercase
|
||
hexadecimal accepted. Canonical output uses lowercase. Omitting an identity
|
||
creates a fresh UUID for that parse. After Apply, accepted source includes the
|
||
generated identity. Authors must keep identity clauses to preserve existing
|
||
objects across subsequent edits.
|
||
|
||
All declaration aliases are collected before references resolve, so forward
|
||
references are legal, including references to nodes and diagrams. Unknown
|
||
``@alias`` values are errors at their reference occurrence. Quoted UUIDs and
|
||
bare words cannot substitute for reference-valued fields. Alias resolution
|
||
produces UUID references; the alias itself remains stored on its declaration.
|
||
Changing an alias in source requires updating its uses. Display names never
|
||
resolve references.
|
||
|
||
Unknown fields, duplicate fields, incompatible constructor payloads, unsupported
|
||
enum spellings, duplicate aliases/identities, and structural validation errors
|
||
reject the entire candidate. No declaration silently replaces another.
|
||
Ordinary string fields require quoted strings and cannot contain an unquoted
|
||
``@alias`` 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.
|
||
|
||
6.1. Modular source projects
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
The pure ``source_project`` core API compiles a virtual source bundle, containing
|
||
``entry`` and a ``files`` map from logical paths to UTF-8 strings. Its entry is a
|
||
root-level ``.arcadia`` file with the source4 project header above. A project entry
|
||
MAY also be ``include string ";"``. 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 at document level,
|
||
never inside an element body or typed field value. For example::
|
||
|
||
arcadia 4;
|
||
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";
|
||
}
|
||
|
||
An include path is relative to its containing file. ``.`` and ``..`` 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
|
||
``.arcadia`` 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.
|
||
|
||
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. The native loader is responsible
|
||
for translating a directory into this explicit bundle and enforcing physical
|
||
path ownership; the pure compiler grants no filesystem access.
|
||
|
||
``inspect_includes(path, source, is_entry, limits)`` 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.
|
||
|
||
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.
|
||
|
||
``ProjectLimits`` adds file, include-depth and include-edge budgets to the existing
|
||
``language::ParseLimits``. 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.
|
||
|
||
``compile_bundle`` returns either located errors and no candidate, or a
|
||
``CompiledSourceProject`` with the validated ``DecodeResult``, stabilized bundle,
|
||
derived ``SourceIndex`` 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.
|
||
|
||
Bundle diagnostics wrap the existing Diagnostic with a logical path and optional
|
||
related locations. Declaration spans, own-field value spans, lexical owners,
|
||
declaration bodies, project header/body/description spans and resolved includes are available in
|
||
the source index. Columns remain one-based Unicode scalars within the real file;
|
||
spans never refer to concatenated or synthetic source.
|
||
|
||
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 explicit migration. Modular projects accept source3 and source4;
|
||
source3 is upgraded as one project, preserving file paths, includes, nested
|
||
ownership and comments through targeted token edits. Generated allocation
|
||
declarations stay in their interface's existing file. Individual include fragments
|
||
are not independently migrated. Missing UUIDs stabilize before migration so new
|
||
allocation identities are deterministic on subsequent compilation.
|
||
|
||
6.2. Nested element ownership
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
An element body MAY contain element declarations interleaved with its ordinary
|
||
fields. Its immediate enclosing element is its lexical owner. For example::
|
||
|
||
sa_actor harbor "Harbor operator" {
|
||
sa_port radio "Radio" {
|
||
contract { Component { kind Standard; orientation Unset; }; };
|
||
}
|
||
}
|
||
|
||
Nesting expresses semantic ``Element.parent`` only. It does not allocate a
|
||
function to an actor or System, deploy equipment, or add or reorder occurrence
|
||
references in an owner's explicit ``steps`` list. Those relationships retain
|
||
their explicit records and fields. The
|
||
same parent-kind, layer and acyclicity constraints apply as for flat source.
|
||
Only element declarations can nest: relations, diagrams, placements, artifacts,
|
||
traces and include directives remain at document level. A typed record value
|
||
contains fields, never element declarations.
|
||
|
||
If a nested declaration omits ``parent``, it inherits its lexical owner's UUID.
|
||
An explicit ``parent`` MUST reference that owner; another reference or ``none``
|
||
is an error located at the parent value. At document level, omitted ``parent``
|
||
means ``none`` and explicit parent references retain their existing meaning.
|
||
Nesting creates no alias namespace. Aliases and UUIDs remain globally unique,
|
||
and references can target nested declarations before or after their definition
|
||
or from another included file. Identity stabilization inserts missing UUIDs in
|
||
nested headers just as it does in document-level headers.
|
||
|
||
Source positions distinguish each declaration's own fields from its descendants'
|
||
fields. A declaration's body span encloses its lexical children as well as its
|
||
own fields. An inherited parent has no synthetic source token or field span.
|
||
Located diagnostics and editor navigation MUST address real source bytes.
|
||
|
||
7. Canonical output and source tooling
|
||
--------------------------------------
|
||
|
||
For every structurally valid Project P, parsing its canonical output MUST
|
||
reproduce P, and canonicalizing that result MUST be idempotent:
|
||
|
||
.. code-block:: text
|
||
|
||
parse(format(P)) == P
|
||
format(parse(format(P))) == format(P)
|
||
|
||
Equality includes all persistent fields, stored aliases, body variants,
|
||
references, placements, artifacts, trace baselines, and ordered occurrences.
|
||
Map order is irrelevant. The writer preserves signed coordinate zero and
|
||
emits decimals that recover the original binary32 value.
|
||
|
||
Canonical output uses LF, four-space indentation, explicit identities,
|
||
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.
|
||
|
||
Comments and input whitespace are lexical trivia to the canonical writer.
|
||
Canonical export does not preserve them. The source-project editor and compiler
|
||
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, collapse state, and manual port anchors inside
|
||
NodePlacement are model data.
|
||
|
||
The pure ``format_bundle`` exporter uses the same typed declaration writer as
|
||
``format``. 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, ``compile_bundle(format_bundle(P)).decoded.project == P``
|
||
when the caller supplies sufficient admission budgets.
|
||
|
||
``update_bundle(compiled, P, limits)`` is a core source update facility. It
|
||
checks that the compiled document/index/model snapshot still agrees, preserves
|
||
untouched document bytes, and recompiles the result before returning it. Flat
|
||
declarations retain their document-level position and file when reparented.
|
||
Nested declarations move into their new semantic owner's body, across files if
|
||
necessary; becoming a root moves them to document level. New children prefer
|
||
their owner's body. 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.
|
||
|
||
A moved declaration carries its contiguous leading comment block and comments
|
||
following its closing brace on the same line. A blank line separates a comment
|
||
block from the following declaration; such gap comments stay in the enclosing
|
||
scope. Comments trailing a preceding field likewise stay with that field.
|
||
Deletion retains annotations in the nearest surviving original scope and
|
||
separates them from adjacent declarations with blank lines. Surviving descendants
|
||
move with an enclosing declaration unless their own semantic parent changes;
|
||
independent parent and child moves are resolved together. Leading whitespace
|
||
adjusts to the destination scope; other token spelling remains authored.
|
||
|
||
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
|
||
``@`` 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.
|
||
|
||
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.
|
||
|
||
List entries use stable referenced UUIDs, message-value ``field`` references or
|
||
lifeline-binding ``referenced`` 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.
|
||
|
||
Retained declaration UUIDs remain unchanged unless explicitly edited. Source
|
||
ownership remains unchanged except for the nested relocation rules above.
|
||
Records match by UUID, not display name or alias. The model-only ``update_bundle`` treats an
|
||
explicit UUID replacement as removal and creation. The desktop instead uses
|
||
``update_bundle_with_identity_map`` with the surviving-record provenance from
|
||
``prepare_command``: explicit identity edits and sequential identity swaps MUST
|
||
preserve each original declaration's owning file and attached source trivia,
|
||
unless the same edit changes its nested semantic parent and requires relocation.
|
||
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. Equal model values do not imply a no-op if command
|
||
provenance removes or replaces a declaration; the resulting model and source
|
||
bundle together determine whether the accepted state changed.
|
||
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.
|
||
|
||
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-project`` endpoints exchange the accepted
|
||
bundle with all its files. One revision and ETag protect the model and source
|
||
together, including source-only comment edits; stored envelopes contain both.
|
||
Canonical ``source`` endpoints remain explicit model interchange. The precise
|
||
transport, admission and persistence contract is in ``api.rst``.
|
||
|
||
``parse`` 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
|
||
contain severity (Error or Warning), a code identifying the diagnostic category,
|
||
optional object UUID and field path, a message, one-based line and Unicode-scalar
|
||
column, and a half-open UTF-8 byte Span. Tabs count as one scalar; LF advances
|
||
the line. Structural errors and engineering warnings point to a relevant
|
||
declaration or field when available. Clients MUST use severity/code rather than
|
||
parse the human message; diagnostic wording is not a stable machine API.
|
||
|
||
``parse_limited`` and ``decode_limited`` accept caller admission budgets for
|
||
input bytes, graph objects, total persistent records and ordered step references.
|
||
Counts MUST be checked before expensive structural validation; migration budgets
|
||
include generated records before migration. Exceeding a budget does not mutate
|
||
the model. Admission limits are host capacity policy, not hidden restrictions
|
||
on otherwise valid language semantics; ordinary ``parse`` has no such model
|
||
size policy. The REST service's fixed policy is specified in ``api.rst``.
|
||
|
||
``tokenize`` is tolerant: it covers every input byte with nonoverlapping
|
||
TokenSpans, including incomplete strings and invalid characters. Token classes
|
||
are Keyword, Identifier, String, Number, Comment, Punctuation, Whitespace,
|
||
and Error. ``@`` is punctuation followed by the referenced alias token.
|
||
``lint`` returns syntax, structural and engineering warning diagnostics for the
|
||
current draft without adopting a model. A valid unallocated SA function, for
|
||
example, can report missing System and allocation warnings before Apply.
|
||
``analyze``
|
||
combines tokens, diagnostics, and declaration spans with alias, optional
|
||
explicit UUID, and declaration kind. A malformed later declaration does not
|
||
erase earlier declaration spans. None of these APIs mutates a session.
|
||
|
||
8. Graphical parity and transactional editing
|
||
---------------------------------------------
|
||
|
||
The graphical editor MUST expose all persistent properties through typed
|
||
controls, including optional references, lists, variant constructors, aliases,
|
||
IDs, nested parent changes, diagram placements, artifact metadata, and trace
|
||
baselines. Inspector controls may provide operations unavailable as a canvas
|
||
gesture. Exact strings, including tabs and line breaks in names, must remain
|
||
editable through an appropriate escaped-string input when ordinary widgets
|
||
cannot represent them.
|
||
|
||
A move into a functional parent, an allocation onto a performer, and a diagram
|
||
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.
|
||
|
||
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.
|
||
|
||
Source and property drafts contribute to unsaved-work state. Invalid drafts
|
||
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 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.
|
||
|
||
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
|
||
leaving dangling references. Deleting a sequence does not delete the semantic
|
||
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.
|
||
|
||
9. Persistence and explicit migration
|
||
-------------------------------------
|
||
|
||
Loading detects JSON from its first non-whitespace ``{``; other input is parsed
|
||
as Arcadia source regardless of filename. Saving an ``.arcadia`` suffix uses
|
||
the accepted V4 source bundle (``arcadia 4``); other suffixes use V4 JSON. Both forms preserve the same
|
||
complete model. JSON rejects unknown fields throughout typed payloads,
|
||
duplicate maps, unsupported versions, and structural errors.
|
||
|
||
The schema-3 reader freezes the changed data payloads and old constructor catalog;
|
||
schema-4 fields/constructors MUST NOT be silently accepted as schema 3. Existing
|
||
typed PortContract records remain unchanged. Information/Material/Energy retain
|
||
their nature with Unspecified mechanism; old Event becomes Information with Event
|
||
mechanism. Old bounds/defaults/supertypes are absent, String length is 0..unbounded,
|
||
and fields retain type/multiplicity/unit with Unspecified direction, Value storage
|
||
and no explicit default. No physical mechanism or direction is guessed.
|
||
|
||
Each old Interface.items entry generates one InterfaceItemAllocation with its
|
||
original zero-based order and Unspecified protocols. UUID v5 uses the project UUID
|
||
namespace and name ``v2-interface-item:<interface-uuid>:<item-uuid>`` consistently
|
||
for schema-2 and schema-3 inputs. Aliases are deterministic and collision-free;
|
||
collision with any existing identity is an error rather than an overwrite. Existing
|
||
interface/item identities remain intact. Old nested message values acquire a path
|
||
only when exactly one valid path exists. Ambiguous paths, including recursive
|
||
reuse, retain the old annotation with a located warning rather than guessing.
|
||
|
||
Migration reports additionally contain ``semantic_defaults`` (object, field,
|
||
description), ``generated_interface_allocations`` (id, source, target, alias,
|
||
order) and ``unresolved_message_values`` (occurrence, field, reason). These new
|
||
report arrays default empty when reading older responses. Version 1 normalizes
|
||
through V2, then the typed-port V3 adapter and this shared V4 data upgrade. Original
|
||
V2 and real V3 fixtures remain unchanged compatibility inputs. Current exports
|
||
always use version 4; reading/migrating alone never saves or changes revisions.
|
||
|
||
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.
|
||
|
||
The frozen schema-2 reader retains staged compatibility defaults. Old Scenario bodies without a
|
||
``viewpoint`` retain MixedLegacy, and old Exchange occurrence bodies without
|
||
``message_kind``, ``reply_to`` or ``values`` retain Asynchronous, none and [].
|
||
Old StateTransition bodies without ``transition_kind``, ``triggers`` or
|
||
``effects`` retain External, [] and []; existing ``trigger``, ``guard`` and
|
||
``effect`` strings are preserved exactly. Source declaration defaults and JSON
|
||
compatibility defaults MUST agree; no event or work reference is inferred from
|
||
legacy prose.
|
||
This compatibility applies equally to source and JSON. It adds explicit
|
||
defaults without changing any prior identity, name, reference, order, geometry,
|
||
artifact or trace field. The original V2 golden source/JSON in
|
||
``crates/oa-core/tests/fixtures`` MUST NOT be regenerated from the newer demo;
|
||
they verify that every old persistent field survives. Canonical output writes
|
||
the added defaults through the explicit schema-3 and schema-4 migrations.
|
||
|
||
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 ``v2-fe-port:<fe-id>:source`` or ``v2-fe-port:<fe-id>:target``. 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 ``oriented true``; no
|
||
PortAllocation is inferred.
|
||
|
||
``decode_with_report``, ``load_with_report`` 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 4. Model/source exports contain only the canonical model. Migration
|
||
reports are transient response metadata, not persisted model facts.
|
||
|
||
Admission checks account for generated objects and their references before
|
||
construction. Both the old V2 contract and the resulting V4 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 these same V2-to-3-to-4 stages.
|
||
|
||
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
|
||
and crash recovery are outside this storage contract.
|
||
|
||
Version 1 text and JSON are accepted through an explicit adapter. Migration
|
||
preserves project, element, and relation UUIDs; names and descriptions; relation
|
||
endpoints; all coordinates; and exact process exchange order and repetition.
|
||
Allocation and Interaction remain their corresponding V2 relations.
|
||
Contribution becomes CapabilityInvolvement; the old Process-to-Capability
|
||
Realization becomes ChainInvolvement, retaining its ID and name.
|
||
|
||
Legacy positions become nodes in one OA Overview diagram. Each old process
|
||
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 V4 result, including repeated occurrences.
|
||
No System or SA content is invented during an OA-only migration.
|
||
|
||
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
|
||
V4 projects. Future versions remain errors until a separate migration exists.
|
||
|
||
10. Complete authoring example
|
||
------------------------------
|
||
|
||
This document intentionally omits IDs for new authoring. Apply and Save write
|
||
the assigned UUIDs explicitly.
|
||
|
||
.. code-block:: text
|
||
|
||
arcadia 4;
|
||
project harbor "Harbor assistance" {
|
||
oa_entity control "Harbor control" {}
|
||
oa_activity assess "Assess assistance" {}
|
||
allocation performs "Performs" {
|
||
source @control;
|
||
target @assess;
|
||
}
|
||
sa_system service "Harbor assistance system" {}
|
||
sa_function evaluate "Evaluate assistance request" {}
|
||
allocation system_performs "Performs" {
|
||
source @service;
|
||
target @evaluate;
|
||
}
|
||
trace assessment_trace "Operational realization" {
|
||
oa @assess;
|
||
sa @evaluate;
|
||
kind Refinement;
|
||
}
|
||
diagram operational_view "Operational allocation" {
|
||
layer Oa;
|
||
projection Allocation;
|
||
}
|
||
node assessment_card {
|
||
diagram @operational_view;
|
||
element @assess;
|
||
position { x 360; y 70; };
|
||
}
|
||
}
|
||
|
||
11. Verification and primary references
|
||
---------------------------------------
|
||
|
||
``cargo test -p oa-core --test language --locked`` verifies typed round-trips,
|
||
stable aliases, strict syntax/reference failures, Unicode source spans,
|
||
deterministic V1 migration, occurrence identity, coordinate bits, persistence,
|
||
and model-history integration. Core validation and session tests cover domain
|
||
mutation rules; native UI and API verification are separate evidence.
|
||
|
||
The research record in ``docs/research-v2-semantics.md`` distinguishes method
|
||
requirements from Studio design choices and links to original UI evidence.
|
||
The following sources inform this language without extending its scope:
|
||
|
||
* `Arcadia Q&A <https://mbse-capella.org/arcadia-qna.html>`_
|
||
* `Arcadia language reference <https://mbse-capella.org/resources/arcadia-reference/Arcadia%20Language%20-%20MetaModel.pdf>`_
|
||
* `Capella allocation guide <https://github.com/eclipse-capella/capella/blob/master/doc/plugins/org.polarsys.capella.ui.doc/html/05.%20Diagram%20Management/Allocating%20Functions%20on%20Components.mediawiki>`_
|
||
* `Capella iterative transitions <https://github.com/eclipse-capella/capella/blob/master/doc/plugins/org.polarsys.capella.transitions.doc/html/11.%20Iterative%20Transitions/11.1.%20Concepts.mediawiki>`_
|
||
* `W3C XML 1.0 characters <https://www.w3.org/TR/xml/#charsets>`_
|