pi-observational-memory 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +118 -22
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,35 +1,100 @@
1
1
  # pi-observational-memory
2
2
 
3
- Observational memory extension for [Pi](https://github.com/mariozechner/pi). Replaces Pi's default compaction with a two-tier system of **observations** (timestamped event log) and **reflections** (stable long-term facts), giving the agent persistent memory across long conversations.
3
+ **Make Pi sessions feel endless.**
4
4
 
5
- Inspired by [Mastra's Observational Memory](https://mastra.ai/blog/observational-memory#how-it-works) concept. This is an independent implementation adapted for Pi's extension system and compaction model.
5
+ Every session has a cliff. You're three hours in, the context window fills up, compaction runs, and suddenly the agent doesn't remember what you decided in hour one. You start repeating yourself. The session that was flowing now feels like a new conversation with an amnesiac.
6
+
7
+ pi-observational-memory pushes that cliff out far enough that you stop thinking about it. It replaces Pi's compaction summary with a two-tier memory system — **observations** (a timestamped, priority-tagged event log) and **reflections** (stable long-term facts) — so the agent carries forward *what* you decided, *when*, *why*, and what's already done. Not as prose that degrades with each compaction cycle, but as structured memory that stays sharp.
8
+
9
+ ```
10
+ <reflections>
11
+ - User works at Acme Corp, building "Acme Dashboard"
12
+ - Stack: Next.js 15, Supabase auth, server components with client-side hydration
13
+ - Hard constraint: ship by January 22nd 2026
14
+ </reflections>
15
+
16
+ <observations>
17
+ Date: 2026-01-15
18
+ - 🔴 14:30 User decided to switch from REST to GraphQL for the public API
19
+ - 🟡 14:32 Motivation: reduce over-fetching on mobile clients
20
+ - 🟢 14:35 Agent scaffolded GraphQL schema in src/schema.ts
21
+ - ✅ 14:50 GraphQL migration completed — user confirmed queries working
22
+ - 🔴 15:10 User wants rate limiting on all public endpoints
23
+ - 🟡 15:12 Prefers token bucket algorithm, 100 req/min per API key
24
+ </observations>
25
+ ```
26
+
27
+ Hour six should feel like hour one. The agent knows who you are, what you've built together, and what's left to do.
28
+
29
+ Pi's built-in compaction handles most sessions well — it tracks file operations, manages split turns, and keeps recent messages intact. This extension is for the sessions where "most" isn't enough: long builds, multi-feature sprints, and the kind of deep work where breaking flow to start a new session costs you more than the tokens.
30
+
31
+ Inspired by [Mastra's Observational Memory](https://mastra.ai/blog/observational-memory) research (94.87% on LongMemEval). This is an independent implementation built for Pi's extension system and compaction model.
32
+
33
+ ## Why this matters
34
+
35
+ Pi's default compaction summarizes old messages into prose and tracks which files were read and modified. This works well for short-to-medium sessions. But prose summaries are inherently lossy in ways that compound over time — the third compaction summarizes a summary of a summary, and specific decisions, timestamps, and completion states get flattened.
36
+
37
+ Observational memory uses a different format that's designed to survive repeated compaction cycles:
38
+
39
+ | What you get | Why it matters |
40
+ |---|---|
41
+ | 🔴 Priority tags | Agent knows what's important vs. what's noise |
42
+ | Timestamps | Temporal reasoning — agent knows *when* things happened |
43
+ | ✅ Completion markers | Agent won't redo finished work |
44
+ | State change tracking | "Switched from A to B" — no stale decisions |
45
+ | User quotes preserved | Your exact words survive compression |
46
+ | Reflections tier | Identity and constraints never get pruned |
6
47
 
7
48
  ## How it works
8
49
 
9
- When Pi's context window fills up, this extension intercepts the compaction event and runs two LLM passes:
50
+ Two LLM passes intercept Pi's compaction to produce structured output instead of prose:
51
+
52
+ ```
53
+ Raw messages accumulate
54
+
55
+ ▼ exceeds observationThreshold (default: 50k tokens)
56
+ ┌─────────┐
57
+ │ Observer │──▶ Compresses messages into timestamped,
58
+ └─────────┘ priority-tagged observations. Append-only.
59
+
60
+ ▼ observations exceed reflectionThreshold (default: 30k tokens)
61
+ ┌───────────┐
62
+ │ Reflector │──▶ Promotes stable facts to reflections.
63
+ └───────────┘ Prunes only what it's certain is dead.
64
+
65
+
66
+ ┌──────────────────────────────┐
67
+ │ Agent context: │
68
+ │ 1. System prompt │
69
+ │ 2. Reflections (stable) │
70
+ │ 3. Observations (event log) │
71
+ │ 4. Recent raw messages │
72
+ └──────────────────────────────┘
73
+ ```
10
74
 
11
- 1. **Observer**reads recent conversation messages and compresses them into concise, timestamped observations with priority levels (🔴 important, 🟡 maybe important, 🟢 info, completed).
12
- 2. **Reflector** — when observations grow past a threshold, promotes stable facts to reflections and prunes dead observations.
75
+ The observer is aggressive it compresses everything into dense observations. The reflector is conservative it only prunes what's clearly dead. Between reflector runs, no information is lost.
13
76
 
14
- The resulting `<reflections>` + `<observations>` block becomes the compaction summary that Pi injects at the top of the agent's context. Pi still keeps the most recent raw messages (controlled by `keepRecentTokens`), so the agent sees both structured memory and recent conversation.
77
+ For the full technical breakdown compaction lifecycle, state persistence, configuration interactions see **[docs/how-it-works.md](docs/how-it-works.md)**.
15
78
 
16
79
  ## Install
17
80
 
18
- Install from npm with pi:
19
-
20
81
  ```bash
21
82
  pi install npm:pi-observational-memory
22
83
  ```
23
84
 
24
- Or install directly from GitHub with pi:
85
+ Or from GitHub:
25
86
 
26
87
  ```bash
27
- pi install https://github.com/elpapi42/pi-observational-memory
88
+ pi install git:github.com/elpapi42/pi-observational-memory
28
89
  ```
29
90
 
91
+ That's it. The extension hooks into Pi's compaction lifecycle automatically. No config file needed to start — defaults work well for most sessions.
92
+
30
93
  ## Configuration
31
94
 
32
- Create `~/.pi/agent/observational-memory.json`:
95
+ ### Extension settings
96
+
97
+ Create `~/.pi/agent/observational-memory.json` (or `.pi/observational-memory.json` per project):
33
98
 
34
99
  ```json
35
100
  {
@@ -38,29 +103,60 @@ Create `~/.pi/agent/observational-memory.json`:
38
103
  }
39
104
  ```
40
105
 
41
- | Field | Default | Description |
42
- |-------|---------|-------------|
43
- | `observationThreshold` | `50000` | Token count that triggers the observer |
44
- | `reflectionThreshold` | `30000` | Observation token count that triggers the reflector |
45
- | `compactionModel` | session model | Optional `{ "provider": "...", "id": "..." }` to use a different model for observation/reflection |
106
+ | Setting | Default | What it controls |
107
+ |---|---|---|
108
+ | `observationThreshold` | `50,000` tokens | How much raw conversation accumulates before the observer runs |
109
+ | `reflectionThreshold` | `30,000` tokens | How large observations grow before the reflector promotes and prunes |
110
+ | `compactionModel` | session model | Optional use a cheaper model for observer/reflector passes |
46
111
 
47
- ### Custom model example
112
+ ### Using a cheaper model for compaction
113
+
114
+ The observer and reflector don't need the same capabilities as your coding agent. Offload them to something fast and cheap:
48
115
 
49
116
  ```json
50
117
  {
51
- "observationThreshold": 6000,
52
- "reflectionThreshold": 1000,
53
118
  "compactionModel": { "provider": "openrouter", "id": "google/gemma-4-31b-it" }
54
119
  }
55
120
  ```
56
121
 
122
+ ### Pi compaction settings
123
+
124
+ The extension works with Pi's built-in compaction settings in `~/.pi/agent/settings.json`:
125
+
126
+ ```json
127
+ {
128
+ "compaction": {
129
+ "keepRecentTokens": 20000
130
+ }
131
+ }
132
+ ```
133
+
134
+ | Setting | Default | What it controls |
135
+ |---|---|---|
136
+ | `keepRecentTokens` | `20,000` | Tokens of recent conversation kept verbatim (not summarized) |
137
+ | `reserveTokens` | `16,384` | Headroom for LLM response; Pi auto-compacts when context exceeds `window - reserveTokens` |
138
+
139
+ **How they interact:** Pi decides *when* to compact and *how many recent messages to keep raw*. The extension decides *how* to compact (observations + reflections instead of a flat summary) and *when to proactively trigger* compaction before the window fills. Both paths end up at the same `session_before_compact` hook.
140
+
57
141
  ## Commands
58
142
 
59
143
  | Command | Description |
60
- |---------|-------------|
61
- | `/om-status` | Show token counts and current thresholds |
144
+ |---|---|
145
+ | `/om-status` | Token counts, thresholds, and when the next observer/reflector pass will trigger |
62
146
  | `/om-view` | Print current reflections and observations |
63
- | `/om-view --full` | Same as above, plus raw kept messages |
147
+ | `/om-view --full` | Same as above, plus the raw kept messages |
148
+
149
+ ## Design decisions
150
+
151
+ **Why observations are append-only.** Between reflector runs, nothing is lost. The observer only compresses new messages — it doesn't decide what to keep. This keeps the observer simple and predictable.
152
+
153
+ **Why the reflector is conservative.** It only prunes what it's certain is dead: completed tasks no longer referenced, superseded information, exact duplicates. Being old or low-priority is not a reason to prune. If in doubt, it keeps.
154
+
155
+ **Why user messages are captured near-verbatim.** When the context window shrinks, observations become the only record of what you said. Short messages are preserved exactly; long ones are summarized with key phrases quoted.
156
+
157
+ **Why state changes are explicit.** When you say "switching from A to B," the observation notes both the new state and what it replaces. This prevents the agent from acting on stale information after compaction.
158
+
159
+ **Why memory lives in the session.** State is stored in Pi's session entries as compaction `details` — no external database, no filesystem state, no separate sync. On session resume, the extension walks backward through entries to restore memory. If you use `/tree` to branch, each branch gets its own memory state.
64
160
 
65
161
  ## License
66
162
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-observational-memory",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Observational memory extension for pi — cache-friendly tiered compaction with observations and reflections.",
5
5
  "type": "module",
6
6
  "license": "MIT",