schema stamps: lazy v1 for chats + the graph family, honest refusal

Chat records gain version (CURRENT_CHAT_VERSION), stamped by a single
writeChat choke point in the store; absence reads as v1 — existing files
migrate on their next write, no mass rewrite. The graph family (four JSONL
ledgers, sources.json, render-settings.json) shares one lazy sidecar,
graph/format.json; positions stays unstamped (rebuildable) and jobs stay
unstamped (transient).

Downgrade scenario ruled honest-refusal: records stamped newer than the
running build read as absent (chats, logged) or throw (graph family) — a
read-modify-write store never rewrites what it doesn't understand.

Golden fixtures stay the unstamped legacy shape on purpose (lazy v1 is
current-valid by design); the stamped write path is pinned by
tests/schema-stamps.test.ts. Reads never write — the golden byte-identical
pin holds.
This commit is contained in:
amosblomqvist
2026-10-10 13:54:17 +03:00
parent bc09ec25e1
commit eda5491010
10 changed files with 245 additions and 10 deletions
+7
View File
@@ -86,6 +86,13 @@ export const POSITIONS_FILE = path.join(PATHS.graph, "positions.json");
*/
export const RENDER_SETTINGS_FILE = path.join(PATHS.graph, "render-settings.json");
/** The graph-family FORMAT STAMP sidecar (schema-versioning wave,
* 2026-10-10): one version for the whole family — the four JSONL ledgers,
* sources.json, render-settings.json. LAZY v1: absent = v1; the first
* graph-family write creates it. positions.json is REBUILDABLE and rides
* along unversioned by design (owner ruling). */
export const GRAPH_FORMAT_FILE = path.join(PATHS.graph, "format.json");
/**
* THE USER SETTINGS RECORD (settings-storage wave, 2026-09-19): one
* versioned, DELTA-shaped JSON blob at the data-dir seam holding every