1158 lines
63 KiB
ReStructuredText
1158 lines
63 KiB
ReStructuredText
Arcadia Studio OA / SA Language and Editing Contract
|
||
====================================================
|
||
|
||
:Version: 3
|
||
: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 and 2. MUST, MUST NOT,
|
||
and MAY indicate requirements, prohibitions, and permitted choices.
|
||
|
||
Schema 3 introduces typed function and component ports, required functional
|
||
exchange endpoints, independently oriented boundary exchanges, and explicit
|
||
PortAllocation relations. First-release scenario/state additions remain in
|
||
scope; this schema change does not declare native acceptance or the wider
|
||
release complete. The preserved schema-2 reader validates the original
|
||
contract before migration.
|
||
|
||
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`` (3), ``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``). 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, Event
|
||
- Information
|
||
* - ``oa_data_type``, ``sa_data_type``
|
||
- ``definition``: Boolean, Integer, Real, String, Record, or Enumeration constructor
|
||
- String
|
||
* - ``oa_data_field``, ``sa_data_field``
|
||
- ``type_ref``; ``minimum``: u32; ``maximum``: optional u32; ``unit``: string
|
||
- String; 1; 1; ``""``
|
||
* - ``oa_interface``, ``sa_interface``
|
||
- ``items``: exchange-item refs
|
||
- ``[]``
|
||
* - ``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
|
||
* - ``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.
|
||
|
||
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 3;
|
||
project ports_example "Typed function contract" {
|
||
sa_function send "Send" {}
|
||
sa_function receive "Receive" {}
|
||
sa_exchange_item payload "Payload" {}
|
||
sa_interface old_service "Preserved service" { items [@payload]; }
|
||
sa_port output "Output" {
|
||
parent @send;
|
||
contract { FunctionOutput { outgoing_items [@payload]; }; };
|
||
}
|
||
sa_port input "Input" {
|
||
parent @receive;
|
||
contract { FunctionInput { incoming_items [@payload]; }; };
|
||
}
|
||
functional_exchange message "Message" {
|
||
source @send; target @receive;
|
||
source_port @output; target_port @input; items [@payload];
|
||
}
|
||
sa_port preserved "Unresolved original" {
|
||
parent @send; contract Legacy;
|
||
legacy { direction InOut; interface @old_service; };
|
||
}
|
||
|
||
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 ``{ field @data_field; expression "value expression"; }``.
|
||
The field MUST be a DataField carried by the message exchange, including fields
|
||
inside named nested records. At most one annotation for a given field is
|
||
allowed in one message. Values do not overwrite the referenced type or global
|
||
exchange item. Expression text is preserved exactly; 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.
|
||
|
||
5. Diagrams, artifacts, and cross-layer traceability
|
||
----------------------------------------------------
|
||
|
||
``diagram`` has name, identity, alias, description, ``layer`` (Oa by default),
|
||
and ``projection`` (Overview by default). Other projections are Decomposition,
|
||
Allocation, FunctionalDataflow, Capabilities, and Traceability. 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. Changing the projection hides
|
||
inapplicable placements without deleting them or changing semantic records.
|
||
|
||
Ports are calculated boundary anchors of visible owners, with their existing
|
||
semantic identity. An explicitly placed port is not rendered as a separate
|
||
large node. Functional exchanges use their declared source/target ports;
|
||
boundary exchanges attach to their participant ports even if those ports have
|
||
no separate placement. Collapsing an owner hides its interior; projected links
|
||
may terminate at a visible ancestor without creating a new port or exchange.
|
||
|
||
``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). Node identity is independent of its semantic element.
|
||
Coordinates are absolute diagram coordinates. Placement does not alter parent,
|
||
allocation, or realization. Hiding an element from a diagram must remain
|
||
distinguishable from deleting it from the model.
|
||
Changing a node's diagram preserves the placement identity, alias, coordinates,
|
||
size, collapse state, and attached artifacts. The destination must accept the
|
||
element's layer and must not already contain another placement of that element.
|
||
|
||
``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.
|
||
``kind`` is exactly an element/relation keyword listed above. Typed field
|
||
sets and enum constructors are closed by sections 3–5.
|
||
|
||
.. code-block:: text
|
||
|
||
document = "arcadia" "3" ";" project
|
||
project = "project" alias string identity? "{" project-entry* "}"
|
||
project-entry = "description" string ";" | declaration
|
||
declaration = (kind | "diagram" | "artifact" | "trace")
|
||
alias string identity? fields
|
||
| "node" alias identity? fields
|
||
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, canonical text 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 source3 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 source3 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 between declarations,
|
||
never inside a typed field value. For example::
|
||
|
||
arcadia 3;
|
||
project rescue "Rescue" id "00000000-0000-4000-8000-000000000001" {
|
||
description "Operational model";
|
||
include "oa/participants.arcadia";
|
||
include "oa/activities/activity_respond.arcadia";
|
||
include "views/diagram_operational.arcadia";
|
||
}
|
||
|
||
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. A future native loader is responsible
|
||
for translating a directory into this explicit bundle and enforcing physical
|
||
path ownership; the pure compiler grants no filesystem access.
|
||
|
||
``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, top-level field value spans, project
|
||
header/body/description spans and resolved include locations are available in
|
||
the source index. Columns remain one-based Unicode scalars within the real file;
|
||
spans never refer to concatenated or synthetic source.
|
||
|
||
Single-string parse/lint APIs remain filesystem-free and reject include
|
||
statements with an explicit source-bundle requirement. V1/V2 single-file imports
|
||
continue through their existing migration readers and reports. Modular projects
|
||
require source3; migration is performed before modular export, not independently
|
||
on included fragments. Modular source does not change the semantic JSON schema.
|
||
|
||
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 and the current desktop single-document Apply path do not
|
||
preserve them; the editor MUST explain that behavior. This existing path does not
|
||
define an acceptable lossless authoring policy for a future project editor.
|
||
The pure project compiler in section 6.1 preserves them while inserting missing
|
||
identities. Project update/export distinctions are described below.
|
||
Camera position, selection, source cursor, and undo history are not stored
|
||
model fields. Layout and collapse state inside NodePlacement are model data.
|
||
|
||
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
|
||
existing declaration file ownership and all untouched document bytes, and
|
||
recompiles the result before returning it. New children inherit their owner's
|
||
file; new roots use canonical module rules and add an explicit entry include.
|
||
Removed declarations do not delete source files. Alias changes also update
|
||
declarations containing references to that alias. Invalid or stale updates
|
||
return errors without mutating the input workspace.
|
||
|
||
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 and source ownership remain unchanged. Records match
|
||
by UUID, not display name or alias; an explicit UUID replacement is a removal
|
||
and creation, retaining the removed record's comments in its original file. The
|
||
result is recompiled, reindexed and checked for equality with the requested
|
||
model before return. Source changes needed for undo are workspace history data;
|
||
callers should retain complete compiled workspace snapshots rather than infer
|
||
past omission/layout choices from a model-only undo.
|
||
|
||
Canonical modular export is a distinct, explicit operation and does not promise
|
||
original comment/layout preservation. No native multi-file editor, project save
|
||
transaction or REST bundle endpoint is claimed by the pure core APIs.
|
||
|
||
``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 complete source is one model transaction. Graphical edits regenerate
|
||
the matching canonical source. Both paths validate their candidate 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, including aliases, trace links, and occurrence identity.
|
||
|
||
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
|
||
canonical V3 text (``arcadia 3``); other suffixes use V3 JSON. Both forms preserve the same
|
||
complete model. JSON rejects unknown fields throughout typed payloads,
|
||
duplicate maps, unsupported versions, and structural errors.
|
||
|
||
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 migration.
|
||
|
||
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 3. 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 V3 graph are
|
||
validated. Migration itself does not save or increase a stored revision.
|
||
Canonical second saves are stable. V1 normalization produces the frozen V2
|
||
model and then uses this same V2-to-3 stage.
|
||
|
||
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 V3 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
|
||
V3 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 3;
|
||
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>`_
|