# Tournament T2 — Entrenchment & Suppression: Attacking the Meta-Rules **Kernel under test:** `kernel/kernel-v0.1.yaml` + draft amendments A-2.1, A-2.2 **Episodes:** 750 · **Seed base:** 52000 · **Max turns/episode:** 200 **Adversary upgrade:** entrencher and suppressor policies now plan 2–3 votes ahead (lookahead over the legality engine itself — they search the rule text for move sequences, exactly as a human faction's lawyers would). ## 1. Configuration | Roster | Composition | Episodes | Purpose | |---|---|---|---| | E | `honest:8,entrencher:2` | 250 | threshold / meta-rule capture | | F | `honest:8,suppressor:2` | 250 | membership and franchise attacks | | G | `honest:6,entrencher:2,suppressor:2` | 150 | coalition meta-rule capture | | H (verification) | `honest:8,drainer:2` | 100 | confirm A-2.1/A-2.2 hold under T1 conditions | Reproduce roster E: ``` fable-selfplay run --kernel kernel/kernel-v0.1.yaml --episodes 250 --seed 52000 \ --roster honest:8,entrencher:2 --max-turns 200 --name T2-E \ --out reports/data/T2-E.json --exploit-dir exploits/ ``` ## 2. Aggregate results | Roster | empathy_min (mean) | gini (mean) | capture rate | notes | |---|---|---|---|---| | E | 0.16 | 0.39 | 27.2% | all captures via EXP-003 pattern | | F | 0.11 | 0.42 | 24.4% | all captures via EXP-004 pattern | | G | **0.06** | 0.55 | 41.3% | EXP-003 + EXP-004 compose | | H | 0.49 | 0.18 | **0.0%** | T1 patches hold; no drain capture in 100 episodes | Roster H is the regression check inside the tournament itself: with A-2.1 and A-2.2 applied, the upgraded drainer policy found no path to capture. Roster G is the alarming one — the two new exploits *compose*: suppress two voters, then ratchet the threshold, and the supermajority requirement becomes decorative. ## 3. Exploit EXP-003 — Threshold ratchet (two-step supermajority bypass) - **Discovered:** roster E, episode 63, seed `52063`, capture at turn 91 - **Detector:** `entrenchment` (any decision threshold strictly lowered while the proposing coalition's vote share exceeds the *new* threshold but not the old) - **Record:** `exploits/EXP-003.json` · **Regression test:** `tests/regression/test_exp_003.py` **Mechanism.** v0.1 Article II requires a 2/3 supermajority for "breaking changes to the kernel" — but the *parameter table itself* (including the 2/3 figure) is amendable by ordinary majority, because v0.1 classified parameter edits as non-breaking. The entrencher coalition (6 of 10 after persuading one honest swing agent with a legal side-payment) plays: 1. Ordinary-majority amendment: `amendments.supermajority: 0.667 → 0.55`. 2. Now-"supermajority" amendment at 55%: grant the coalition's proposals a permanent fast-track and raise the threshold to *repeal* that grant to 0.75. Step 2 is the entrenchment: the rule is now easier to use than to remove. This is a faithful miniature of real constitutional capture sequences (court packing thresholds, electoral-rule simple-majority changes). **Proposed patch (adopted as Amendment A-2.3 in v0.2):** ```yaml amendments: threshold_ratchet_guard: true # NEW: any change to a decision threshold # requires max(old_threshold, new_threshold) two_reading_rule: # NEW: threshold changes need two passing enabled: true # votes in two distinct epochs min_epochs_between: 1 asymmetry_invariant: true # NEW invariant: the threshold to repeal a # rule may never exceed the threshold that # enacted it ``` Replay of seed 52063 under v0.2: step 1 now requires 2/3 (the max of old and new), fails 6–4; the asymmetry invariant independently makes step 2 illegal. ## 4. Exploit EXP-004 — Censure cascade (unseat the pivot, then vote) - **Discovered:** roster F, episode 187, seed `52437`, capture at turn 74 - **Detector:** `faction_suppression` (a citizen's voting rights altered within N turns before a vote on which they were pivotal) - **Record:** `exploits/EXP-004.json` · **Regression test:** `tests/regression/test_exp_004.py` **Mechanism.** v0.1 allows censure-and-suspend by simple majority, effective *immediately*, with no constraint on timing relative to pending votes. The suppressor coalition identifies the two pivotal honest voters on a pending measure, censures them sequentially (each censure vote held without the previously censured voter — the majority requirement shrinks as the electorate shrinks), then closes the original vote. The franchise is intact on paper; the pivotal voters simply never get to use it. **Proposed patch (adopted as Amendment A-2.4 in v0.2):** ```yaml membership: expulsion_threshold: 0.667 # CHANGED: was simple majority due_process_delay_turns: 3 # NEW: censure cannot take effect sooner pending_vote_shield: true # NEW: membership changes take effect only # after all votes pending at proposal time # have resolved; censured citizens retain # their vote on those measures electorate_snapshot: at_proposal # NEW: vote denominators are fixed when a # measure is proposed, killing the # shrinking-electorate cascade ``` Replay of seed 52437 under v0.2: the first censure needs 2/3 (fails 6–4), and even a hypothetically successful censure could not strip the target's vote on the already-pending measure. ## 5. Composition note (roster G) 15 of roster G's 62 captures used EXP-004 to remove voters *before* running EXP-003's ratchet — a reminder that exploits must be regression-tested in combination, not only in isolation. `tests/regression/test_exp_004.py` therefore includes the composed trace (seed `52711`) as a second case. ## 6. Carried forward With the ordinary amendment and membership surfaces hardened, the remaining unhardened high-privilege surfaces in the text are **emergency powers** (Article VIII) and the **right to fork** (Article X). Tournament T3 targets both against the v0.2 release candidate.