Files
vyndr/tests/unit/lineageProductization.test.js
T
builtbykev e5b20b0509 Software watches coverage now, and ancestry becomes a product contract
Three closeout items, traced before building.

THE OBSERVER WAS DIAGNOSTICS, NOT MONITORING. Traced from the deployed tree:
exactly two callsites, both manual internal routes, and nothing in the scheduler
or ops path consumed it. A persistent lineage failure could have sat unnoticed
until a human asked.

The monitor now runs on the scheduler's per-minute tick, throttled to 30
minutes. It is placed there rather than after a snapshot on purpose: an
in-snapshot audit structurally cannot report that no snapshot ran, which is the
failure mode that matters most, and it would run under peak write contention
where the audit already demonstrably times out. It reads only the durable
observer and never `attachLineage`'s counters, and every failure path is
swallowed — a monitor that can take down the pipeline it watches is worse than
no monitor.

HEALTHY IS SILENCE; EVERYTHING ELSE SPEAKS. `coverageAlarm` is pure, so the
policy is testable and cannot drift into the scheduler. AUDIT_UNAVAILABLE says
"could not be measured — the audit did not run", deliberately worded so it can
never be read as "coverage is zero": those are different claims and collapsing
them is how a monitor starts lying in the reassuring direction. Alerts dedupe on
(health, cohort) so a standing fault states itself once and a NEW cohort with
the same fault speaks again.

ANCESTRY BECOMES A PRODUCT CONTRACT. It was internal-only. `GET
/api/ancestry/ledger/:id` (requireAuth, rate-limited) plus the Next proxy that
makes it browser-reachable, keyed on the LEDGER ROW ID — a stable identifier the
ledger API already returns — rather than a raw natural key exposed because it
was convenient. Its own router, so `routes/ledger.js` stays free of lineage
entirely and the grade-badge guard keeps its teeth. Every response declares
`authority: LOCAL, authority_scope: ANCESTRY_ONLY`.

THREE TEETH CAME BACK GREEN AND ALL THREE WERE MY TESTS, NOT SAFE DEFECTS.
The badge guard was CASE-SENSITIVE, so `LINEAGE_ANCESTRY` and `readAncestry`
walked straight past it. `try/finally` is valid JavaScript, so removing the
monitor's catch produced no load error and nothing asserted the containment.
And the multi-date cohort check was a grep for `.gte('game_date'` that the
head query satisfied on its own. All three replaced with behavioural tests,
including a scheduler double whose fake client HONOURS its filters — a
pass-through would have made a narrowed cohort walk look correct.

Suite 398/5,522/0 · tsc 0 · web build 0 · teeth 14/14 and 15/15.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQJeAG8vcDoL5zkiaJyVb8
2026-08-30 23:44:46 -04:00

544 lines
25 KiB
JavaScript

/**
* LINEAGE PRODUCTIZATION — persistent shadow writer, independent coverage
* observer, additive ancestry surface.
*
* Three properties this suite exists to hold:
* the product never depends on lineage;
* the observer never trusts the writer;
* the ancestry surface never invents history it does not have.
*/
const svc = require('../../src/services/snapshotService');
const mode = require('../../src/services/lineageWriteMode');
const coverage = require('../../src/services/lineageCoverage');
const ancestry = require('../../src/services/read/readAncestry');
const retention = require('../../src/services/retentionService');
const ENV = mode.ENV_VAR;
const setPersistent = (v) => { if (v === null) delete process.env[ENV]; else process.env[ENV] = v; };
afterEach(() => setPersistent(null));
/* ─────────────────────────── WRITE MODE ─────────────────────────── */
describe('write mode — three modes, one evaluator', () => {
test('unset -> OFF, nothing enabled', () => {
setPersistent(null);
expect(mode.evaluate().mode).toBe(mode.WRITE_MODE.OFF);
expect(mode.isEnabled('mlb')).toBe(false);
});
test('PERSISTENT_SHADOW writes without any lease', () => {
setPersistent('mlb');
const e = mode.evaluate();
expect(e.mode).toBe(mode.WRITE_MODE.PERSISTENT_SHADOW);
expect(mode.isEnabled('mlb')).toBe(true);
// No lease is involved, and none is required.
expect(e.canary_sports).toEqual([]);
expect(mode.modeFor('mlb')).toBe(mode.WRITE_MODE.PERSISTENT_SHADOW);
});
test('a sport outside the allowlist fails closed, and takes the whole list with it', () => {
setPersistent('wnba');
expect(mode.evaluate().persistent_invalid_reason).toBe('INVALID_SPORT_NOT_PERSISTABLE');
expect(mode.isEnabled('wnba')).toBe(false);
setPersistent('mlb,wnba');
// Keeping the valid half would enable a subset nobody asked for on its own.
expect(mode.isEnabled('mlb')).toBe(false);
});
test('the allowlist is the canary\'s, not a second one', () => {
const canary = require('../../src/services/lineageCanaryConfig');
expect(mode.PERSISTABLE_SPORTS).toBe(canary.LEASABLE_SPORTS);
});
test('another sport cannot become enabled by accident', () => {
setPersistent('mlb');
for (const s of ['wnba', 'nba', 'soccer', '']) expect(mode.isEnabled(s)).toBe(false);
});
test('status and gate come from the SAME evaluator', () => {
setPersistent('mlb');
const st = mode.state();
expect(st.mode).toBe(mode.evaluate().mode);
expect(st.effective_sports).toEqual(mode.evaluate().sports);
expect(st.authority).toBe('NON_AUTHORITATIVE');
});
test('rollback ON -> OFF disables future writes and touches nothing else', () => {
setPersistent('mlb');
expect(mode.isEnabled('mlb')).toBe(true);
setPersistent(null);
expect(mode.isEnabled('mlb')).toBe(false);
expect(mode.evaluate().mode).toBe(mode.WRITE_MODE.OFF);
});
});
describe('canary and persistent are DIFFERENT modes', () => {
test('an ambiguous configuration fails closed rather than double-enabling', () => {
// The two instructions disagree about WHEN WRITING STOPS. We cannot know
// which the operator meant, so the sport writes nothing.
const e = mode.evaluate.call(null);
const fake = {
lease_state: 'ACTIVE', effective_active_sports: ['mlb'],
};
jest.isolateModules(() => {
jest.doMock('../../src/services/lineageCanaryConfig', () => ({
LEASABLE_SPORTS: ['mlb'],
evaluate: () => fake,
}));
const m2 = require('../../src/services/lineageWriteMode');
process.env[m2.ENV_VAR] = 'mlb';
const ev = m2.evaluate();
expect(ev.conflict).toBe(m2.CONFLICT.SPORT_IN_BOTH_MODES);
expect(ev.conflict_sports).toEqual(['mlb']);
expect(ev.mode).toBe(m2.WRITE_MODE.OFF);
expect(m2.isEnabled('mlb')).toBe(false);
delete process.env[m2.ENV_VAR];
});
expect(e).toBeDefined();
});
test('a lease alone still enables, with the canary contract untouched', () => {
jest.isolateModules(() => {
jest.doMock('../../src/services/lineageCanaryConfig', () => ({
LEASABLE_SPORTS: ['mlb'],
evaluate: () => ({ lease_state: 'ACTIVE', effective_active_sports: ['mlb'] }),
}));
const m2 = require('../../src/services/lineageWriteMode');
delete process.env[m2.ENV_VAR];
expect(m2.evaluate().mode).toBe(m2.WRITE_MODE.CANARY_LEASED);
expect(m2.isEnabled('mlb')).toBe(true);
});
});
test('an EXPIRED lease enables nothing — dynamic expiry is preserved', () => {
jest.isolateModules(() => {
jest.doMock('../../src/services/lineageCanaryConfig', () => ({
LEASABLE_SPORTS: ['mlb'],
evaluate: () => ({ lease_state: 'EXPIRED', effective_active_sports: [] }),
}));
const m2 = require('../../src/services/lineageWriteMode');
delete process.env[m2.ENV_VAR];
expect(m2.isEnabled('mlb')).toBe(false);
expect(m2.evaluate().mode).toBe(m2.WRITE_MODE.OFF);
});
});
});
/* ────────────────── FAILURE ISOLATION (the product first) ────────────────── */
describe('lineage failure can never reach authoritative product truth', () => {
// HERMETIC. Injecting `retention` activates pipeline paths the other snapshot
// tests never reach, and several resolve a real Supabase client when the
// environment offers one. Blanking the credentials makes every database
// dependency a no-op, so this measures the ISOLATION PROPERTY and not the
// network. Restored afterwards so no other suite inherits it.
const SUPA_KEYS = ['SUPABASE_URL', 'SUPABASE_SERVICE_ROLE_KEY', 'SUPABASE_SERVICE_KEY', 'SUPABASE_ANON_KEY'];
const saved = {};
beforeAll(() => { for (const k of SUPA_KEYS) { saved[k] = process.env[k]; delete process.env[k]; } });
afterAll(() => { for (const k of SUPA_KEYS) { if (saved[k] === undefined) delete process.env[k]; else process.env[k] = saved[k]; } });
const memCache = () => { const store = {}; return { store, cacheGet: async (k) => (k in store ? store[k] : null), cacheSet: async (k, v) => { store[k] = v; } }; };
const sampleProps = [{ player: 'Aaron Judge', stat_type: 'total_bases', line: 1.5, over_odds: -115, under_odds: -105, book: 'draftkings' }];
const grades = [{ player: 'Aaron Judge', stat_type: 'total_bases', line: 1.5, direction: 'over', grade: 'A+', confidence: 80 }];
const deps = (cache, extra = {}) => ({
getOdds: async () => ({ sport: 'mlb', props: sampleProps, provider: 'propline' }),
// Fires the retention hook the real grader fires. Without it the collector
// stays empty, `persistedRows` stays null and the lineage gate is never
// reached — which would make every assertion below vacuously true.
gradeAndCacheSlate: async (_s, _p, opts) => {
if (typeof opts.onGraded === 'function') {
opts.onGraded(
{
player: 'Aaron Judge', stat_type: 'total_bases', line: 1.5, book: 'draftkings',
game_time: '2026-08-31T23:05:00Z', game_date: '2026-08-31',
canonical_event_id: 'mlb:gamepk:999001',
},
[
{ player: 'Aaron Judge', stat_type: 'total_bases', line: 1.5, direction: 'over', grade: 'A+', confidence: 80 },
{ player: 'Aaron Judge', stat_type: 'total_bases', line: 1.5, direction: 'under', grade: 'D', confidence: 40 },
],
);
}
await opts.cacheSet('grades:x', { grades });
return { written: true, count: 1 };
},
resolveStats: async () => ({ found: false }),
classify: require('../../src/services/archetypeService').classify,
cacheGet: cache.cacheGet, cacheSet: cache.cacheSet,
now: () => '2026-08-31T01:00:00Z', nowMs: () => 1000,
...extra,
});
test('a throwing lineage commit leaves the slate published and the run ok', async () => {
setPersistent('mlb');
const cache = memCache();
// The counter is the point. Without it this test passes when the lineage
// path is never entered at all, which asserts nothing about isolation.
let commits = 0;
const r = await svc.runSnapshot('mlb', deps(cache, {
retention: {
persist: async () => ({ attempted: 1, written: 1 }),
commitPublication: async () => { commits += 1; throw new Error('lineage exploded'); },
rowsFromSides: retention.rowsFromSides,
createCollector: retention.createCollector,
newSnapshotId: retention.newSnapshotId,
},
}));
expect(commits).toBe(1); // the failure really happened
expect(r.status).toBe('ok'); // and the run still completed
// The authoritative product write happened regardless...
expect(cache.store['snapshot:mlb:latest']).toBeTruthy();
// ...and so did every step AFTER the lineage block. This is what separates
// "the slate was already written" from "the exception was contained".
expect(cache.store['grades:mlb']).toBeTruthy();
});
test('a throwing lineage commit does not stop the Ledger write', async () => {
setPersistent('mlb');
const cache = memCache();
const ledgerCalls = [];
let commits = 0;
await svc.runSnapshot('mlb', deps(cache, {
retention: {
persist: async () => ({ attempted: 1, written: 1 }),
commitPublication: async () => { commits += 1; throw new Error('lineage exploded'); },
rowsFromSides: retention.rowsFromSides,
createCollector: retention.createCollector,
newSnapshotId: retention.newSnapshotId,
},
ledger: {
recordPipelineGrades: async (...a) => { ledgerCalls.push(a); return { written: 1 }; },
captureClosing: async () => ({}),
},
}));
expect(commits).toBe(1);
expect(ledgerCalls.length).toBe(1);
// read_id linkage is absent, never guessed.
expect(ledgerCalls[0][3].lineageIndex).toBeNull();
});
test('with the mode OFF no lineage commit is attempted at all', async () => {
setPersistent(null);
const cache = memCache();
let commits = 0;
await svc.runSnapshot('mlb', deps(cache, {
retention: {
persist: async () => ({ attempted: 1, written: 1 }),
commitPublication: async () => { commits += 1; return { published: 0, candidates: 0 }; },
rowsFromSides: retention.rowsFromSides,
createCollector: retention.createCollector,
newSnapshotId: retention.newSnapshotId,
},
}));
expect(commits).toBe(0);
});
});
/* ─────────────── PARTIAL-LINEAGE ATOMICITY (no half actions) ─────────────── */
describe('a failed lineage attempt writes no half action', () => {
test('a throwing family lookup leaves every row completely blank', async () => {
const rows = [
{ sport: 'mlb', game_date: '2026-08-31', player_key: 'a b', stat: 'hits', side: 'over', line: 0.5, published: true },
{ sport: 'mlb', game_date: '2026-08-31', player_key: 'c d', stat: 'hits', side: 'over', line: 0.5, published: true },
];
const out = await retention.attachLineage(rows, { fetchExisting: async () => { throw new Error('boom'); } });
expect(out.error).toMatch(/boom/);
for (const r of rows) {
expect(retention.isValidLineageAction(r)).toBe(false);
for (const k of retention.LINEAGE_KEYS) expect(r[k]).toBeNull();
}
// The natural key stamped before the lookup is cleared too — it is family
// identity, and a failed attempt has no claim to it.
expect(rows[0].read_natural_key).toBeNull();
expect(out.incomplete_cleared).toBe(2);
});
});
/* ───────────── INDEPENDENT COVERAGE OBSERVER (never trust the writer) ───────────── */
describe('coverage observer', () => {
const row = (o) => ({
sport: 'mlb', game_date: '2026-08-31', player_key: 'aaron judge', stat: 'hits',
side: 'over', line: 0.5, published: true, ...o,
});
const action = (o) => ({
read_id: 'r1', read_natural_key: 'k', lineage_action: 'ORIGIN', claim_digest: 'd',
revision_ordinal: 0, lineage_state: 's', lineage_version: 'lin@1',
claim_schema_version: 'claim@1', digest_algorithm_version: 'sha256-json-sorted@1', ...o,
});
test('THE DENOMINATOR IGNORES lineage_action — the property, not the spelling', () => {
const base = [row({ player_key: 'a' }), row({ player_key: 'b' })];
const withLineage = base.map((r) => ({ ...r, ...action({ read_natural_key: r.player_key }) }));
const without = base.map((r) => ({ ...r }));
// Same rows, opposite lineage state, identical expectation.
expect(coverage.expectedKeys(withLineage).keys.size).toBe(coverage.expectedKeys(without).keys.size);
expect([...coverage.expectedKeys(withLineage).keys].sort())
.toEqual([...coverage.expectedKeys(without).keys].sort());
});
test('unpublished rows are not expected to have lineage', () => {
expect(coverage.expectedKeys([row({ published: false })]).keys.size).toBe(0);
expect(coverage.expectedKeys([row({ published: null })]).keys.size).toBe(0);
});
test('a row with no derivable identity is counted, not silently dropped', () => {
const e = coverage.expectedKeys([row({ player_key: '' })]);
expect(e.keys.size).toBe(0);
expect(e.unkeyable_rows).toBe(1);
});
test('WRITER NEVER RAN: full slate, zero lineage -> MISSING_COVERAGE', () => {
const a = coverage.auditRows([row({ player_key: 'a' }), row({ player_key: 'b' })]);
expect(a.expected_keys).toBe(2);
expect(a.covered_keys).toBe(0);
expect(a.health).toBe(coverage.HEALTH.MISSING_COVERAGE);
});
test('zero expected and zero written are DIFFERENT answers', () => {
const none = coverage.auditRows([row({ published: false })]);
expect(none.health).toBe(coverage.HEALTH.NO_ELIGIBLE_CLAIMS);
expect(none.health).not.toBe(coverage.HEALTH.MISSING_COVERAGE);
});
test('partial coverage is detected', () => {
const rows = [
{ ...row({ player_key: 'a' }), ...action({ read_natural_key: 'mlb|2026-08-31|a|hits|over|0.500000' }) },
row({ player_key: 'b' }),
];
const a = coverage.auditRows(rows);
expect(a.health).toBe(coverage.HEALTH.PARTIAL_COVERAGE);
expect(a.missing_keys).toBe(1);
expect(a.coverage_pct).toBe(50);
});
test('full coverage is HEALTHY', () => {
const rows = ['a', 'b'].map((p) => ({
...row({ player_key: p }),
...action({ read_natural_key: `mlb|2026-08-31|${p}|hits|over|0.500000`, read_id: `r-${p}` }),
}));
const a = coverage.auditRows(rows);
expect(a.health).toBe(coverage.HEALTH.HEALTHY);
expect(a.coverage_pct).toBe(100);
expect(a.missing_keys).toBe(0);
expect(a.extra_keys).toBe(0);
});
test('an invalid partial action is INVALID_GRAPH, never counted as covered', () => {
const partial = { ...row({ player_key: 'a' }), read_natural_key: 'k', read_id: 'r' }; // 2 of 9
const a = coverage.auditRows([partial]);
expect(a.invalid_partial_actions).toBe(1);
expect(a.covered_keys).toBe(0);
expect(a.health).toBe(coverage.HEALTH.INVALID_GRAPH);
});
test('extra lineage — covered but never expected — is a defect', () => {
const rows = [{ ...row({ published: false, player_key: 'a' }), ...action({ read_natural_key: 'ghost' }) }];
const a = coverage.auditRows(rows);
expect(a.expected_keys).toBe(0);
expect(a.extra_keys).toBe(1);
expect(a.health).toBe(coverage.HEALTH.INVALID_GRAPH);
});
test('a forked chain is a graph defect', () => {
const k = 'mlb|2026-08-31|a|hits|over|0.500000';
const rows = [
{ ...row({ player_key: 'a' }), ...action({ read_natural_key: k, revision_ordinal: 0 }) },
{ ...row({ player_key: 'a' }), ...action({ read_natural_key: k, revision_ordinal: 0 }) },
];
const a = coverage.auditRows(rows);
expect(a.graph_defects).toBeGreaterThan(0);
expect(a.health).toBe(coverage.HEALTH.INVALID_GRAPH);
});
test('the observer\'s valid-action fields match the writer\'s, without importing it', () => {
expect([...coverage.VALID_ACTION_FIELDS].sort())
.toEqual([...retention.VALID_LINEAGE_ACTION_FIELDS].sort());
});
test('a cohort spanning two game_dates is audited whole, not one slice', () => {
// The real 2026-08-31 03:00Z shape: a late slot spanning midnight ET. Rows
// from BOTH dates are eligible and both must be counted, or a date slice
// with no lineage stays invisible behind a HEALTHY verdict.
const mk = (d, p, covered) => ({
sport: 'mlb', game_date: d, player_key: p, stat: 'hits', side: 'over',
line: 0.5, published: true,
...(covered ? {
read_id: `r-${p}`, read_natural_key: `mlb|${d}|${p}|hits|over|0.500000`,
lineage_action: 'ORIGIN', claim_digest: 'd', revision_ordinal: 0,
lineage_state: 's', lineage_version: 'lin@1', claim_schema_version: 'claim@1',
digest_algorithm_version: 'sha256-json-sorted@1',
} : {}),
});
const a = coverage.auditRows([mk('2026-08-31', 'a', true), mk('2026-08-30', 'b', false)]);
expect(a.expected_keys).toBe(2);
expect(a.covered_keys).toBe(1);
expect(a.health).toBe(coverage.HEALTH.PARTIAL_COVERAGE);
});
test('an unavailable audit is not a coverage claim', () => {
expect(coverage.classify({ audit_available: false })).toBe(coverage.HEALTH.AUDIT_UNAVAILABLE);
});
});
/* ───────────────────────── ADDITIVE ANCESTRY ───────────────────────── */
describe('ancestry surface tells the truth about what it has', () => {
const A = ancestry.ANCESTRY_STATE;
const act = (o) => ({
id: 1, read_id: 'r1', read_natural_key: 'k', lineage_action: 'ORIGIN', claim_digest: 'd0',
revision_ordinal: 0, lineage_state: 'PUBLISHED', lineage_version: 'lin@1',
claim_schema_version: 'claim@1', digest_algorithm_version: 'sha256-json-sorted@1',
publication_id: 'p1', ...o,
});
test('a row lineage never ran for is LEGACY_UNVERIFIED, and nothing is synthesized', () => {
const out = ancestry.classifyAncestry([{ id: 1, publication_id: null, grade: 'B' }]);
expect(out.state).toBe(A.LEGACY_UNVERIFIED);
expect(out.revisions).toEqual([]);
expect(out.read_id).toBeUndefined();
});
test('a row lineage RAN for but did not complete is LINEAGE_UNAVAILABLE, not legacy', () => {
// This is the shape of the 1,119 historical partial rows.
const out = ancestry.classifyAncestry([{ id: 1, publication_id: 'p1', read_natural_key: 'k' }]);
expect(out.state).toBe(A.LINEAGE_UNAVAILABLE);
expect(out.state).not.toBe(A.LEGACY_UNVERIFIED);
});
test('a partial row is never elected as an ancestry head', () => {
const out = ancestry.classifyAncestry([
{ id: 1, publication_id: 'p1', read_natural_key: 'k', read_id: 'r1' },
]);
expect(out.state).toBe(A.LINEAGE_UNAVAILABLE);
expect(out.current).toBeUndefined();
});
test('ORIGIN alone reads as a one-entry chronology', () => {
const out = ancestry.classifyAncestry([act({})]);
expect(out.state).toBe(A.LINEAGE_AVAILABLE);
expect(out.revision_count).toBe(0);
expect(out.original.action).toBe('ORIGIN');
expect(out.current.action).toBe('ORIGIN');
expect(out.authority).toBe('NON_AUTHORITATIVE');
});
test('REVISION ancestry names the exact parent and order', () => {
const out = ancestry.classifyAncestry([
act({ id: 1, revision_ordinal: 0, lineage_action: 'ORIGIN' }),
act({ id: 2, revision_ordinal: 1, lineage_action: 'REVISION', supersedes_id: 1, claim_digest: 'd1', change_type: 'MIXED_CHANGE' }),
]);
expect(out.state).toBe(A.LINEAGE_AVAILABLE);
expect(out.revision_count).toBe(1);
expect(out.current.revision_ordinal).toBe(1);
expect(out.current.supersedes_row_id).toBe(1);
expect(out.current.change_type).toBe('MIXED_CHANGE');
});
test('RECAPTURE is reported as a recapture, never as a revision', () => {
const out = ancestry.classifyAncestry([
act({ id: 1, lineage_action: 'ORIGIN', revision_ordinal: 0 }),
act({ id: 2, lineage_action: 'RECAPTURE', revision_ordinal: 0, recaptures_id: 1 }),
]);
expect(out.state).toBe(A.LINEAGE_AVAILABLE);
expect(out.revision_count).toBe(0);
expect(out.recapture_count).toBe(1);
expect(out.recaptures[0].action).toBe('RECAPTURE');
});
test('a broken chain REFUSES rather than electing a head', () => {
const out = ancestry.classifyAncestry([
act({ id: 1, lineage_action: 'ORIGIN', revision_ordinal: 0 }),
act({ id: 2, lineage_action: 'REVISION', revision_ordinal: 1, supersedes_id: 999 }),
]);
expect(out.state).toBe(A.INVALID_LINEAGE);
expect(out.revisions).toEqual([]);
});
test('two read_ids under one natural key is INVALID_LINEAGE', () => {
const out = ancestry.classifyAncestry([act({ id: 1, read_id: 'r1' }), act({ id: 2, read_id: 'r2' })]);
expect(out.state).toBe(A.INVALID_LINEAGE);
});
test('the projection carries only what lineage knows', () => {
const p = ancestry.project({ ...act({}), p_win: 0.6, grade: 'A', locked_odds: '-110', outcome: 'hit' });
for (const forbidden of ['p_win', 'grade', 'locked_odds', 'outcome', 'projection']) {
expect(p[forbidden]).toBeUndefined();
}
expect(p.read_id).toBe('r1');
expect(p.claim_digest).toBe('d0');
});
test('a valid chain with a stamped-but-unrecorded sibling discloses the hole', () => {
// The production shape: one good ORIGIN plus a later publication that was
// attempted and never recorded. The chain stays valid and the partial row
// stays out of it, but the answer must not claim the chronology is whole.
const out = ancestry.classifyAncestry([
act({ id: 1, publication_id: 'p1' }),
{ id: 2, publication_id: 'p2', read_natural_key: 'k' },
]);
expect(out.state).toBe(A.LINEAGE_AVAILABLE);
expect(out.revisions).toHaveLength(1);
expect(out.revisions[0].snapshot_row_id).toBe(1); // the partial is excluded
expect(out.chronology_complete).toBe(false);
expect(out.unrecorded_publications).toBe(1);
});
test('a chain with no unrecorded siblings is complete', () => {
const out = ancestry.classifyAncestry([act({ id: 1, publication_id: 'p1' })]);
expect(out.chronology_complete).toBe(true);
expect(out.unrecorded_publications).toBe(0);
});
test('nothing found is NOT_FOUND, which is not an absence of lineage', () => {
expect(ancestry.classifyAncestry([]).state).toBe(A.NOT_FOUND);
});
});
/* ────────────────────── PRESERVATION ────────────────────── */
describe('this tranche changes nothing it was told not to', () => {
const fs = require('fs'); const path = require('path');
const ROOT = path.resolve(__dirname, '..', '..');
test('the grade-shift badge is untouched — no lineage anywhere near it', () => {
for (const f of ['src/routes/ledger.js', 'src/routes/profiles.js']) {
const src = fs.readFileSync(path.join(ROOT, f), 'utf8');
expect(src).toMatch(/revised_from_grade/);
expect(src).not.toMatch(/lineage|ancestry|read_id/i);
}
});
test('retention identity and its collision counter are unchanged', () => {
expect(retention.RETENTION_CONFLICT.split(',')).toEqual(
['snapshot_id', 'game_id', 'canonical_event_id', 'player_key', 'stat', 'line', 'side']);
const dup = [
{ snapshot_id: 's', game_id: 'g', canonical_event_id: 'e', player_key: 'a', stat: 'hits', line: 0.5, side: 'over' },
{ snapshot_id: 's', game_id: 'g', canonical_event_id: 'e', player_key: 'a', stat: 'hits', line: 0.5, side: 'over' },
];
expect(retention.expectedMaterialization(dup).collision_count).toBe(1);
});
test('participant identity guards are unchanged', () => {
const pid = require('../../src/services/model/participantIdentity');
const a = pid.auditParticipantIdentity([
{ canonical_event_id: 'e', mlb_person_id: 1, player_key: 'x' },
{ canonical_event_id: 'e', mlb_person_id: 1, player_key: 'y' },
]);
expect(a.participant_identity_split_count).toBe(1);
expect(pid.semanticPlayerKey({ player: 'Mickey Gasper', mlb_person_id: 681508, canonical_player_name: 'Mickey Gasper' }).canonical).toBe(true);
});
test('the ancestry surface writes nothing', () => {
const src = fs.readFileSync(path.join(ROOT, 'src/services/read/readAncestry.js'), 'utf8')
.replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '');
for (const verb of ['.insert(', '.update(', '.upsert(', '.delete(']) {
expect(src).not.toContain(verb);
}
});
test('the coverage observer writes nothing', () => {
const src = fs.readFileSync(path.join(ROOT, 'src/services/lineageCoverage.js'), 'utf8')
.replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '');
for (const verb of ['.insert(', '.update(', '.upsert(', '.delete(']) {
expect(src).not.toContain(verb);
}
});
});