How Pinned Pages in ai-memory Are Exempt from Memory Decay

Pinned pages in ai-memory are exempt from the memory decay process because the is_decayable function in the consolidation sweep explicitly short-circuits when encountering the pinned flag or front-matter metadata, preventing decay evaluation regardless of the page's memory tier.

The ai-memory system implements a forgetting mechanism to manage ephemeral information, but certain critical pages must remain permanent. These pinned pages bypass the automatic decay process through a dual-layer protection system implemented in the consolidation sweep. Understanding this exemption mechanism is essential for managing long-term versus short-term memory in AI applications.

Two Methods for Pinning Pages in ai-memory

The repository identifies pinned pages through two distinct pathways, both of which set the pinned flag on the PageMeta struct to true.

Automatic Pinning via the _slots/ Directory Hierarchy

Pages residing in the special _slots/ hierarchy are automatically treated as pinned. When a page is written, the system checks is_slot_path(&path) during the write operation in crates/ai-memory-wiki/src/wiki.rs (lines 1185-1187). If the path contains the _slots/ prefix, the pinned field is automatically set to true.

let path = PagePath::new("_slots/personal/todo.md").unwrap();
let req = NewPage {
    // … other fields …
    pinned: is_slot_path(&path),   // true because of `_slots/` prefix
    ..Default::default()
};
wiki.write_page(req).await?;

Explicit Front-Matter Declaration

Users can manually pin any page by including pinned: true in the front-matter. During indexing, the derive_index_metadata function reads this field and sets meta.pinned = true (wiki.rs lines 84-86).

---
title: "Important Fact"
tier: episodic
pinned: true
---
The fact should never decay.

The Decay Exemption Logic in the Forget-Sweep

The forget-sweep process begins by collecting candidate rows via Reader::decay_candidates in crates/ai-memory-store/src/reader.rs, which selects all pages where is_latest = 1. However, eligibility for actual decay is determined by the is_decayable function in crates/ai-memory-consolidate/src/sweep.rs (lines 30-41).

This function implements a strict hierarchy of checks:

fn is_decayable(c: &DecayCandidate) -> bool {
    if c.tier != Tier::Episodic { return false; }
    if c.pinned { return false; }                       // <-- pinned flag blocks decay
    if let Ok(fm) = serde_json::from_str::<serde_json::Value>(&c.frontmatter_json)
        && fm.get("pinned").and_then(serde_json::Value::as_bool) == Some(true)
    {
        return false;                                   // <-- front-matter overrides
    }
    true
}

The sweep immediately returns false (non-decayable) for any page where:

  • The c.pinned boolean is true
  • The frontmatter_json contains "pinned": true

This dual-check ensures that both automatically pinned slot pages and manually pinned pages are excluded from the decay pipeline.

Technical Implementation of Decay Prevention

The decay process filters candidates through a pipeline that guarantees pinned page persistence. Only pages that pass all is_decayable checks proceed to eviction or TTL deletion:

let candidates = reader.decay_candidates(ws, proj).await?;
let decayable = candidates.into_iter().filter(is_decayable);
for cand in decayable {
    // eviction or TTL delete …
}

Key implementation details:

  • Tier restriction: Only episodic tier pages can decay; semantic pages are excluded at the first conditional in is_decayable.
  • Flag precedence: The c.pinned check occurs before front-matter parsing, providing a fast path for slot pages.
  • Persistence guarantee: Because the sweep skips pinned pages entirely, they never undergo soft deletion or hard deletion operations defined in crates/ai-memory-store/src/ops.rs.

The integration tests in crates/ai-memory-consolidate/tests/slot_visibility.rs confirm that slot pages are forced-pinned and remain visible across sweep cycles, verifying the decay-immunity mechanism.

Summary

  • Pinned pages are identified either by residing in _slots/ or via explicit pinned: true front-matter, both setting the PageMeta flag in wiki.rs.
  • The is_decayable function in crates/ai-memory-consolidate/src/sweep.rs immediately returns false for any page with the pinned flag or front-matter property.
  • Only episodic tier pages that are not pinned are eligible for decay; semantic tier pages are excluded by tier regardless of pin status.
  • This architecture ensures critical memory remains persistent while ephemeral, non-pinned content is properly managed through the forget-sweep cycle.

Frequently Asked Questions

What is the difference between slot pages and manually pinned pages in ai-memory?

Slot pages are automatically pinned when created in the _slots/ directory hierarchy via the is_slot_path function during the write operation, while manually pinned pages require explicit pinned: true in their front-matter metadata. Both methods result in identical decay protection because both set the same pinned boolean on the DecayCandidate struct that is_decayable evaluates.

Can semantic tier pages be pinned to prevent decay?

No, pinning is unnecessary for semantic tier pages because the decay process exclusively targets the episodic tier. The is_decayable function checks c.tier != Tier::Episodic as its first conditional, meaning semantic pages are already excluded from decay regardless of their pinned status. Pinning only provides protection within the episodic tier.

Where does the forget-sweep check for pinned status in the codebase?

The primary check occurs in crates/ai-memory-consolidate/src/sweep.rs within the is_decayable function (lines 30-41). This function validates both the c.pinned boolean flag from the database row and parses the frontmatter_json field to detect the "pinned" key, ensuring comprehensive protection regardless of how the pin was originally set.

How can I verify that my slot pages are immune to memory decay?

The repository includes integration tests in crates/ai-memory-consolidate/tests/slot_visibility.rs that explicitly confirm slot pages are forced-pinned and excluded from decay cycles. You can also verify behavior by checking that the decay_candidates query in crates/ai-memory-store/src/reader.rs filters out pages where is_slot_path returned true during the initial write operation in wiki.rs.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →