feat(recovery): the fold-checkpoint bound — crash folds (checkpoint, head], never the whole log twice
The fold checkpoint (_system/fold-checkpoint.json) is stamped strictly after a canonical-sync barrier over every live entity touched since the last stamp (syncEntityCanonical: ids → canonical paths → fsync; an absent file fsyncs its parent directory so deletes are as durable as writes). An unclean open under log authority now folds only (checkpoint, head]; the chain bootstraps at an empty brain's adoption (three-phase hooks around adoptLogAuthority) or at a brain's first whole-log fold — existing brains converge at their first crash with zero regression. Rollback restores sync immediately; abort paths feed the barrier; a failed barrier retains the old bound (bigger fold later, never a lost write). Five structural pins including boundedness itself. Also: the production-shaped write-flow gate leg (mixed traffic racing flushes, crash mid-traffic, every ack survives — from a consumer-reported gate miss), and two release-ceremony cures (tag-first push so the publish never queues behind the release commit's CI run; raw-curl npmjs shasum probe with propagation grace instead of a one-shot false divergence).
This commit is contained in:
parent
cbe34d115e
commit
ff43de1ada
8 changed files with 695 additions and 12 deletions
|
|
@ -462,6 +462,18 @@ export interface GenerationStorage {
|
|||
/** @see beginWriteBarrier — fsync every canonical write since begin. */
|
||||
flushWriteBarrier?(): Promise<void>
|
||||
|
||||
/**
|
||||
* OPTIONAL fold-checkpoint durability barrier: make the listed entities'
|
||||
* CANONICAL live objects durable — fsync each present metadata/vector file
|
||||
* AND the parent directory entry of each absent one (so a delete is as
|
||||
* durable as a write). The generation store may only advance the fold
|
||||
* checkpoint (`_system/fold-checkpoint.json`) after this resolves; the
|
||||
* checkpoint bounds crash recovery's log fold to `(checkpoint, head]`.
|
||||
* Adapters whose writes are durable per-call may leave this undefined —
|
||||
* the store then treats canonical durability as immediate.
|
||||
*/
|
||||
syncEntityCanonical?(nouns: string[], verbs: string[]): Promise<void>
|
||||
|
||||
/** Read an entity's raw stored metadata+vector objects. */
|
||||
readNounRaw(id: string): Promise<{ metadata: any | null; vector: any | null }>
|
||||
/** Restore an entity's raw stored objects (`null` part ⇒ delete that file). */
|
||||
|
|
|
|||
Reference in a new issue