# Anti-Smuggle Refactor Plan — Implementation Design **Generated:** 2026-06-29 **Source:** AGENTS.md "Beyond Rigorous — Anti-Smuggle Protocol" (§5) **Design agents:** Layers 0+1 (determinism + cross-validation), Layers 2+3 (mutation testing + CAS/SMT) --- ## Overview 15 new files, ~1,400 lines total, zero changes to Lean source code. | Layer | Files | Est. Effort | Verdict When Missing | |-------|-------|-------------|---------------------| | 0: Determinism | 3 new + 15 shim modifications | 3 hr | Non-reproducible artifacts | | 1: Cross-validation | 2 new | 2.5 hr | Single-LLM blind spots | | 2: Mutation testing | 7 new | 2.5 hr | Verifier passes bad proofs | | 3: CAS/SMT grounding | 1 new | 2 hr | Vacuous/tautological proofs | | **Entry gate** | 1 new + 1 CI | 0.5 hr | — | | **Total** | **15 new** | **~10.5 hr** | | --- ## Layer 0: Deterministic Reproducibility (scripts/seedlock.py + check_determinism.py) ### Core: scripts/seedlock.py - `SeededRNG(seed)` class — canonical RNG using Python's `random.Random` (stable across CPython versions) - `lock(seed)` — monkey-patches `random.seed()` and `np.random.seed()` to raise `RuntimeError` after locking - All existing Python shims (`python/*.py`, `qubo/*.py`) gain `--seed 0` parameter - Every `np.random.default_rng()` → `SeededRNG(seed).np_random()` ### Scanner: scripts/check_determinism.py - Checks all artifacts in `extraction/` for `content_sha256` hash chain integrity - Scans Python sources for unseeded RNG calls → exit code 3 on violation - Supports `--seed 0`, `--receipt-dir`, `--check-all`, `--output` - Receipt: `anti_smuggle_layer0_receipt_v1` ### Shim modifications (15 files) All `python/*.py` and `qubo/*.py` gain argparse `--seed` (default 0). `seedlock.SeedingRNG` replaces all bare `random.Random()` and `np.random.default_rng()` calls. --- ## Layer 1: Cross-Validation (scripts/cross_validate.py) ### Key design constraint Does NOT call LLMs directly. User provides proof files from 2+ models — verification is offline, no API keys embedded. ### Workflow 1. Extract provenance headers from `.lean` files (`# Provenance: model=..., generation_id=...`) 2. Extract theorem signatures (name + type) from both files 3. Build both independently (`lake build SilverSightRRC`) 4. Equivalence check: normalize binder names to canonical form, compare statement types 5. Receipt: `anti_smuggle_layer1_crossval_v1` ### CLI ``` python3 scripts/cross_validate.py \ --model-a-proof path/to/A.lean --model-b-proof path/to/B.lean \ --model-a-label gemma4-12b --model-b-label deepseek-v4-flash \ --lean-target SilverSightRRC --output crossval_receipt.json ``` --- ## Layer 2: Mutation Testing (scripts/qc-flag/) ### Directory structure ``` scripts/qc-flag/ __init__.py # Empty __main__.py # CLI: python3 -m scripts.qc-flag manifest.json # 22 mutations across 6 modules mutation_generator.py # Regex-based mutation engine mutation_runner.py # Backup → build → restore → score mutations/.gitkeep # Generated mutation Lean files receipts/.gitkeep # Per-run coverage receipts ``` ### Manifest (22 mutations over 6 modules) | Module | Theorems | Mutations | Pattern | |--------|----------|-----------|---------| | `HachimojiN8.lean` | `n8_satisfies`, `n8_is_minimum`, `n8_unique`, `n8_necessity` | 9 | `= true` ↔ `= false`, `↔` → `→`, `≥` → `<` | | `RRC/Emit.lean` | `ncDerived_mul`, `ncDerived_independence_justification` | 4 | `mul` → `add`, `True` → `False` | | `FisherRigidity.lean` | `spectralGapIntCompare` | 2 | `>` → `<`, `9984` → `9361` | | `CartanConnection.lean` | `Jacobiator_basis_all`, `Jacobiator_basis_zero` | 2 | `= ∅` → `≠ ∅`, `= 0` → `= 1` | | `HachimojiN8Bridge.lean` | `hachimoji_card...` | 2 | `Fintype.card = 8` → `= 7` | | `ReceiptCore.lean` | `hasReceiptOfKind` | 2 | `r.valid` → `¬r.valid` | ### Protocol 1. Back up original `.lean` file 2. Copy mutation over source 3. `lake build SilverSightRRC` — expect FAIL 4. Restore original 5. Coverage = `#failed / #total`. Verdict FAIL if any mutation passes the build --- ## Layer 3: CAS/SMT Grounding (scripts/verify_with_sympy.py) ### Three extractors, one verifier engine **Extractor A: Q16_16.ofRatio** — extract all `Q16_16.ofRatio N D` patterns from Lean sources. Compute expected raw value = `floor(N * 65536 / D)` in SymPy. Compare with Lean build output. **Extractor B: ncDerived chain** — for each FixtureRow fixture, follow the computation chain: - `residualRisk × scaleBandDeclared → ncDerived` - SymPy: `Rational(n1, d1) * Rational(n2, d2)` - Compare Q16_16 raw values: `floor(expr * 65536)` **Extractor C: Z3 SMT-LIB2** — for each `by decide`/`by native_decide` block, generate an SMT2 script with the negated goal. Run `z3 -smt2` and expect `unsat`. ### Receipt: cas_verification_receipt_v1 ```json { "sympy_results": {"ofratio_checks": 95, "match": 95, "ncderived_chains": 6, "match": 6}, "z3_results": {"scripts": 7, "unsat": 7, "sat_unexpected": 0}, "verdict": "PASS" } ``` --- ## Entry Gate (scripts/run_entry_gate.sh) ```bash #!/usr/bin/env bash set -euo pipefail echo "=== Layer 0: Determinism ==="; python3 scripts/check_determinism.py --seed 0 echo "=== Layer 1: Cross-Validation ==="; python3 scripts/cross_validate.py echo "=== Layer 2: Mutation Suite ==="; python3 -m scripts.qc-flag --run echo "=== Layer 3: CAS/SMT Grounding ==="; python3 scripts/verify_with_sympy.py echo "=== Build Gate ==="; lake build SilverSightRRC echo "=== ALL 5 LAYERS PASS ===" ``` --- ## Zero Changes to Lean Source The anti-smuggle protocol is entirely external to the formal content: - Mutations are generated as separate files that temporarily overwrite originals - No Lean pragmas, feature flags, or `@[mutation]` attributes - Backup/restore protocol keeps the checkout clean between tests - `lake build SilverSightRRC` stays as the single build target --- ## Risk Register | Risk | Mitigation | |------|-----------| | LLM hallucinates fake `# Provenance:` headers | Cross-validate proves only build equivalence; generation_id is audit-only | | Two models produce syntactically different but semantically identical statements | Equivalence checker normalizes alpha-renaming; CAS grounding catches numeric disagreement | | `np.random.default_rng(seed)` differs between numpy versions | Canonical RNG is Python's `random.Random` (stable across CPython) | | Mutation backup/restore race in CI | Sequential execution per file; single worker by default | | Z3 unavailable on CI | Skippable with `--skip-z3`; CAS-only mode available |