Repository navigation
fix(engine): a lane activation never writes the node's top-level slot - #195
Conversation
Lane slots are never cleared between loop passes, and the gather counted every slot under its predecessors against the scatter's lane_count, taken from the first lane_count anywhere in state. A pass with 3 lanes followed by one with 2 released [20, 21, 12], where 12 is the first pass's third lane. The scatter now stamps each lane envelope with its activation step, every lane slot records `_scatter` and `_scatter_step`, and the gather counts only slots from its own scatter's current activation, reading lane_count from that scatter. Slots from checkpoints written before this carry no stamp and count as before while no stamped slot exists. Also corrects the reason given for refusing a gather with no scatter: it releases empty and silently drops its predecessors' output.
Four paths in a scatter lane wrote `nodes.<id>` instead of the lane's slot: a cancel seen at the node boundary, a cancel during retry or backoff, a cancel while waiting to re-enter, and a Reenter (a gate or approval polling), which also re-activated with a bare id and so left its lane. A cancelled lane also kept routing down its static edge, so its successor ran outside the lane. A cancelled lane now marks its lane slot "cancelled" and stops; a re-entering lane writes "pending" notes to its lane slot and re-activates with its own lane envelope. The gather counts neither as arrived, and gate and approval read their poll count from the lane's slot.
|
Warning Review limit reached
This review includes 17 billable files and costs up to $4.25. Or wait 4 minutes for your next included review. View limit details
|
Tiny Sweeper reviewVerdict: Incomplete · Priority: none Diagnostics and supporting detailsFull summaryPull request purpose (title): fix(engine): a lane activation never writes the node's top-level slot. Tiny Sweeper reviewed this change across 5 lane(s) and found 0 active actionable finding(s). Detailed lane evidence and any incomplete work are listed below. Unreviewed paths
Partial review reasons
Review snapshot
Completeness: Incomplete FeaturesNone identified with supported citations. TestsNo supported feature-to-test mapping was produced. Test execution is not inferred. FindingsNo active actionable findings. Before merge
Agent review detailscritique
security
tests
commits
description
Evidence and run details
|
Resolves the CHANGELOG conflict with the engine fixes that landed on main (tinyhumansai#192-tinyhumansai#195): both Unreleased entries are kept.
Stacked on
fix/gather-current-pass-lanes: merge that first. This branch contains its commit until then.Summary
Inside a
scatterlane, an activation must write onlynodes.<id>.lanes.<lane>, never the node's top-levelnodes.<id>. Four paths broke that. This fixes them and keeps the gather counting correctly.Root cause per path
engine/build/activation/gates.rs): wroteitems_update(&node.id, &[], None)whether or not the activation was in a lane. It also returned a plainUpdate, so the static edge scheduled the successor outside the lane, where it wrote its own top-level slot.activation.rs): the same write and the same static-edge leak.outcome.rs): wroteitems_update_with_meta(&node.id, …)and re-activated withCommand::goto([node.id]), a bare id. So the re-entered activation lost its_laneenvelope and ran outside the lane. Cancel while waiting to re-enter had the same write.gateandapprovalreadpolls, and a gate itsfromspawn's tickets, from the top-level slot. Inside a lane,max_pollsnever bounded them, andgate { from: [spawn] }never found the lane's tickets.Fix
engine::state::cancelled_result: in a lane it writes the lane slot with status"cancelled"and goes toEND. Outside a lane the behaviour is unchanged."pending", and re-activates through aSendcarrying the same lane envelope, including the scatter step from the stacked fix.gatherskips"pending"and"cancelled"slots when counting arrivals.NodeContext::slotreturns the lane slot when present, otherwise the top-level slot. Gate and approval read through it.Validation
On a Linux build host, merged onto main 8b22179:
cargo test --workspace --all-features --locked: 2866 passed, 0 failed, 35 ignored (no new ignores).tests/lane_top_level_writes_tests.rson its base (the stacked fix alone) fails all three tests. Boundary cancel and retry cancel fail with "lane body node … has a top-level slot". The re-entering gate fails with "graph exceeded the recursion limit of 200 steps", because its re-activation left the lane. All three pass with this change.-D warnings, fmt,cargo +1.88.0 check --all-features, rustdoc-D warnings.Tests
tests/lane_top_level_writes_tests.rs(mockfeature):backoff_ms: 0) and during backoff (backoff_ms: 40) inside a lane;ticketsandfromforms. It asserts no top-level writes at any checkpoint, that the gather never releases while a lane is pending, and that results come in lane order.Found while writing #46's fuzz targets.