Three cures on the JS metadata index, one seam:
- THE CATCHUP WIRING. The index computed its three-way watermark verdict at
open and nothing consumed it — after a crash + adopt reopen, find() served
the pre-crash index while canonical reads and counts recovered (caught by
the lifecycle lane's first run). The open path now consumes the verdict:
'adopt' is a no-op, 'catchup' folds the fact window (stamped, committed]
through the index legs — nouns and verbs, remove-then-add, one mechanism
for add and update — and 'rescan' runs the explicit rebuild, each narrated.
The lane's Ch4–6 release-blocking marker comes off: the contract holds.
Bonus root-cause: close() never stamped the projection watermarks (only
flush() did), so any close without a prior flush verdicted a needless
'rescan' on reopen — both doors now stamp.
- THE LIVE VERB PATH. Verb rows entered the metadata index only via rebuild
walks, so every rebuilt store minted phantom/stale verb postings from its
first live relate(). relate()/unrelate()/updateRelation() and remove()'s
cascade now post/retract the verb's row in the same commit as the graph
leg — transact() planners mirror identically — using the exact record
shape the rebuild walk uses, so live and rebuilt populations agree.
- THE ONLINE REBUILD. rebuild() was clear-then-walk — every metadata read
empty for the duration. rebuildMetadataIndexOnline builds a fresh manager
beside the serving one (shared identity, in-memory build, dual-write via
a shadow seam with zero call-site changes), atomically swaps the
reference, and persists exactly once post-swap. A find() polled ~200x
during a 2k-noun rebuild never dropped below its baseline.
repairIndex({ rebuild: ['metadata'] }) uses it automatically.
|
||
|---|---|---|
| .. | ||
| biography.test.ts | ||
| biographyHarness.ts | ||
| README.md | ||
The Lifecycle Lane
One brain, driven through founding, a working day, a clean restart, a
crash, a repair, and a second life, checked chapter by chapter against an
independent shadow-model referee (biographyHarness.ts). It catches
COMPOSITION regressions unit tests miss — a store fine in one process but
broken across a restart/crash/repair. Runs on the plain JS engine, so it
gates every commit.
Run it: npx vitest run tests/lifecycle --pool=forks
A red names the chapter label, the id, and expected-vs-actual — diagnosable
from the message alone. biography.test.ts is split into two it blocks
(Ch1-3, then Ch4-6) purely for reporting; it is still ONE fixed-order story.
Chapters must never be reordered, skipped, or made conditional, and a
failing chapter's assertion must never be weakened to force green.