Files
vyndr/scripts/teeth-certified-probability.js
T
builtbykev 22cf51c4b0 The mapping that ran now has a name, and the row carries it
Runtime probes say the fleet is on a8de676, one process generation. But
"isotonic" was a label, not a claim: probabilityContractService refits per
snapshot against `game_date < todayEt()`, so the mapping changes as outcomes
settle, and nothing on a row could say WHICH mapping produced its number.

The artifact now has an identity:

  estimator_type / estimator_version / certification_version / model_version
  fit_as_of         the exact lt(game_date) bound   2026-09-02
  training_cutoff   last date INSIDE the fit        2026-08-21
  fit_n / knot_count                                6,084 / 28
  knot_digest       d9d571d728ba76de
  served_curve      the COMPLETE served function over [0.50,0.80)
  served_curve_digest

The served curve is not a sample. p_win is quantised to three decimals at the
source, so a step table at 0.001 granularity is the mapping itself for every
input that can occur — six steps, ~200 bytes. Storing it makes a Read
reconstructable WITHOUT re-deriving a training set that may since have been
re-settled, and a claim you can only verify when the inputs happen not to have
moved is not a reconstructable claim.

Proven, not asserted: the production construction path run twice gives an
identical digest, and an INDEPENDENT reconstruction — re-walk 9,361 settled
ledger rows at the declared bound, refit from scratch — reproduces
d9d571d728ba76de exactly, 28 knots for 28.

A teeth injection found a real defect behind a coverage hole. `resolve` checked
the CONTRACT's model era and never the ARTIFACT's, so a mapping fitted for a
different era could be recorded beside a served number with every test green.
Both the era and the estimator type are now checked, and a mismatch serves
nothing rather than serving quietly.

OBSERVED AND NOT CHANGED: calibrationService splits 65/35 to certify its own
bands, a step this contract does not consume because support comes from the
frozen artifact. So the served map is fitted through 2026-08-21 while 3,277
more recent settled rows sit unused, and that lag grows with history. Changing
it would change the fitted function, which this tranche froze.

Shadow still defaults OFF. CALIBRATION_DEPLOYED still []. served_probability is
referenced by nothing outside the contract layer — asserted by a tooth.

Suite 401/401, 5,593 passed, 4 skipped. Teeth 23/23 (prior) + 7/7 (new).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQJeAG8vcDoL5zkiaJyVb8
2026-09-02 21:44:52 -04:00

138 lines
7.5 KiB
JavaScript

#!/usr/bin/env node
'use strict';
/**
* teeth-certified-probability — the NEW ground in this tranche.
*
* Teeth 6-15 and 19-23 of the order are already landed independently by
* scripts/teeth-probability-contract.js (23/23) and are not re-asserted here;
* this runner covers runtime observability, artifact identity, point-in-time
* evidence, shadow harmlessness, and the activation ordering.
*
* Teeth 17, 18 and 24 target a LIVE SERVING path that does not exist yet.
* They are recorded UNREACHABLE rather than asserted weakly.
*/
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const { execSync } = require('child_process');
const ROOT = path.join(__dirname, '..');
const sha = (f) => crypto.createHash('sha256').update(fs.readFileSync(f)).digest('hex');
const codeOf = (s) => s.replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '');
const results = [];
function runSuite(file) {
try { execSync(`npx jest ${file} --silent --testTimeout=45000`, { cwd: ROOT, stdio: 'pipe', timeout: 300000 });
return true; } catch { return false; }
}
function injectionTooth(id, name, file, find, replace, suite) {
const full = path.join(ROOT, file);
const before = fs.readFileSync(full, 'utf8');
const beforeSha = sha(full);
let landed = false, detail = '';
try {
if (!before.includes(find)) {
results.push({ id, name, landed: false, detail: `ANCHOR NOT FOUND in ${file} — the injection would have silently no-opped` });
return;
}
fs.writeFileSync(full, before.replace(find, replace));
if (fs.readFileSync(full, 'utf8') === before) throw new Error('injection produced no change');
landed = runSuite(suite) === false;
detail = landed ? `defect installed -> ${suite} FAILED as required`
: `defect installed and ${suite} STILL PASSED — coverage hole`;
} catch (e) { detail = 'threw: ' + e.message; }
finally {
fs.writeFileSync(full, before);
const ok = sha(full) === beforeSha;
detail += ok ? ' | restored byte-identical' : ' | RESTORE MISMATCH';
if (!ok) landed = false;
}
results.push({ id, name, landed, detail });
}
function logicTooth(id, name, fn) {
let landed = false, detail = '';
try { const r = fn(); landed = r.caught === true; detail = r.detail || ''; }
catch (e) { detail = 'threw: ' + e.message; }
results.push({ id, name, landed, detail });
}
// ── 1 — runtime SHA observability actually exists and is used ─────────────
logicTooth(1, 'runtime SHA verification waits for a snapshot despite working runtime status', () => {
const src = codeOf(fs.readFileSync(path.join(ROOT, 'src/routes/internal.js'), 'utf8'));
const block = src.slice(src.indexOf("router.get('/snapshot/status'"), src.indexOf("router.get('/snapshot/status'") + 4000);
const hasSha = /runtime:\s*\{[\s\S]*?code_sha:\s*codeSha\(\)/.test(block);
const hasStart = /started_at:\s*PROCESS_STARTED_AT/.test(block);
// and it must resolve from the SAME provenance source, not git HEAD
const ret = codeOf(fs.readFileSync(path.join(ROOT, 'src/services/retentionService.js'), 'utf8'));
const sameResolver = /function codeSha\(\)\s*\{\s*return process\.env\.SOURCE_COMMIT/.test(ret);
return { caught: hasSha && hasStart && sameResolver,
detail: `status exposes runtime.code_sha=${hasSha} started_at=${hasStart}; same resolver as provenance=${sameResolver}` };
});
// ── 2 — the estimator must carry a reconstructable identity ──────────────
injectionTooth(2, 'runtime estimator lacks a reconstructable artifact identity',
'src/services/model/probabilityContractService.js',
` knot_digest: digest(fitted.map),`,
` knot_digest: 'static-placeholder',`,
'tests/unit/probabilityContract.test.js');
// ── 3 — the artifact must be tied to the certified model era ─────────────
injectionTooth(3, 'runtime artifact differs from the certified artifact',
'src/services/model/probabilityContractService.js',
` model_version: contract.model_version,`,
` model_version: 'engine1@some-other-era',`,
'tests/unit/probabilityContractShadow.test.js');
// ── 4 — point-in-time evidence ───────────────────────────────────────────
injectionTooth(4, 'dynamic refit uses future settlement evidence for an earlier Read',
'src/services/model/calibrationService.js',
` .lt('game_date', cutoff), // STRICTLY before — the whole point`,
` .lte('game_date', cutoff),`,
'tests/unit/probabilityContract.test.js');
// ── 5 — the shadow may not move served product ───────────────────────────
injectionTooth(5, 'shadow changes current user-facing output',
'src/services/retentionService.js',
` return {
...r,
probability_contract: {`,
` return {
...r,
p_win: res.served_probability != null ? res.served_probability : r.p_win,
probability_contract: {`,
'tests/unit/probabilityContractShadow.test.js');
// ── 16 — activation ordering ─────────────────────────────────────────────
logicTooth(16, 'live serving activates before the shadow has passed', () => {
const snap = codeOf(fs.readFileSync(path.join(ROOT, 'src/services/snapshotService.js'), 'utf8'));
const deployedEmpty = /CALIBRATION_DEPLOYED\s*=\s*Object\.freeze\(\[\s*\]\)/.test(snap);
// no live consumer may read served_probability yet
const srcFiles = execSync(`grep -rl "served_probability" ${ROOT}/src ${ROOT}/web/src 2>/dev/null || true`)
.toString().trim().split('\n').filter(Boolean).map((f) => f.replace(ROOT + '/', ''));
const allowed = ['src/services/model/probabilityContract.js',
'src/services/model/probabilityContractService.js', 'src/services/retentionService.js'];
const leaked = srcFiles.filter((f) => !allowed.includes(f));
return { caught: deployedEmpty && leaked.length === 0,
detail: `CALIBRATION_DEPLOYED empty=${deployedEmpty}; served_probability referenced outside the contract layer: ${leaked.join(', ') || 'none'}` };
});
// ── the shadow flag itself ───────────────────────────────────────────────
logicTooth(25, 'shadow flag parses loosely or defaults ON', () => {
const snap = fs.readFileSync(path.join(ROOT, 'src/services/snapshotService.js'), 'utf8');
const strict = snap.includes("String(process.env.PROBABILITY_CONTRACT_SHADOW || '') === '1'");
const scoped = snap.includes("&& sp === 'mlb'");
const statScoped = snap.includes("{ sport: 'mlb', stat: 'hits' }");
return { caught: strict && scoped && statScoped,
detail: `strict '1' compare=${strict}; sport-scoped=${scoped}; stat-scoped=${statScoped}` };
});
const unreachable = [
{ id: 17, name: 'UI displays raw exact confidence for UNCERTIFIED', why: 'no live-serving UI path exists; nothing consumes served_probability yet' },
{ id: 18, name: 'live EV/Kelly/VALUE consumers bypass served_probability', why: 'live consumers are unchanged by design in this tranche — tooth 16 asserts none exist' },
{ id: 24, name: 'rollback rewrites historical probability contracts', why: 'nothing is activated, so there is no activation to roll back' },
];
const landed = results.filter((r) => r.landed).length;
console.log(JSON.stringify({ teeth_landed: `${landed}/${results.length}`, results, unreachable }, null, 2));
process.exit(landed === results.length ? 0 : 1);