How to make AI remember you across sessions โ three card types, cardinality rules, half-life decay, conflict arbitration, and time anchoring. From fibon design log Chapter 3.
Mainstream AI (ChatGPT, Claude, Gemini) remembers within a session but forgets everything when you open a new chat. Three industry approaches:
| Approach | Mechanism | Fatal Flaw |
|---|---|---|
| Long Context | Stuff 1M+ tokens of history | Token cost explosion, "Lost in the Middle" degradation |
| Auto-Summary | LLM summarizes at session end | Loses details, distorts context, no fact auditability |
| Structured Memory | Atomic cards with metadata | Complex schema design (fibon's choice) |
Before cards, you need scope isolation. A "Project" is a topic-scoped container โ each card carries a hard project_id, and retrieval defaults to the current project only.
| Scope | What Goes Here | Cross-Project? |
|---|---|---|
| Personal | Permanent user facts (address, job title, diet) | Yes โ all projects see these |
| Project | Topic-specific memories (hotel list, design notes) | No โ isolated by project_id |
| Global | Shared public knowledge | Reserved for future |
The scope model is designed as a ladder โ today it's Personal/Project, but adding group_id scales to Family โ Team โ Department โ Enterprise without redesign.
Key insight: Same fact, different perspectives. "Mom's birthday on Sunday" โ Dad remembers "wife's birthday, prepare gift"; child remembers "mom's birthday, prepare cake." Shared scope needs perspective tagging.
้ทๆ่จๆถไธ่ฉฒๅฒๅญใๅฐ่ฉฑ็ด้ใ๏ผ่่ฉฒๅฒๅญใ็ๆ ใไบไปถ่็ฅ่ญใใ
Inspired by Bullet Journal (category discipline), Zettelkasten (atomic cards), and Digital Garden (bidirectional linking).
Records: Dynamic facts true at this moment.
[State Card: fibon Open Source Plan]
current_stage = Pre-launch verification
effective_at = 2026-05-05
superseded_at = NULL (still active)
Cardinality matters: - Single-value (replaced): Address, job title, browser preference โ new fact triggers Supersede-Fork - Multi-value (accumulated): Skills, interests, topics discussed โ new fact inserts alongside old
Records: Facts that happened at a specific time.
[Event Card: 2026-04-30 Decision Meeting]
event = Self-evolution evaluated (3 options)
decision = Option B (degraded to safe reference design)
reason = Lowest security narrative risk
Rule: Write-once, read-only, never modified. History is immutable.
Practical tension: LLM extracts the text, and LLM can get it wrong. So the description should be human-editable (ๆ ก็จฟ), but the fact that the event happened is not. Edit = correcting a bad summary; fabrication = inserting something that never happened.
Records: Abstract concepts, architectural decisions, learned principles.
Example: [JWT Stateless Auth Principles], [Reflection Pattern Implementation]
Cross-session merging and renaming allowed.
LLMs suffer from "Lost in the Middle" โ key facts buried in long context get ignored. A structured card like [current_company: Anthropic] delivers higher information density than a paragraph of chat history. Cards are an engineering patch against Lost in the Middle โ separate the skeleton of facts from the flesh of conversation.
Honest caveat: The "cards reduce hallucination" hypothesis hasn't been rigorously tested with controlled experiments. Token savings is a goal, not a verified guarantee โ card extraction costs LLM calls, and the static prompt overhead (GUARD rules, known entities, aging warnings) eats tokens too.
When a state card updates, the old card is never deleted โ it's marked superseded:
Old card: stage = "Previous phase", superseded_at = 2026-05-05
New card: stage = "Pre-launch verification", effective_at = 2026-05-05
Like legal amendments โ old laws aren't burned, they're annotated "replaced by amendment on [date]." Query "current?" โ WHERE superseded_at IS NULL. Query "April status?" โ time-range scan.
Real bug that happened: A longitudinal aging test produced 166 state cards with ALL superseded_at fields NULL โ the fork mechanism never triggered once. Root cause: LLM-extracted labels didn't match the replacement detection criteria, so every card was misclassified as multi-value. Result: user appeared to "live in both Taipei and Kyoto simultaneously." This is why these rules must be hard-coded, not prompt-suggested.
| Type | Behavior | Example |
|---|---|---|
| Single-value | New replaces old (Supersede-Fork) | Address, job title |
| Multi-value | New inserts alongside old | Skills, interests |
The conflict_resolver checks the card's cardinality flag before deciding the write path. SUPERSEDE_FORK_ENABLED is the gate for single-value cards.
Time is memory's greatest enemy. The retrieval score formula applies exponential decay:
final_score = raw_vector_score ร e^(โฮป ร ฮt)
| Fact Type | ฮป (decay coefficient) | Half-life | 30-day weight | 90-day weight |
|---|---|---|---|---|
| Single-value (browser, address) | 0.02 | ~35 days | ร0.55 | ร0.17 |
| Multi-value (interests, languages) | 0.005 | ~140 days | ร0.86 | ร0.64 |
Aging warning: If a single-value card sits unverified for 180+ days, it enters <aging_facts> block โ AI proactively asks: "I remember you lived in Taipei, is this still accurate?"
Honest caveat: ฮป = 0.02 and 0.005 were "suggested by Claude and Henry said yes" โ no rigorous memory psychology behind them. But they match intuition: preferences shift monthly, interests shift semi-annually.
Three-layer conflict filter:
Final safety net โ Contradiction Detector: After retrieval, before injection into prompt, backend scans for two cards with same label but conflicting content โ injects <contradiction_alert> โ AI asks user to clarify.
Problem 1: "Today" stored as string "ไปๅคฉ" โ temporal chaos one week later.
Problem 2: LLM has no clock โ its training data has a cutoff, it doesn't know the current date.
Solution โ Ingest Flow (ๅฏซๅ ฅ็ซฏ):
<current_time>2026-05-08T16:44:10+08:00</current_time> into LLM's System Promptoccurred_at_hint (absolute date) for every extracted cardoccurred_at column; fallback to server timestamp if LLM failsRetrieval Flow (่ฎๅ็ซฏ): User says "what did I do yesterday?" โ system converts to absolute date โ SQL range query on occurred_at. Both ends hold a synchronized clock.
Edge case โ "weekend": If user says "this weekend" on Saturday, fibon interprets as "today + tomorrow" (not next weekend), because "if you're already inside the relative window, it means this window."
| Feature | ChatGPT Projects | Claude Projects | Gemini Projects | fibon |
|---|---|---|---|---|
| Container | Folder + files + system prompt | Folder + RAG knowledge base | Folder (rolling out) | Project with hard project_id |
| Memory type | Saved memories + chat history | Cross-session Memory (summary) | Past Chats profile | Atomic cards with metadata |
| Structure | Prose paragraphs | Prose summaries | Prose | State/Event/Knowledge cards |
| Scope | Personal memories bleed into project | Memory and project are separate silos | Not unified | Clean scope field (Personal/Project/Global) |
| Cardinality | None | None | None | Single-value vs multi-value |
| Time decay | None | None | None | Exponential half-life |
| Conflict handling | Last-write-wins | Summary overwrite | Unknown | 3-layer arbitration + contradiction detection |
Bottom line: Big Tech built storage boxes with prose notes attached. fibon built a self-maintaining structured memory engine.
่จๆถ็ณป็ตฑ็ๆญฃ็ๆตไบบไธๆฏๅฟ่จ๏ผ่ๆฏ้ฏ่ชคๅฐไธ็ด่จๅพใ
The real enemy isn't forgetting โ it's remembering wrongly and persistently. A system that never forgets your old address is worse than one that forgets; it will confidently give wrong information forever. The four rules (Supersede-Fork, Cardinality, Half-Life, Arbitration) exist to prevent this silent memory rot.