Research-Stack/0-Core-Formalism/lean/Semantics/Semantics/GeneticsPromotionGate.lean
2026-05-05 21:26:18 -05:00

296 lines
12 KiB
Text

/-
GeneticsPromotionGate.lean — Mass Number Gate for Genetics Model Promotion
Wires the core MassNumber admissibility gate into genetics-specific promotion.
Every genetics model must pass this gate before being promoted from
REGISTRY_ONLY → CANONICAL_PLUMBED.
Gate criteria:
1. MassLeDefault (admissible <= threshold * guarded_residual)
2. depth <= 2 (no deep abstraction recursion in biological claims)
3. boundCheck = true (must declare data source and validation plan)
4. biological_equivalence_check (must not claim DNA equivalence without receipt)
5. taxonomy_gap_fill (must declare which GCCL group it covers)
Reference:
- Semantics/Core/MassNumber.lean (three-layer gate)
- otom/docs/genetics_information_substrate_boundary.md (four buckets)
-/
import Semantics.Core.MassNumber
namespace Semantics.GeneticsPromotionGate
open Q16_16
/- ============================================================================
§0 Genetics-Specific Promotion Criteria
============================================================================ -/
/-- Which GCCL taxonomy group this model claims to cover.
Must be explicit — "none" is allowed but means the model is generic. -/
inductive GCCLGroup
| A_molecular_alphabets
| B_codon_translation
| C_protein_peptide
| D_ambiguity_degeneracy
| E_sequence_file_quality
| F_alignment_assembly_graph
| G_variant_haplotype_population
| H_annotation_feature
| I_epigenetic_regulatory
| J_structural_3d_genome
| K_expression_multi_omics
| L_compression_indexing
| M_synthetic_expanded
| N_gccl_native
| none
deriving Repr, Inhabited, DecidableEq, BEq
/-- A genetics model's self-declared coverage and claim state. -/
structure GeneticsClaim where
modelName : String
gcclGroup : GCCLGroup
hasRealData : Bool -- Does it use biological data (gnomAD, NCBI, etc.)?
hasLeanProof : Bool -- Is there a compiled Lean module?
hasPythonImpl: Bool -- Is there a running Python script?
hasDataReceipt: Bool -- Does it declare data source + validation plan?
claimsBiologicalEquivalence : Bool -- Dangerous: claims "GCCL is DNA" etc.
deriving Repr, Inhabited
/-- Default claim for a new model (conservative, no claims). -/
def defaultClaim (name : String) : GeneticsClaim :=
{ modelName := name
, gcclGroup := .none
, hasRealData := false
, hasLeanProof := false
, hasPythonImpl := false
, hasDataReceipt := false
, claimsBiologicalEquivalence := false
}
/- ============================================================================
§1 The Genetics Promotion Gate
============================================================================ -/
/-- Calculate admissible reduction for a genetics model.
Scoring:
- hasLeanProof: +3 (formalization is high value)
- hasPythonImpl: +2 (running code is medium value)
- hasRealData: +2 (grounding in biology is medium value)
- hasDataReceipt: +1 (hygiene is low but necessary)
- fillsZeroGroup: +2 (filling a gap is valuable)
- claimsBiologicalEquivalence: -10 (heavily penalized)
-/
def admissibleReduction (claim : GeneticsClaim) (fillsZeroGroup : Bool) : Q16_16 :=
let withLean := if claim.hasLeanProof then Q16_16.ofNat 3 else Q16_16.zero
let withPython := if claim.hasPythonImpl then Q16_16.ofNat 2 else Q16_16.zero
let withData := if claim.hasRealData then Q16_16.ofNat 2 else Q16_16.zero
let withReceipt := if claim.hasDataReceipt then Q16_16.ofNat 1 else Q16_16.zero
let withGapFill := if fillsZeroGroup then Q16_16.ofNat 2 else Q16_16.zero
let penalty := if claim.claimsBiologicalEquivalence then Q16_16.ofInt (-10) else Q16_16.zero
withLean + withPython + withData + withReceipt + withGapFill + penalty
/-- Calculate residual risk for a genetics model.
Scoring (higher = more risk):
- !hasLeanProof: +2 (unformalized = risk)
- !hasPythonImpl: +1 (no running code = some risk)
- !hasDataReceipt: +3 (no validation plan = high risk)
- claimsBiologicalEquivalence: +5 (dangerous claim = very high risk)
- depth > 0: +1 per depth (abstraction recursion risk)
-/
def residualRisk (claim : GeneticsClaim) (depth : Nat) : Q16_16 :=
let noLean := if !claim.hasLeanProof then Q16_16.ofNat 2 else Q16_16.zero
let noPython := if !claim.hasPythonImpl then Q16_16.ofNat 1 else Q16_16.zero
let noReceipt := if !claim.hasDataReceipt then Q16_16.ofNat 3 else Q16_16.zero
let bioClaim := if claim.claimsBiologicalEquivalence then Q16_16.ofNat 5 else Q16_16.zero
let depthRisk := Q16_16.ofNat depth
noLean + noPython + noReceipt + bioClaim + depthRisk
/-- The genetics promotion gate.
Parameters:
claim : the model's self-declared claim state
fillsZeroGroup: does this model fill a zero-coverage GCCL group?
depth : recursion depth of abstraction (default 0)
threshold : promotion boundary (default 0.5 = generous)
Returns true iff the model is admissible for promotion.
-/
def geneticsPromotionGate
(claim : GeneticsClaim)
(fillsZeroGroup : Bool)
(depth : Nat := 0)
(threshold : Q16_16 := Q16_16.ofRatio 1 2)
: Bool :=
let a := admissibleReduction claim fillsZeroGroup
let r := residualRisk claim depth
-- Promotion gate: quality must EXCEED threshold * risk
-- (MassLe is designed for cost<=threshold*risk compression decisions;
-- genetics promotion needs quality>threshold*risk)
let qualityBeatsRisk := a.toInt > (threshold * r).toInt
let depthOk := depth ≤ 2
let receiptOk := claim.hasDataReceipt
qualityBeatsRisk && depthOk && receiptOk
/-- Warden rule: if a model claims biological equivalence without receipt,
emit Underverse packet and block promotion. -/
def biologicalEquivalenceWarden (claim : GeneticsClaim) : String :=
if claim.claimsBiologicalEquivalence && !claim.hasDataReceipt then
"UNDERVERSE: biological_equivalence_without_receipt — model " ++ claim.modelName ++ " blocked"
else
"PASS"
/- ============================================================================
§2 Audit Existing Canonical Models
============================================================================ -/
/-- Claim state for GeneticCode.lean -/
def geneticCodeClaim : GeneticsClaim :=
{ defaultClaim "GeneticCode.lean" with
gcclGroup := .B_codon_translation
, hasLeanProof := true
, hasDataReceipt := true -- NCBI Table 1 is well-documented
}
/-- Claim state for CodonOTOM.lean -/
def codonOTOMClaim : GeneticsClaim :=
{ defaultClaim "CodonOTOM.lean" with
gcclGroup := .B_codon_translation
, hasLeanProof := true
, hasDataReceipt := true
}
/-- Claim state for PeptideMoE.lean -/
def peptideMoEClaim : GeneticsClaim :=
{ defaultClaim "PeptideMoE.lean" with
gcclGroup := .C_protein_peptide
, hasLeanProof := true
, hasDataReceipt := true
}
/-- Claim state for GenomicCompression.lean -/
def genomicCompressionClaim : GeneticsClaim :=
{ defaultClaim "GenomicCompression.lean" with
gcclGroup := .L_compression_indexing
, hasLeanProof := true
, hasDataReceipt := true
}
/-- Claim state for SyntheticGeneticCoding.lean -/
def syntheticGeneticCodingClaim : GeneticsClaim :=
{ defaultClaim "SyntheticGeneticCoding.lean" with
gcclGroup := .M_synthetic_expanded
, hasLeanProof := true
, hasDataReceipt := true
}
/-- Claim state for GeneticGroundUp.lean -/
def geneticGroundUpClaim : GeneticsClaim :=
{ defaultClaim "GeneticGroundUp.lean" with
gcclGroup := .N_gccl_native
, hasLeanProof := true
, hasDataReceipt := true
}
/-- Claim state for HachimojiPipeline.lean -/
def hachimojiClaim : GeneticsClaim :=
{ defaultClaim "HachimojiPipeline.lean" with
gcclGroup := .M_synthetic_expanded
, hasLeanProof := true
, hasDataReceipt := true
}
/-- Claim state for CodonPeptideConsistency.lean -/
def codonPeptideConsistencyClaim : GeneticsClaim :=
{ defaultClaim "CodonPeptideConsistency.lean" with
gcclGroup := .B_codon_translation
, hasLeanProof := true
, hasDataReceipt := true
}
/-- Claim state for Allelica.py (Python script on real data) -/
def allelicaClaim : GeneticsClaim :=
{ defaultClaim "Allelica.py" with
gcclGroup := .G_variant_haplotype_population
, hasRealData := true
, hasPythonImpl := true
, hasDataReceipt := true -- gnomAD source declared
}
/-- Run the promotion gate on all canonical models.
This is the infrastructure test: it reveals which models pass/fail. -/
def auditCanonicalModels : String :=
let models := [
("GeneticCode.lean", geneticCodeClaim, false)
, ("CodonOTOM.lean", codonOTOMClaim, false)
, ("PeptideMoE.lean", peptideMoEClaim, false)
, ("GenomicCompression.lean", genomicCompressionClaim, false)
, ("SyntheticGeneticCoding.lean", syntheticGeneticCodingClaim, false)
, ("GeneticGroundUp.lean", geneticGroundUpClaim, false)
, ("HachimojiPipeline.lean", hachimojiClaim, false)
, ("CodonPeptideConsistency.lean", codonPeptideConsistencyClaim, false)
, ("Allelica.py", allelicaClaim, false)
]
let results := models.map (fun (name, claim, fillsZero) =>
let passes := geneticsPromotionGate claim fillsZero
let warden := biologicalEquivalenceWarden claim
let aInt := (admissibleReduction claim fillsZero).toInt
let rInt := (residualRisk claim 0).toInt
s!"{name}: passes={passes} | warden={warden} | a={aInt} | r={rInt}"
)
String.intercalate "\n" results
#eval! auditCanonicalModels
/- ============================================================================
§3 Audit REGISTRY_ONLY Models (Should Fail Gate)
============================================================================ -/
/-- Claim state for a typical REGISTRY_ONLY model (no implementation). -/
def registryOnlyClaim (name : String) (group : GCCLGroup) : GeneticsClaim :=
{ defaultClaim name with
gcclGroup := group
, hasDataReceipt := false -- No implementation = no validation plan
}
/-- Run the gate on REGISTRY_ONLY models to confirm they fail.
This demonstrates the gate is working: unimplemented models are blocked. -/
def auditRegistryOnlyModels : String :=
let models := [
("Hardy-Weinberg (registry)", registryOnlyClaim "Hardy-Weinberg" .G_variant_haplotype_population, false)
, ("Wright-Fisher Drift (registry)", registryOnlyClaim "Wright-Fisher" .G_variant_haplotype_population, true) -- fills zero group
, ("RNA Folding deltaG (registry)", registryOnlyClaim "RNA_Folding" .C_protein_peptide, true) -- fills zero group F
, ("Jukes-Cantor (registry)", registryOnlyClaim "JukesCantor" .D_ambiguity_degeneracy, false)
, ("Quasispecies (ghost)", registryOnlyClaim "Quasispecies" .L_compression_indexing, false)
]
let results := models.map (fun (name, claim, fillsZero) =>
let passes := geneticsPromotionGate claim fillsZero
let a := admissibleReduction claim fillsZero
let r := residualRisk claim 0
let aInt := a.toInt
let rInt := r.toInt
s!"{name}: passes={passes} | a={aInt} | r={rInt}"
)
String.intercalate "\n" results
#eval! auditRegistryOnlyModels
/- ============================================================================
§4 Gate Configuration
============================================================================ -/
/-- Threshold configuration for different promotion contexts. -/
def conservativeThreshold : Q16_16 := Q16_16.ofRatio 3 10 -- 0.3: strict
def defaultThreshold : Q16_16 := Q16_16.ofRatio 1 2 -- 0.5: normal
def generousThreshold : Q16_16 := Q16_16.ofRatio 7 10 -- 0.7: lenient
/-- Which threshold to use for which context. -/
def thresholdFor (context : String) : Q16_16 :=
if context == "conservative" then conservativeThreshold
else if context == "generous" then generousThreshold
else defaultThreshold
end Semantics.GeneticsPromotionGate