.agents/memory/2026-02-15-pre-compaction-flush.md

151 lines
4.7 KiB
Markdown

# Pre-Compaction Flush Implementation Analysis
**Date:** 2026-02-15
**Spec Reference:** Signet SPEC.md Section 6.4
## Spec Requirements (Section 6.4)
### 6.4.1 Trigger
- MUST trigger flush when token usage reaches compaction threshold - safety margin
- RECOMMENDED margin: 4,000 tokens
### 6.4.2 Protocol
1. Send system instruction: "Pre-compaction memory flush. Store durable memories now."
2. Agent writes accumulated context to database
3. Agent responds with acknowledgment (e.g., "NO_REPLY")
4. Implementation proceeds with compaction
5. Flush MUST be invisible to user
### 6.4.3 Content
- Decisions made during session
- New facts learned about user
- Project progress and blockers
- Action items and todos
---
## Harness Implementation Status
### OpenClaw ✓ FULL COMPLIANCE
**Location:** `/usr/lib/node_modules/openclaw/dist/auto-reply/reply/memory-flush.js`
**Key Constants:**
```javascript
DEFAULT_MEMORY_FLUSH_SOFT_TOKENS = 4000 // safety margin
DEFAULT_MEMORY_FLUSH_PROMPT = "Pre-compaction memory flush. Store durable memories now..."
DEFAULT_MEMORY_FLUSH_SYSTEM_PROMPT = "Pre-compaction memory flush turn. The session is near auto-compaction..."
```
**Implementation Details:**
- `resolveMemoryFlushSettings(cfg)` - reads config, returns settings or null if disabled
- `resolveMemoryFlushContextWindowTokens(params)` - calculates context window for model
- `shouldRunMemoryFlush(params)` - determines if flush is needed based on token count
- `runMemoryFlushIfNeeded(params)` - executes the flush turn
**Trigger Logic:**
```javascript
threshold = contextWindow - reserveTokens - softThreshold
if (totalTokens >= threshold && !alreadyFlushedAtThisCompactionCount) {
// trigger flush
}
```
**State Tracking:**
- `memoryFlushAt` - timestamp of last flush
- `memoryFlushCompactionCount` - prevents re-triggering at same compaction count
**Config Options:**
- `agents.defaults.compaction.memoryFlush.enabled` (default: true)
- `agents.defaults.compaction.memoryFlush.softThresholdTokens` (default: 4000)
- `agents.defaults.compaction.memoryFlush.prompt` (customizable)
- `agents.defaults.compaction.memoryFlush.systemPrompt` (customizable)
- `agents.defaults.compaction.reserveTokensFloor`
---
### OpenCode ⚠️ PARTIAL IMPLEMENTATION
**Location:** `~/.config/opencode/memory.mjs`
**Available Hook:** `experimental.session.compacting`
**Current Implementation:**
```javascript
"experimental.session.compacting": async (input, output) => {
output.context.push('[memory active: /remember to save, /recall to query]')
}
```
**Limitations:**
- Only adds context reminder during compaction
- Does NOT trigger a full agent turn for memory saving
- Cannot execute memory save operations before compaction
**Available Hooks (OpenCode Plugin API):**
- `experimental.chat.messages.transform` - transform chat messages
- `experimental.chat.system.transform` - transform system prompt
- `experimental.session.compacting` - hook during compaction (limited)
- `experimental.text.complete` - text completion hook
**What's Missing:**
1. Token monitoring before compaction threshold
2. Ability to inject a memory flush turn before compaction
3. State tracking for flush operations
**Possible Enhancement:**
The plugin API would need a new hook like `experimental.session.preCompaction` that:
- Receives current token count
- Can inject a system message
- Can pause compaction until agent responds
- Can execute tool calls (like memory save)
---
### Claude Code ⚠️ INTERNAL MECHANISMS
Claude Code uses its own internal memory mechanisms. No external plugin API
for pre-compaction flush.
**Notes:**
- May have internal memory management
- Not configurable via user-facing hooks
- Would need Claude/Anthropic to implement spec compliance
---
## Recommendations
### For OpenCode
1. Request new hook: `experimental.session.preCompaction`
2. This hook should receive token count and allow injecting messages
3. Alternative: Document that pre-compaction flush requires harness-level changes
### For Claude Code
1. Document that flush is handled internally (if it is)
2. Or note as "implementation pending"
### For Signet Spec
1. Document that pre-compaction flush is a HARNESS-LEVEL feature
2. Provide reference implementation based on OpenClaw
3. Define minimum hook requirements for plugin-based harnesses
---
## Test Verification
To verify pre-compaction flush is working:
1. Start a long session that approaches context limit
2. Check if memory save operations occur before compaction
3. Verify saved memories contain session decisions, facts, progress, todos
4. Confirm NO_REPLY is stripped from user output
**OpenClaw Test:**
```bash
# Check config
openclaw config get agents.defaults.compaction.memoryFlush
# Monitor session for flush events
# Look for "Pre-compaction memory flush" in logs
```