Skip to content

v5.5.2 — The One Where npm Stops Blocking Your Search Database

Choose a tag to compare

@tpierrain tpierrain released this 26 Sep 09:11
· 33 commits to main since this release

What this release is about

If your brain's search stopped working after an install, the update brings it back on its own.

Your brain finds your notes through a small database that lives next to them. Building it takes one step during installation, and the newest version of npm (the tool that installs the engine's parts) now skips that step unless it has been told the step is expected. Kenjaku did not tell it. So on a machine with that new npm, an install or an update could finish without errors and leave a brain that could no longer search its own notes.

This is recent and does not concern most brains. If yours is one of them, this release fixes the cause and repairs the damage: the engine now declares that step, and the update checks the database really opens. If it does not, the update rebuilds it once and tells you it did.

Two smaller things are fixed along the way. After an update you may have read a warning about a dozen known vulnerabilities, with advice to report it to the author: they were real, in third-party libraries, all with a fix already published, and they are fixed. And on two machines, /sync could tell you your other machine had pushed nothing when its work had simply arrived earlier, in the background.

What you get

When you update your brain (/update-engine)

  • 🩹 Search works again if it had stopped. The update checks that your brain's search database opens; if the new npm left it unbuilt, it rebuilds it once and says so. If it ever cannot, it shows you the one command that does it by hand.
  • 🔒 The next install cannot break it. The engine now tells npm which of its parts need a build step, so the new npm lets them build.
  • 🛡️ No more vulnerability warning. The libraries are at their fixed versions, and every future release is checked before it ships.

The rest of the time, when you type /sync

  • 🔄 It says what came from your other machine, even if it arrived earlier in the background. You see how many files, from which machine, and when.
  • 📅 Every date and weekday is computed, never written from memory. If it says Friday, it was Friday.

What you have to do

Ask your brain to update its engine (/update-engine), then restart Claude once. Your notes, your keys and your constitution are untouched, as always.


Under the hood

The dependency fix (#132). npm audit fix in rag/ and local-mirror/: lockfiles only, no direct range moved, no major bump. The two notable transitive jumps are sharp 0.34→0.35 and global-agent 3→4, both pulled by @huggingface/transformers 4.2→4.3. The in-process embedder's vectors are unchanged (EmbeddingGemma q8, cosine 1.000000 on three probe texts, 4.2 vs 4.3), so no reindex.

The check that never ran. A new Dependency audit CI job runs on every push and every PR and fails on any fixable finding at moderate or above, in both package directories. Run against v5.5.1's lockfiles it exits 1 with 11 + 6 findings. A test pins that the job carries no if:, so it cannot be scoped away in silence.

The "unapproved install scripts". Both package.json files now declare, in allowScripts, the packages expected to run an install script (all native bindings or their loaders). A test reads each lockfile's hasInstallScript entries and fails if one is not declared. This is also what npm 12 needs: it blocks undeclared install scripts, and better-sqlite3 then has no native binary.

Healing brains npm 12 already broke. Declaring the scripts is not enough for a brain installed with npm 12 before this release: neither npm install nor npm rebuild re-runs a script npm 12 blocked. After its npm install, the update now opens an in-memory database from rag/ in a child Node; on exactly "Could not locate the bindings file" it removes rag/node_modules/better-sqlite3 and reinstalls it, once. An ABI skew (a binary built for another Node) is left to the search server's existing start-time rebuild. A repair that fails prints the manual command and never fails the update. On a real update it runs in the auto-finalize child, i.e. the new engine's code, so it fires on the first update to v5.5.2 even though the old engine drives. Rehearsed with the real npm 12.1.0 on v5.5.1's dependencies: broken before, "Search database repaired", database opens, a second pass silent.

/sync (#131). scripts/sync-report.mjs (pure core scripts/lib/sync-report.mjs, English and French) writes the whole report; the skill's step 5 runs it and relays it verbatim. It reads remote-arrivals.json regardless of announcedAt (that stamp is right for the unprompted announcement and wrong for an explicit question), and names the last push the remote received with its committer, so two machines with different git identities read as "from your other machine". Three acceptance tests, red first, process-level against a throwaway brain with a real remote. On the way, the guard for "a script a shipped skill calls must be shipped" only scanned engine-skills/; widened to .claude/skills/**, it found sync-report.mjs and pick-folder.mjs (called by /import since June) undeclared. Both are now carried by the update.

The nightly mutation run finishes again. local-mirror died at mutant 349 on most nights: a mutant made sync re-enter itself through syncAll, an async recursion that ate memory until the machine was killed. Fixed at the root (syncAll calls syncOne) and braced with a 3 GB heap ceiling. The scripts package, 13 306 mutants at ~30 s each, could never fit in six hours; it leaves the nightly and is measured per change instead.

Versions. scripts 1.20.0, rag 1.5.1, local-mirror 0.3.1.

Proof. Mutation on every production file the branch writes: local-mirror.ts hunk 100 %, audit-gate.mjs 91.46 %, install-scripts.mjs 97.67 %, lib/sync-report.mjs 100 %, sync-report.mjs 92 %, native-binding-heal.mjs 97.56 % (the one survivor is equivalent). The heal's first pass surfaced one real defect before it shipped: its failure message would have quoted a file path instead of npm's error.