docs(release): the 10.4.0 entry, the index-health concept doc, and the API surfaces — written from the tree, not the plan
This commit is contained in:
parent
b9ba50fbec
commit
8cced871a0
8 changed files with 454 additions and 63 deletions
|
|
@ -1451,6 +1451,34 @@ const count = await brain.getVerbCount()
|
|||
|
||||
---
|
||||
|
||||
### The canonical count ledger (`StorageAdapter.getCanonicalCounts()`)
|
||||
|
||||
An OPTIONAL method on the `StorageAdapter` interface (implemented by both
|
||||
built-in adapters), not a method on `Brainy` itself — relevant if you're
|
||||
writing a custom storage adapter or composing a provider's own
|
||||
`healthReport()`. O(1), no I/O. Per family (`nouns`/`verbs`):
|
||||
|
||||
```typescript
|
||||
interface CanonicalCounts {
|
||||
nouns: { counted: number; all: number }
|
||||
verbs: { counted: number; all: number }
|
||||
suspect: boolean
|
||||
}
|
||||
```
|
||||
|
||||
- `counted` mirrors `getNounCount()` / `getVerbCount()` (public + internal tiers).
|
||||
- `all` is the ALL-visibility scalar — every tier, including system/internal
|
||||
records — the denominator a derived index's own coverage math is measured
|
||||
against.
|
||||
- `suspect` is `true` when an unprovable delete has left `all` unverified since
|
||||
the last recount; `brain.repairIndex()` clears it with a real canonical walk.
|
||||
|
||||
Adapters without the ledger omit the method; treat absence as "no
|
||||
denominator," never as zero. See
|
||||
**[Index Health](../concepts/index-health.md)** for the full story.
|
||||
|
||||
---
|
||||
|
||||
### Subtype & facet APIs
|
||||
|
||||
Full guide: **[Subtypes & Facets](../guides/subtypes-and-facets.md)**.
|
||||
|
|
@ -1852,6 +1880,81 @@ await brain.repairIndex({ rebuild: ['graph'] })
|
|||
await brain.repairIndex({ rebuild: 'all' })
|
||||
```
|
||||
|
||||
**`RepairReport`:**
|
||||
- `families: RepairFamilyReport[]` — one row per family checked
|
||||
- `healedTotal: number` — items healed across every family
|
||||
- `durationMs: number`
|
||||
|
||||
**`RepairFamilyReport`** (one row):
|
||||
- `family: string` — e.g. `'orphaned-containers'`, `'count-rollups'`,
|
||||
`'vfs-containment'`, `'metadata-corruption'`, `'provider:metadata'`,
|
||||
`'provider:graph'`, `'provider:vector'`
|
||||
- `checked: boolean` — was this family actually examined (`false` ⇒ see `skipped`)
|
||||
- `healed: number` — items re-posted/corrected in place (the incremental heal count)
|
||||
- `missing?: { count: number; sample: string[] }` — exact count plus a capped id
|
||||
sample when the check can name what diverged (never the full list)
|
||||
- `rebuilt?: boolean` — a full generational rebuild ran (vs. an incremental heal)
|
||||
- `detail?: string` / `reason?: string` — narration
|
||||
- `skipped?: string` — why the family wasn't checked
|
||||
|
||||
Full walkthrough — what each family checks, degraded-but-serving vs. not-ready,
|
||||
and what `suspect` counts mean — in
|
||||
**[Index Health](../concepts/index-health.md)**.
|
||||
|
||||
---
|
||||
|
||||
### Index readiness: typed errors, `healthReport()`, `disableAutoRebuild`
|
||||
|
||||
Every derived-index provider (vector, graph, metadata) may expose a named,
|
||||
synchronous, O(1) `healthReport()` composed from its own exact ledgers — the
|
||||
signal Brainy's read gate trusts over sampling or size heuristics. `init()`
|
||||
brings every provider to serving before it returns; there is no first-query
|
||||
lazy-rebuild path. A read that reaches a provider whose health report says it
|
||||
isn't serving throws instead of rebuilding mid-query:
|
||||
|
||||
| Error | Thrown by | Meaning |
|
||||
|---|---|---|
|
||||
| `GraphIndexNotReadyError` | `find({ connected })`, `neighbors()`, `related()` | Graph adjacency isn't serving |
|
||||
| `MetadataIndexNotReadyError` | `find({ where })` | Metadata/field index isn't serving |
|
||||
| `VectorIndexNotReadyError` | `find({ query })`, `similar()` | Vector index isn't serving |
|
||||
|
||||
All three are exported from `@soulcraft/brainy`. Catch them to distinguish
|
||||
"index not ready" from a genuine empty result:
|
||||
|
||||
```typescript
|
||||
import { MetadataIndexNotReadyError } from '@soulcraft/brainy'
|
||||
|
||||
try {
|
||||
const rows = await brain.find({ where: { status: 'active' } })
|
||||
} catch (err) {
|
||||
if (err instanceof MetadataIndexNotReadyError) {
|
||||
// reconcile: await brain.repairIndex(), then retry
|
||||
} else {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**`disableAutoRebuild`** no longer defers index construction to the first
|
||||
query. A needed rebuild always runs at `open()`, regardless of this flag or
|
||||
dataset size; the flag has no effect on *when* a rebuild runs. Full manual
|
||||
control lives in `repairIndex({ rebuild: [...] })`, above.
|
||||
|
||||
### `validateIndexConsistency()` → `Promise<...>`
|
||||
|
||||
The deep, async diagnostic counterpart to `healthReport()` — safe to run on a
|
||||
live brain, but does more work (a provider's `validateInvariants()` may run a
|
||||
full scan, not just read a ledger). Aggregates the JS metadata index's own
|
||||
consistency check with every derived-index provider's invariant report.
|
||||
|
||||
```typescript
|
||||
const validation = await brain.validateIndexConsistency()
|
||||
if (!validation.healthy) {
|
||||
console.log(validation.recommendation) // what to run, e.g. repairIndex()
|
||||
console.log(validation.providers) // each provider's own invariant report, when exposed
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Lifecycle
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue