/** * @module tests/unit/brainy/maintenance-debt * @description Coverage for `brain.maintenanceDebt()` (8.10.1) — the * observability seam so an operator sees a provider's outstanding background * maintenance work (compaction, deferred writes, a build-new→verify→swap in * flight, ...) BEFORE it grinds a transaction into a budget-busting op, the * same failure class documented on `TransactionTimeoutError` * (src/transaction/errors.ts). Sibling to tests/unit/brainy/warm.test.ts, * which establishes this file's technique: shape the probe points brain.ts * reads (`typeof provider.maintenanceDebt === 'function'`) directly on the * REAL, live provider instances rather than hand-rolling full fakes for the * larger `MetadataIndexProvider` / `GraphIndexProvider` interfaces. * * `brain.maintenanceDebt()` is a PURE PASSTHROUGH: no thresholds, no * polling, no JS-side estimation — these tests pin exactly that by asserting * the returned payload is the provider's object, verbatim. */ import { describe, it, expect } from 'vitest' import { Brainy } from '../../../src/brainy.js' import { NounType } from '../../../src/types/graphTypes.js' import type { ProviderMaintenanceDebt } from '../../../src/plugin.js' // Brainy's ValidationConfig fixes vectors at exactly 384 dimensions // (src/utils/paramValidation.ts) — match it so add() doesn't reject test data. const DIM = 384 const V = (seed = 1): number[] => Array.from({ length: DIM }, (_, i) => Math.sin(seed + i)) async function freshBrain(): Promise> { const brain = new Brainy({ requireSubtype: false, storage: { type: 'memory' }, silent: true }) await brain.init() await brain.add({ data: 'a', type: NounType.Thing, vector: V(1) }) return brain } describe('brain.maintenanceDebt()', () => { it('reports "unavailable" for every surface when no active provider implements maintenanceDebt() (the built-in JS stack today)', async () => { const brain = await freshBrain() const report = await brain.maintenanceDebt() expect(report.vector.outcome).toBe('unavailable') expect(report.vector.debt).toBeUndefined() expect(report.metadata.outcome).toBe('unavailable') expect(report.metadata.debt).toBeUndefined() expect(report.graph.outcome).toBe('unavailable') expect(report.graph.debt).toBeUndefined() await brain.close() }) it('reports "reported" + the exact payload when the active provider implements maintenanceDebt() (verbatim passthrough, no thresholding)', async () => { const brain = await freshBrain() const vectorDebt: ProviderMaintenanceDebt = { pendingBytes: 4_096, pendingItems: 12, lastPassCompletedAt: 1_700_000_000_000, lastPassOutcome: 'completed', converging: true } ;(brain as any).index.maintenanceDebt = async () => vectorDebt const report = await brain.maintenanceDebt() expect(report.vector.outcome).toBe('reported') // Verbatim passthrough — the exact object, not a re-derived copy. expect(report.vector.debt).toBe(vectorDebt) // Untouched surfaces stay honestly 'unavailable'. expect(report.metadata.outcome).toBe('unavailable') expect(report.graph.outcome).toBe('unavailable') await brain.close() }) it('mixed surfaces: each surface\'s outcome depends ONLY on its OWN active provider — one surface reporting never leaks into another', async () => { const brain = await freshBrain() const metadataDebt: ProviderMaintenanceDebt = { pendingItems: 3, lastPassOutcome: 'partial', converging: false } const graphDebt: ProviderMaintenanceDebt = { pendingBytes: 0, converging: true } ;(brain as any).metadataIndex.maintenanceDebt = async () => metadataDebt ;(brain as any).graphIndex.maintenanceDebt = async () => graphDebt // Vector is deliberately left unpatched. const report = await brain.maintenanceDebt() expect(report.vector.outcome).toBe('unavailable') expect(report.vector.debt).toBeUndefined() expect(report.metadata.outcome).toBe('reported') expect(report.metadata.debt).toBe(metadataDebt) expect(report.graph.outcome).toBe('reported') expect(report.graph.debt).toBe(graphDebt) await brain.close() }) it('an empty ProviderMaintenanceDebt object (every field omitted) is still honestly "reported" — presence of the hook, not the payload\'s richness, drives the outcome', async () => { const brain = await freshBrain() const emptyDebt: ProviderMaintenanceDebt = {} ;(brain as any).graphIndex.maintenanceDebt = async () => emptyDebt const report = await brain.maintenanceDebt() expect(report.graph.outcome).toBe('reported') expect(report.graph.debt).toEqual({}) await brain.close() }) })