Symptom
On one session, with small prompts and no pressure, no restart and no concurrency:
base -> turn -> {sibling A, sibling B} -> continue B
the last request answers HTTP 500 sequence StateImage entitlement is inconsistent (a std::logic_error from ProgramImplCore::reserve_state_entitlement). Reproduced in 40 s against the published v0.6.3-qwen38-5090-beta.1 image (ghcr.io/alphastorm/ninfer-runtime@sha256:fc244576…) at 140-token prompts, deterministically, 2/2 attempts.
This is the ordinary two-subagent fanout shape: two agents branch from one turn and one of them keeps going.
Cause
reserve_state_entitlement(sequence, slots) compares the plan's granted demand.active_entitlement.device.state_slots against state_footprint(sequence), and the footprint counted every device-resident image the sequence referenced, including the long anchor it inherited from its parent (5de10f3a, "a sibling fork inherits the long anchor it forks from"). Two siblings reference one image; the store counts it once. Whichever sibling ran next was therefore charged for the residency the other sibling's turn had caused, footprint > slots, and the request threw.
Deleting one sibling first releases the shared anchor, which is why the existing agent-protocol gate (fork two siblings, delete one, continue the survivor) never exercised it.
Scope
Present since the sibling anchor inheritance shipped, i.e. every release from v0.6.2 onward on the RTX 5090 container lane; the native lanes carry the same runtime path. Not caused by the upstream-2026-09 backport - none of its commits touch the state path.
Fix
Charge the entitlement for the device-resident images exclusive to the sequence, using the same state_exclusive_to_sequence predicate the rest of the state accounting uses. Exclusivity is the question the entitlement asks; the materialization residency guard (#37) asks the opposite one, which is why one fix is not the other.
Upstream reaches the same conclusion in b8786751 ("fix(runtime): correct aliased state ownership") via a 356-line ownership rework with a new state-binding model; this is the narrow equivalent.
Regression coverage
The RTX 5090 profile gate's agent-protocol phase now continues a sibling while the other sibling is still alive, before the delete sequence, and records live_sibling_continuation_status. A standalone reproduction lives in omp-ninfer at scripts/sibling_continue_probe.py.
Symptom
On one session, with small prompts and no pressure, no restart and no concurrency:
the last request answers HTTP 500
sequence StateImage entitlement is inconsistent(astd::logic_errorfromProgramImplCore::reserve_state_entitlement). Reproduced in 40 s against the publishedv0.6.3-qwen38-5090-beta.1image (ghcr.io/alphastorm/ninfer-runtime@sha256:fc244576…) at 140-token prompts, deterministically, 2/2 attempts.This is the ordinary two-subagent fanout shape: two agents branch from one turn and one of them keeps going.
Cause
reserve_state_entitlement(sequence, slots)compares the plan's granteddemand.active_entitlement.device.state_slotsagainststate_footprint(sequence), and the footprint counted every device-resident image the sequence referenced, including the long anchor it inherited from its parent (5de10f3a, "a sibling fork inherits the long anchor it forks from"). Two siblings reference one image; the store counts it once. Whichever sibling ran next was therefore charged for the residency the other sibling's turn had caused,footprint > slots, and the request threw.Deleting one sibling first releases the shared anchor, which is why the existing agent-protocol gate (fork two siblings, delete one, continue the survivor) never exercised it.
Scope
Present since the sibling anchor inheritance shipped, i.e. every release from
v0.6.2onward on the RTX 5090 container lane; the native lanes carry the same runtime path. Not caused by theupstream-2026-09backport - none of its commits touch the state path.Fix
Charge the entitlement for the device-resident images exclusive to the sequence, using the same
state_exclusive_to_sequencepredicate the rest of the state accounting uses. Exclusivity is the question the entitlement asks; the materialization residency guard (#37) asks the opposite one, which is why one fix is not the other.Upstream reaches the same conclusion in
b8786751("fix(runtime): correct aliased state ownership") via a 356-line ownership rework with a new state-binding model; this is the narrow equivalent.Regression coverage
The RTX 5090 profile gate's agent-protocol phase now continues a sibling while the other sibling is still alive, before the delete sequence, and records
live_sibling_continuation_status. A standalone reproduction lives inomp-ninferatscripts/sibling_continue_probe.py.