fix(runtime,verify): make simulation delivery single-owner (ARN-236) - #387
fix(runtime,verify): make simulation delivery single-owner (ARN-236)#387rita-aga wants to merge 10 commits into
Conversation
|
Independent GPT-5.6 re-review of PR #387 at head No blocking findings. Reviewed the open GitHub PR diff and current-head files for correctness, durability, deterministic-simulation behavior, budgets, compatibility, and regression coverage.
The architectural decision and tests align with the implementation. I found no correctness, durability, DST, or compatibility issue that should block ARN-236. Verdict: PASS |
|
Fresh independent GPT-5.6 review of hosted head Blocking finding:
I inspected the complete hosted PR file set, including scheduler ownership transfer, cyclic bounded draining, final-tick flushing, verifier/runtime action reservations, callback cascades, deterministic collections/time, ADR, and downstream config updates. I found no other blocking issue in those paths. Verdict: FAIL |
|
Fresh independent GPT-5.6 review of hosted head No blocking findings. I re-reviewed the complete PR diff and specifically re-audited the callback-lifecycle failure reported in #387 (comment):
I also verified the scheduler/durability design:
Verdict: PASS |
ARN-236 live local E2E and validation evidenceHead: RED (before the fix)This reproduced durable loss without a fault drop: GREEN (current head)Live serverThe server was then stopped cleanly with Ctrl-C. Full gates
No files under |
|
CI is fully green at head Run: https://github.com/nerdsane/temper/actions/runs/29329902725 The first Tests attempt was terminated by GitHub runner infrastructure ( |
|
@greptile review |
|
Independent GPT-5.6 review of the complete open PR diff at Finding:
The callback remediation itself is sound: callback rejection and reaction-budget exhaustion clear the remaining cascade, record one terminal execution error, and prevent both Verdict: FAIL |
|
Fresh independent GPT-5.6 review of the complete hosted open PR diff at No blocking findings. I re-audited the current diff after the prior compatibility failure at #387 (comment) and the fixes in
Independent focused validation at this exact commit passed: public API compatibility 1/1, actor-system regressions 10/10, and verifier simulation regressions 9/9. No files under Verdict: PASS |
ARN-236 final-head verificationHead: Live serverThe server was stopped with Ctrl-C after the health check. Exact current-head regressions
Review remediation
No files under |
|
ARENA SHIPPABLE · GPT-5.6 · 2026-07-18T20:12:02Z Current head: Ordered review gate evidence
Validation evidence
PR remains open and unmerged. |
Summary
Fixes ARN-236: delayed simulation messages could be removed from pending scheduler ownership without being consumed by the verifier/runtime driver, causing silent loss at the simulation horizon.
The implementation establishes one deterministic ownership path:
tick()advances logical time and enqueues due messages into bounded scheduler mailboxes.drain_ready()transfers each message exactly once.ADR:
docs/adrs/0171-single-owner-simulation-delivery.md.Evidence
11875b5e.e48b3cd1.cargo test --workspace: PASS, including 100-seed randomized platform DST.-D warnings: PASS.Scope
No files under
crates/temper-actor-runtimeare modified. Do not merge as part of the ARN-165 arena; this PR is submitted for review only.Linear: ARN-236
Greptile Summary
This PR fixes ARN-236 by establishing a deterministic single-owner delivery path for simulation messages:
tick()enqueues due messages into bounded per-actor mailboxes, anddrain_ready()is the sole transfer point to simulation drivers. BothSimActorSystem(runtime) andrun_simulation_impl(verifier) now use the same drain-loop pattern with terminal-tick flushing and shared reaction budgets.SimSchedulergains a bounded mailbox per actor,drain_ready()for cyclic starvation-free bulk draining, andwith_mailbox_budget()constructor;tick()no longer returns messages directly.SimActorSystem::run_random()drives adrain_readyinner loop with terminal-tick flushing, budget-tracked integration callbacks, andensure_execution_active()guards that prevent stale work after any callback rejection or budget exhaustion.temper-verify/src/simulation.rsis aligned to the same drain loop model, with per-actor reservation accounting viaactor_in_flight_actionsand assert-backed single-delivery guarantees.Confidence Score: 5/5
Safe to merge — the single-owner delivery contract is correctly implemented across both crates, the previous callback-cascade and budget-exhaustion findings are addressed, and the RED/GREEN regression suites cover the exact failure modes from ARN-236.
The drain-loop, terminal-tick flushing, reservation accounting, and invalidation path all behave correctly. Test coverage spans single-seed, multi-seed, cross-mode (step to run_random), callback rejection, budget exhaustion, and exact-once delivery across 16 seeds. The only finding is a cosmetic naming inconsistency on the loop variable in run_random().
No files require special attention.
Important Files Changed
drain_ready(), andwith_mailbox_budget()constructor.tick()now enqueues to mailboxes (single owner). Logic is correct;run_until_quiescent()correctly documents that callers must drain separately.run_random()drives a drain-loop with terminal-tick flushing;ensure_execution_active()guards prevent stale resumption. One minor style issue: the loop variable is named_tickdespite being actively used in the break condition.invalidate_callback_cascade()correctly clears pending callbacks and records the error; both rejection and budget exhaustion call this path. No issues found.actor_in_flight_actionsaccounting, assert-backed delivery invariants, and identical terminal-tick flushing logic. Usestick(correct) as the loop variable name, consistent with Rust conventions.reserve/releasehelpers with assert-backed invariant (reservation must be owned before release). Correct.send_atsemantics.SimActorResultagainst unintentional public field additions. Correct and sufficient.Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant Driver as Sim Driver participant Sched as SimScheduler participant Mailbox as Actor Mailboxes participant Handler as SimActorHandler Driver->>Sched: send + reserve() note over Sched: message in pending heap Driver->>Sched: tick() Sched->>Mailbox: enqueue due messages Driver->>Sched: drain_ready(batch_budget) Sched->>Mailbox: pop_front() cyclic Sched-->>Driver: Vec SimMessage (owned once) loop each message Driver->>Driver: release(in_flight) Driver->>Handler: apply_action() Handler->>Driver: schedule_integration_callbacks() end Driver->>Driver: deliver_integration_callbacks alt budget exhausted or rejected Driver->>Driver: invalidate and break else terminal tick with ready messages Driver->>Sched: drain_ready again else normal Driver->>Driver: break inner loop end%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant Driver as Sim Driver participant Sched as SimScheduler participant Mailbox as Actor Mailboxes participant Handler as SimActorHandler Driver->>Sched: send + reserve() note over Sched: message in pending heap Driver->>Sched: tick() Sched->>Mailbox: enqueue due messages Driver->>Sched: drain_ready(batch_budget) Sched->>Mailbox: pop_front() cyclic Sched-->>Driver: Vec SimMessage (owned once) loop each message Driver->>Driver: release(in_flight) Driver->>Handler: apply_action() Handler->>Driver: schedule_integration_callbacks() end Driver->>Driver: deliver_integration_callbacks alt budget exhausted or rejected Driver->>Driver: invalidate and break else terminal tick with ready messages Driver->>Sched: drain_ready again else normal Driver->>Driver: break inner loop endReviews (5): Last reviewed commit: "fix(runtime): preserve result API compat..." | Re-trigger Greptile