File size: 2,649 Bytes
518343a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// SPDX-License-Identifier: Apache-2.0
// © 2026 Lutar, Stephen P. — SZL Holdings
// ORCID: 0009-0001-0110-4173
//
// Layer 6 — a11oy policy gate for ReceiptChainConfluence (TH5)
//
// Policy rationale:
//   The receipt chain is the cofree comonad of the receipt functor. Two replay
//   runs produce the same comonad element iff they agree on all observations.
//   This gate validates that two independently generated chain roots agree,
//   which proves that both runs followed the unique normal form.
//
//   Lean theorem cited: `receiptChainConfluence` (TH5)
//   Lean file: Lutar/Composition/ReceiptChainConfluence.lean
//   Lean commit SHA: 1dca00032dfc9aa8559cc6c2e4b63192fcf52371
//   Lean status: conjectured (pending formal Lean formalization)
//
// References:
//   Zenodo: https://doi.org/10.5281/zenodo.20119582

export interface ReceiptChainConfluenceGateConfig {
  /** If true, deny on non-confluence. Default: true. */
  enforced?: boolean;
}

export interface ReceiptChainConfluenceGateOpts {
  chainRootA: string;
  chainRootB: string;
}

export interface ReceiptChainConfluenceDecision {
  allow:         boolean;
  rationale:     string;
  formula:       string;
  leanTheorem:   string;
  leanFile:      string;
  leanCommitSha: string;
  confluent:     boolean;
  lambdaScore:   number;
}

const LEAN_THEOREM = "receiptChainConfluence";
const LEAN_FILE    = "Lutar/Composition/ReceiptChainConfluence.lean";
const LEAN_COMMIT  = "1dca00032dfc9aa8559cc6c2e4b63192fcf52371";

export function receiptChainConfluenceGate(
  config: ReceiptChainConfluenceGateConfig = {}
): (opts: ReceiptChainConfluenceGateOpts) => ReceiptChainConfluenceDecision {
  const enforced = config.enforced ?? true;

  return function gate(opts: ReceiptChainConfluenceGateOpts): ReceiptChainConfluenceDecision {
    const { chainRootA, chainRootB } = opts;
    if (!chainRootA || !chainRootB) throw new Error(`ReceiptChainConfluenceGate: both chain roots required`);

    const confluent   = chainRootA === chainRootB;
    const allow       = confluent || !enforced;
    const lambdaScore = confluent ? 1.0 : 0.0;

    const rationale = confluent
      ? `ReceiptChainConfluence (TH5): rootA="${chainRootA.slice(0,16)}…" = rootB — unique normal form confirmed. Passes. Lean: ${LEAN_THEOREM} @${LEAN_COMMIT.slice(0, 12)}`
      : `ReceiptChainConfluence (TH5): rootA≠rootB — non-deterministic chain paths. Denied. Lean: ${LEAN_THEOREM} @${LEAN_COMMIT.slice(0, 12)}`;

    return { allow, rationale, formula: "ReceiptChainConfluence", leanTheorem: LEAN_THEOREM, leanFile: LEAN_FILE, leanCommitSha: LEAN_COMMIT, confluent, lambdaScore };
  };
}