8.5 KiB
Typed activation / lifecycle union handoff
Source-only contribution by /root/nested_call_design for root-owned #21/comment716. Isolated worktree .local/nested-lifecycle-union-20260912, branch codex/nested-lifecycle-union-956atf-20260912, base d61f1f38779ab70a77efcde523ae31c432aefcfd. Root owns integration, Gitea, compiler and native acceptance. No root tracked files were edited.
Committed source: f6595ebf66e88ec42c37b5c1a3c014f5e52cb32d; isolated worktree clean. Six files, 2,151 insertions and 77 deletions, mostly the published lifecycle bridge and retained renderer tests.
Inputs and boundary
Read the complete .local/nested-lifecycle-union-review-20260912.md and actual core admission logic before implementation. Published peer source was retrieved through Gitea at 7aa007b0777aa182a99f46e90eeb9b2558f3ad2a: behavior blob d199096df61cacde7858ab1915f352b5c479e347, lifecycle projection blob 6fe044890864ecf3095d0fedf590104f6121abf7, lifecycle bridge blob a066d9671cb60070f507d8840977e100aac89792, render tests blob 02673f0636faacc6d51fbe38f8fa8b223e884bdc. Root's existing test-only lifecycle projection differed only by the missing render-module declaration. The bridge was independently confirmed identical at 911f63e63ca9e35af631ae02cbf731f2b34b72a2; its behavior blob 3f9fd97e038733ac92749b1543e9fa68cd3dda2c was read to locate the upstream test hook, not imported wholesale. Peer 66a1f1690f778c8814bfefff7f46fe7f6bbe520e lifetime experiment note was also read as unexecuted supporting design evidence.
Only behavior.rs, scenario_activation.rs, scenario_lifecycle.rs and scenario_lifecycle/{render.rs,render_tests.rs,union_tests.rs} change. No WIP navigation, free-layout policy, persisted anchor schema, geometry edit transaction or upward-anchor floor is imported.
Integrated behavior
The pipeline is occurrence geometry (including published 16-unit self-Create/Delete clearance), final scene height, lifecycle projection, Create/Delete endpoint alignment, typed activation clipping/columns, final Call/Reply/Asynchronous anchors. There is one activation traversal. Scenario lifetime lanes replace undifferentiated vertical guides; non-scenario guides remain unchanged. Birth/death markers and bounded capsule/header text painting come from the published renderer. The root's background-before-activation paint fix and activation-before-label hit priority remain intact. Exact lifecycle markers precede other hits; broad marker/message tolerances are compared by distance after exact shapes and labels.
Logical Call starts and correlated Reply send times are collected from recorded model rows, using actual polylines where available. They do not come from clipped rectangles. Incomplete calls lacking sender polylines still receive logical metadata, avoiding absent-map lookups when their visible execution competes with another call. Only a visible segment whose end equals the actual reply-send y and whose exact scope/Reply ID match may supply a reply anchor.
Visible pieces intersect only Alive intervals for their receiver and exact scope. They retain call/receiver/scope/column identity; a clipped end is Finish::Clipped, never a fabricated Reply. Receiver Delete gives Finish::Terminated(delete_id) and an unanswered cue. Cues are emitted from logical traversal independently of surviving rectangles and follow the chosen call column, so entirely invisible open paths retain their uncertainty presentation.
Root explicitly chose the conservative conditional-death rule during this task: preserve each sibling's bars/cues and original model correlation, but stop definite parent continuation when a compatible branch may terminate the receiver execution. A later Create cannot revive that Call. The rejected bool(any-open) propagation can resume an old execution after conditional death/recreation. The implementation carries separate open and may-be-terminated outcomes; no model semantics/schema are changed.
Admission distinction
Core validation.rs:1766–1791 rejects a fully bound use before Create or after Delete, including potentially ordered conditional/parallel paths. Therefore fully bound Call→Delete→Reply/Create and ALT(Delete,open)→Create→Reply are not admitted editing workflows. Tests explicitly require lifeline_lifetime errors before invoking raw Scene projection defensively on those invalid models. A leading Create in the conditional-recreation defensive fixture establishes an actual alive prefix so the unaffected sibling's 26-unit open span remains a discriminating oracle.
Ordinary Document-admitted cases separately cover valid delayed Create/nested Call/Reply/Delete, receiver death followed by an incomplete correlated Reply with no dead sender endpoint, self lifecycle plus self Call/Reply, an unresolved ALT operand with no visible activation, and incomplete calls without sender polylines. Validation is never weakened. Source review predicts admission from actual endpoint/order rules; execution is still required to confirm it.
Evaluators (unrun)
All 17 published lifecycle renderer tests are retained. Adaptations are the legacy width-8 anonymous-box query to typed call/receiver segments, and the peer-only Lane · title prefix expectation to root's preserved actual lane name. The existing root typed activation and pixel/hit tests remain unchanged. Published header clipping helper/painting is retained so its Unicode/wide-glyph, viewport and pan/zoom assertions remain meaningful.
Nine new combined tests in scenario_lifecycle/union_tests.rs:
admitted_delayed_create_nested_calls_replies_delete_share_one_geometry_pipeline: OA/SA exact receive/send endpoints, typed identity/depth, lifetime containment and marker hits.admitted_death_and_incomplete_later_reply_do_not_fabricate_an_answered_execution: terminated metadata, retained repair card and unanswered cue.admitted_self_lifecycle_and_self_call_keep_distinct_send_receive_rows: action clearance, marker receive rows, self-call lower receive start and exact reply send end.admitted_unresolved_operand_keeps_unanswered_cue_without_any_visible_segment: wholly invisible open execution still has a cue and lane-anchored message.admitted_calls_without_sender_polylines_still_have_logical_correlation_metadata: incomplete nested calls do not lose correlation or crash anchoring.invalid_prebirth_call_and_postdeath_reply_remain_rejected_with_defensive_scene_clipping: explicit admission errors; no invented death-boundary Reply or revived execution; pre-birth clipping does not move the original Call receive event.conditional_death_then_recreate_never_revives_call_but_keeps_open_sibling: rejected model, defensive terminated/open/uncertain cues, no later bar or false Reply anchor.clipped_operand_preserves_original_nested_or_crossed_correlation_distinction: compare nested and crossed actual reply order even when the later replies cannot terminate visible pieces; nested outgoing messages use the inner bar and crossed ones fall back to the lane.test_only_upstream_row_offsets_update_lifetime_segments_and_endpoints_without_authoring: a scoped test-only row offset before row recording changes lifecycle and complete typed segment tuples coherently; compares final polylines, labels, frames, IDs, scope/slot geometry, exact source bundle, whole Project and clean history. The hook resets on unwind and is absent in production; it is not a placement policy.
The existing Rendering::alive_spans tests and new lifetime assertions cover exact scope clipping. The union retains the root headless WGPU regression for label-backplate erasure; its success on the combined source must be re-established by root.
Verification and remaining risk
Executed only source inspection, installed standalone rustfmt with edition2024/skip_children=true, and Git whitespace/status checks. No Cargo, rustc, tests, native UI or Gitea mutation. The peer reports and root's earlier tests each describe their own source; no combined pass is claimed here.
Root should review this source, run the scenario_lifecycle, scenario_activation, and atomic graphical Call/Reply tests, then the required combined desktop/strict gates. Native acceptance must inspect birth/death markers, self-event clearance, long headers/capsules at pan/zoom, and selected/unselected nested bars/shoulders. Global palette issue26, min-scale bar legibility, free editing requirements20/22 and Linux remain separate. Published lifecycle/header clipping adds actual painter ordering and hit boundaries; the full native rendering result remains a required gate.