opencode-working-memory 1.0.0

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.
@@ -0,0 +1,375 @@
1
+ # Architecture Documentation
2
+
3
+ ## Overview
4
+
5
+ The Working Memory Plugin implements a **four-tier memory architecture** designed to maximize context efficiency for AI agents in OpenCode sessions.
6
+
7
+ ```
8
+ ┌─────────────────────────────────────────────────────────────┐
9
+ │ TIER 1: CORE MEMORY │
10
+ │ Persistent blocks: goal (1000) | progress (2000) | context (1500) │
11
+ │ Survives compaction, always visible in system prompt │
12
+ └─────────────────────────────────────────────────────────────┘
13
+
14
+ ┌─────────────────────────────────────────────────────────────┐
15
+ │ TIER 2: WORKING MEMORY │
16
+ │ Session-scoped slots + memory pool │
17
+ │ Slots: error(3) | decision(5) | todo(3) | dependency(3) │
18
+ │ Pool: Exponential decay (γ=0.85) + mention tracking │
19
+ └─────────────────────────────────────────────────────────────┘
20
+
21
+ ┌─────────────────────────────────────────────────────────────┐
22
+ │ TIER 3: SMART PRUNING │
23
+ │ Filters tool outputs before adding to conversation │
24
+ │ Removes: file lists, verbose logs, repetitive content │
25
+ │ Modes: normal → aggressive → hyper-aggressive │
26
+ └─────────────────────────────────────────────────────────────┘
27
+
28
+ ┌─────────────────────────────────────────────────────────────┐
29
+ │ TIER 4: PRESSURE MONITORING │
30
+ │ Tracks context usage: safe → moderate → high │
31
+ │ Thresholds: 75% (moderate) | 90% (high) │
32
+ │ Intervention: Sends promptAsync() with full visible prompt │
33
+ └─────────────────────────────────────────────────────────────┘
34
+ ```
35
+
36
+ ## Phase 1: Core Memory Foundation
37
+
38
+ ### Purpose
39
+ Provide persistent memory blocks that survive conversation compaction and are always injected into the system prompt.
40
+
41
+ ### Storage
42
+ - **Location**: `.opencode/memory-core/<sessionID>.json`
43
+ - **Schema**:
44
+ ```typescript
45
+ {
46
+ sessionID: string;
47
+ blocks: {
48
+ goal: { content: string; chars: number; maxChars: 1000; updatedAt: string };
49
+ progress: { content: string; chars: number; maxChars: 2000; updatedAt: string };
50
+ context: { content: string; chars: number; maxChars: 1500; updatedAt: string };
51
+ };
52
+ updatedAt: string;
53
+ }
54
+ ```
55
+
56
+ ### Character Limits
57
+ - **goal**: 1000 chars (ONE specific task)
58
+ - **progress**: 2000 chars (done/in-progress/blocked checklist)
59
+ - **context**: 1500 chars (current working files + key patterns)
60
+
61
+ ### Operations
62
+ - **replace**: Completely replace block content
63
+ - **append**: Add content to end (auto-adds newline)
64
+
65
+ ### Tools
66
+ - `core_memory_update`: Update or append to blocks
67
+ - `core_memory_read`: Read current state of all blocks
68
+
69
+ ### System Prompt Injection
70
+ Blocks are injected into every agent message as:
71
+ ```
72
+ <core_memory>
73
+ <goal chars="87/1000">...</goal>
74
+ <progress chars="560/2000">...</progress>
75
+ <context chars="479/1500">...</context>
76
+ </core_memory>
77
+ ```
78
+
79
+ ## Phase 2: Smart Pruning
80
+
81
+ ### Purpose
82
+ Reduce context bloat by filtering tool outputs before they enter the conversation history.
83
+
84
+ ### Pruning Modes
85
+
86
+ #### Normal Mode (Pressure < 75%)
87
+ - Remove file/directory listings > 50 lines
88
+ - Truncate verbose tool outputs
89
+ - Keep first/last 30 lines of long outputs
90
+ - Preserve error messages and key information
91
+
92
+ #### Aggressive Mode (75% ≤ Pressure < 90%)
93
+ - Threshold drops to 30 lines
94
+ - More aggressive truncation (first/last 20 lines)
95
+ - Filter repetitive content
96
+
97
+ #### Hyper-Aggressive Mode (Pressure ≥ 90%)
98
+ - Threshold drops to 15 lines
99
+ - Keep only first/last 10 lines
100
+ - Maximum compression
101
+
102
+ ### Pruning Heuristics
103
+
104
+ 1. **File Listings**: Detect `ls`, `find`, `glob` outputs
105
+ 2. **Directory Trees**: Detect tree-like structures with `/`
106
+ 3. **Log Files**: Detect timestamp patterns, stack traces
107
+ 4. **Repetitive Content**: Detect similar consecutive lines
108
+ 5. **Synthetic Content**: Preserve `synthetic: true` markers
109
+
110
+ ### Implementation
111
+ Pruning happens in `tool.execute.after` hook before tool output enters conversation.
112
+
113
+ ## Phase 3: Working Memory
114
+
115
+ ### Purpose
116
+ Provide session-scoped memory with structured slots and a general-purpose pool with intelligent decay.
117
+
118
+ ### Storage
119
+ - **Location**: `.opencode/memory-working/<sessionID>.json`
120
+ - **Schema**:
121
+ ```typescript
122
+ {
123
+ sessionID: string;
124
+ slots: {
125
+ error: Array<WorkingMemoryItem>; // Max 3
126
+ decision: Array<WorkingMemoryItem>; // Max 5
127
+ todo: Array<WorkingMemoryItem>; // Max 3
128
+ dependency: Array<WorkingMemoryItem>; // Max 3
129
+ };
130
+ pool: Array<WorkingMemoryItem>;
131
+ eventCounter: number;
132
+ updatedAt: string;
133
+ }
134
+ ```
135
+
136
+ ### Slot Types
137
+
138
+ | Slot | Max Items | Purpose |
139
+ |------|-----------|---------|
140
+ | **error** | 3 | Recent errors that need fixing |
141
+ | **decision** | 5 | Important decisions made |
142
+ | **todo** | 3 | Current task checklist |
143
+ | **dependency** | 3 | File/package dependencies |
144
+
145
+ ### Memory Pool
146
+
147
+ General-purpose storage with **exponential decay**:
148
+
149
+ ```typescript
150
+ score = exp(-γ * age) + mentionCount
151
+ ```
152
+
153
+ Where:
154
+ - `γ = 0.85` (decay rate, 15% per event)
155
+ - `age = eventCounter - item.eventNumber`
156
+ - `mentionCount`: Number of times item mentioned in conversation
157
+
158
+ Items with `score < 0.01` are pruned.
159
+
160
+ ### Auto-Extraction
161
+
162
+ Working memory items are **automatically extracted** from:
163
+ - Tool outputs (file paths, errors, dependencies)
164
+ - User messages (decisions, todos)
165
+ - Assistant responses (key information)
166
+
167
+ ### Manual Management
168
+
169
+ Tools:
170
+ - `working_memory_add`: Manually add item
171
+ - `working_memory_clear`: Clear all items
172
+ - `working_memory_clear_slot`: Clear specific slot (e.g., after fixing all errors)
173
+ - `working_memory_remove`: Remove specific item by content match
174
+
175
+ ### System Prompt Injection
176
+
177
+ ```
178
+ <working_memory>
179
+ Recent session context (auto-managed, sorted by relevance):
180
+
181
+ ⚠️ Errors:
182
+ - TypeError at line 42 in utils.ts
183
+ - Missing import in index.ts
184
+
185
+ 📁 Key Files:
186
+ - src/components/Button.tsx
187
+ - src/utils/helpers.ts
188
+
189
+ (15 items shown, updated: 9:46:47 AM)
190
+ </working_memory>
191
+ ```
192
+
193
+ ## Phase 4: Pressure Monitoring
194
+
195
+ ### Purpose
196
+ Track conversation context usage and trigger interventions when approaching limits.
197
+
198
+ ### Pressure Calculation
199
+
200
+ ```typescript
201
+ pressure = (visiblePromptChars / estimatedContextLimit) * 100
202
+ ```
203
+
204
+ Where:
205
+ - `visiblePromptChars`: Total characters in system prompt + tool outputs
206
+ - `estimatedContextLimit`: ~180,000 chars (conservative estimate)
207
+
208
+ ### Pressure Levels
209
+
210
+ | Level | Threshold | Behavior |
211
+ |-------|-----------|----------|
212
+ | **safe** | < 75% | Normal operation |
213
+ | **moderate** | 75-89% | Warning in system prompt + aggressive pruning |
214
+ | **high** | ≥ 90% | Hyper-aggressive pruning + intervention |
215
+
216
+ ### Pressure Storage
217
+
218
+ - **Location**: `.opencode/memory-working/<sessionID>_pressure.json`
219
+ - **Schema**:
220
+ ```typescript
221
+ {
222
+ sessionID: string;
223
+ level: "safe" | "moderate" | "high";
224
+ percentage: number;
225
+ visiblePromptChars: number;
226
+ estimatedLimit: 180000;
227
+ lastChecked: string;
228
+ interventionsSent: number;
229
+ }
230
+ ```
231
+
232
+ ### Intervention Mechanism
233
+
234
+ When pressure reaches **high** (≥90%):
235
+ 1. Plugin sends `promptAsync()` message to agent
236
+ 2. Message includes full visible prompt for review
237
+ 3. Agent can compress core memory, clear working memory, or continue
238
+ 4. Intervention tracked in `interventionsSent` counter
239
+
240
+ ### System Prompt Injection
241
+
242
+ ```
243
+ [Memory Pressure: 87% (high) - 156,600/180,000 chars]
244
+ ⚠️ High memory pressure detected. Consider:
245
+ - Compressing core_memory blocks (use core_memory_update)
246
+ - Clearing resolved errors (use working_memory_clear_slot)
247
+ - Removing old pool items (auto-pruned at score < 0.01)
248
+ ```
249
+
250
+ ## Phase 4.5: Storage Governance
251
+
252
+ ### Purpose
253
+ Prevent `.opencode/` directory bloat from accumulating tool output caches and orphaned memory files.
254
+
255
+ ### Layer 1: Session Deletion Cleanup
256
+
257
+ **Trigger**: `experimental.session.deleted` hook
258
+
259
+ **Actions**:
260
+ 1. Remove `.opencode/memory-core/<sessionID>.json`
261
+ 2. Remove `.opencode/memory-working/<sessionID>.json`
262
+ 3. Remove `.opencode/memory-working/<sessionID>_pressure.json`
263
+ 4. Remove `.opencode/memory-working/<sessionID>_compaction.json`
264
+
265
+ ### Layer 2: Tool Output Cache Sweep
266
+
267
+ **Trigger**: Every 500 events (`eventCounter % 500 === 0`)
268
+
269
+ **Target**: `.opencode/cache/tool-outputs/` directory
270
+
271
+ **Policy**:
272
+ - Keep most recent **300 files** (sorted by mtime)
273
+ - Delete files older than **7 days** (TTL policy)
274
+
275
+ **Logging**: Write sweep results to `.opencode/memory-working/<sessionID>_sweep.json`
276
+
277
+ ```typescript
278
+ {
279
+ sessionID: string;
280
+ timestamp: string;
281
+ eventCounter: number;
282
+ results: {
283
+ filesScanned: number;
284
+ filesDeleted: number;
285
+ bytesReclaimed: number;
286
+ errors: Array<string>;
287
+ };
288
+ }
289
+ ```
290
+
291
+ ## Performance Considerations
292
+
293
+ ### Memory Budgets
294
+ - **Core Memory**: 4,500 chars (injected every message)
295
+ - **Working Memory**: ~1,600 chars (injected every message)
296
+ - **Total Overhead**: ~6,100 chars per message
297
+
298
+ ### Compaction Behavior
299
+ When OpenCode compacts conversation (clears old messages):
300
+ - Core memory: **Preserved** (persistent across compactions)
301
+ - Working memory: **Preserved** (session-scoped, cleared on session end)
302
+ - Pressure state: **Preserved** (tracks across compaction)
303
+ - Compaction log: Saved to `<sessionID>_compaction.json`
304
+
305
+ ### Storage Footprint
306
+ - Each session: 4 JSON files (~5-20 KB total)
307
+ - Tool output cache: Max 300 files (~10-50 MB depending on outputs)
308
+ - Sweep every 500 events keeps storage bounded
309
+
310
+ ## Extension Points
311
+
312
+ ### Custom Slot Types
313
+ To add new slot types:
314
+ 1. Update `SlotType` union in types
315
+ 2. Add to `SLOT_CONFIG` with max items
316
+ 3. Update `formatWorkingMemoryForPrompt()` for display
317
+ 4. Update extraction heuristics in `tool.execute.after`
318
+
319
+ ### Custom Pruning Rules
320
+ To add pruning heuristics:
321
+ 1. Update `shouldPrune()` with new detection logic
322
+ 2. Add to `pruneToolOutput()` with filtering rules
323
+ 3. Test with representative tool outputs
324
+
325
+ ### Custom Pressure Thresholds
326
+ Adjust in constants:
327
+ ```typescript
328
+ const PRESSURE_THRESHOLDS = {
329
+ moderate: 70,
330
+ high: 85,
331
+ critical: 95,
332
+ };
333
+ ```
334
+
335
+ ## Migration & Compatibility
336
+
337
+ ### Old Format → New Format
338
+ Plugin automatically migrates from old format:
339
+ ```typescript
340
+ // Old format (pre-Phase 3)
341
+ { items: Array<Item> }
342
+
343
+ // New format (Phase 3+)
344
+ { slots: Record<SlotType, Array<Item>>, pool: Array<Item> }
345
+ ```
346
+
347
+ Migration happens on first load of old format files.
348
+
349
+ ## File System Layout
350
+
351
+ ```
352
+ .opencode/
353
+ ├── memory-core/
354
+ │ └── <sessionID>.json # Core memory blocks
355
+ ├── memory-working/
356
+ │ ├── <sessionID>.json # Working memory (slots + pool)
357
+ │ ├── <sessionID>_pressure.json # Pressure monitoring state
358
+ │ ├── <sessionID>_compaction.json # Compaction event log
359
+ │ └── <sessionID>_sweep.json # Storage sweep log
360
+ └── cache/
361
+ └── tool-outputs/
362
+ └── *.json # Tool output cache (auto-swept)
363
+ ```
364
+
365
+ ## Security Considerations
366
+
367
+ - All files written with `0644` permissions (owner read/write, group/others read)
368
+ - Directories created with `0755` permissions (owner rwx, group/others rx)
369
+ - No sensitive data should be stored in memory blocks (user responsibility)
370
+ - Session IDs are opaque identifiers, not derived from sensitive data
371
+
372
+ ---
373
+
374
+ **Last Updated**: February 2026
375
+ **Implementation**: `index.ts` (1700+ lines)