9.7 KiB
Nested activation / lifecycle union review — 2026-09-12
Bounded independent source review for root-owned #21. Read peer comment698 by Codex-ytr83r at22:23:59UTC and relevant #2 publication comments. No source edits, compilation, UI, Gitea mutation or integration approval. The active paint-repair worker's ownership is unchanged.
Exact source boundary
- Root typed activation source inspected at
83f53c7c6e. Its activation implementation is unchanged by root HEAD419c78c at review time.crates/oa-desktop/src/behavior.rs:23–26compiles scenario_lifecycle only for tests;scenario_activation.rs:99–119emits raw spans. - Peer experimental source inspected directly through Gitea at
911f63e63c. behavior.rs blob3f9fd97e03has production lifecycle wiring and the two-site test-only Scene anchor hook. - Confirmed that lifecycle support predates that unexecuted experiment by reading published checkpoint
7aa007b077. Its behavior.rs blobd199096df6has production module line23, align_messages line1329 and alive_spans clipping line1655. The checkpoint identifies its implementation as33e30c1; peer reported gates are not rerun or adopted here. - scenario_lifecycle/render.rs is identical blob
a066d9671cat911f63e and7aa007b.scenario_lifecycle.rsat911f63e is blob6fe0448908.
Peer698 is substantively correct: this is an explicit union dependency, not evidence that either branch regressed an already integrated counterpart. Do not replace either renderer wholesale or treat911f63e's source experiment as accepted implementation.
Required integration contract
-
One ordered geometry pipeline. Record occurrences/rows/scopes after peer's16-unit self-Create/Delete clearance and any test-only row-anchor hook (peer behavior.rs1432–1454). Establish final scene height before Rendering::new, which uses height−20 as its root extent (render.rs32–65). Build lifecycle from those same world coordinates, align Create/Delete messages, then derive typed activations and final Call/Reply anchors. Do not run the old and new activation_sequence implementations together. The pre-row hook remains upstream and cfg(test); it is not a persisted-layout contract.
-
Keep message kinds' endpoint meanings separate. Lifecycle align_messages (render.rs113–151) places a self-Create/Delete receive point on its marker row and send point24 above; Create points at the capsule edge. Root typed activation anchoring (scenario_activation.rs216) intentionally handles Call/Reply/Asynchronous only. Keep that exclusion: a self-Call starts at its lower receive endpoint, while self-Create/Delete's marker row must not be shifted or rewritten as a Call loop. Both aligners must preserve occurrence IDs and use the same recorded rows.
-
Clip visible activation pieces by receiver AND exact scope. alive_spans (render.rs154–175) intersects only Life::Alive intervals with the requested extent and rejects absent/unresolved regions. It may return zero, one or multiple pieces. Peer lifecycle projection gives siblings the same entry rather than the previous screen operand's exit, and marks conditional/repeated/parallel continuation unresolved when appropriate (scenario_lifecycle.rs197–205,246–273). Preserve that conservative meaning unless root separately decides otherwise. A parent activation must not bridge a death, pre-birth region or another operand merely because screen y is continuous. Retain typed call/receiver/scope/column identity for each surviving piece.
-
Keep logical correlation timing distinct from clipped rectangle edges. Root currently reconstructs Correlation.start and reply times from Segment.rect/Finish at scenario_activation.rs216–232; reply anchoring finds a segment by Finish::Reply without checking that its visible end is the reply's send y (around258–265). Blindly clipping rects while retaining the original finish on every piece is unsafe.
Concrete union falsifier: raw Call at148, receiver Delete at240, correlated Reply at332. Clipping the Call→Reply segment to148…240 and leaving Finish::Reply(reply332) makes the geometric end look like a reply at240. It also lets the actual reply at332 attach to that displaced execution's x despite no visible execution there. If several alive pieces survive, copying Reply to all pieces creates ambiguous first-match anchoring. Conversely, simply deleting Reply metadata can erase the real correlation used to distinguish crossed calls.
Required observable rule: only a visible piece that actually reaches the terminal reply-send coordinate can supply that reply anchor/cap. A lifetime-clipped end is not a reply. Preserve original call/compatible-reply timing for correlation decisions even when its visible representation is clipped or absent. This can be a small separation of logical metadata from visible fragments; it is not a request for another traversal engine or new model schema.
-
Deletion terminates the local execution without pretending to answer the call. Peer behavior.rs1723–1734 explicitly handles receiver Delete, clips at death, preserves an unanswered-call cue, and stops that local traversal. Root Finish currently has Reply/Boundary/Continuation/Open but no explicit death terminal. Decide a typed representation that distinguishes “execution terminated, call unanswered” from both reply and ordinary continuation. Preserve the sibling-open path and unresolved post-fragment state. Do not derive all unresolved cues only from surviving clipped fragments: an entirely invisible fragment can otherwise erase the semantic uncertainty cue. Nor may a later Create automatically resurrect an execution already terminated by Delete.
-
Columns, hit geometry and paint use the same visible pieces. One call's related pieces must retain a consistent chosen track; clipping cannot silently change call identity or make different siblings chronological. No active_segment result may come from an absent interval or from fabricated nesting caused by clipped start/end times (root scenario_activation.rs313–380). Preserve source/receiver anchors at real events, marker hit identity, and the paint worker's existing selection/layering correction. Integration must explicitly reconcile lifecycle lanes/markers with that painter; this report does not allocate or edit its files.
Minimal combined acceptance cases before adoption
Retain the existing root nested/crossed/reentrant/self/UUID tests and peer lifecycle tests, adapting representations rather than dropping assertions. Add these discriminating combined cases in OA and SA where the core admits them:
- Delayed Create → C1 → C2 → R2 → R1 → Delete: typed starts are actual call receives, each reply reaches its correlated visible end, and bars remain inside alive spans.
- C1 → ALT(left: Delete; right: empty): preserve left death termination plus unanswered cue, right26-unit open span, and no definite post-frame bar. Peer
render_tests.rs:478–545already provides the independent lifecycle oracle. Replace its width8 anonymous-box lookup with typed call/receiver/scope lookup; preserve the actual assertions. - Call before delayed birth, Call spanning Delete, and a later correlated Reply after Delete: preserve admitted semantic data and lifecycle uncertainty; no invented reply finish at a clipping boundary or detached bar anchor. If a constructed sequence is rejected by core semantics, record that and use an admitted incomplete case.
- Delete then later Create: no automatic resurrection of the prior terminated activation. Multiple alive pieces must not duplicate reply finishes or unresolved cues.
- Self-Create/Delete after an Action retains16-unit clearance, marker receive row and hit identity; self-Call/Reply still uses the typed lower receive start. Peer
render_tests.rs:666–737covers the marker half. - Crossed replies spanning a clipped/uncertain operand: compare original compatible correlation endpoints so clipping cannot manufacture an innermost caller execution.
- Passive source roundtrip and moved test-only anchors compare both lifecycle geometry and complete typed segment tuples, plus final polylines, IDs, labels, frames and whole Project. Peer Scene experiment
mod.rs:88–104already compares lifecycle but predates typed segments. Keep that assertion and add segment metadata. Its baseline self-call x oracle at175–178 must change from lane+75 to the actual typed lane/lane+66/lane+66/lane+6 for its isolated self-call; its send/receive y oracle remains636/660. - Native pan/zoom and selection at birth/death markers and each exposed nested shoulder, including unselected bars, must verify the final combined painter. Root's native83f53c7 and peer historical renderer results each remain scoped to their own source.
The bounded Scene experiment at911f63e is explicitly uncompiled/unexecuted and does not cover delayed creation/deletion or nested activations. Passing its seven tests alone could not establish this union. Required interface decisions are the endpoint/clip/finish distinction and one geometry pipeline; no peer schema or general free-editing policy is accepted by this review.