open-brainy/tests/unit/utils/indexReadiness.test.ts
David Snelling f8f64780b1
All checks were successful
CI / Node 22 (push) Successful in 12m19s
CI / Node 24 (push) Successful in 12m16s
CI / Integration + conformance (Node 22) (push) Successful in 18m41s
CI / Bun (latest) (push) Successful in 12m20s
feat(health): the gate reads the named report — reads refuse loudly, never rebuild; open serves before it returns; the ceremony door
The read gate stops consulting the unnamed isReady() boolean: every provider
may expose healthReport() (sync, O(1), composed from exact ledgers —
HealthReport with a monotonic generation, per-invariant source
ledger|deep|unledgered, missing {count, sample}), and one readiness
authority (assessProviderHealth) derives the verdict. Unledgered families
are UNKNOWN — never healthy, never broken; a report that throws is a loud
not-ready, never a shrug. Reads at the four index choke points refuse with
the typed NotReady errors, narrated once per (provider, generation) — a
read NEVER starts a store walk:

- the first-read lazy build retires (open builds instead, regardless of
  size — the ≥10k deferral and the "lazy loading on first query" branch go;
  disableAutoRebuild is re-meant honestly in its docs);
- the verify*Live read-path rebuild triggers retire (refuse-or-serve);
- the read-time consistency probe that could launch a dark rebuild from an
  ordinary find() retires;
- repairIndex({ rebuild: ['metadata'|'graph'|'vector'] | 'all' }) is the
  one explicit door: rebuilds the named leg unconditionally and reports
  rebuilt per family; bare repairIndex() stays report-driven.

test(lifecycle): the biography lane — a store's whole life, refereed

tests/lifecycle/: an independent shadow model referees every read after
every chapter (founding, a working day, clean restart, crash, repair,
second life). Chapters 1-3 green. Chapters 4-6 assert the true contract and
are marked .fails as a release-blocking finding (the kill-matrix
convention): after a crash + adopt reopen the metadata index computes its
'catchup' watermark verdict and nothing consumes it — find() serves the
pre-crash index while canonical and counts recover. The catchup wiring is
the cure; a passing .fails will force the marker's removal. The lane runs
in the integration gate (config + coverage guard).
2026-08-24 12:45:51 -07:00

153 lines
6.5 KiB
TypeScript

/**
* @module tests/unit/utils/indexReadiness
* @description Pins for the read-gate authority, {@link assessProviderHealth}, and
* its older sibling {@link assessIndexReadiness}. The health-gate law: a provider's
* NAMED, synchronous, O(1) health report — when exposed — REPLACES the `isReady()`/
* size-heuristic fallback as the read gate's source of truth. A throw from
* `healthReport()` is a CONTRACT VIOLATION (never read as healthy, never swallowed
* into "unknown"); an `unledgered` family is UNKNOWN (never healthy, never broken —
* `serving` is always the provider's own verdict, verbatim).
*/
import { describe, it, expect } from 'vitest'
import { assessIndexReadiness, assessProviderHealth } from '../../../src/utils/indexReadiness.js'
import type { HealthReport, LedgerInvariantResult } from '../../../src/plugin.js'
function invariant(overrides: Partial<LedgerInvariantResult> = {}): LedgerInvariantResult {
return {
name: 'manifest-residency',
holds: true,
detail: 'ok',
heal: 'none',
source: 'ledger',
...overrides
}
}
function report(overrides: Partial<HealthReport> = {}): HealthReport {
return {
provider: 'vector',
healthy: true,
serving: true,
invariants: [],
checkedAt: Date.now(),
durationMs: 1,
generation: 1,
unledgered: [],
...overrides
}
}
describe('assessIndexReadiness (legacy isReady() classifier)', () => {
it('unknown when the provider is null/undefined', () => {
expect(assessIndexReadiness(null)).toBe('unknown')
expect(assessIndexReadiness(undefined)).toBe('unknown')
})
it('unknown when isReady() is absent', () => {
expect(assessIndexReadiness({})).toBe('unknown')
})
it('ready / not-ready mirror isReady()', () => {
expect(assessIndexReadiness({ isReady: () => true })).toBe('ready')
expect(assessIndexReadiness({ isReady: () => false })).toBe('not-ready')
})
})
describe('assessProviderHealth — the read-gate authority', () => {
it('via "none": no provider at all', () => {
const a = assessProviderHealth(null)
expect(a.via).toBe('none')
expect(a.readiness).toBe('unknown')
expect(a.report).toBeNull()
expect(a.reasons.length).toBeGreaterThan(0)
})
it('via "size-heuristic": provider exposes neither healthReport() nor isReady()', () => {
const a = assessProviderHealth({})
expect(a.via).toBe('size-heuristic')
expect(a.readiness).toBe('unknown')
expect(a.report).toBeNull()
})
it('via "is-ready": provider exposes isReady() but no healthReport() — ready', () => {
const a = assessProviderHealth({ isReady: () => true })
expect(a.via).toBe('is-ready')
expect(a.readiness).toBe('ready')
expect(a.reasons).toEqual([])
})
it('via "is-ready": isReady() === false — not-ready with a reason', () => {
const a = assessProviderHealth({ isReady: () => false })
expect(a.via).toBe('is-ready')
expect(a.readiness).toBe('not-ready')
expect(a.reasons.length).toBeGreaterThan(0)
})
it('healthReport() present REPLACES isReady() — serving:true wins even if isReady() lies false', () => {
const p = { isReady: () => false, healthReport: () => report({ serving: true }) }
const a = assessProviderHealth(p)
expect(a.via).toBe('health-report')
expect(a.readiness).toBe('ready')
})
it('serving:true, healthy:true, no invariants failing → ready, no reasons', () => {
const p = { healthReport: () => report({ serving: true, healthy: true }) }
const a = assessProviderHealth(p)
expect(a.readiness).toBe('ready')
expect(a.reasons).toEqual([])
expect(a.report).toEqual(report({ serving: true, healthy: true }))
})
it('serving:false with a named heal:"rebuild" failing invariant → not-ready, reason names it', () => {
const failing = invariant({ name: 'posted-count-floor', holds: false, heal: 'rebuild', detail: 'posted 10 < canonical 20' })
const p = { healthReport: () => report({ serving: false, healthy: false, invariants: [failing] }) }
const a = assessProviderHealth(p)
expect(a.readiness).toBe('not-ready')
expect(a.reasons.some((r) => r.includes('posted-count-floor') && r.includes('heal:rebuild') && r.includes('posted 10 < canonical 20'))).toBe(true)
})
it('unledgered-only report (serving:true, no failing invariant) → ready, reason names the unledgered family', () => {
const p = { healthReport: () => report({ serving: true, healthy: true, unledgered: ['canonical-verb-coverage'] }) }
const a = assessProviderHealth(p)
expect(a.readiness).toBe('ready')
expect(a.reasons.some((r) => r.includes('unledgered') && r.includes('canonical-verb-coverage'))).toBe(true)
})
it('UNLEDGERED IS UNKNOWN: an unledgered family never flips a NOT-serving provider to ready', () => {
const failing = invariant({ holds: false, heal: 'rebuild', name: 'x' })
const p = { healthReport: () => report({ serving: false, healthy: false, invariants: [failing], unledgered: ['some-family'] }) }
const a = assessProviderHealth(p)
expect(a.readiness).toBe('not-ready')
})
it('serving:true, healthy:false with a heal:"repair" failure → still ready (degraded-but-serving)', () => {
const failing = invariant({ name: 'stale-counter', holds: false, heal: 'repair', detail: 'counter drift' })
const p = { healthReport: () => report({ serving: true, healthy: false, invariants: [failing] }) }
const a = assessProviderHealth(p)
expect(a.readiness).toBe('ready')
expect(a.reasons.some((r) => r.includes('stale-counter') && r.includes('heal:repair'))).toBe(true)
})
it('healthReport() that THROWS is a CONTRACT VIOLATION: not-ready, via health-report, reason names the throw — never "unknown"', () => {
const p = { healthReport: () => { throw new Error('mmap window busy') } }
const a = assessProviderHealth(p)
expect(a.via).toBe('health-report')
expect(a.readiness).toBe('not-ready')
expect(a.report).toBeNull()
expect(a.reasons.some((r) => r.includes('mmap window busy'))).toBe(true)
expect(a.readiness).not.toBe('unknown')
})
it('healthReport() that throws a non-Error value still produces a named reason (String(err))', () => {
const p = { healthReport: () => { throw 'boom' } }
const a = assessProviderHealth(p)
expect(a.readiness).toBe('not-ready')
expect(a.reasons.some((r) => r.includes('boom'))).toBe(true)
})
it('the returned report carries the generation for narration dedup', () => {
const p = { healthReport: () => report({ generation: 42 }) }
const a = assessProviderHealth(p)
expect(a.report?.generation).toBe(42)
})
})