Spaces:
Starting
Starting
File size: 3,626 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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | // Contradiction probe — cheap consistency check between the index branch's
// top-k predicted block-set and the sparse branch's actual attended block-set.
//
// Per the MiniMax M2 retrospective, a sparse plan that AGREES with its index
// at small scale but DIVERGES at deep multi-hop is the silent failure mode.
// The probe is therefore the gate between sparse and full attention: low
// agreement triggers `sparse.contradiction.v1` and a paired `sparse.escalated.v1`.
import type { SparseAttentionEnvelope } from "./envelope.js";
import type { SparseReceiptCommon } from "./receipts.js";
export interface SparseContradictionReceipt extends SparseReceiptCommon {
readonly receiptClass: "sparse.contradiction.v1";
readonly regimeRef: string; // SparseAttentionEnvelope.regimeId
readonly agreement: number; // [0,1]
readonly threshold: number; // envelope.minIndexAgreement
readonly indexBlocks: ReadonlyArray<number>;
readonly sparseBlocks: ReadonlyArray<number>;
}
export interface SparseEscalatedReceipt extends SparseReceiptCommon {
readonly receiptClass: "sparse.escalated.v1";
readonly regimeRef: string;
readonly fromMode: "sparse";
readonly toMode: "full";
readonly reasonReceiptRef: string; // points at the contradiction receipt
}
/**
* Jaccard agreement between two block-id sets. ∈ [0,1]. Pure; deterministic.
*/
export function jaccard(a: ReadonlyArray<number>, b: ReadonlyArray<number>): number {
if (a.length === 0 && b.length === 0) return 1;
const A = new Set(a);
const B = new Set(b);
let inter = 0;
for (const x of A) if (B.has(x)) inter += 1;
const union = A.size + B.size - inter;
return union === 0 ? 1 : inter / union;
}
export interface ProbeInput {
readonly envelope: SparseAttentionEnvelope;
readonly indexBlocks: ReadonlyArray<number>;
readonly sparseBlocks: ReadonlyArray<number>;
readonly tenant: string;
readonly nonce: string;
readonly issuedAt?: string;
}
export type ProbeOutput =
| { contradicted: false; agreement: number }
| {
contradicted: true;
agreement: number;
contradiction: SparseContradictionReceipt;
escalation: SparseEscalatedReceipt;
};
/**
* Probe and (on contradiction) emit a paired contradiction + escalation
* receipt. Caller is responsible for persisting the receipts and for
* actually switching the orchestrator to full attention — this function
* is pure and side-effect-free.
*/
export function probe(input: ProbeInput): ProbeOutput {
const { envelope, indexBlocks, sparseBlocks, tenant, nonce } = input;
const issuedAt = input.issuedAt ?? new Date().toISOString();
const agreement = jaccard(indexBlocks, sparseBlocks);
if (agreement >= envelope.minIndexAgreement) {
return { contradicted: false, agreement };
}
const contradictionId = `${envelope.regimeId}:${nonce}:contradiction`;
const contradiction: SparseContradictionReceipt = {
receiptClass: "sparse.contradiction.v1",
freshnessNonce: nonce,
issuedAt,
tenant,
parentRef: envelope.regimeId,
regimeRef: envelope.regimeId,
agreement,
threshold: envelope.minIndexAgreement,
indexBlocks: [...indexBlocks].sort((a, b) => a - b),
sparseBlocks: [...sparseBlocks].sort((a, b) => a - b),
};
const escalation: SparseEscalatedReceipt = {
receiptClass: "sparse.escalated.v1",
freshnessNonce: nonce,
issuedAt,
tenant,
parentRef: envelope.regimeId,
regimeRef: envelope.regimeId,
fromMode: "sparse",
toMode: "full",
reasonReceiptRef: contradictionId,
};
return { contradicted: true, agreement, contradiction, escalation };
}
|