Spaces:
Running
Running
| // SPDX-License-Identifier: Apache-2.0 | |
| // © 2026 Lutar, Stephen P. — SZL Holdings | |
| // ORCID: 0009-0001-0110-4173 | |
| // | |
| // Layer 6 — a11oy policy gate for SoundnessAxiom (A1) | |
| // | |
| // Policy rationale: | |
| // A receipt is allowed to pass only when all 9 Λ-axis scores meet or exceed | |
| // the conjunctive floor of 0.90. The soundness axiom guarantees: if gate_pass(r) | |
| // then lambda(r) >= 0.90 conjunctively. This gate enforces that claim at | |
| // the policy layer — rejecting any receipt that would silently under-score. | |
| // | |
| // Lean axiom cited: `soundnessAxiom` (A1) | |
| // Lean file: Lutar/Gate/SoundnessAxiom.lean | |
| // Lean commit SHA: 1dca00032dfc9aa8559cc6c2e4b63192fcf52371 | |
| // Lean status: theorem (ENFORCED) | |
| // | |
| // Policy: if all axes >= floor → allow; else → deny | |
| // | |
| // References: | |
| // Zenodo: https://doi.org/10.5281/zenodo.20119582 | |
| // Thesis §4.1: soundnessAxiom — conjunctive Λ floor | |
| export interface SoundnessAxiomGateConfig { | |
| /** Conjunctive floor per axis. Default: 0.90. */ | |
| floor?: number; | |
| } | |
| export interface SoundnessAxiomGateOpts { | |
| /** Array of 9 axis scores in [0,1]. */ | |
| axisScores: number[]; | |
| } | |
| export interface SoundnessAxiomDecision { | |
| allow: boolean; | |
| rationale: string; | |
| formula: string; | |
| leanTheorem: string; | |
| leanFile: string; | |
| leanCommitSha: string; | |
| floor: number; | |
| minAxis: number; | |
| failingAxes: number[]; | |
| lambdaScore: number; | |
| } | |
| const LEAN_THEOREM = "soundnessAxiom"; | |
| const LEAN_FILE = "Lutar/Gate/SoundnessAxiom.lean"; | |
| const LEAN_COMMIT = "1dca00032dfc9aa8559cc6c2e4b63192fcf52371"; | |
| const DEFAULT_FLOOR = 0.90; | |
| const AXIS_COUNT = 9; | |
| // ── Inline formula ──────────────────────────────────────────────────────────── | |
| // A1: gate_pass(r) ⟹ ∀i ∈ {0..8}: lambda_i(r) ≥ 0.90 | |
| function _geometricMean(scores: number[]): number { | |
| if (scores.length === 0) return 0; | |
| const logSum = scores.reduce((acc, s) => acc + Math.log(Math.max(s, 1e-12)), 0); | |
| return Math.exp(logSum / scores.length); | |
| } | |
| /** | |
| * SoundnessAxiom (A1) policy gate. | |
| * | |
| * Passes only when every axis in the 9-axis Λ-vector meets or exceeds the | |
| * configured conjunctive floor. This is the primary gating axiom of the | |
| * SZL receipt system. | |
| * | |
| * Lean axiom: `soundnessAxiom` (A1) | |
| * Lean file: Lutar/Gate/SoundnessAxiom.lean (commit 1dca00032dfc9aa8559cc6c2e4b63192fcf52371) | |
| * Zenodo: https://doi.org/10.5281/zenodo.20119582 | |
| */ | |
| export function soundnessAxiomGate( | |
| config: SoundnessAxiomGateConfig = {} | |
| ): (opts: SoundnessAxiomGateOpts) => SoundnessAxiomDecision { | |
| const floor = config.floor ?? DEFAULT_FLOOR; | |
| if (!Number.isFinite(floor) || floor < 0 || floor > 1) { | |
| throw new Error(`SoundnessAxiomGate: floor must be in [0,1]; got ${floor}`); | |
| } | |
| return function gate(opts: SoundnessAxiomGateOpts): SoundnessAxiomDecision { | |
| const { axisScores } = opts; | |
| if (!Array.isArray(axisScores) || axisScores.length !== AXIS_COUNT) { | |
| throw new Error(`SoundnessAxiomGate: axisScores must be length ${AXIS_COUNT}; got ${axisScores?.length}`); | |
| } | |
| for (const s of axisScores) { | |
| if (!Number.isFinite(s) || s < 0 || s > 1) { | |
| throw new Error(`SoundnessAxiomGate: each axis score must be in [0,1]; got ${s}`); | |
| } | |
| } | |
| const failingAxes = axisScores.map((s, i) => ({ s, i })).filter(x => x.s < floor).map(x => x.i); | |
| const minAxis = Math.min(...axisScores); | |
| const lambdaScore = _geometricMean(axisScores); | |
| const allow = failingAxes.length === 0; | |
| const rationale = allow | |
| ? `SoundnessAxiom (A1): all ${AXIS_COUNT} axes ≥ ${floor}; min=${minAxis.toFixed(4)}, Λ=${lambdaScore.toFixed(4)}. Receipt passes. Lean: ${LEAN_THEOREM} @${LEAN_COMMIT.slice(0, 12)}` | |
| : `SoundnessAxiom (A1): axes [${failingAxes.join(',')}] below floor ${floor}; min=${minAxis.toFixed(4)}. Receipt denied. Lean: ${LEAN_THEOREM} @${LEAN_COMMIT.slice(0, 12)}`; | |
| return { allow, rationale, formula: "SoundnessAxiom", leanTheorem: LEAN_THEOREM, leanFile: LEAN_FILE, leanCommitSha: LEAN_COMMIT, floor, minAxis, failingAxes, lambdaScore }; | |
| }; | |
| } | |