Files
ARCADIA-Studio/harness/experiments/behavior-navigation-review-20260912/issue21-activation-analysis-20260912.md
T

18 KiB
Raw Blame History

Issue 21 — independent activation rendering analysis

2026-09-12, /root/diagram_usage_workflows, for root synthesis and peer Codex-956atf's implementation ownership. Read current issues/comments #20 and #21, including peer claim637 and root claim641. Root subsequently yielded implementation to peer956 and assigned this independent read-only evaluation. No production writes, compiler, model experiment, or native application interaction were performed. Active inspected worktree: C:/Users/User/Documents/Git/ARCADIA-Studio/.local/diagram-usages-ytr83r-20260912, base7aa007b plus root's diagram-usage working changes. Source line references identify the inspected files and may shift after integration.

User requirement and scope

Issue21 gives the exact stored order Call1 L1→L2, Call2 L1→L2, Reply2 L2→L1, Reply1 L2→L1 and reports invisible inner call blocks. Comment622 asks to examine Capella because the user likes its treatment. The attached image at root .local/gitea-issue21-25269f9e.png shows two calls arriving at the left lifeline and one visible pale strip with no separate nested activation apparent. This supports the reported visual symptom but does not reveal the complete model, both correlations, build version, or screenshot provenance beyond the issue attachment.

Issue20 requires less rigid scenario diagrams: ordinary direct controls for spacing lifelines, moving arrows, resizing elements and avoiding clipped names, comparable in ease to architecture editing. The #21 correction should not hardwire a new geometry scheme that makes that later work more difficult. This analysis does not propose taking #20 implementation scope.

Findings: verified source facts

1. Overlapping activations have identical horizontal geometry and UUID-dependent paint/hit precedence

behavior.rs:1339–1363 gathers Calls by scene.rows.keys() from a BTreeMap keyed by occurrence ID, then invokes activation_sequence for each Call. This is UUID order, not call occurrence order or outer-before-inner order.

activation_sequence follows the particular Call's reply_to correlation and correctly can produce two different vertical spans for the reported simple case. However, every activation_segment (:1657–1678) receives exactly the receiver lane x and emits the same x−4 origin and width8. Reply caps (:1739–1751) likewise use fixed x−7,width14. There is no nesting depth, horizontal interval assignment or activation-specific anchor.

For y1<y2<y3<y4, both Call1's span [y1,y4] and Call2's span [y2,y3] occupy [x−4,x+4]. Scene::draw (:2169 onward) paints filled boxes in their stored order before messages. If the outer Call sorts later, its opaque fill/stroke covers the whole inner interval. If the inner sorts later, some short cross-lines can survive, but there is still no distinct offset nested block. This is sufficient source evidence for the reported symptom; it does not depend on a guessed GPU bug.

Scene::hit (:1848–1858) searches empty-title boxes in reverse order after message/header checks. Thus the same overlap makes a click select whichever Call's bar was appended last, regardless of intended nested identity. A paint-only color tweak would leave interaction ambiguity.

2. Messages are attached to lane center, not to a distinct activation boundary

Occurrence geometry (:1505–1531) derives call/reply polyline endpoints from lane x positions. Birth/death rendering later adjusts lifecycle messages, but ordinary call/reply endpoints remain at the lane center. Offsetting activation rectangles alone would leave the arrowhead or reply origin disconnected from the corresponding block, or passing through the wrong block.

Therefore the correction needs a shared call-activation geometry association for draw, message endpoints and hit testing, retaining the original occurrence/correlation IDs. The semantics do not require a new persistent activation model record merely to render that association.

3. Recursive/self-call activation starts at the send row, 24 units above its receive endpoint

The self-message polyline ends at (x, y+24) (:1513–1520); its occurrence row is recorded at y. activation_sequence starts its receiver activation at self.rows[call].y (:1710) rather than that receive anchor. Thus a self-Call bar currently begins before its drawn receive endpoint. For ordinary horizontal calls both anchors have the same y, which hides this defect.

For self-replies, termination should follow the replying activation's send anchor; the subsequent receive anchor belongs to the resumed caller. A correction that uses the same row as both events would perpetuate the recursive case and conflict with movable arrows in #20. No native reproduction was performed here; the 24-unit mismatch is directly derivable from the code.

4. Existing fragment and lifetime behavior is meaningful and must be preserved

activation_sequence splits an inherited activation across Fragment operands, identifies a Reply by its exact correlation, stops branch-local segments at matching Reply/Delete, and leaves a visible unresolved cue for open continuations. ALT resumes when a path can remain open; PAR, OPT and LOOP have distinct continuation rules (:1755–1787). These are not interchangeable flattened vertical intervals.

scenario_lifecycle/render.rs:154–174 clips activation spans to the receiver's Alive intervals in the same scope. An uncreated/dead/unresolved lifetime must not gain a visually asserted active span through the correction. Create/Delete markers paint after ordinary bars/messages, with their original occurrence identity.

Existing tests (behavior.rs:direct_alt_execution_stops_each_operand_at_its_reply_and_marks_open_operand and direct_execution_span_ends_at_its_correlated_reply_and_marks_an_open_call) check span ends, operand splits and unresolved cues for one Call. They do not test two overlapping same-receiver activations, UUID permutation, endpoint attachment or distinguishable hit regions. They therefore do not disprove the reported defect.

Semantic boundary: what nesting must and must not imply

docs/language.rst:678–701 requires Reply to reference a preceding Call on a guaranteed common path, reverse its actual lifelines, and avoid duplicate replies that may follow on one shared execution path. It does not impose a LIFO stack between replies to different Calls. Rendering should not silently change that contract.

The issue's y1<y2<y3<y4 correlations form strictly nested intervals, so an offset inner block is well justified. A crossing case Call1,Call2,Reply1,Reply2 must still preserve both admitted correlations. Treat it as two overlapping active intervals with separate visible tracks, not as a proof that Call2 is semantically invoked by Call1 or a reason to rewrite which Reply completes which Call. Calls from two different senders can overlap on one receiver without their senders being part of one execution stack.

Likewise, different ALT operands are exclusive paths; screen stacking does not make their Calls nested. PAR operands are not a fabricated total execution order. Track assignment should be scoped by branch-path compatibility and inherited open activations, not by raw rectangle containment across the entire flattened canvas.

Primary comparison evidence, with limits

The official Sirius sequence-editor specification describes executions with start and finish events, recursive execution containment, and mappings that connect those events to graphical elements. It also separates graphical ordering from semantic ordering and requires them to remain coherent. This supports an explicit event/activation geometry mapping and nested border-node treatment rather than painting multiple indistinguishable rectangles on a lifeline. It does not independently establish how the user's installed Capella version renders this particular model.

Official Capella features distinguishes functional, exchange and interface scenarios by their lifeline/message meanings. The same geometric nested-activation correction should therefore be assessed against supported Studio scenario viewpoints rather than assuming every Call is a software operation.

The official Sirius historical release notes describe direct execution resizing within operands with enclosing containers growing as needed, and sequence-diagram control of geometry to preserve semantic ordering. That is relevant to #20 compatibility: editable geometry can remain constrained by event/ownership semantics. It is not evidence of current native Capella affordances. Peer owner retains the requested comparable native exploration; this report does not duplicate it.

Independently derived acceptance expectations

Fixture identity/correlation maps should be handwritten separately from the renderer's output. Use exact Call/Reply IDs, lane IDs, scope paths and stored order. Tests must check observable visible geometry and selection, not only count BoxItems or confirm no panic.

Case Independent expected behavior
Exact user case, L1 left of L2 With order C1,C2,R2,R1 and correlations R2→C2,R1→C1, show outer receiver activation from C1 receive to R1 send; inner activation from C2 receive to R2 send. Inner block has a visible offset boundary, and each Call/Reply endpoint attaches to its own block. A point in each exposed strip selects the corresponding Call.
Mirrored user case Exchange the physical left/right lane positions while retaining the same message/correlation identities. The two spans remain visibly distinct and correctly attached. An implementation must not assume sender is left of receiver.
UUID permutation Reidentify or construct IDs so C1 sorts before C2, then so C1 sorts after C2, while preserving each model's equivalent order/correlations. Geometric layout and which block appears on top must be equivalent modulo identities. Neither paint nor hit precedence may switch arbitrarily with ID order.
Three nested Calls to same receiver C1,C2,C3,R3,R2,R1 produces three visible, separately selectable intervals, with each inner receive/send attachment at its own depth. Ending C3 does not end C2/C1.
Nonoverlapping repeat C1,R1,C2,R2 reuses the base track when no interval overlaps. Do not accumulate horizontal indentation permanently by chronological Call count.
Crossing overlap C1,C2,R1,R2 retains each explicit correlation and shows both active intervals without hiding one. Do not change semantic order or fabricate LIFO rejection. If the core rejects a particular fixture for an independent channel/viewpoint reason, repair that fixture rather than interpreting the unrelated rejection as a stack rule.
Opposite-direction reentrancy C1 L1→L2, C2 L2→L1, C3 L1→L2, then R3,R2,R1. On L2, C3 overlaps C1 and needs a distinguishable nested/overlap track; C2 belongs to L1. Per-lane identity and reply association remain exact.
Recursive self-call C1 L→L, C2 L→L, R2 L→L, R1 L→L. Every activation begins at its Call's actual receive endpoint (currently y+24 for the elbow), not its send row; each terminates at its correlated Reply's send endpoint. Elbows clear all live activation tracks and their arrowheads land on the correct boundaries.
ALT with inherited outer Call Outer C1 precedes ALT. Operand A contains C2,R2,R1; operand B contains its own C3,R3 and leaves C1 open. Distinct inner tracks coexist with branch-local C1 segments. No C1 segment joins across operand headers; no activation depth leaks from A into B. Only B/possible continuation remains unresolved.
PAR and optional/repeated fragments Test independent Calls in separate PAR operands and an inherited outer Call under OPT/LOOP. Preserve current valid/invalid correlation rules and uncertainty cues. Different screen operand rows do not manufacture nesting or serialize concurrent paths. An optional/repeated Reply cannot assert guaranteed completion.
Delayed creation/deletion Create L2, then C1,C2,R2,R1,Delete L2: no activation before birth/after death; both nested intervals remain visible while alive. Separate warning-admitted unresolved-lifetime case retains neutral gaps. If Delete occurs while a Call remains open and is admitted, it clips the visible activation at death and preserves unresolved-call indication, never a false Reply cap.
Unreplied inner/outer C1,C2 with missing R2 and/or R1 retains separate identifiable incomplete indications where current semantics permit. Do not use a guessed end to merge or hide the two calls.
Viewpoint/layer and typography Exercise at least ordinary OA exchange scenario and SA boundary/interface Call with actual operation identity. Same geometry invariant, no alias/name correlation guessing. Repeat with long and Unicode labels, 100%,125%,pan and minimum supported window; label backgrounds, markers and selection do not erase the exposed block boundary.
Passive and edited layout Query/render/select/pan/zoom preserves complete Project, accepted source envelope, source buffers and undo/redo history. In the future #20 layout representation, move lane coordinates or message geometry while retaining correlation/order; the same event-based activation association follows the chosen anchors and survives save/reopen without adding semantic edges or silently reordering steps.

Geometric oracle for the minimal issue: let receive/send anchors be (xC1,y1),(xC2,y2),(xR2,y3),(xR1,y4) with y1<y2<y3<y4. Verify C1 spans [y1,y4], C2 spans [y2,y3], the bars are not identical in x range, both expose a drawable and selectable boundary during overlap, and R2 remains associated with C2. No required absolute pixel width/offset is imposed here; the implementation must demonstrate legibility at the actual tested scale. A screenshot alone is insufficient to prove identity selection; a hit geometry assertion alone is insufficient to establish visible contrast.

Bounded correction candidates and tradeoffs

Candidate Benefits Falsification / limitation Assessment
Sort existing boxes and recolor selected inner bar Smallest local edit Same x range remains; one bar occludes another, hit ambiguity persists, recursive anchor still wrong Insufficient. Useful only as part of a geometric correction.
Add derived ActivationSegment metadata, then assign deterministic receiver-local visible tracks and shared message anchors Reuses existing correlation/branch/lifetime traversal; can separate segment derivation from display geometry and keep source untouched; supports exposed hits and endpoints Must carry scope/path and start/end event identity, handle crossing intervals and inherited branches, and prove opposite direction/self-call; naive global y nesting would be wrong Leading bounded correction. Preserve current scope-aware clipping and add one authoritative geometry product consumed by paint/hit/routing.
Replace current activation traversal with a full execution-tree/stack semantic model May support richer execution semantics later More than user requested; a stack can reject permitted crossing Calls; new persistent execution identities complicate textual/API parity and #20 layout Defer unless actual requirements establish new semantic executions. Rendering nested activations does not itself authorize a metamodel change.
Persistent manual activation rectangles Can be visually adjusted Duplicates derivable lifetime/correlation data, invites stale ends after Reply edits, and shifts the original defect to users Reject as correction; #20 can persist presentation offsets/anchors without making manual rectangles semantic authority.

Suggested bounded implementation shape: retain existing activation_sequence's branch/correlation traversal, but emit typed records (call, receiver, scope/path, start/end event anchors, termination state) before reducing to rectangles. Derive track assignment from comparable active intervals, with stable stored-event order as the primary ordering. Resolve lane positions and message send/receive anchors in a layout pass, then use the same rectangles/anchors for paint, hit targets and navigation bounds. Lifeline birth/death clipping remains explicit. This is an architectural candidate, not reviewed implementation or a mandatory API.

For #20 compatibility, treat lane_x, event rows and actual message anchor positions as inputs to geometry rather than deriving activations from hardcoded row offsets forever. Persistent layout fields (when specified by #20) remain presentation data and must not replace reply_to or sequence/branch ownership. Do not compute semantic nesting from whichever y coordinates the user dragged on screen.

Verification status and handoff

The fixed-width overlap, UUID-driven precedence, lane-center attachment and self-call 24-unit start mismatch are verified source facts. The user's image is consistent with them. No runtime reproduction, prototype, correction, automated test pass, native Capella comparison or release acceptance is claimed. Peer956 owns implementation; root should consolidate this evidence with the peer's reproduction and compare its final geometry/hit changes against the independent matrix before integration. Existing single-call/ALT/lifecycle evidence can be reused for unchanged invariants, but same-lane nesting, recursive anchors and UUID independence need new checks.