10 KiB
S1 contextual analysis projection — proposed final rule, 2026-09-06
Read-only design against current validation.rs::validate_sequence and
validate_topology, the updated S1 contract and its resolver probe. No production
edit, Cargo, simulation or native input. Address, constructor, deletion and
cache-independent admission choices are already ratified; this note resolves the
remaining diagnostic projection.
Decision for X → R1.B
Yes: emit a caller-qualified advisory ambiguous_sequence_branch at
(O, [R1], B) when the resolved authored Precedence inputs are A→B and X→B.
It is a non-control contribution with two incoming precedence links, matching the
current structural heuristic. Do not suppress it because one edge crosses a reuse
boundary. Do not turn it into an error, silently create a Join, edit P, or declare
an execution ambiguous as a proven fact. In particular, the warning does not mean
that X must precede A or that either dependency may be ignored.
Use wording such as: “This contribution has multiple incoming precedence links in this caller context. Review whether explicit merge/join control is needed to describe the intended paths.” The current generic alternative/parallel wording is too strong if presented as a theorem about a caller's additional constraint. The engine checks graph shape; it does not evaluate guards or model token flow.
Standalone P remains A→B→C with no new warning, and R2.B has one incoming link. The qualified warning belongs to caller O, with breadcrumb R1/B and the two link identities. It must not appear as an unqualified defect on B's shared definition. The engineer may retain the advisory if independent precedence constraints are intentional; resolving it is not a prerequisite for saving this valid relationship.
This preserves Studio's existing non-control fan-in/fan-out advisory convention. It is a design choice, not a claim that Capella mandates the same warning. The official guide establishes precedence/conditions and distinguishes assembly incidence, but does not specify Studio's completeness algorithm. Primary guide, Sequencing and Control / Assembling Functional Chains.
Three deterministic projections
- Precedence: existing SequenceLink plus ContextualLink::Precedence. Keep distinct authored link IDs, guard text and qualified endpoints. Existing control-cardinality, missing-guard and non-control degree rules inspect these edges, never assembly incidence. Distinct authored parallel links still count separately as today; memoization must not collapse different guards/link IDs.
- Assembly incidence: ContextualLink::Exchange and CommonWork retain typed source/target addresses and the engineering exchange/work identity. They are available for drawing, selection and connectivity inspection, but add no precedence arc, control branch, execution merge or unique-entry claim. Do not introduce a new assembly-completeness ruleset in this slice.
- Coverage: resolved Action/Exchange occurrences and references retain their existing involvement meaning. An Exchange-purpose link is explicit involvement of its selected Interaction/FunctionalExchange in its caller; count it as that context's exchange evidence. CommonWork points to work already identified by its Action endpoints and does not count two copies of a work definition. Precedence alone never invents a global exchange. Do not mark standalone P as covering a caller-only exchange merely because its B is an endpoint.
All are derived views of one immutable accepted Project and its validated address resolver. Purpose switches change only the corresponding projections, followed by ordinary whole-candidate validation. Analysis output must be independent of cache, traversal order and the renderer's expanded/folded state.
Repeated and nested qualification
Analyze one root caller O. Every occurrence instance has key (O, path, leaf).
For each reference occurrence R in a resolved sequence instance with prefix path q,
its callee's contributions use prefix q ++ [R]. Qualify that callee's ordinary
links by the same prefix. Qualify a contextual link defined in the callee by
prepending q to both of its local paths; a contextual link defined in O appears
once with its own exact paths. Preserve both definition relation ID and instance
prefix in derived edge identity/provenance.
Thus P's A→B exists as R1.A→R1.B and R2.A→R2.B, while O's X→R1.B appears only
once. If P itself references Q through N, the address is [R1,N], not [P,Q].
Expanding one preview or following Open source cannot change these identities.
Reference boundary expansion without invented scheduling
Use ephemeral entry/exit boundary vertices for each reference instance solely for graph connectivity; they are not semantic contributions, execution records, stored IDs, guard-bearing links, or controls. A caller link targeting a reference attaches to its entry boundary; one sourced at the reference attaches to its exit boundary. A link targeting an explicit interior address attaches directly to that contribution and does not acquire a dependency on its earlier contributions.
Compute a callee instance's boundary candidates from its own local precedence projection before the containing caller's links are attached. Include contextual Precedence defined in that callee, qualified to this instance. Connect the entry boundary to its structurally zero-incoming contributions, and its zero-outgoing contributions to the exit boundary using marked synthetic arcs. Nested references use the same rule recursively with memoized shape, within the ratified limits. Never choose the first list element as a hidden fallback. Preserve established legacy exchange-only list order when expanding a legacy sequence; this does not silently convert it to saved SequenceLinks.
Synthetic boundary arcs support reachability only. Exclude them from authored degree counts, control cardinalities and missing-guard checks. A reference's own authored incoming/outgoing degrees are counted on its entry/exit boundary and reported against that reference occurrence, preserving existing direct-reference diagnostics. Do not count both the collapsed reference and its inner contributions as independent work executions.
Multiple intrinsic entry/exit candidates remain advisory incompleteness; boundary arcs do not assert AND versus OR synchronization. Missing reference, empty callee, or a callee with no structural entry/exit supplies no proven pass-through path: retain its located incompleteness warning and mark dependent caller connectivity analysis incomplete. Do not add entry→exit bypass, nor infer nontermination from an incomplete subgraph. Structural address validation is still exact.
Small evaluator oracles
All cases below use the same P=A→B→C and references R1(P), R2(P), with no implicit ordering between R1/R2/X unless stated. These are algorithm expectations for future tests, not newly executed results.
| Case | Exact expected distinction |
|---|---|
| R1, R2 only | Instances remain distinct; each B has one authored predecessor. Root has two independent precedence entries/exits and may retain the existing start/end advisory. Reuse itself adds no non-control degree warning. |
| Add X→R1.B Precedence | R1.B has two authored inputs and one output: one qualified branch advisory. R2.B and standalone P unchanged. Root starts are R1 entry, R2 entry and X; root exits are the two reference exits. X has a path to R1 exit through B/C. No edge X→R1.A exists. |
| Replace with X→R1 Precedence | Caller edge ends at R1 entry, so A lies downstream of X. This is observably different from the interior-target case; B has only A as its authored predecessor. |
| Add X→R1.B Exchange-purpose instead | Adds exchange incidence and caller exchange coverage, but not a second precedence input to B. Any unsequenced X/start/end warning remains honest precedence-only feedback; it must not say that no assembly connection exists. |
| Add R1.B↔R2.B CommonWork | Two exact contextual incidences; no B→B global exchange, no execution fusion and no precedence path between instances. |
| Use target [R1,N].B | Only that nested instance receives the input; [R2,N].B and any other reference to Q remain untouched. |
| Callee entry Choice already lacks required input | Its intrinsic warning is not “repaired” merely by a synthetic entry arc. A real authored contextual input can change the caller instance's degree, with qualified provenance, while standalone definition diagnostics remain separately visible. |
| Missing/empty/budget-exceeded callee expansion | No complete-looking reachability result. Exact structural failures reject; analysis-limit/incomplete-reference notices prevent conclusions from a partial expansion. No guessed bypass or unreachable/nonterminating cascade. |
Diagnostic location and release bounds
Existing Issue fields can locate the root owner or authored contextual link and include a breadcrumb in the message, but unambiguous graphical navigation requires preserving the full owner/path/leaf provenance in an internal diagnostic target. If exposing that target in REST/source diagnostics, add a closed optional context record rather than overloading the leaf ID. Do not attribute the same qualified warning several times through folded and expanded renderings.
Do not replace historical direct-only diagnostics merely to normalize counts. Use the contextual evaluator for affected caller contexts and test existing SequenceLink-only fixtures unchanged. Start/end/reachability checks remain conservative structural assistance, not scheduling, liveness proof, execution counts or guard satisfiability. Tests should assert qualified warning locations, purpose-specific coverage and exact no-cross-instance effects rather than one aggregate number of warnings for an arbitrarily incomplete whole fixture.