From 36c10c1e205955ac1a45ac2604368f85b5a5cfa6 Mon Sep 17 00:00:00 2001 From: David Snelling Date: Mon, 13 Jul 2026 10:44:11 -0700 Subject: [PATCH] chore: hold loadBinaryBlob fault-propagation for the cortex column-store lockstep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Pass-1 hardening made loadBinaryBlob distinguish genuine absence (ENOENT → null) from a real fault (EIO/EACCES/… → throw), so a present-but-unreadable blob stops masquerading as "absent". The native column-store still has two call sites that rely on the old null-on-error contract; publishing the throw ahead of them would break a consumer running new brainy + old cortex. Per the cortex coordination (accept: cor first, then brainy), this temporarily restores the shipped 8.2.5 swallow-on-fault behavior for loadBinaryBlob ONLY, so the rest of Pass 1 — saveBinaryBlob write-honesty, clear() native wipe, pending-flush durability, count symmetry, degraded surfacing, aggregation loudness — can release now. The method carries an inline restore guide; the throwing form goes back in and ships lockstep with the native hardening. No other Pass-1 change depends on this behavior (ColumnStore's own fault test uses a direct-throwing storage stub), so the split is behaviour-neutral for every consumer versus 8.2.5. --- src/storage/adapters/fileSystemStorage.ts | 28 +++++++++++++++-------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/storage/adapters/fileSystemStorage.ts b/src/storage/adapters/fileSystemStorage.ts index 95d3951d..f676d091 100644 --- a/src/storage/adapters/fileSystemStorage.ts +++ b/src/storage/adapters/fileSystemStorage.ts @@ -17,7 +17,6 @@ import { WriterLockInfo } from '../baseStorage.js' import { getBrainyVersion } from '../../utils/index.js' -import { isAbsentError } from '../../utils/errorClassification.js' // Node.js modules - dynamically imported to avoid issues in browser environments let fs: any @@ -1229,14 +1228,25 @@ export class FileSystemStorage extends BaseStorage { await this.ensureInitialized() try { return await fs.promises.readFile(this.blobPath(key)) - } catch (err) { - // Absent blob → null (the documented contract). A real fault - // (EIO/EACCES/EMFILE/…) must NOT be masked as "absent": doing so makes a - // present-but-unreadable blob look missing and drives a needless rebuild - // or an empty read (the native provider consumes this). Mandate: loud - // errors, never quiet losses. - if (isAbsentError(err)) return null - throw err + } catch { + // COORDINATION HOLD — restore the fault-propagating form lockstep with + // cortex 3.0.13 (CORTEX-BILLION-SCALE-SPINE). The correct behavior + // distinguishes genuine absence from a real fault so a present-but- + // unreadable blob no longer masquerades as "absent" (which drove needless + // rebuilds / empty reads). Restore to: + // } catch (err) { + // // re-add: import { isAbsentError } from '../../utils/errorClassification.js' + // if (isAbsentError(err)) return null + // throw err + // } + // The throw is HELD because the native column-store still has 2 call sites + // that rely on null-on-error; cortex hardens them in 3.0.13, then this + // reverts to the throwing form and ships lockstep. Until then this + // preserves the shipped 8.2.5 swallow-on-fault behavior, so a consumer on + // new-brainy + old-cortex can never break. All other Pass-1 hardening + // (saveBinaryBlob honesty, clear(), pending-flush durability, count + // symmetry, degraded surfacing, aggregation) ships now, independent of this. + return null } }