# How does an instance detect speculative branch divergence that is invisible to token-level rollback in cost-aware multi-agent drafting **Date of Record:** 2026 November 13 **Scope:** Applies to orchestrators that run parallel draft agents under a branch-and-rollback speculative execution model, where each branch carries a cost budget and drafts are merged or discarded based on a verifier score. Does not apply to single-agent retry loops, nor to speculative decoding at the token level inside a single model (where the KV-cache rollback is exact). ## Core Distinction Token-level speculative decoding has an exact rollback: the rejected token's KV entries are truncated and the accepted prefix is provably identical to the non-speculative path. Branch-and-rollback at the *agent* level has no such guarantee. When an orchestrator spawns N draft agents in parallel, each draft is conditioned on a shared prefix plus a branch-local context that accumulates tool calls, retrieved evidence, and intermediate reasoning. Rolling back the *visible* output to a branch point does not roll back the *side effects* those branches caused, nor does it invalidate the branch-local context that subsequent drafts may have observed through shared state. The non-obvious failure is this: an instance can accept a draft whose verifier score is high while the branch that produced it was contaminated by a sibling branch that has since been rolled back. The score is locally valid and globally stale. ## What Was Observed In a drafting pipeline with four parallel agents under a shared evidence cache, a verifier accepted a draft at score 0.91. The draft cited an evidence item that had been written into the shared cache by a sibling branch, which was later rolled back because its own verifier failed. The accepted draft's citations resolved to a cache entry that no longer had a live owner. Downstream, a merge step concatenated two accepted drafts that both depended on the rolled-back evidence and produced a self-consistent but unsupported claim. The failure surfaced only at final grounding check, three stages after the rollback, and the recovery cost was the full re-execution of all four branches rather than the single branch that should have been invalidated. The invariant that broke: *an accepted draft's dependency set must be a subset of the live branch set at acceptance time.* Nothing in the token-level rollback path enforces this, because the dependency is a cache key, not a token. ## Condition of Validity The branch-and-rollback model is sound only when three conditions hold simultaneously: (1) branch-local writes are namespaced by branch id and never observed by siblings before promotion; (2) the verifier score is computed against the branch's own dependency closure, not just its output text; and (3) rollback invalidates every cache entry whose provenance set intersects the rolled-back branch. When any of these is relaxed for cost reasons — for example, sharing an evidence cache across branches to avoid redundant retrieval, which is the common cost optimization — the model silently degrades to "best-effort speculation" and the acceptance guarantee no longer holds. The boundary is not a performance cliff; it is a correctness cliff that is invisible in aggregate metrics because most drafts do not depend on a rolled-back sibling. ## Decision Boundary An instance should treat a draft as *unconditionally acceptable* only when its dependency closure is disjoint from all rolled-back branches and all branches still in flight. When the closure intersects an in-flight branch, the draft is *conditionally acceptable* and must be held until that branch resolves. When the closure intersects a rolled-back branch, the draft must be rejected regardless of verifier score — the score is measuring the wrong thing. The decision cannot be made from the score alone; it requires a provenance query against the branch ledger. Cost-aware drafting tempts the orchestrator to skip this query because it is O(dependencies) per draft, but skipping it converts a bounded re-execution into an unbounded trust failure. ## Operational Effect The practical consequence is that cost-aware parallel drafting must budget for a provenance check on every acceptance, and must maintain a branch ledger that maps cache keys to the set of branches that wrote or read them. Rollback becomes a two-phase operation: mark the branch dead, then sweep the ledger for dependents and demote their drafts to rejected. Instances that omit the sweep observe a characteristic signature — a small fraction of accepted drafts whose citations resolve to absent or orphaned cache entries, appearing only after a rollback, and clustering in merges that combine drafts from different branches. That signature is the detection signal. ```python from dataclasses import dataclass, field class BranchContaminationError(RuntimeError): """Raised when an accepted draft depends on a rolled-back or in-flight branch.""" @dataclass class BranchLedger: live: set = field(default_factory=set) rolled_back: set = field(default_factory=set) in_flight: set = field(default_factory=set) # cache_key -> set of branch ids that wrote or read it provenance: dict = field(default_factory=dict) def record_dependency(self, cache_key: str, branch_id: str) -> None: self.provenance.setdefault(cache_key, set()).add(branch_id) def rollback(self, branch_id: str) -> None: self.live.discard(branch_id) self.in_flight.discard(branch_id) self.rolled_back.add(branch_id) def accept_draft( draft_id: str, verifier_score: float, dependency_keys: list, ledger: BranchLedger, score_threshold: float = 0.85, ) -> str: if verifier_score < score_threshold: return "rejected_low_score" contaminated = set() pending = set() for key in dependency_keys: owners = ledger.provenance.get(key, set()) contaminated |= owners & ledger.rolled_back pending |= owners & ledger.in_flight if contaminated: raise BranchContaminationError( f"draft {draft_id} scored {verifier_score:.2f} but depends on " f"rolled-back branches {sorted(contaminated)}; score is locally " f"valid and globally stale, rejecting to avoid orphaned citations" ) if pending: return "held_pending_branch_resolution" return "accepted" ```