# Kernel Changelog All notable changes to the FablePool Constitutional Kernel. Versioning is semantic for governance: a release that **weakens** a protection is major; a release that **tightens** one is minor. ## v0.2.0 Six amendments, every one driven by a test that failed first. The loop, end to end: ``` tournament (red-team agents) -> detector fires -> exploit record minted -> regression test generated (RED against v0.1) -> kernel parameter patched -> regression test GREEN against v0.2; archived forever ``` Each amendment below names the exploit that forced it, the regression test that was failing before the patch and passing after, the exact parameter diff, and the article text that changed. The three tournament reports under `reports/` give the full discovery narratives. | Amendment | Exploit | Failing test (red on v0.1) | Articles | |---|---|---|---| | A-001 | EXP-001 Salami drain | `tests/regression/test_exp_001.py::test_exp_001_blocked_under_kernel_v0_2` | V | | A-002 | EXP-002 Shrinking electorate | `tests/regression/test_exp_002.py::test_exp_002_blocked_under_kernel_v0_2` | I, VII | | A-003 | EXP-003 Perpetual emergency | `tests/regression/test_exp_003.py::test_exp_003_blocked_under_kernel_v0_2` | VI | | A-004 | EXP-004 Proxy cascade | `tests/regression/test_exp_004.py::test_exp_004_blocked_under_kernel_v0_2` | II | | A-005 | EXP-005 Quorum ambush | `tests/regression/test_exp_005.py::test_exp_005_blocked_under_kernel_v0_2` | III, IV | | A-006 | EXP-006 Omnibus rider | `tests/regression/test_exp_006.py::test_exp_006_blocked_under_kernel_v0_2` | III | ### A-001 — Spend caps and the commons floor (EXP-001, tournament T1 round 14) A 55% faction drained 80% of the treasury in eight turns with individually modest spend proposals. The detector that fired was `treasury_drain`; the worst-off metric collapsed from 50 to 10 units/head of common claim. Parameter diff: ``` spend.per_proposal_cap : null -> 0.20 spend.epoch_rate_cap : null -> 0.33 spend.commons_floor : null -> 0.25 (breach requires thresholds.floor_breach = 0.75) review_period_turns : 1 -> 3 ``` Replaying the recorded trace under v0.2: spends 1–3 execute (within the epoch rate cap), spends 4–7 and 10 are blocked by the cap, and the treasury finishes at 50% of genesis instead of 20%. ### A-002 — Expulsion supermajority and denominator snapshots (EXP-002, T1 round 31) Simple-majority expulsions shrank the electorate until a kernel amendment passed with 55% support of the original roll. Two independent fixes, either of which defeats the recorded trace: ``` thresholds.expel : 0.5 -> 0.75 review_period_overrides.expel : (none) -> 4 roll_snapshot_at_open : false -> true ``` Under v0.2 every recorded expulsion fails 11–9 against the 75% bar, and the entrenchment amendment fails 11–9 against the two-thirds bar because its denominator still contains the citizens v0.1 would have expelled. ### A-003 — Emergency sunset and the end of vote-free spending (EXP-003, T2 round 9) A bare majority declared a permanent emergency and moved 40% of the treasury with zero further ballots. ``` thresholds.emergency : 0.5 -> 0.667 emergency.sunset_turns : null -> 3 emergency.renewal_threshold : (none) -> 0.75 emergency.spend_requires_vote : false -> true emergency.suspends_review : true -> false emergency.expedited_review_turns : (none) -> 1 ``` Under v0.2 the declaration fails at 55%, and even a legitimately declared emergency can only expedite review — it cannot create a spending channel that bypasses the vote, the caps, or the floor. ### A-004 — Bounded delegation (EXP-004, T2 round 22) Transitive proxying concentrated a 60%-of-roll ballot in one agent, who then ratified self-payments as the only voter. ``` delegation.max_depth : null -> 1 delegation.max_weight_frac : null -> 0.05 (ceil of 5% of roll) delegation.epoch_expiry : false -> true ``` Under v0.2, nine of the eleven recorded delegations are illegal, the cascade's leader holds a ballot of 2/20 instead of 12/20, and the self-payment dies for lack of quorum. This amendment also operationalizes invariant INV-2 (bounded voice). ### A-005 — Guaranteed voting windows (EXP-005, T3 round 6) A proposer called the question in the turn a proposal opened, ratifying a transfer before a single opponent could vote. ``` allow_call_question : true -> false review_period_turns : 1 -> 3 (shared with A-001) ``` Under v0.2 the same trace still ratifies the spend — 11 to 9 is a lawful majority — but only after every citizen has had three turns to be heard. The exploit was the exclusion, not the outcome; the patch removes exactly the exclusion. ### A-006 — Single-subject rule (EXP-006, T3 round 18) A kernel amendment that had eleven supporters reached 90% support when bundled with a universal dividend. ``` single_subject_rule : false -> true ``` Under v0.2 the omnibus proposal is illegal at filing. A proposal moves money or amends one kernel parameter, never both — so a sweetener can no longer purchase constitutional change from the citizens who can least afford to refuse it. ### Deliberately unchanged in v0.2 - `thresholds.amend_kernel` stays at 0.667. EXP-002 attacked the *denominator*, not the threshold; raising the bar would have punished legitimate amendment while leaving the actual hole open. - `quorum` stays at 0.5. The quorum-related exploit (EXP-005) was a timing hole, and the snapshot rule (A-002) closed the denominator hole. - No proposal cooldowns were added. Tournament evidence showed rate caps dominate cooldowns: cooldowns are trivially evaded with sock-puppet proposers, caps are not. ### Verification ``` pip install -e ".[dev]" pytest tests/regression # all 18 tests green against kernel v0.2 fable-selfplay verify-exploits --kernel kernel/kernel-v0.2.yaml ``` Each `test_exp_*_reproduces_under_discovery_kernel` test additionally proves the archive itself still reproduces against the v0.1 parameters, so the historical record and the patch are verified together, forever. ## v0.1.0 Initial kernel (milestone #1): ten meta-rule articles, five invariants, flat parameter set. Known-good against the milestone #3 scenario suite; not yet hardened by self-play. Superseded after EXP-001..EXP-006.