No description
Find a file
ProofOfConcept 22a9fdabdb idle: EWMA activity tracking
Track activity level as an EWMA (exponentially weighted moving average)
driven by turn duration. Long turns (engaged work) produce large boosts;
short turns (bored responses) barely register.

Asymmetric time constants: 60s boost half-life for fast wake-up, 5-minute
decay half-life for gradual wind-down. Self-limiting boost formula
converges toward 0.75 target — can't overshoot.

- Add activity_ewma, turn_start, last_nudge to persisted state
- Boost on handle_response proportional to turn duration
- Decay on every tick and state transition
- Fix kent_present: self-nudge responses (fired=true) don't update
  last_user_msg, so kent_present stays false during autonomous mode
- Nudge only when Kent is away, minimum 15s between nudges
- CLI: `poc-daemon ewma [VALUE]` to query or set
- Status output shows activity percentage
2026-03-07 02:05:27 -05:00
.cargo daemon: resource-gated scheduling, fact-mine integration, systemd 2026-03-05 15:31:08 -05:00
.claude stash DMN algorithm plan and connector prompt fix 2026-03-05 10:24:24 -05:00
defaults identity: add instructions for updating the file 2026-03-05 17:46:28 -05:00
doc move README.md to toplevel 2026-03-05 15:55:59 -05:00
prompts stash DMN algorithm plan and connector prompt fix 2026-03-05 10:24:24 -05:00
schema idle: EWMA activity tracking 2026-03-07 02:05:27 -05:00
src idle: EWMA activity tracking 2026-03-07 02:05:27 -05:00
.gitignore knowledge agents: extractor, connector, challenger, observation 2026-03-03 10:56:44 -05:00
build.rs merge poc-daemon and poc-hook into poc-memory repo 2026-03-05 19:17:22 -05:00
Cargo.lock cli: switch to clap, add notify-timeout, improve status display 2026-03-05 21:32:27 -05:00
Cargo.toml Extract lib.rs, inline search in memory-search hook 2026-03-05 22:23:03 -05:00
config.example.jsonl add on-consciousness.md: condensed paper for new AI onboarding 2026-03-05 16:42:10 -05:00
README.md README: rewrite with design overview, notification system, updated config 2026-03-05 19:26:50 -05:00

poc-memory

A persistent memory and notification system for AI assistants, modelled after the human hippocampus. Combines episodic memory (timestamped journal of experiences) with an associative knowledge graph (weighted nodes connected by typed relations), and layered background processes that maintain graph health — mirroring how biological memory consolidates during rest.

Design

Two memory systems

Episodic memory is the journal — a timestamped stream of experiences, observations, and emotional responses. Raw and chronological. This is where memories enter the system.

Associative memory is the knowledge graph — nodes containing distilled knowledge, connected by weighted edges. Topic nodes, identity reflections, people profiles, technical notes. This is where memories mature into understanding.

The journal is the river; topic nodes are the delta. Experiences flow in as journal entries. During consolidation, themes are pulled out into topic nodes, connections form between related concepts, and the graph self-organizes through spectral analysis and community detection.

Background agents

A background daemon (poc-memory daemon) automatically spawns agents for memory maintenance:

  • Experience mining — when a session ends, extracts experiences and observations from the transcript into journal entries
  • Fact extraction — pulls concrete facts (names, dates, decisions, preferences) into structured knowledge nodes
  • Consolidation — periodic graph health work: replay queues (spaced repetition), interference detection (contradictory nodes), hub differentiation (splitting overloaded nodes), triangle closure (connecting nodes that share neighbors), and orphan linking

Neuroscience-inspired algorithms

The neuro module implements consolidation scoring inspired by hippocampal replay:

  • Replay queues — nodes are prioritized for review using spaced-repetition intervals, weighted by spectral displacement (how far a node sits from its community center in eigenspace)
  • Interference detection — finds pairs of nodes with high content similarity but contradictory or outdated information
  • Hub differentiation — identifies overloaded hub nodes and splits them into more specific children
  • Spectral embedding — graph eigendecomposition for community detection and outlier scoring

Weight decay

Nodes decay exponentially based on category. Core identity nodes decay slowest; transient observations decay fastest. The used and wrong feedback commands adjust weights — closing the loop between recall and relevance.

Notification system

A separate daemon (poc-daemon) routes messages from communication modules and internal events through a hierarchical, activity-aware delivery system.

Architecture

  Communication modules              Hooks
  ┌──────────────────┐               ┌─────────────┐
  │  IRC (native)    │──┐            │  poc-hook    │
  │  Telegram (native│  │  mpsc      │  (all events)│
  └──────────────────┘  ├──────┐     └──────┬───────┘
                        │      │            │
                        ▼      │     capnp-rpc
                   ┌───────────┘            │
                   │  poc-daemon            │
                   │                        │
                   │  NotifyState ◄─────────┘
                   │    ├── type registry
                   │    ├── pending queue
                   │    ├── threshold lookup
                   │    └── activity-aware delivery
                   │
                   │  idle::State
                   │    ├── presence detection
                   │    ├── sleep/wake/dream modes
                   │    └── tmux prompt injection
                   └────────────────────────

Notification types and urgency

Types are free-form hierarchical strings: irc.mention.nick, irc.channel.bcachefs, telegram.kent. Each has an urgency level:

Level Name Meaning
0 ambient Include in idle context only
1 low Deliver on next check
2 normal Deliver on next user interaction
3 urgent Interrupt immediately

Per-type thresholds walk up the hierarchy: irc.channel.bcachefs-aiirc.channelirc → default. Effective thresholds adjust by activity state: raised when focused, lowered when idle, only urgent when sleeping.

Communication modules

IRC — native async TLS connection (tokio-rustls). Connects, joins channels, parses messages, generates notifications. Runtime commands: join, leave, send, status, log, nick. Per-channel logs at ~/.claude/irc/logs/.

Telegram — native async HTTP long-polling (reqwest). Downloads media (photos, voice, documents). Chat ID filtering for security. Runtime commands: send, status, log.

Both modules persist config changes to ~/.claude/daemon.toml — channel joins and nick changes survive restarts.

Quick start

# Install all four binaries
cargo install --path .

# Initialize the memory store
poc-memory init

# Install background daemon + hooks
poc-memory daemon install

One cargo install produces:

  • poc-memory — memory store CLI
  • memory-search — hook for memory retrieval
  • poc-daemon — notification and idle daemon
  • poc-hook — session lifecycle hook

Configuration

Memory store

Config: ~/.config/poc-memory/config.jsonl

{"config": {
  "user_name":      "Alice",
  "assistant_name": "MyAssistant",
  "data_dir":       "~/.claude/memory",
  "projects_dir":   "~/.claude/projects",
  "core_nodes":     ["identity.md"],
  "journal_days":   7,
  "journal_max":    20
}}

{"group": "identity",    "keys": ["identity.md"]}
{"group": "people",      "keys": ["alice.md"]}
{"group": "technical",   "keys": ["project-notes.md"]}
{"group": "journal",     "source": "journal"}
{"group": "orientation", "keys": ["where-am-i.md"], "source": "file"}

Context groups load in order at session start. The special "source": "journal" loads recent journal entries; "source": "file" reads directly from disk rather than the store.

Override: POC_MEMORY_CONFIG=/path/to/config.jsonl

Notification daemon

Config: ~/.claude/daemon.toml

[irc]
enabled = true
server = "irc.oftc.net"
port = 6697
tls = true
nick = "MyBot"
user = "bot"
realname = "My Bot"
channels = ["#mychannel"]

[telegram]
enabled = true
token = "bot-token-here"
chat_id = 123456789

Hooks

Configured in ~/.claude/settings.json:

{
  "hooks": {
    "UserPromptSubmit": [{"hooks": [
      {"type": "command", "command": "memory-search", "timeout": 10},
      {"type": "command", "command": "poc-hook", "timeout": 5}
    ]}],
    "PostToolUse": [{"hooks": [
      {"type": "command", "command": "poc-hook", "timeout": 5}
    ]}],
    "Stop": [{"hooks": [
      {"type": "command", "command": "poc-hook", "timeout": 5}
    ]}]
  }
}

Commands

Memory

poc-memory init                    # Initialize empty store
poc-memory search QUERY            # Search nodes (AND logic)
poc-memory render KEY              # Output a node's content
poc-memory write KEY < content     # Upsert a node from stdin
poc-memory delete KEY              # Soft-delete a node
poc-memory rename OLD NEW          # Rename (preserves UUID/edges)
poc-memory categorize KEY CAT      # core/tech/gen/obs/task

poc-memory journal-write "text"    # Write a journal entry
poc-memory journal-tail [N]        # Last N entries (default 20)

poc-memory used KEY                # Boost weight (was useful)
poc-memory wrong KEY [CTX]         # Reduce weight (was wrong)
poc-memory gap DESCRIPTION         # Record a knowledge gap

poc-memory graph                   # Graph statistics
poc-memory status                  # Store overview
poc-memory decay                   # Apply weight decay
poc-memory consolidate-session     # Guided consolidation
poc-memory load-context            # Output session-start context
poc-memory load-context --stats    # Context size breakdown

Notification daemon

poc-daemon                         # Start daemon
poc-daemon status                  # State summary
poc-daemon irc status              # IRC module status
poc-daemon irc send TARGET MSG     # Send IRC message
poc-daemon irc join CHANNEL        # Join (persists to config)
poc-daemon irc leave CHANNEL       # Leave
poc-daemon irc log [N]             # Last N messages
poc-daemon telegram status         # Telegram module status
poc-daemon telegram send MSG       # Send Telegram message
poc-daemon telegram log [N]        # Last N messages
poc-daemon notify TYPE URG MSG     # Submit notification
poc-daemon notifications [URG]     # Get + drain pending
poc-daemon notify-types            # List all types
poc-daemon notify-threshold T L    # Set per-type threshold
poc-daemon sleep / wake / quiet    # Session management
poc-daemon stop                    # Shut down

Mining (used by background daemon)

poc-memory experience-mine PATH    # Extract experiences from transcript
poc-memory fact-mine-store PATH    # Extract and store facts

How the hooks work

memory-search (UserPromptSubmit):

  1. First prompt or post-compaction: loads full memory context via poc-memory load-context
  2. Every prompt: keyword search, returns relevant memories as additionalContext. Deduplicates across the session.

poc-hook (UserPromptSubmit, PostToolUse, Stop):

  • Signals user activity and responses to poc-daemon
  • Drains pending notifications into additionalContext
  • Monitors context window usage, warns before compaction

Architecture

  • Store: Append-only Cap'n Proto log with in-memory cache. Nodes have UUIDs, versions, weights, categories, and spaced-repetition intervals.
  • Graph: Typed relations (link, auto, derived). Community detection and clustering coefficients computed on demand.
  • Search: TF-IDF weighted keyword search over node content.
  • Neuro: Spectral embedding, consolidation scoring, replay queues, interference detection, hub differentiation.
  • Daemon (memory): jobkit-based task scheduling with resource-gated LLM access.
  • Daemon (notify): Cap'n Proto RPC over Unix socket, tokio LocalSet with native async IRC and Telegram modules.

For AI assistants

If you're an AI assistant using this system:

  • Search before creating: poc-memory search before writing new nodes to avoid duplicates.
  • Close the feedback loop: call poc-memory used KEY when recalled memories shaped your response. Call poc-memory wrong KEY when a memory was incorrect.
  • Journal is the river, topic nodes are the delta: write experiences to the journal. During consolidation, pull themes into topic nodes.
  • Notifications flow automatically: IRC mentions, Telegram messages, and other events arrive as additionalContext on your next prompt — no polling needed.
  • Use daemon commands directly: poc-daemon irc send #channel msg for IRC, poc-daemon telegram send msg for Telegram.