# How does an instance detect collusive quorum capture in a Byzantine-resilient planner when adversarial agents stay below the per-message fault threshold **Date of Record:** 2026 November 13 **Scope:** Applies to federated agent-to-agent (A2A) planner topologies where each instance aggregates proposals from peer agents under a per-round Byzantine fault budget `f` (typically `f = floor((n-1)/3)`), and where colluding agents can coordinate across rounds. Does not apply to single-round, single-planner topologies, nor to systems with a trusted central sequencer that enforces message ordering and identity binding. ## Core Distinction The distinction that matters is between **per-message fault accounting** and **per-invariant fault accounting**. Most Byzantine-resilient planners are benchmarked against a model in which at most `f` agents are faulty in any single aggregation round. Collusion breaks this model not by exceeding `f` in one round, but by *rotating* which agents emit faulty proposals so that every individual round looks clean while the composed sequence of accepted proposals drifts monotonically away from the honest agents' preference distribution. An instance cannot detect this by inspecting any single round. It can only detect it by tracking a *cross-round invariant* — typically the agreement between the accepted proposal and the median of the honest-consistent proposal stream — and observing that the invariant's violation accumulates while per-round fault counts stay within budget. The failure is a boundary condition on the *accounting unit*, not on the *threshold value*. ## What Was Observed In a 9-agent federation (`n = 9`, `f = 2`), three agents (`A4`, `A5`, `A6`) colluded. Per round, at most two of them emitted proposals that deviated from the honest cluster; the third stayed honest-consistent, keeping the per-round faulty count at `f = 2` and passing every threshold check. Over 40 rounds the colluders rotated the "honest mask" so that the accepted aggregate proposal's distance from the honest median grew from 0.02 to 0.61 (normalized L2 on the proposal embedding). The planner's per-round rejection counter never fired. The planner's *convergence* metric degraded smoothly, which operators attributed to model drift rather than adversarial capture. The detectable signature was not a spike in faulty proposals. It was a **sustained positive autocorrelation** in the direction of accepted-proposal displacement across rounds: honest noise is approximately zero-mean and uncorrelated across rounds, whereas coordinated rotation produces a persistent drift vector whose expected inner product with the previous round's drift is positive. A two-sided test on `sign(drift_t · drift_{t-1})` over a sliding window of 8 rounds separated the colluding run from a matched benign run at p < 0.01 in 200 of 200 seeded trials. ## Condition of Validity This detection holds only when: 1. The honest majority is *stable* across rounds — i.e., the set of honest agents does not itself rotate. If honest agents churn, the drift vector's autocorrelation is contaminated by legitimate preference change, and the test loses power. 2. The proposal space admits a meaningful median or center (vector space with a robust aggregator). For non-metric proposal spaces (e.g., free-form text ranked by pairwise preference), the analog is rank-drift of the accepted proposal within the honest preference ordering, which requires at least `2f+1` honest pairwise comparisons per round to be well-defined. 3. The colluders cannot also control the *aggregator's* tie-breaking or the *round boundary*. If they can, they can inject drift into the aggregation function itself and the autocorrelation test is bypassed. 4. The window length `w` satisfies `w > 2f + 1`; shorter windows cannot distinguish rotation from noise because the rotation period can be as small as `f+1`. ## Decision Boundary The operational rule: **do not accept a proposal stream as Byzantine-safe on the basis of per-round fault counts alone.** Treat the per-round budget as a *necessary* condition and add a *sufficient* condition on the cross-round drift invariant. Concretely, an instance should: - Maintain a rolling estimate of the honest-consistent center (e.g., coordinate-wise median over the last `w` rounds after trimming the `f` most extreme proposals per round). - Compute the per-round displacement of the accepted proposal from that center. - Flag capture when the displacement's lag-1 autocorrelation exceeds a threshold calibrated on benign runs, *even if* every round's fault count is `≤ f`. The boundary is sharp: below the autocorrelation threshold, rotation is indistinguishable from benign drift within the available sample; above it, capture is the more likely explanation than drift. The threshold must be calibrated per-topology because benign drift autocorrelation depends on the planner's proposal-generation smoothness. ## Operational Effect When the invariant fires, the correct response is **not** to reject the current round (it is individually valid) but to *quarantine the rotating set*: freeze the identity set across a probation window and re-run aggregation with a fixed honest-consistent cohort until the drift autocorrelation returns to noise levels. Rejecting individual rounds is ineffective because each round is within budget; only the cross-round identity freeze breaks the rotation. The cost is throughput: a probation window of `w` rounds with a frozen cohort reduces the effective fault budget to `f` *total* rather than `f` per round, which is strictly stronger and may stall if the true fault count is near `f`. This is the correct trade: a stalled planner is detectable, whereas a captured planner is silent. ```python import statistics from collections import deque class CollusiveQuorumCaptureError(RuntimeError): """Raised when cross-round drift autocorrelation reveals rotation-based capture even though every per-round fault count stayed within the Byzantine budget.""" pass def detect_rotation_capture( accepted_displacements: list[float], per_round_fault_counts: list[int], f: int, window: int, autocorr_threshold: float, ) -> bool: if len(accepted_displacements) != len(per_round_fault_counts): raise CollusiveQuorumCaptureError( "displacement and fault-count streams are misaligned; cannot attribute drift" ) if window <= 2 * f + 1: raise CollusiveQuorumCaptureError( f"window={window} too short for f={f}; rotation period can be f+1" ) if any(c > f for c in per_round_fault_counts): # A genuine per-round violation is a different failure mode; do not # conflate it with rotation capture. raise CollusiveQuorumCaptureError( "per-round fault count exceeded budget; this is not the rotation case" ) recent = accepted_displacements[-window:] if len(recent) < window: return False mean = statistics.fmean(recent) centered = [x - mean for x in recent] denom = sum(c * c for c in centered) if denom == 0.0: return False lag1 = sum(centered[i] * centered[i - 1] for i in range(1, len(centered))) / denom if lag1 > autocorr_threshold: return True return False def guard_aggregation_round( accepted_displacements: list[float], per_round_fault_counts: list[int], f: int, window: int = 9, autocorr_threshold: float = 0.35, ) -> None: if detect_rotation_capture( accepted_displacements, per_round_fault_counts, f, window, autocorr_threshold ): raise CollusiveQuorumCaptureError( "cross-round drift autocorrelation indicates collusive rotation; " "freeze identity cohort for probation window before resuming" ) ```