Skip to content

forge-update permanently stuck once kb.bak-*/kb.install-preserved-* accumulate; no reclaim/prune command exists #335

Description

@pacphi

Summary

npx ruvnet-brain --update refuses to run once ~/.cache/ruvnet-brain/ accumulates old
kb.bak-* / kb.install-preserved-* snapshots that forge-update's own safety check can't
clear ("unresolved rollback state exists; refusing to create another full-KB copy."). There's
no CLI path to resolve this — --doctor, --what-changed, and --uninstall don't touch it,
and there's no prune/reclaim/gc subcommand. The only way out today is deleting directories by
hand and manually verifying you're not losing data.

Repro

After enough --update cycles (installs on 2026-09-08, 09 (x3), 10, 19), my cache held 12
legacy snapshot dirs (~21GB total) alongside the live kb/ (~1.2GB). Attempting --update to
4.3.29 fails at the source-enumeration phase:

unresolved rollback state exists; refusing to create another full-KB copy.
  kb.bak-2026-07-13T10-47-54-235Z: inventory is incomplete; refusing destructive reclaim
    (legacy inventory contains unclassified non-RVF files)
  ...(4 more kb.bak-* dirs, same reason)...
  kb.install-preserved-69VtSI: it holds 183 store(s) the new copy does NOT have:
    concepts.big.rvf, ruv-gists.big.rvf, __MACOSX/._agentdb.big.rvf…
  kb.install-preserved-6oa0th: it holds 2 store(s) the new copy does NOT have:
    concepts.big.rvf, ruv-gists.big.rvf
  ...(4 more kb.install-preserved-* dirs, same 2 stores)...
  kb.install-preserved-vvWguB: PRESERVED_UNCLASSIFIED: complete byte redundancy is not proven;
    different bytes: kb.install-preserved-vvWguB/.console-runtime/bin/install.mjs
  Restore or reconcile that copy first, then re-run.

legacyBackupRetention in the refresh-run receipt confirms this isn't a fluke: it's a real
(non-dry-run) evaluation that kept everything, "freed": 0.

What I found investigating by hand

  • 6 of the kb.install-preserved-* dirs (6oa0th, AezwrD, O9aAIg, bwOYOX, ksPDYz, vvWguB) are
    byte-identical to each other for every file they hold beyond what's already in the live
    kb/ (verified via sha256: concepts.*, ruv-gists.*, cognitum-ruos-primer.md,
    cognitum-ruos.symbols.json — same hash in every copy that has each file). Each also carries
    its own node_modules/ (an old installer's dependency tree, not knowledge data).
    vvWguB's flagged install.mjs byte diff is just a different installer script version
    (5634 vs ~5170-5259 lines) — not KB content.
  • kb.install-preserved-69VtSI is a different story: ~300 non-junk top-level files (plus 758
    __MACOSX/._* zip-extraction artifacts) that don't exist in the current kb/ under the same
    names — mostly a legacy dual-variant layout (<repo>.rvf + <repo>.big.rvf per repo) from
    before the KB apparently consolidated to a single .big.rvf-only naming scheme. I could not
    fully rule out real content loss here without deeper tooling, so I left it alone.
  • The 5 kb.bak-* dirs are pre-RVF-format legacy backups; I could not verify their inventory
    either way and left them alone too.

So roughly a third of the accumulation (7GB of the 21GB on my machine) was provably-safe,
byte-verified duplication I could clean up manually — the rest needs the tool's own format
knowledge to judge safely, which a user shelling out and grepping error text doesn't have.

Ask

A --reclaim (or similar) subcommand that:

  1. Runs the same store-diff logic already computed during --update (it's already computing
    legacyBackupRetention per snapshot — this data exists, it's just not exposed standalone).
  2. Reports, per snapshot dir, which are byte-identical duplicates of another kept snapshot vs.
    genuinely divergent, using the sha256 comparison the updater already has the infrastructure
    for.
  3. Offers to archive the small set of genuinely non-redundant files (like concepts.* /
    ruv-gists.* here) to one canonical location and delete the rest, or at minimum prints
    the exact rm -rf command for entries it CAN prove are pure duplicates — the same evidence
    I had to reconstruct by hand.

Even a read-only --doctor-style report ("N snapshots use X GB; Y GB of that is provably
duplicate; Z GB needs manual review because ") would turn this from "silently stuck
forever" into something a user can act on without spelunking refresh-runs/*.json.

Environment

  • ruvnet-brain bin install.mjs version: 4.3.29 (installed plugin: 4.3.28)
  • darwin, Node via mise
  • RUVNET_BRAIN_KB unset (default ~/.cache/ruvnet-brain/kb)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions