9.6 KiB
Architecture and extension guide
The normative contract is language.rst; scope.md explains deliberate differences from the complete Arcadia/Capella ecosystem. V2 uses one typed model and one validated mutation boundary across the desktop, text editor and REST service.
Crate boundaries
| Crate | Responsibility | Does not depend on |
|---|---|---|
oa-core |
Model, structural/completeness rules, commands/history, reference maintenance, diagram projection, OA/SA transitions, text and file persistence | Iced, renderer, HTTP or native UI |
oa-desktop |
Iced events/state, property and source drafts, graphical views, file interactions | Server availability or an account |
oa-server |
HTTP contract, authentication/admission, resource revisions and atomic current-model storage | Iced or a desktop session |
The server reuses the same core library as the desktop. A new automation endpoint must produce a core command/candidate rather than implement a second version of domain rules. Desktop and server are separate storage clients: there is currently no desktop HTTP adapter. Canonical source/JSON import/export is the explicit integration path.
Model, identity and references
model.rs defines Project maps for typed Elements, Relations, Diagrams, Traces and ArtifactLinks. Each diagram owns NodePlacements. All records share one UUID/alias namespace. UUIDs are durable reference identity; stored aliases are stable text labels; display names can change independently or repeat.
Element kind and layer derive from closed OA/SA bodies. Shared typed bodies represent data, interfaces, scenarios, state machines and constraints; payload variants cannot disagree with an independent kind tag. Relations are separate typed records, including relation-to-relation exchange allocation. Sequence occurrences have their own element identity; repeating an exchange uses distinct occurrences. Semantic parent, performer allocation and diagram placement are independent.
references.rs visits stored references for reidentification, deletion cleanup and transition mapping. New reference fields must join these visitors and their regression cases. Reidentification updates map keys, owned records, endpoints, occurrence lists, placement targets, traces and artifact owners atomically. Deleting a sequence does not delete its referenced semantic exchanges. Deleting an OA/SA element does not own or delete its cross-layer counterpart.
Validated transactions and history
session.rs clones a candidate, applies a command or batch, validates the complete result, and adopts it only when valid and changed. Replace(Project) supports full source replacement. Record edits apply drafted properties together; typed operations handle reparenting, placement relocation, grouped movement, ordering and layout. A rejected batch leaves accepted state and history intact. Public builders construct candidates and fixtures; they are not a substitute for final validation.
validation.rs separates structural errors from incomplete-model warnings. Dangling references, wrong kinds/layers, ownership cycles, incompatible ports and invalid uniqueness reject a candidate. Missing allocations, incomplete references and coverage gaps allow continued authoring. Small predicates support parent/relationship choices; they must agree with the committed-model policy.
The desktop retains up to 100 full-model history snapshots and compares against a saved snapshot to compute dirty state. This favors straightforward correctness for modest models. The cost is proportional to model size; indexed validation, persistent collections or delta history should follow profiling, not speculative infrastructure.
Nesting and graphical views
projection.rs derives visible nodes, visual parents and edges from a stored diagram's projection. Decomposition uses semantic ownership; allocation uses direct/effective leaf performers and computed parent summaries. Node positions/sizes/collapse belong to each view, so multiple diagrams can represent the same semantic element independently.
diagram.rs uses the shared projection for drawing, hit testing, Fit, grouped movement and SVG. A placement move never implicitly reparents or reallocates an element. RelocateNode moves a placement between diagrams while retaining its UUID, alias, geometry, collapse and references; validation rejects an incompatible destination or duplicate placement. behavior.rs presents sequence/scenario and state-machine content from the same typed records. UI acceptance is recorded separately from these implementation boundaries.
Counterpart planning
transitions.rs builds a candidate plan from source IDs, direction, dependency scope, explicit mappings and reviewed field decisions. Participant/system-boundary choices remain explicit. Shared content and ownership references map when creating counterparts; ambiguous or incompatible mappings produce conflicts. OA-to-SA traces retain canonical endpoints regardless of which perspective starts the operation.
Existing counterparts receive reviewed name/description changes, not structural synchronization. Per-trace baselines record those reviewed values, including intentional divergence. Ordinary editing never propagates automatically. Apply rejects a stale project fingerprint or unresolved conflict, then uses the same batch validator. Desktop application creates one history entry; the service additionally checks resource revision/ETag before committing. The fingerprint is a deterministic change token, not a security signature.
Keep domain mapping choices in the core or derive UI choices from its queries. Independent desktop match tables can drift from accepted semantics; the V2 review found and corrected this kind of mismatch for fragment construction and capability/mission transition options.
Text and draft state
language.rs provides a lexer/parser, deterministic formatter, tolerant source analysis and explicit V1 adapters. It collects declaration aliases before resolving UUID references, accepts forward references, rejects unknown/duplicate fields and typed-constructor errors, and validates the complete candidate. Canonical arcadia 2 text preserves every persistent field, alias, UUID and ordered occurrence. Comments/whitespace are lexical trivia and normalize on Apply. V1 migration preserves existing identities and derives new placement/occurrence IDs deterministically.
forms.rs is a closed adapter over typed records. JSON values are temporary form structure; incomplete numbers, references and escaped strings stay in drafts until decoding a typed Command. This is not an extensible runtime schema or an alternate persisted metamodel. Every added field needs a usable control and meaningful authoring coverage; a no-op serialization test alone cannot establish graphical reachability.
app.rs coordinates the Session, selection, draft, source buffer/history, active view/camera, workflow dialogs and file state. views.rs renders task navigation and inspectors; workflow.rs handles explicit relationship/manual-trace/counterpart choices. highlight.rs translates tolerant core tokens to source coloring. Source lint runs after a short debounce and ignores obsolete results. Valid Apply commits once; rejected text stays editable with located diagnostics. Text-buffer history is distinct from committed-model history.
File and service persistence
Core persistence detects JSON by content and otherwise parses Arcadia text. .arcadia saves canonical text; other suffixes save strict JSON. A validated snapshot is written to a sibling temporary file, flushed and atomically installed. Normal desktop saves compare the previously read bytes to detect external changes before replacement. This is an optimistic local-file check, not a guarantee against every concurrent writer or power-loss scenario. File tasks run on blocking workers; the desktop preserves drafts and pending New/Open/Close continuations on failure or cancellation.
The service stores one {resource_id, revision, model} envelope per current hosted project. Service identity is immutable and independent of editable model identity. A directory lock enforces one local owner; a store mutex serializes revision checks and writes. Disk replacement precedes in-memory adoption. Authentication, body/admission limits, object/query limits and total store capacity are explicit. No distributed database, retained history, idempotency ledger or automatic artifact fetching is hidden behind this interface. See server.md and api.rst for deployment, error and concurrency behavior.
Extending a supported concept
- Define the semantics, field types, references and both editing obligations in
language.rst; choose migration behavior if the stored schema changes. - Update the closed core model, reference visitors, validation and applicable command/transition/projection behavior.
- Extend parser and formatter together; verify exact round-trip, invalid-input preservation and identity/reference maintenance.
- Expose graphical creation/editing for each field/variant, including optional values and ordering. Keep draft and modal failure paths intact.
- Update the REST/OpenAPI contract for new command or data variants; exercise actual HTTP candidate acceptance/rejection and persistence.
- Run focused domain/interaction tests, strict workspace checks, and native Windows/Linux workflows with visual inspection at supported sizes. Update acceptance evidence only after observing the result.
No runtime plugin ABI, general extension framework or later-layer infrastructure is present. The documented core and REST boundaries provide practical development seams without requiring speculative abstractions.