js-rigor: reliability crucibles across the campaigns; denied-decision leak fixed
The reliability gap found last round was invisible to every parity mirror (they compared possibility only). Hardened the existing campaigns so the mirrors carry reliability too: - batch-order-parity: batch ops carry reliability; the mirror tracks last-write-wins reliability and the crucible asserts engine reliability parity (mirror corrected: add-on-existing preserves reliability, it does not reset it). - rule-kind-partial-parity: the TTU differential property now generates per-edge reliabilities and asserts the winning intermediate's reliability (tupleset.reli * computed.reli); a new chain reliability differential property does the same for 2-step chains. - snapshot-quantization-parity: edges carry deterministic reliabilities and the round-trip pins the codec's reliability channel (product-aware tolerance: chain reliability multiplies two quantized inputs). - model-based-graph: the reference model tracks reliability per tuple and checks it alongside possibility for direct and chain queries. The model crucible immediately caught a real bug: the direct-check fast path returned the relation's reliability on a DENIED decision (possibility 0), while the rule-collection path zeroes it — denied results leaked reliability. Both fast-path branches (direct match and threshold_not_met) now report reliability 0 when the decision is denied.
This commit is contained in:
@@ -48,7 +48,12 @@ function buildGraph(edges, values) {
|
||||
]
|
||||
});
|
||||
for (let i = 0; i < edges.length; i++) {
|
||||
arb.addRelation(nodeKey(edges[i][0]), edges[i][1], nodeKey(edges[i][2]), { possibility: values[i] });
|
||||
arb.addRelation(nodeKey(edges[i][0]), edges[i][1], nodeKey(edges[i][2]), {
|
||||
possibility: values[i],
|
||||
// deterministic per-edge reliability so the round-trip pins the
|
||||
// codec's reliability channel, not just possibility
|
||||
reliability: 0.1 + ((i * 7 + 3) % 9) / 10
|
||||
});
|
||||
}
|
||||
return arb;
|
||||
}
|
||||
@@ -64,12 +69,14 @@ for (const u of [0, 1]) {
|
||||
function roundTripReport(edges, values) {
|
||||
const live = buildGraph(edges, values);
|
||||
const before = QUERIES.map(([rel, u, d]) => live.check(nodeKey(u), rel, nodeKey(d)).possibility);
|
||||
const beforeReliability = QUERIES.map(([rel, u, d]) => live.check(nodeKey(u), rel, nodeKey(d)).reliability ?? 0);
|
||||
|
||||
live.enableCondensedSnapshot();
|
||||
const buffer = serializeArbiterSnapshot(live);
|
||||
|
||||
const r1 = ArbiterSnapshot.fromSnapshotBinary(buffer, {}, () => new Arbiter());
|
||||
const after1 = QUERIES.map(([rel, u, d]) => r1.check(nodeKey(u), rel, nodeKey(d)).possibility);
|
||||
const after1Reliability = QUERIES.map(([rel, u, d]) => r1.check(nodeKey(u), rel, nodeKey(d)).reliability ?? 0);
|
||||
|
||||
const r1b = ArbiterSnapshot.fromSnapshotBinary(buffer, {}, () => new Arbiter());
|
||||
const after1b = QUERIES.map(([rel, u, d]) => r1b.check(nodeKey(u), rel, nodeKey(d)).possibility);
|
||||
@@ -78,7 +85,7 @@ function roundTripReport(edges, values) {
|
||||
const r2 = ArbiterSnapshot.fromSnapshotBinary(buffer2, {}, () => new Arbiter());
|
||||
const after2 = QUERIES.map(([rel, u, d]) => r2.check(nodeKey(u), rel, nodeKey(d)).possibility);
|
||||
|
||||
return { before, after1, after1b, after2, graphBytes: live.snapshotGraph.toBinary().byteLength };
|
||||
return { before, after1, after1b, after2, beforeReliability, after1Reliability, graphBytes: live.snapshotGraph.toBinary().byteLength };
|
||||
}
|
||||
|
||||
describe('Condensed snapshot quantization parity (rigor)', () => {
|
||||
@@ -106,6 +113,16 @@ describe('Condensed snapshot quantization parity (rigor)', () => {
|
||||
}
|
||||
assert.deepEqual(r.after1, r.after1b, 'restoring the same buffer is deterministic');
|
||||
assert.deepEqual(r.after1, r.after2, 'snapshot-of-snapshot preserves values');
|
||||
// Reliability passes through the same 16-bit quantization; chain
|
||||
// reliabilities multiply two quantized inputs, so the band is 4x the
|
||||
// single-value tolerance (still far tighter than any codec loss).
|
||||
const reliabilityTol = TOL * 4;
|
||||
for (let i = 0; i < r.beforeReliability.length; i++) {
|
||||
assert.ok(
|
||||
Math.abs(r.after1Reliability[i] - r.beforeReliability[i]) <= reliabilityTol,
|
||||
`query ${i}: live reliability=${r.beforeReliability[i]} restored=${r.after1Reliability[i]} exceeds tolerance ${reliabilityTol}`
|
||||
);
|
||||
}
|
||||
|
||||
const g1 = buildGraph(edges, values);
|
||||
g1.enableCondensedSnapshot();
|
||||
|
||||
Reference in New Issue
Block a user