feat(repair): a heal:'repair' verdict routes to the provider's own incremental repair()
Some checks failed
CI / Node 24 (push) Failing after 7m47s
CI / Node 22 (push) Successful in 12m19s
CI / Bun (latest) (push) Successful in 12m20s
CI / Integration + conformance (Node 22) (push) Successful in 19m22s

repairIndex() acted only on heal:'rebuild' — an invariant asking for the
INCREMENTAL heal (re-post exactly what the ledger names, O(missing), never
a store-sized rebuild) did nothing on brainy's side. A failing 'repair'
verdict now routes to the provider's feature-detected repair(); the
post-heal RE-READ of the report decides success (the acceptance meta-pin's
law — run the named heal once, re-read, nothing may still fail the same
way), and a repair that does not converge is recorded with the escalation
named: repairIndex({ rebuild: [family] }).
This commit is contained in:
David Snelling 2026-08-25 10:47:51 -07:00
parent ddd5e71928
commit 553e0d97ae
2 changed files with 83 additions and 1 deletions

View file

@ -17549,10 +17549,50 @@ export class Brainy<T = any> implements BrainyInterface<T> {
} else {
await p.rebuild()
}
} else if (
report.invariants.some((i) => !i.holds && i.heal === 'repair') &&
typeof (provider as { repair?: () => Promise<unknown> }).repair === 'function'
) {
// INCREMENTAL HEAL ROUTING (ADR-008 D4): a failing verdict whose heal
// is 'repair' routes to the provider's own repair() — O(missing),
// re-posting exactly what its ledger names, never a store-sized
// rebuild. The return shape is the provider's own; the RE-READ of the
// report is what decides success (the acceptance meta-pin's law: run
// the named heal once, re-read, nothing may still fail the same way).
const failingRepairs = report.invariants
.filter((i) => !i.holds && i.heal === 'repair')
.map((i) => i.name)
prodLog.warn(
`[Brainy] repairIndex(): provider '${report.provider}' asks for an incremental ` +
`repair (${failingRepairs.join(', ')}) — running its own repair().`
)
await (provider as { repair: () => Promise<unknown> }).repair()
let cleared = false
let after: ProviderInvariantReport | null = null
try {
after = await p.validateInvariants()
cleared = !after.invariants.some(
(i) => !i.holds && i.heal === 'repair' && failingRepairs.includes(i.name)
)
} catch {
// The post-heal re-read failing is itself reportable, never a crash.
}
record(`provider:${report.provider}`, {
checked: true,
healed: cleared ? failingRepairs.length : 0,
detail: cleared
? `incremental repair cleared: ${failingRepairs.join(', ')}`
: `repair() ran but the re-read still fails (${
after
? after.invariants.filter((i) => !i.holds).map((i) => `${i.name}${i.heal}`).join(', ')
: 're-read threw'
}) escalate to repairIndex({ rebuild: ['${familyName}'] })`,
reason: cleared ? undefined : 'repair did not converge'
})
} else {
record(`provider:${report.provider}`, {
checked: true, healed: 0,
detail: `unhealthy without a rebuild verdict (failing: ${report.invariants.filter((i) => !i.holds).map((i) => `${i.name}${i.heal}`).join(', ')})`
detail: `unhealthy without a routable verdict (failing: ${report.invariants.filter((i) => !i.holds).map((i) => `${i.name}${i.heal}`).join(', ')})`
})
}
}