open-brainy/tests/unit/brainy/metadata-provider-contract.test.ts

70 lines
3.2 KiB
TypeScript
Raw Normal View History

/**
* @module tests/unit/brainy/metadata-provider-contract
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
* @description Brainy-side wiring of the metadata-provider contract.
*
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
* `getIdsForFilter(filter, opts?)` brainy passes a page bound on the UNSORTED
* `find({ type, where, limit })` path so a native provider can early-stop. The JS
* index ignores `opts`.
*
* RETIRED (health-gate law): `probeConsistency()` / `ensureMetadataConsistencyProbed()`
* a read-time consistency probe that launches `detectAndRepairCorruption()` on
* `false` was exactly the read-triggered dark rebuild the law forbids (a read must
* never start a store walk or a rebuild). The probe's diagnostic value lives on in
* `validateIndexConsistency()` / `repairIndex()`, which remain explicit, operator-invoked
* calls. The pin below confirms the retirement: `probeConsistency()` is never called by
* a read, even when a provider exposes it.
*
* These are unit tests of brainy's CALL behaviour (the real end-to-end honoring is
* exercised by cor's combined matrix); they inject probe/spy hooks onto the live JS
* metadata index, which has neither method by default.
*/
import { describe, it, expect, beforeEach } from 'vitest'
import { Brainy } from '../../../src/brainy'
import { NounType } from '../../../src/types/graphTypes'
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
describe('metadata-provider contract wiring (getIdsForFilter opts)', () => {
let brain: Brainy<any>
let mi: any
beforeEach(async () => {
brain = new Brainy({ requireSubtype: false, storage: { type: 'memory' }, silent: true })
await brain.init()
await brain.add({ data: 'a', type: NounType.Thing, metadata: { kind: 'x' } })
await brain.add({ data: 'b', type: NounType.Thing, metadata: { kind: 'y' } })
mi = (brain as any).metadataIndex
})
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
it('RETIRED: a read never calls probeConsistency() / self-heals via detectAndRepairCorruption — that is the read-triggered dark rebuild the health-gate law forbids', async () => {
let probes = 0
let repairs = 0
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
mi.probeConsistency = async () => { probes++; return false } // would-be corrupt signal
const origRepair = mi.detectAndRepairCorruption.bind(mi)
mi.detectAndRepairCorruption = async () => { repairs++; return origRepair() }
await brain.find({ where: { kind: 'x' } })
await brain.find({ where: { kind: 'y' } })
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
expect(probes).toBe(0) // no read-time probe exists anymore
expect(repairs).toBe(0) // and therefore no read-triggered self-heal either
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
delete mi.probeConsistency
mi.detectAndRepairCorruption = origRepair
})
it('passes a page bound to getIdsForFilter on the unsorted find path (offset 0, brainy re-windows)', async () => {
let seenOpts: { limit?: number; offset?: number } | undefined
const orig = mi.getIdsForFilter.bind(mi)
mi.getIdsForFilter = async (filter: any, opts?: { limit?: number; offset?: number }) => {
seenOpts = opts
return orig(filter, opts)
}
const rows = await brain.find({ where: { kind: 'x' }, limit: 5 })
expect(rows.length).toBe(1) // result correctness preserved (JS ignores opts)
expect(seenOpts).toBeDefined()
expect(typeof seenOpts!.limit).toBe('number')
expect(seenOpts!.limit).toBeGreaterThanOrEqual(5)
expect(seenOpts!.offset).toBe(0) // brainy applies offset itself via slice
})
})