pi-observational-memory 2.4.3 → 3.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 (38) hide show
  1. package/README.md +318 -103
  2. package/package.json +9 -9
  3. package/src/agents/dropper/agent.ts +281 -0
  4. package/src/agents/dropper/coverage.ts +128 -0
  5. package/src/agents/dropper/pool.ts +67 -0
  6. package/src/agents/dropper/prompts.ts +48 -0
  7. package/src/{observer.ts → agents/observer/agent.ts} +11 -13
  8. package/src/agents/observer/prompts.ts +119 -0
  9. package/src/agents/reflector/agent.ts +203 -0
  10. package/src/agents/reflector/prompts.ts +81 -0
  11. package/src/clipboard.ts +63 -0
  12. package/src/commands/status.ts +79 -78
  13. package/src/commands/view.ts +58 -66
  14. package/src/config.ts +78 -55
  15. package/src/debug-log.ts +24 -5
  16. package/src/hooks/compaction-hook.ts +24 -369
  17. package/src/hooks/compaction-trigger.ts +12 -21
  18. package/src/hooks/consolidation-trigger.ts +368 -0
  19. package/src/index.ts +3 -3
  20. package/src/model-budget.ts +1 -1
  21. package/src/runtime.ts +46 -19
  22. package/src/serialize.ts +1 -1
  23. package/src/session-ledger/fold.ts +100 -0
  24. package/src/session-ledger/index.ts +6 -0
  25. package/src/session-ledger/progress.ts +129 -0
  26. package/src/session-ledger/projection.ts +220 -0
  27. package/src/session-ledger/recall.ts +237 -0
  28. package/src/session-ledger/render-summary.ts +31 -0
  29. package/src/session-ledger/types.ts +200 -0
  30. package/src/tokens.ts +1 -1
  31. package/src/tools/recall-observation.ts +84 -214
  32. package/src/branch.ts +0 -577
  33. package/src/compaction.ts +0 -1030
  34. package/src/hooks/observer-trigger.ts +0 -129
  35. package/src/progress.ts +0 -155
  36. package/src/prompts.ts +0 -302
  37. package/src/relevance.ts +0 -15
  38. package/src/types.ts +0 -155
package/README.md CHANGED
@@ -1,57 +1,175 @@
1
+ > [!IMPORTANT]
2
+ > **V3 update notice:** this extension now uses the new V3 memory model. If you used V2, update your `observational-memory` settings before running this version. V3 does **not** read the old V2 settings or memory format, and you should start a new clean Pi session after upgrading. See [Migrating from V2](#migrating-from-v2).
3
+
4
+ > [!NOTE]
5
+ > The `master` branch is the active development branch and may include unreleased or unstable changes. For stable versions, install the published npm package with `pi install npm:pi-observational-memory`.
6
+
1
7
  # pi-observational-memory
2
8
 
3
- > **Make long sessions feel endless.** A Pi extension that keeps your agent in hour six knowing what you decided in hour one.
9
+ > **Make Pi sessions feel endless.**
10
+
11
+ `pi-observational-memory` is a Pi extension that keeps long agent sessions coherent across compactions, handoffs, and days of work.
12
+
13
+ It helps Pi remember what matters while you work, so your agent does not lose the thread when the session gets long.
14
+
15
+ Built for engineers who use Pi for real coding work: multi-day refactors, deep debugging sessions, architecture exploration, migrations, product implementation, and long-running branches where context matters.
4
16
 
5
17
  ---
6
18
 
7
- ## The cliff
19
+ ## The problem
8
20
 
9
- Every long AI session has a cliff.
21
+ Long AI coding sessions eventually hit a wall.
10
22
 
11
- You're three hours in. The context window fills up. Compaction runs. 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.
23
+ Not because the agent stops being useful. Not because the work is too complex. But because the session starts getting compressed.
12
24
 
13
- Worse, compaction often hits *mid-work* right when you were about to ask the next question. Whatever the summary captured (and didn't) becomes what the agent knows from now on.
25
+ A compaction summarizes the session. Later, another compaction summarizes that summary. Then another. After enough cycles, your agent is no longer carrying the real working context. It is carrying a compressed version of a compressed version of a compressed version.
14
26
 
15
- This is a universal problem for AI agents. Context windows are finite, sessions aren't, and the bridge between the two is fragile. Compactions are necessary, but they're also where memory degrades — the more you do, the further you drift from what was actually said and decided early in the session.
27
+ That is when the small but important details start disappearing:
16
28
 
17
- ## What this gives you
29
+ * why a design decision was made
30
+ * what approaches were already rejected
31
+ * which constraint mattered most
32
+ * what the current branch is trying to achieve
33
+ * what the user already clarified
34
+ * what the agent already investigated
35
+ * what should not be reopened
18
36
 
19
- `pi-observational-memory` runs an **observer** silently in the background while you work, summarizing the conversation in ~1k token chunks into a structured event log. When compaction runs, the extension assembles that log — plus stable long-term **reflections** crystallized from it — into the new summary.
37
+ The session is still alive, but it no longer feels connected to the work that came before.
20
38
 
21
- What the agent sees after compaction looks like this:
39
+ For engineers, that is painful. Long coding sessions are built out of accumulated decisions. When those decisions lose their rationale, the agent starts drifting.
40
+
41
+ ---
42
+
43
+ ## The second problem: slow compaction
44
+
45
+ Compaction can also break flow.
46
+
47
+ You are deep in a coding session, the agent needs to compact, and suddenly you wait while a model rewrites the past. In large sessions, that pause can take minutes.
48
+
49
+ That interruption is costly because it happens exactly when the session is already complex and you most need continuity.
50
+
51
+ `pi-observational-memory` changes the experience: memory work happens as the session progresses, so when compaction time arrives, Pi can move forward quickly.
52
+
53
+ The goal is simple:
54
+
55
+ > When compaction happens, you should barely notice.
56
+
57
+ ---
58
+
59
+ ## What this extension gives you
60
+
61
+ `pi-observational-memory` continuously captures useful session memory while you work.
62
+
63
+ It focuses on two simple concepts:
64
+
65
+ ### Observations
66
+
67
+ Observations are concrete things that happened or were established during the session.
68
+
69
+ Examples:
70
+
71
+ * the user decided to switch from REST to GraphQL
72
+ * the migration was completed and validated
73
+ * a bug was traced to a specific module
74
+ * a branch is focused on replacing one implementation with another
75
+ * a deadline, constraint, or preference was stated
76
+
77
+ Observations keep the session grounded in actual work.
78
+
79
+ ### Reflections
80
+
81
+ Reflections are durable facts distilled from observations.
82
+
83
+ Examples:
84
+
85
+ * the user is building a Next.js 15 dashboard with Supabase auth
86
+ * the current implementation must ship by a specific date
87
+ * the project prefers minimal abstractions over framework-heavy patterns
88
+ * the branch is about improving long-session agent memory
89
+
90
+ Reflections help the agent stay oriented over time. The reflector treats coverage as stewardship: every active observation it reviews includes a `none`, `partial`, or `strong` coverage tier, but those tiers are review context rather than quotas. When the reflector emits a durable reflection, its support ids should cover all and only the observations whose durable meaning is actually preserved, because those ids later become dropper coverage evidence.
91
+
92
+ Together, observations and reflections let Pi carry the important parts of the session forward without depending on fragile summary chains.
93
+
94
+ ---
95
+
96
+ ## What it feels like
97
+
98
+ With `pi-observational-memory`, long sessions feel less like racing against the context window and more like working with an agent that can stay with you.
99
+
100
+ You can keep a session alive across many compactions. You can come back after a long break. You can hand work across sessions with less context loss. The agent has a better chance of remembering what was decided, what matters, and why the work is shaped the way it is.
101
+
102
+ This extension was built from real long-session usage, including Pi sessions that lasted for weeks without feeling close to the end of the usable working context.
103
+
104
+ The promise is not magic infinite memory.
105
+
106
+ The promise is practical continuity:
107
+
108
+ > Your agent keeps understanding the work, even after days of iteration.
109
+
110
+ ---
111
+
112
+ ## Why it works
113
+
114
+ Traditional compaction asks a model to rewrite the past at the moment the context window needs relief.
115
+
116
+ `pi-observational-memory` does the important memory work earlier, while the session is still happening.
117
+
118
+ As you work, the extension captures observations and distills reflections in the background. When Pi needs to compact, the memory is already prepared. Compaction becomes a fast rendering step instead of a slow summarization event.
119
+
120
+ That gives you two big benefits:
121
+
122
+ 1. **Less coherence loss** — important context is preserved as observations and reflections instead of repeatedly compressed through summary chains.
123
+ 2. **Faster compaction** — the expensive memory work happens before compaction, not while you are waiting.
124
+
125
+ ---
126
+
127
+ ## Example
128
+
129
+ At compaction time, Pi may receive memory like this:
130
+
131
+ ```md
132
+ These are condensed memories from earlier in this session.
133
+
134
+ - Reflections: stable, long-lived facts about the user, project, decisions, and constraints. New reflection lines may include ids in brackets.
135
+ - Observations: timestamped events from the conversation history, in chronological order. Observation lines include ids in brackets.
136
+
137
+ Treat these as past records. When entries conflict, the most recent observation reflects the latest known state. Work that prior observations describe as completed should not be redone unless the user explicitly asks to revisit it.
138
+
139
+ When exact source context is needed for precision or traceability, use the recall tool with the relevant observation or reflection id. This is especially useful when a reflection materially affects a decision or is too compressed to continue confidently. Do not use recall as broad search or inject raw source unless it is needed.
22
140
 
23
- ```
24
141
  ## Reflections
25
142
  [a1b2c3d4e5f6] User works at Acme Corp building Acme Dashboard on Next.js 15 with Supabase auth.
26
143
  [b2c3d4e5f6a1] Hard constraint: ship by January 22nd 2026.
27
- [c3d4e5f6a1b2] Public API uses GraphQL (switched from REST to reduce mobile over-fetching).
28
144
 
29
145
  ## Observations
30
146
  [d4e5f6a1b2c3] 2026-01-15 14:30 [high] User decided to switch from REST to GraphQL for the public API; motivation was reducing over-fetching on mobile clients.
31
- [e5f6a1b2c3d4] 2026-01-15 14:35 [medium] Agent scaffolded GraphQL schema in src/schema.ts.
32
- [f6a1b2c3d4e5] 2026-01-15 14:50 [medium] GraphQL migration completed; user confirmed queries working.
33
- [a6b1c2d3e4f5] 2026-01-15 15:10 [critical] User wants rate limiting on all public endpoints; prefers token bucket algorithm at 100 req/min per API key.
147
+ [e5f6a1b2c3d4] 2026-01-15 14:50 [medium] GraphQL migration completed; user confirmed queries working.
34
148
  ```
35
149
 
36
- Two layers of memory, two different jobs:
150
+ The IDs are useful because the agent-facing `recall` tool can recover source evidence for a specific observation or reflection.
151
+
152
+ That means memory is not just a vague statement. The agent can look back at the evidence behind it.
37
153
 
38
- - **Reflections** are durable patterns — who you are, what you've decided, hard constraints. They render as plain prose with an id handle when recallable, and persist across future compactions.
39
- - **Observations** are timestamped events with an id and a per-entry relevance tier (`low` / `medium` / `high` / `critical`). They're written near-real-time, then pruned over time — but never paraphrased.
154
+ ---
40
155
 
41
- Those ids are not decoration. When the agent needs exact evidence behind a compacted memory item, it can call the agent-facing `recall` tool with a reflection or observation id. The TUI shows a compact evidence summary, while the agent receives the full raw source context that produced the memory.
156
+ ## Who this is for
42
157
 
43
- Hour six should feel like hour one. The agent knows who you are, what you've built together, and what's left to do.
158
+ Use `pi-observational-memory` if you use Pi for:
44
159
 
45
- ## What you actually get from it
160
+ * long coding sessions
161
+ * multi-day feature work
162
+ * architecture exploration
163
+ * large refactors
164
+ * production debugging
165
+ * repository migrations
166
+ * agent-assisted planning
167
+ * sessions that need to survive many compactions
168
+ * workflows where handoff quality matters
46
169
 
47
- - **Continuity across many compactions.** The summary is built by mechanical concatenation, not an LLM rewrite. Kept observations and reflections are carried forward without paraphrase; observations may be pruned later, but they are never rewritten into summary-of-summary drift.
48
- - **Temporal reasoning.** Every observation carries a per-minute timestamp. The agent can reason about *when* something happened, not just *that* it happened.
49
- - **Source-backed recall.** Observation and reflection ids let the agent recover the exact prior conversation/tool evidence behind compacted memory when precision matters.
50
- - **Relevance-aware pruning.** Four relevance tiers drive what gets dropped first when the observation pool grows. Trivia goes; user assertions, decisions, and verbatim errors stay.
51
- - **Reflections that crystallize.** Identity, constraints, and durable preferences settle into a separate layer that doesn't get re-paraphrased on each compaction.
52
- - **Predictable token cost.** Properly configured for your use case, this can save real money. The reflector + pruner only run above a configurable gate, so below-gate compactions skip those LLM calls; they only call a model if sync catch-up observation is needed. The observer can be pointed at a cheap fast model independently of your main coding model.
53
- - **Cache-friendly by design.** Memory updates are batched at compaction boundaries instead of injected into every turn, so prompt prefix caching keeps working between compactions.
54
- - **Fewer mid-work surprises.** The extension proactively triggers compaction when the agent is idle, and this will not affect your current work as after compaction you still keep the tail of your session intact.
170
+ This extension is especially useful when the session contains decisions that should survive over time.
171
+
172
+ ---
55
173
 
56
174
  ## Install
57
175
 
@@ -59,129 +177,226 @@ Hour six should feel like hour one. The agent knows who you are, what you've bui
59
177
  pi install npm:pi-observational-memory
60
178
  ```
61
179
 
62
- Or from GitHub:
180
+ Or install from GitHub/local development:
63
181
 
64
182
  ```bash
65
183
  pi install git:github.com/elpapi42/pi-observational-memory
184
+ # or, from a local checkout:
185
+ pi install /absolute/path/to/pi-observational-memory
66
186
  ```
67
187
 
68
- That's it. The extension hooks into Pi's lifecycle automatically. Defaults work well for most sessions — no config file needed to start.
69
-
70
- ## How it works (60-second version)
71
-
72
- Three tiers, two of them mostly asynchronous:
188
+ Pi loads the extension from `src/index.ts` through the package `pi.extensions` entry.
73
189
 
74
- ```mermaid
75
- flowchart TD
76
- Conv([Conversation accumulates])
77
- Obs[Observer<br/>async, fire-and-forget<br/>compresses each chunk into timestamped,<br/>relevance-tagged observations<br/>stored as silent tree entries]
78
- Comp[Compaction<br/>extension-owned; merges accumulated<br/>observations with prior compaction state]
79
- RP[Reflector + Pruner<br/>Reflector runs two focused passes<br/>to crystallize durable patterns<br/>Pruner drops observations by id<br/>across up to 2 passes]
80
- Sum[Summary mechanically assembled<br/>## Reflections<br/>&nbsp;&nbsp;[id] durable insight<br/>## Observations<br/>&nbsp;&nbsp;[id] YYYY-MM-DD HH:MM relevance ...<br/>Becomes the compactionSummary<br/>the agent sees on the next turn]
81
-
82
- Conv -->|every ~1k raw tokens since last bound| Obs
83
- Obs -->|live tail reaches ~50k raw tokens| Comp
84
- Comp -->|observation pool ≥ 30k tokens| RP
85
- RP --> Sum
86
- Comp -.->|pool below gate — skip reflector/pruner| Sum
87
- ```
190
+ ---
88
191
 
89
- - **Observer** runs in the background as turns complete. The user never waits on it.
90
- - **Compaction** is owned by the extension. The summary is *mechanically concatenated* from current reflections + current observations — never an LLM rewrite. This is what eliminates the summary-of-a-summary problem.
91
- - **Reflector + Pruner** run as an inseparable pair, and only when there's enough material to crystallize. Below the gate, those roles are skipped; compaction only calls a model if sync catch-up observation is needed for uncovered raw history.
192
+ ## Quick configuration
92
193
 
93
- The agent only ever sees the most recent compaction summary, packaged as a normal `compactionSummary` message. Observations and reflections are never injected into the live message stream — that would invalidate prefix caching with every observation. By batching memory updates at compaction boundaries, the prefix stays stable between compactions and prefix caching keeps working.
194
+ Settings live under the `observational-memory` namespace in either:
94
195
 
95
- For the full picture, read on:
196
+ * `~/.pi/agent/settings.json`
197
+ * project-local `.pi/settings.json`
96
198
 
97
- - **[docs/concepts.md](docs/concepts.md)** vocabulary and mental model. Start here if you're new.
98
- - **[docs/how-it-works.md](docs/how-it-works.md)** — the full lifecycle, data shapes, and async-race handling.
99
- - **[docs/configuration.md](docs/configuration.md)** — every setting, what it trades off, and tuning recipes.
199
+ Project settings override global settings.
100
200
 
101
- ## Configuration in 30 seconds
201
+ `PI_OBSERVATIONAL_MEMORY_PASSIVE` can override only `passive`.
102
202
 
103
- Settings live in Pi's `settings.json` — globally at `~/.pi/agent/settings.json` or per-project at `.pi/settings.json` (project values override global).
203
+ A typical config:
104
204
 
105
205
  ```json
106
206
  {
107
207
  "observational-memory": {
108
- "observationThresholdTokens": 1000,
109
- "compactionThresholdTokens": 50000,
110
- "reflectionThresholdTokens": 30000,
111
- "passive": false
112
- },
113
- "compaction": {
114
- "keepRecentTokens": 20000
208
+ "observeAfterTokens": 10000,
209
+ "reflectAfterTokens": 20000,
210
+ "compactAfterTokens": 81000,
211
+ "observationsPoolMaxTokens": 20000,
212
+ "observationsPoolTargetTokens": 10000,
213
+ "agentMaxTurns": 16,
214
+ "model": {
215
+ "provider": "openrouter",
216
+ "id": "google/gemma-4-31b-it",
217
+ "thinking": "low"
218
+ },
219
+ "passive": false,
220
+ "debugLog": false
115
221
  }
116
222
  }
117
223
  ```
118
224
 
119
- To run the background memory work (observer, reflector, pruner) on a cheaper / faster model than your main coding agent — often the single biggest cost lever the extension exposes add `compactionModel`:
225
+ Most users can start with the defaults and tune only if they have a specific reason.
120
226
 
121
- ```json
122
- {
123
- "observational-memory": {
124
- "compactionModel": { "provider": "openrouter", "id": "google/gemma-4-31b-it" }
125
- }
126
- }
227
+ ### Defaults
228
+
229
+ | Setting | Default | Meaning |
230
+ | --------------------------- | ------------- | ------------------------------------------------------------------------------------------------- |
231
+ | `observeAfterTokens` | `10000` | Raw/source token threshold for observation runs. |
232
+ | `reflectAfterTokens` | `20000` | Raw/source token threshold for reflection runs; successful reflection creates dropper opportunities. |
233
+ | `compactAfterTokens` | `81000` | Raw/source token threshold for proactive auto-compaction. |
234
+ | `observationsPoolMaxTokens` | `20000` | Observation-token budget used for compaction full-fold pressure. |
235
+ | `observationsPoolTargetTokens` | half of max | Active observation target used by post-reflection dropper maintenance. |
236
+ | `agentMaxTurns` | `16` | Shared turn cap for background memory-agent loops. |
237
+ | `model` | session model | Optional memory-worker model override: `{ provider, id, thinking }`. |
238
+ | `passive` | `false` | Disables proactive background observation, reflection, maintenance, and auto-compaction triggers. |
239
+ | `debugLog` | `false` | Writes opt-in per-session extension debug events to Pi's agent directory. |
240
+
241
+ Valid `model.thinking` values are:
242
+
243
+ * `off`
244
+ * `minimal`
245
+ * `low`
246
+ * `medium`
247
+ * `high`
248
+ * `xhigh`
249
+
250
+ If no `model` is configured, memory workers use the session model.
251
+
252
+ `observationsPoolMaxTokens` and `observationsPoolTargetTokens` intentionally describe different pools. Max tokens control when compaction performs a full fold over visible memory. Target tokens control the folded active observation pool that the dropper maintains after successful reflection. If the target is omitted, it defaults to half of max.
253
+
254
+ Dropper pruning balances age, relevance, and reflection coverage. Relevance is importance/resistance, not a permanent active-memory pin: `critical` observations require the strongest evidence but can be dropped when they are older and safely represented by reflections, superseded by newer memory, redundant, or obsolete. Dropper input annotates each active observation with deterministic coverage evidence: `none`, `partial`, or `strong`; coverage guides model judgment and is not an automatic drop rule. Dropping removes observations from active memory, not ledger history.
255
+
256
+ When `debugLog` is enabled, debug events are written as local NDJSON files under Pi's agent directory. Normal sessions write to `observational-memory/debug/<session-id>.ndjson`; contexts without a session id fall back to `observational-memory/debug.ndjson`. Debug rows include `sessionId` and per-consolidation `runId`, so a session file can still be filtered to one observer/reflector/dropper run.
257
+
258
+ For details and tuning guidance, see [`docs/configuration.md`](docs/configuration.md).
259
+
260
+ ---
261
+
262
+ ## Commands and agent tool
263
+
264
+ | Surface | What it does |
265
+ | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
266
+ | `/om-status` | Shows memory counts, plain `+N` / `-N` visible/full drift suffixes, progress clocks, visible and active observation pool pressure, passive/in-flight state, and last worker errors. |
267
+ | `/om-view` | Shows current visible memory and attempts to copy the rendered memory text to the clipboard. |
268
+ | `/om-view full` | Shows the full current memory state for the branch and attempts to copy the rendered memory text to the clipboard. |
269
+ | `recall` agent tool | Recovers source evidence for a 12-character observation/reflection id on the current branch. It is not semantic search or a transcript browser. |
270
+
271
+ `/om-view` copies only the rendered memory content. The success/failure line shown in Pi is not included in the clipboard text. If clipboard support is unavailable, the command still prints the memory view and shows a warning. Before the first V3 compaction, visible memory can be empty because nothing has been folded into `om.folded` details; use `/om-view full` to inspect recorded branch memory.
272
+
273
+ ---
274
+
275
+ ## How it works in 60 seconds
276
+
277
+ ```mermaid
278
+ flowchart TD
279
+ Turn[turn_end]
280
+ Observe[Capture observations]
281
+ Reflect[Distill reflections]
282
+ AgentEnd[agent_end]
283
+ Trigger[auto-compaction trigger]
284
+ Compact[session_before_compact]
285
+ Summary[visible memory for Pi]
286
+
287
+ Turn -->|observation due| Observe
288
+ Turn -->|reflection due| Reflect
289
+ AgentEnd -->|compactAfterTokens and idle| Trigger --> Compact --> Summary
127
290
  ```
128
291
 
129
- Nested agent-loop turns default to `16` for each memory role. To tune them (useful for controlling cost on large observation pools):
292
+ The high-level lifecycle:
293
+
294
+ 1. Pi session continues normally.
295
+ 2. The extension captures observations from the session as work happens.
296
+ 3. Durable reflections are distilled in the background.
297
+ 4. When compaction time arrives, Pi receives prepared memory quickly.
298
+ 5. The agent continues with a compact but useful view of the work so far.
299
+
300
+ The important part: compaction does not need to rethink the whole session from scratch.
301
+
302
+ ---
303
+
304
+ ## Current V3 behavior
305
+
306
+ Current behavior:
307
+
308
+ * **Observation-centered memory.** The extension records useful session observations while you work.
309
+ * **Durable reflections.** The extension distills stable facts that help the agent stay oriented over time.
310
+ * **Fast compaction.** `session_before_compact` does not call a model or wait for background workers. It renders the current prepared memory state.
311
+ * **Background memory work.** Observation and reflection work run from `turn_end` when their token clocks are due; dropper work runs only after successful reflection and prunes the folded active observation ledger toward `observationsPoolTargetTokens`.
312
+ * **Source-backed recall.** Observations and reflections can be traced back through the `recall` tool.
313
+ * **Visible/full views.** `/om-view` shows visible memory and `/om-view full` shows the full current memory state. Use `/om-status` for visible-vs-full drift and for the separate visible observation pool vs active observation pool.
314
+ * **No V2 compatibility layer.** Old V2 settings and memory entries are ignored rather than migrated.
315
+
316
+ ---
317
+
318
+ ## Migrating from V2
319
+
320
+ V3 is **not backwards compatible** with V2 memory or settings.
321
+
322
+ What this means in practice:
323
+
324
+ 1. **Update your settings.** V2 keys are silently ignored by V3. Keeping the old names will make V3 fall back to defaults.
325
+ 2. **Start a new clean Pi session after upgrading.** Existing sessions may still contain old visible compaction-summary text until a new V3 compaction replaces what the agent sees, so a clean session is the safest migration path.
326
+ 3. **Do not expect rollback continuity.** If you create V3 memory entries and then roll back to V2, V2 will not understand the V3 memory format. Treat that as memory reset/visibility loss.
327
+
328
+ ### Settings migration table
329
+
330
+ | V2 setting | V3 setting | What to do |
331
+ | ---------------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
332
+ | `observationThresholdTokens` | `observeAfterTokens` | Rename. Same rough role: observation cadence based on raw/source tokens. |
333
+ | `compactionThresholdTokens` | `compactAfterTokens` | Rename. Same rough role: proactive compaction cadence. |
334
+ | `reflectionThresholdTokens` | `reflectAfterTokens`, `observationsPoolMaxTokens`, and/or `observationsPoolTargetTokens` | Split. Use `reflectAfterTokens` for reflection scheduling, `observationsPoolMaxTokens` for compaction full-fold pressure, and `observationsPoolTargetTokens` for dropper active observation maintenance. |
335
+ | `compactionModel` | `model` | Move `{ provider, id }` to `model`. |
336
+ | `thinkingLevel` | `model.thinking` | Move under `model`. |
337
+ | `observerMaxTurnsPerRun` | `agentMaxTurns` | Replace with the shared memory-agent turn cap. |
338
+ | `reflectorMaxTurnsPerPass` | `agentMaxTurns` | Replace with the shared memory-agent turn cap. |
339
+ | `prunerMaxTurnsPerPass` | `agentMaxTurns` | Replace with the shared memory-agent turn cap. |
340
+ | `compactionMaxToolCalls` | none | Remove. There is no V3 alias. |
341
+ | `passive` | `passive` | Keep if desired. |
342
+ | `debugLog` | `debugLog` | Keep if desired. |
343
+
344
+ Example V2 config:
130
345
 
131
346
  ```json
132
347
  {
133
348
  "observational-memory": {
349
+ "observationThresholdTokens": 1000,
350
+ "compactionThresholdTokens": 50000,
351
+ "reflectionThresholdTokens": 30000,
352
+ "compactionModel": { "provider": "openrouter", "id": "google/gemma-4-31b-it" },
353
+ "thinkingLevel": "low",
134
354
  "observerMaxTurnsPerRun": 8,
135
355
  "reflectorMaxTurnsPerPass": 12,
136
- "prunerMaxTurnsPerPass": 12
356
+ "prunerMaxTurnsPerPass": 12,
357
+ "passive": false
137
358
  }
138
359
  }
139
360
  ```
140
361
 
141
- A turn is one assistant/model response cycle inside Pi's nested agent loop. These caps are checked after a turn finishes; they are not hard mid-stream interrupts and are not literal tool-call counters.
142
-
143
- For memory model calls, you can also tune thinking effort with one unified setting. Valid values are `off`, `minimal`, `low`, `medium`, `high`, and `xhigh`; the default is `low`.
362
+ V3 equivalent:
144
363
 
145
364
  ```json
146
365
  {
147
366
  "observational-memory": {
148
- "thinkingLevel": "low"
367
+ "observeAfterTokens": 10000,
368
+ "reflectAfterTokens": 20000,
369
+ "compactAfterTokens": 81000,
370
+ "observationsPoolMaxTokens": 20000,
371
+ "observationsPoolTargetTokens": 10000,
372
+ "agentMaxTurns": 12,
373
+ "model": {
374
+ "provider": "openrouter",
375
+ "id": "google/gemma-4-31b-it",
376
+ "thinking": "low"
377
+ },
378
+ "passive": false
149
379
  }
150
380
  }
151
381
  ```
152
382
 
153
- The settings most worth knowing:
154
-
155
- | Setting | Default | What it controls |
156
- |---|---|---|
157
- | `observationThresholdTokens` | `1,000` | How often the observer fires in the background |
158
- | `compactionThresholdTokens` | `50,000` | How often the extension proactively triggers compaction |
159
- | `reflectionThresholdTokens` | `30,000` | The observation pool size at which reflector + pruner engage |
160
- | `passive` | `false` | Disables proactive observation and extension-triggered compaction while keeping manual/Pi compaction and commands active |
161
- | `compactionModel` | session model | Which model runs the observer / reflector / pruner — point at a cheaper one to save cost |
162
- | `observerMaxTurnsPerRun` | `16` | Assistant-turn cap for each observer run |
163
- | `reflectorMaxTurnsPerPass` | `16` | Assistant-turn cap for each reflector pass |
164
- | `prunerMaxTurnsPerPass` | `16` | Assistant-turn cap for each pruner pass |
165
- | `thinkingLevel` | `low` | Thinking effort for observer, reflector, and pruner calls; `off` omits Pi's reasoning option |
166
- | `compaction.keepRecentTokens` | `20,000` | How much recent conversation Pi keeps verbatim post-compaction (Pi setting; structural to the extension) |
383
+ ---
167
384
 
168
- For shell/session-level control, `PI_OBSERVATIONAL_MEMORY_PASSIVE` overrides global and project settings. Use `1`, `true`, `yes`, or `on` to enable passive mode; use `0`, `false`, `no`, or `off` to force it off.
385
+ ## More docs
169
386
 
170
- For the full list and tuning recipes, see **[docs/configuration.md](docs/configuration.md)**.
387
+ * [`docs/concepts.md`](docs/concepts.md) — vocabulary and V3 mental model.
388
+ * [`docs/how-it-works.md`](docs/how-it-works.md) — lifecycle, memory shapes, projections, and recall flow.
389
+ * [`docs/configuration.md`](docs/configuration.md) — all V3 settings and migration notes.
171
390
 
172
- > **Upgrading from `pi-observational-memory@1.x`?** The config keys changed: v1's `observationThreshold` is now `compactionThresholdTokens`, v1's `reflectionThreshold` is now `reflectionThresholdTokens`, and `observationThresholdTokens` is new. Old v1 keys are silently ignored — update your `settings.json`.
391
+ ---
173
392
 
174
- ## Commands and agent tool
393
+ ## Credits
175
394
 
176
- | Surface | What it does |
177
- |---|---|
178
- | `/om-status` | Memory totals, percent-to-threshold for each gate, passive-mode status, and in-flight flags for observer and compaction |
179
- | `/om-view` | Full dump of memory state: every reflection, every committed observation, every pending observation. Reflection and observation ids shown here can be used with `recall` |
180
- | `recall` agent tool | Recovers exact source evidence for a specific reflection or observation id on the current branch. It is for agent self-recovery and provenance, not a user command, semantic search, or transcript browser |
395
+ Inspired by [Mastra's Observational Memory](https://mastra.ai/blog/observational-memory) research.
181
396
 
182
- ## Credits
397
+ This is an independent implementation built for Pi's extension system.
183
398
 
184
- 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.
399
+ ---
185
400
 
186
401
  ## License
187
402
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-observational-memory",
3
- "version": "2.4.3",
3
+ "version": "3.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",
@@ -34,16 +34,16 @@
34
34
  "test": "vitest run"
35
35
  },
36
36
  "peerDependencies": {
37
- "@mariozechner/pi-agent-core": "*",
38
- "@mariozechner/pi-ai": "*",
39
- "@mariozechner/pi-coding-agent": "*",
40
- "@mariozechner/pi-tui": "*"
37
+ "@earendil-works/pi-agent-core": "*",
38
+ "@earendil-works/pi-ai": "*",
39
+ "@earendil-works/pi-coding-agent": "*",
40
+ "@earendil-works/pi-tui": "*"
41
41
  },
42
42
  "devDependencies": {
43
- "@mariozechner/pi-agent-core": "^0.73.0",
44
- "@mariozechner/pi-ai": "^0.73.0",
45
- "@mariozechner/pi-coding-agent": "^0.73.0",
46
- "@mariozechner/pi-tui": "^0.73.0",
43
+ "@earendil-works/pi-agent-core": "^0.74.0",
44
+ "@earendil-works/pi-ai": "^0.74.0",
45
+ "@earendil-works/pi-coding-agent": "^0.74.0",
46
+ "@earendil-works/pi-tui": "^0.74.0",
47
47
  "@types/node": "^22.0.0",
48
48
  "typebox": "^1.1.38",
49
49
  "typescript": "^5.6.0",