Merge branch 'release/8.10.1'
All checks were successful
CI / Node 22 (push) Successful in 2m57s
CI / Node 24 (push) Successful in 2m51s
CI / Bun (latest) (push) Successful in 3m2s

# Conflicts:
#	.forgejo/workflows/ci.yml
This commit is contained in:
David Snelling 2026-07-24 16:44:05 -07:00
commit fc9f0d7222
17 changed files with 681 additions and 105 deletions

View file

@ -65,7 +65,8 @@ import type {
OpaqueIdSet,
AtGenerationVectors,
VectorIndexProvider,
GraphIndexProvider
GraphIndexProvider,
ProviderMaintenanceDebt
} from './plugin.js'
import type {
BrainyPlugin,
@ -424,6 +425,30 @@ export interface WarmReport {
totalDurationMs: number
}
/**
* @description Result of {@link Brainy.maintenanceDebt}: one outcome per
* index surface, mirroring {@link WarmReport}'s shape.
* - `'reported'` the active provider for this surface implements
* `maintenanceDebt?()` and its {@link ProviderMaintenanceDebt} payload is
* attached verbatim under `debt`.
* - `'unavailable'` the active provider does not implement the hook, so
* nothing is known; brainy never estimates or infers a payload on its
* behalf.
*/
export type MaintenanceDebtOutcome = 'reported' | 'unavailable'
/**
* @description Per-surface result of {@link Brainy.maintenanceDebt}. Brainy
* performs no thresholding, polling, or estimation over this data it is a
* pure passthrough of each active provider's own self-report (the provider
* owns the numbers; the operator owns the policy).
*/
export interface MaintenanceDebtReport {
vector: { outcome: MaintenanceDebtOutcome; debt?: ProviderMaintenanceDebt }
metadata: { outcome: MaintenanceDebtOutcome; debt?: ProviderMaintenanceDebt }
graph: { outcome: MaintenanceDebtOutcome; debt?: ProviderMaintenanceDebt }
}
/**
* How long a failed aggregation-backfill walk suppresses fresh walk attempts.
* Within the window, queries rethrow the recorded failure instantly (loud,
@ -14352,9 +14377,16 @@ export class Brainy<T = any> implements BrainyInterface<T> {
* *some* backing storage as a side effect but is reported honestly as
* `'probed'`, never `'warmed'`. An empty index or unknown dimension has
* nothing to probe (`'unavailable'`).
* - **Metadata**: full hydration every persisted field's sparse index is
* loaded from storage (`MetadataIndexManager.hydrateAll()`), not just the
* heuristic common-fields subset `init()` warms.
* - **Metadata**: calls the provider's own `warm?()` when the active
* `'metadataIndex'` provider implements it (`'warmed'`) the seam a
* native metadata provider lights up so it is not duck-typed against the
* JS manager's method. Otherwise falls back to full hydration on the
* built-in JS manager every persisted field's sparse index is loaded
* from storage (`MetadataIndexManager.hydrateAll()`), not just the
* heuristic common-fields subset `init()` warms and reports `'warmed'`.
* Neither seam present `'unavailable'` (honest: `init()` is never used
* as a substitute here, since a native provider's `init()` may be a
* cheap verify rather than a real warm).
* - **Graph**: calls the provider's own `warm?()` when the active graph
* provider implements it; otherwise re-runs its existing eager cold-load
* `init()` seam (idempotent the JS adjacency index's `init()` already
@ -14410,12 +14442,23 @@ export class Brainy<T = any> implements BrainyInterface<T> {
// --- Metadata --------------------------------------------------------
const metadataStart = Date.now()
let metadataOutcome: WarmOutcome
const metadataProvider = this.metadataIndex as unknown as MetadataIndexProvider
const metadataWithHydrate = this.metadataIndex as unknown as { hydrateAll?: () => Promise<void> }
if (typeof metadataWithHydrate.hydrateAll === 'function') {
if (typeof metadataProvider.warm === 'function') {
// Active provider (e.g. a native metadata index) declares its own warm
// seam — route through it FIRST so a native provider's warmth is
// reported honestly instead of being duck-typed against the JS
// manager's hydrateAll(), which a native provider does not implement.
await metadataProvider.warm()
metadataOutcome = 'warmed'
} else if (typeof metadataWithHydrate.hydrateAll === 'function') {
// Built-in JS manager path — full sparse-index hydration.
await metadataWithHydrate.hydrateAll()
metadataOutcome = 'warmed'
} else {
// No hydration seam on this metadata provider — nothing to run.
// No hydration seam on this metadata provider — nothing to run. (No
// init() fallback here: init() on a native provider may be a cheap
// verify, and reporting that as warmth would lie.)
metadataOutcome = 'unavailable'
}
const metadataDurationMs = Date.now() - metadataStart
@ -14449,6 +14492,63 @@ export class Brainy<T = any> implements BrainyInterface<T> {
}
}
/**
* Read each index surface's self-reported outstanding maintenance work
* the observability seam so an operator sees a grind coming (rising
* pending bytes/items, a stalled background pass) instead of discovering
* it as a CPU storm or a transaction blowing its budget mid-flight (see
* {@link TransactionTimeoutError}).
*
* PURE PASSTHROUGH: for each of vector/metadata/graph, this calls ONLY the
* ACTIVE provider's own `maintenanceDebt?()` hook (the same per-surface
* provider resolution {@link Brainy.warm} uses) and reports its
* {@link ProviderMaintenanceDebt} payload verbatim. There is no JS-side
* fallback computation, no threshold evaluation, and no polling brainy
* surfaces the truth the provider measured; the provider owns the numbers
* and the operator owns the policy (what threshold matters, what action to
* take). A surface whose active provider does not implement the hook
* reports `'unavailable'` never a guessed or zeroed payload.
*
* @returns A {@link MaintenanceDebtReport}: per-surface outcome + payload.
* @example
* ```typescript
* const debt = await brain.maintenanceDebt()
* if (debt.metadata.outcome === 'reported' && debt.metadata.debt?.pendingBytes) {
* console.log('metadata pending bytes:', debt.metadata.debt.pendingBytes)
* }
* ```
*/
async maintenanceDebt(): Promise<MaintenanceDebtReport> {
await this.ensureInitialized({ needs: ['vector', 'metadata', 'graph'] })
// --- Vector ---------------------------------------------------------
const vectorProvider = this.index as VectorIndexProvider & {
maintenanceDebt?: () => Promise<ProviderMaintenanceDebt>
}
const vector =
typeof vectorProvider.maintenanceDebt === 'function'
? { outcome: 'reported' as const, debt: await vectorProvider.maintenanceDebt() }
: { outcome: 'unavailable' as const }
// --- Metadata --------------------------------------------------------
const metadataProvider = this.metadataIndex as unknown as MetadataIndexProvider
const metadata =
typeof metadataProvider.maintenanceDebt === 'function'
? { outcome: 'reported' as const, debt: await metadataProvider.maintenanceDebt() }
: { outcome: 'unavailable' as const }
// --- Graph -------------------------------------------------------------
const graphProvider = this.graphIndex as GraphIndexProvider & {
maintenanceDebt?: () => Promise<ProviderMaintenanceDebt>
}
const graph =
typeof graphProvider.maintenanceDebt === 'function'
? { outcome: 'reported' as const, debt: await graphProvider.maintenanceDebt() }
: { outcome: 'unavailable' as const }
return { vector, metadata, graph }
}
/**
* Explicitly warm up the embedding engine
*