Measured live (2026-08-26): one tier-1 recall issues 48 recall→store messages, every one carrying a single op — 22 selects, 15 inserts and 5 updates against `recall_scratch`, 2 FTS, 2 ordered selects, 2 `similar`. 20 of the 48 are pure bookkeeping: the phase machine parks its state in the scratch table because a code cell has no memory between invocations. Each round trip costs ~33 ms of interpreter start on the recall side while the store answers in 0–2 ms.
#295 built the primitive (N tool_calls in one message, one reply with `results[]`) and converted tier 0 (9→1). Its closing comment explicitly deferred the tier-1 fan as "the state-machine refactor"; the roadmap carries the defer. This issue redeems it.
Plan: collapse the phases along the REAL data dependencies — (1) every leg that needs no query vector leaves as ONE bundle, (2) the semantic leg waits on the embedder (external, unavoidable), (3) fusion runs in code and the hydration selects ride out with it (the ids are in hand), (4) axis expansion is one bundle. Target: ≤6 round trips per tier-1 recall, `recall_scratch` shrinks to the one honest waiting spot (embed pending).
Acceptance: identical answers across the scenario suite (invariance gate), ≤6 store messages in a live trace, wall-time before/after in the receipt. The resumption semantics (#152) are re-answered deliberately in the new cut, not by accident.
Measured live (2026-08-26): one tier-1 recall issues 48 recall→store messages, every one carrying a single op — 22 selects, 15 inserts and 5 updates against `recall_scratch`, 2 FTS, 2 ordered selects, 2 `similar`. 20 of the 48 are pure bookkeeping: the phase machine parks its state in the scratch table because a code cell has no memory between invocations. Each round trip costs ~33 ms of interpreter start on the recall side while the store answers in 0–2 ms.
#295 built the primitive (N tool_calls in one message, one reply with `results[]`) and converted tier 0 (9→1). Its closing comment explicitly deferred the tier-1 fan as "the state-machine refactor"; the roadmap carries the defer. This issue redeems it.
Plan: collapse the phases along the REAL data dependencies — (1) every leg that needs no query vector leaves as ONE bundle, (2) the semantic leg waits on the embedder (external, unavoidable), (3) fusion runs in code and the hydration selects ride out with it (the ids are in hand), (4) axis expansion is one bundle. Target: ≤6 round trips per tier-1 recall, `recall_scratch` shrinks to the one honest waiting spot (embed pending).
Acceptance: identical answers across the scenario suite (invariance gate), ≤6 store messages in a live trace, wall-time before/after in the receipt. The resumption semantics (#152) are re-answered deliberately in the new cut, not by accident.