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 LambdaMonotonicity (T2) | |
| // | |
| // Policy rationale: | |
| // Adding consistent evidence to a receipt must weakly increase all axis | |
| // scores. If a proposed evidence augmentation decreases any axis score, it | |
| // is classified as conflicting evidence and rejected at the gate. | |
| // | |
| // Lean derivation cited: `lambdaMonotonicity` (T2) | |
| // Lean file: Lutar/Gate/LambdaMonotonicity.lean | |
| // Lean commit SHA: 1dca00032dfc9aa8559cc6c2e4b63192fcf52371 | |
| // Lean status: theorem (ENFORCED) | |
| // | |
| // References: | |
| // Zenodo: https://doi.org/10.5281/zenodo.20119582 | |
| // INNOVATIONS.md §2 T2: lambda monotonicity derivation | |
| export interface LambdaMonotonicityGateConfig { | |
| /** Allowed floating-point tolerance for monotonicity check. Default: 1e-9. */ | |
| tolerance?: number; | |
| } | |
| export interface LambdaMonotonicityGateOpts { | |
| /** Original axis scores. */ | |
| originalScores: number[]; | |
| /** Proposed augmented axis scores (after adding evidence). */ | |
| augmentedScores: number[]; | |
| } | |
| export interface LambdaMonotonicityDecision { | |
| allow: boolean; | |
| rationale: string; | |
| formula: string; | |
| leanTheorem: string; | |
| leanFile: string; | |
| leanCommitSha: string; | |
| decreasingAxes: number[]; | |
| minDelta: number; | |
| lambdaScore: number; | |
| } | |
| const LEAN_THEOREM = "lambdaMonotonicity"; | |
| const LEAN_FILE = "Lutar/Gate/LambdaMonotonicity.lean"; | |
| const LEAN_COMMIT = "1dca00032dfc9aa8559cc6c2e4b63192fcf52371"; | |
| const DEFAULT_TOL = 1e-9; | |
| // ── Inline formula ──────────────────────────────────────────────────────────── | |
| // T2: r' = r ⊕ e_consistent ⟹ Λ(r') ≥ Λ(r) (Lean A1: IsMonotone) | |
| export function lambdaMonotonicityGate( | |
| config: LambdaMonotonicityGateConfig = {} | |
| ): (opts: LambdaMonotonicityGateOpts) => LambdaMonotonicityDecision { | |
| const tolerance = config.tolerance ?? DEFAULT_TOL; | |
| return function gate(opts: LambdaMonotonicityGateOpts): LambdaMonotonicityDecision { | |
| const { originalScores, augmentedScores } = opts; | |
| if (!Array.isArray(originalScores) || !Array.isArray(augmentedScores)) { | |
| throw new Error(`LambdaMonotonicityGate: both score arrays required`); | |
| } | |
| if (originalScores.length !== augmentedScores.length) { | |
| throw new Error(`LambdaMonotonicityGate: score arrays must have equal length`); | |
| } | |
| const decreasingAxes: number[] = []; | |
| let minDelta = Infinity; | |
| for (let i = 0; i < originalScores.length; i++) { | |
| const delta = augmentedScores[i] - originalScores[i]; | |
| if (delta < minDelta) minDelta = delta; | |
| if (delta < -tolerance) decreasingAxes.push(i); | |
| } | |
| const allow = decreasingAxes.length === 0; | |
| const lambdaScore = allow ? 1.0 : Math.max(0, 1 + minDelta); | |
| const rationale = allow | |
| ? `LambdaMonotonicity (T2): all ${originalScores.length} axes weakly increased (minDelta=${minDelta.toExponential(4)}). Consistent evidence. Passes. Lean: ${LEAN_THEOREM} @${LEAN_COMMIT.slice(0, 12)}` | |
| : `LambdaMonotonicity (T2): axes [${decreasingAxes.join(',')}] decreased — conflicting evidence. Denied. Lean: ${LEAN_THEOREM} @${LEAN_COMMIT.slice(0, 12)}`; | |
| return { allow, rationale, formula: "LambdaMonotonicity", leanTheorem: LEAN_THEOREM, leanFile: LEAN_FILE, leanCommitSha: LEAN_COMMIT, decreasingAxes, minDelta, lambdaScore }; | |
| }; | |
| } | |