12 KiB
Bounded coverage diagnostics — decision proposal, 2026-09-06
Read-only design for task 3 in the current coverage audit. No model/schema changes or implementation acceptance. Scope is OA/SA only.
Recommended decision
Add five advisory codes to shared validation, using existing identities and references. They describe missing explicit evidence, not proof of incorrect engineering. All remain Severity::Warning: no rejection of Apply, Save, REST transactions or source compilation solely because of these checks.
The official Arcadia Q&A, “Leaf functions, parent functions?” and “Functional exchanges only on leaf functions?” recommends leaf-level behavioral definition and contextual involvement in finalized models, while recognizing intermediate decomposition work. The exact warning policy below is a Studio design choice; it does not introduce a mandatory Capella conformance test.
| Code / located record and field | Exact trigger and repair |
|---|---|
non_leaf_work_exchange / Interaction or FunctionalExchange, source or target |
The referenced endpoint is work with a direct child of the same work kind. Emit once per affected endpoint. “Choose the leaf activity/function responsible for this exchange.” SA uses the relation's function IDs, not its input/output port IDs; repair must keep port ownership consistent. |
work_without_behavior_context / leaf Activity or Function, record location (field = "") |
No included Action names this work and no included Interaction/FE names it as an endpoint. “Include this leaf in a process/chain or scenario through a work action or exchange occurrence.” |
exchange_without_behavior_context / Interaction or FunctionalExchange, record location |
No included Exchange occurrence names this relation. “Use this exchange in a process/chain or scenario.” Suppress while it has a non-leaf endpoint: first repair the more specific endpoint warning. |
mission_without_capability / OperationalMission or Mission, record location |
No valid outgoing MissionCapability to a capability in its layer. “Connect this mission to a capability that delivers it.” MissionInvolvement is participant responsibility and does not satisfy this check. |
capability_without_behavior_context / Capability or SystemCapability, record location |
Capability has participant/work/role support but no explicit process/chain or scenario context. “Link a process/chain with Chain involvement, or set a scenario's Context to this capability.” Do not emit alongside existing unsupported_capability for the same capability. |
The final code deliberately checks presence of an explicit context, not whether that context is complete. A linked empty chain/scenario has existing empty_sequence and missing-contribution diagnostics; repeating these on the capability would add noise. An isolated leaf capability with no support keeps the existing unsupported_capability warning.
Capability context means either (a) incoming valid ChainInvolvement from a Process/FunctionalChain or (b) an existing same-layer Scenario whose context is this capability. A scenario whose context is a chain already linked to the capability is naturally covered by (a). Narrowly extend the existing unsupported_capability support predicate to recognize (b), so a scenario-only capability is not wrongly called unsupported. No new capability warning is needed on a pure grouping capability with same-kind child capabilities; inspect its children. Capability include/extend/generalization, parent containment, shared performers, mission context and similarly named records do not manufacture a direct context link. The message must say “explicit context,” not “no behavior exists.”
Exact traversal and exclusions
Current seams: model.rs defines OaBody::Process, SaBody::FunctionalChain, SharedBody::Scenario { context, steps, .. }, Element::steps() and the closed OccurrenceBody variants. validation.rs already checks ownership, ordered membership, recursion and reference compatibility. The existing leaf-allocation predicate is kind().is_work() with no p.children(id) child of the same kind; reuse that definition. Build an indexed set of non-leaf work once rather than rescanning all children for every exchange.
Build global covered-work and covered-exchange identity sets in one bounded iterative walk:
- Seed every Process, FunctionalChain and Scenario as a root, even if no capability references it. Coverage asks whether a context exists anywhere in the same project; it does not require every context to serve a capability.
- Follow only identities listed in the owner's
steps(), checking the occurrence's actual parent. For a Fragment follow its explicitbrancheswhose parent is that fragment; for each Branch follow itsoccurrencesthroughsteps(). Do not walk arbitrary descendants: an unordered occurrence is not part of the authored behavior. - For
Exchange { exchange: Some(id), .. }, mark the referenced Interaction/FE and its explicit work endpoints. ForAction { action: Some(id), .. }, mark that referenced Activity/Function. Parent work does not cover its children. Mark identities, not occurrence counts; repeated messages and correlated replies cannot increase or double-count coverage. - Follow
SequenceReference { sequence: Some(id) }only to the same process/chain kind and layer. FollowScenarioUse { scenario: Some(id), .. }to the referenced scenario; ScenarioUse bindings preserve represented identity under current validation and do not substitute different work or exchanges. Visit each container/occurrence ID once. No recursion or per-root transitive-closure materialization. Every referenced sequence is also a root, so reuse does not change global coverage; this explicit treatment prevents later capability-scoped extensions from silently losing reused content. - An explicit work Action counts even when its scenario lifeline is unfinished: the work identity is known, and the existing missing-lifeline warning explains the remaining work. An exchange occurrence likewise counts its known exchange despite missing contextual details. Controls, timer-only occurrences, bare lifelines, State observations, StateAction/Availability links and Scenario.context alone do not mark work/exchanges covered. A state observation on a work lifeline observes state; it does not assert that work contributed. Participant/boundary messages never infer coverage of allocated Interaction/FE records: allocation of a transport is not evidence that every allocated exchange occurs in that scenario.
No warnings for ports, BoundaryExchange, future CommunicationMean, data items, participants, roles, parent work coverage, diagrams or promoted/folded summary edges. Diagram visibility and layout are irrelevant. Allocation/role sharing does not propagate coverage to sibling work. Non-leaf endpoint warnings inspect authored relationships only.
Recommended malformed-candidate policy: run this new completeness pass only when the existing structural validation pass has no Errors. This avoids cascades from dangling references, wrong layers, cycles or invalid ownership; accepted projects and saveable incomplete drafts still receive all new warnings. Keep the walk visited-set guarded regardless. Existing warning-only issues (unordered_occurrence, missing endpoints, empty sequences, topology gaps) do not disable the pass. Ignore incomplete edges with no usable referenced identity.
Existing checks to retain rather than duplicate: unallocated_leaf, unsupported_capability, empty_sequence, unordered_occurrence, incomplete_step, missing_exchange, sequence_gap, isolated_contribution, unreachable_contribution, nonterminating_contribution, sequence_starts/ends, control/guard warnings and recursive-use errors. An unallocated leaf may also lack behavior context: these are distinct repairs.
User location and shared contract
Use Issue.element = Some(record_id), stable code and a real endpoint field or record-level location. Do not fabricate a coverage field absent from the source grammar. source_project::model_diagnostics already maps object/field to its owning file; source lint and REST consume shared validation. views.rs::checks already offers Open on the located identity. Endpoint warnings should open the exchange's properties; coverage warnings open the leaf/exchange or mission/capability and explain the Behavior/Actions repair. No automatic creation, allocation or reassignment is implied.
Warnings must be deterministic by ID and endpoint, share codes/location across GUI/source/JSON/REST, disappear after the stated repair and reappear on Undo. The new helper should be linear in indexed records/references aside from ordered-map lookup costs. It should not call validate() recursively or perform a full graph walk separately for every leaf/capability.
Three acceptance fixtures
-
Valid covered SA, including reuse. One System, one Actor, allocated leaf functions F/G, typed ports and FE E from F to G. Inner chain has an Exchange occurrence E; outer chain reuses inner and has ChainInvolvement to capability C. Mission M has MissionCapability to C. Add a functional scenario with F/G lifelines and repeated E call/reply plus a second scenario reusing it through a branch with identity-preserving bindings. Expected: none of the five new warnings; reuse/repetition does not duplicate facts. Remove E occurrences from every context: F/G and E become uncovered; add an Action F alone: only F's work warning clears, E/G remain. Run an OA counterpart variant with Interaction and Process to prove symmetric layer semantics.
-
Structurally invalid candidate. Starting from fixture 1, make a ScenarioUse cycle, then independently try an FE referencing a missing function and an occurrence listed under the wrong owner. Expected: existing exact structural errors, no new completeness cascade, candidate rejected atomically and accepted model/coverage unchanged. A visited-set traversal must terminate even when invoked directly on these malformed graphs. This fixture does not reinterpret invalid structure as permissible incompleteness.
-
Saveable incomplete OA with exact repair targets. Parent activity P has leaves A/B; independent leaf C. Allocate A/B/C to valid performers. Interaction Eab is A→B and appears in a Process; Ep is P→C and Eca is C→A, neither used in behavior. Mission M has no MissionCapability. Capability Q has only participant involvement. Add a participant scenario with only an observation of C's performer's state and no capability Context. Expected new warnings: Ep/source non-leaf; C uncovered; Eca uncovered; M missing capability; Q missing explicit behavior context. Ep's uncovered-exchange warning is suppressed until its endpoint is repaired. A/B are covered through Eab. Add an unordered occurrence Eca: existing unordered warning appears and coverage stays missing. Put it in ordered steps: Eca and C coverage clear. Repair Ep to A→C with matching source semantics, then include it in the process; link M→Q and process→Q. All five original warnings clear; Undo restores the relevant exact warnings. Repeated/reused Eab must never hide Eca's absence. Separately link an empty chain/scenario to Q: Q's context warning clears while the existing empty-sequence warning remains.
For these fixtures compare code/record/field tuples through core validation, multi-file source lint and real REST; check Save success for fixture 3 and rejection atomicity for fixture 2. Native check Open navigation and repair/Undo at normal and minimum window sizes. These are proposed checks, not completed tests.