Skip to content

Selective forgetting

Forgetting curates the derived graph without ever touching the source files. It archives derived facts; it never deletes Markdown. It reuses the graph’s existing archival state - the same one a contradiction or a removed section uses - so there is exactly one “archived fact” concept, not a parallel one.

Each fact carries a salience score that falls over time and rises with use:

salience(fact, t) = base × decay(Δt) × (1 + log(1 + accesses)) × pin_boost
  • base - the fact’s confidence.
  • decay(Δt) - an exponential curve with a configurable half-life, measured from the fact’s last access (else its first recorded time).
  • accesses - a saturating, logarithmic boost that protects facts the agent keeps using.
  • pin_boost - a durable multiplier while a fact is pinned, making critical facts effectively immune.

Recall stamps each returned fact with an access (count + last-access time), which feeds the boost and resets the decay clock. This is ephemeral tuning state - rebuildable from the file history, never part of the file truth. The whole formula is a pure, exhaustively unit-tested function, identical across the TypeScript and Python reference engines.

Within equal query relevance, recall breaks ties by salience (then recency, then id). So a hotter, more-pinned, less-decayed fact wins among equally-relevant matches - forgetting shapes ranking before it ever archives anything.

await alice.pin('team', factId); // durable salience boost; never let this decay
await alice.unpin('team', factId); // release the boost
await alice.forget('team', factId, 'stale'); // reversibly archive, with a reason
await alice.restoreFact('team', factId); // reverse a forget
  • pin / unpin set the durable boost.
  • forget(space, factId, reason) reversibly archives a believed fact, recording the reason.
  • restoreFact(space, factId) reverses a forget.

A forget is distinguished from a structural archival (a contradiction or a removed section) by its reason, and only a forgotten fact is restorable. A contradiction is undone by editing the source file, not by restoreFact. The factId is the opaque id from a recall result.

Forgetting is reversible because archived facts are kept, not destroyed. Bi-temporal integrity holds too: an as-of query before a forget still sees the fact, because the forget only bounds the fact going forward.

Archived facts are excluded from normal recall and both views. An explicit includeArchived recall surfaces forgotten facts (each flagged archived) so a caller can find one and restore it:

const forgotten = await alice.recall('team', 'old preferences', { includeArchived: true });

pin, forget, and restoreFact are gated by write access to the fact’s source document - the same check write uses. Only a principal who could edit the file may reshape its derived memory, so a read-only grantee cannot forget a fact they can merely read. This runs in the engine over the graph store’s fact handle; the graph still has no capability to write a file.

Because Bezial archives instead of deleting, you can measure the forgetting policy directly: replay history and count how often a forgotten fact had to be restored to answer a later query.

That restore rate is a clean signal almost nobody else can compute, and it lets you tune aggressiveness with evidence rather than guesswork. It is an internal tuning signal only - deliberately never exposed by any call surface, doc, or landing metric, and never a published benchmark number. See Benchmark for the metrics Bezial actually reports.