Skip to content

MemoryWriter's shrink guard misses slow erosion: 12 durable rules lost in 48h with every write passing the guard #1761

Description

@jacobo-ortiz

The shrink guard in `LIFEOS/TOOLS/MemoryWriter.ts` only catches catastrophes. The failure mode that actually destroys memory in practice is slow erosion through LLM re-transcription, and it passes the guard cleanly every time.

What happens

The reviewer rewrites the memory list each cycle. When it re-transcribes rather than edits, a few entries quietly fail to come back. Measured on a live install over two days:

Before After Net Additions present? Guard verdict
41 37 -4 yes passed
39 37 -2 yes passed
40 37 -3 yes passed

Each drop is ~10% and each carries additions, so none trips "nearly empty" or "more than 50% dropped with no additions". Twelve durable rules died in 48 hours and nothing surfaced. Several were behavioural rules the system depends on (do not claim completion without verification; re-verify a remembered state before asserting it).

The guard is doing exactly what it was written to do. The problem is that the modelled failure (a catastrophic wipe) is not the failure that occurs.

Suggested fix

Add a net-loss condition alongside the existing ones:

const netLoss = evictions.length - additions.length;
const erosion = netLoss >= EROSION_LIMIT && !consolidating;   // EROSION_LIMIT = 2

with an explicit allowDrastic escape for deliberate consolidation, and an error message that names it so the caller knows the way out. A legitimate 5→2 consolidation should be possible; it just should not be the silent default.

The non-obvious half, which cost me the most time

The rejection has to be written to the write-log, not just returned. The hook spawns the reviewer with stdio: "ignore", so a rejection that only travels back in the summary object goes to /dev/null and the block is invisible to the surface that is supposed to report it. I traced the rejection into summary.failures, called it done, and only later found that summary was never read by anything.

Validation

Replayed against 94 historical writes from a real install: 5 blocked, all 5 genuine erosion (including the one that removed five honesty rules in a single pass), 0 false positives.

Happy to open a PR with the diff if useful.

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