# pi-ctx-vars — Variable-Based Context Management for pi

Replaces pi's monolithic compaction with an agent-controlled variable store.

## What it does

Normal compaction turns old messages into ONE summary blob. This extension turns
each old message into a **variable** (full content + summary) in a SQLite store,
and lets the **agent** decide what stays in context:

- **PIN** — full content stays visible verbatim (decayable or persistent)
- **ARCHIVE** — only a dense summary stays in context
- **DROP** — no representation in context; content stays recoverable in the store

Nothing is deleted: archived and dropped content is fully searchable and
readable at any time. The raw session JSONL remains the final recovery layer.

At each compaction, a **compaction agent** (a separate LLM call) reviews the
candidates and decides pin / archive / drop per entry, writing per-entry
summaries *while the content is still in front of it*. When the archive section
grows too large, the oldest summaries are rolled into a **historical rollup**
(rolled up content stays recoverable in the store).

## Tools (available to the main agent)

| Tool | Purpose |
|---|---|
| `context_pin(target, decay?)` | Protect a variable (`var_N`) or raw entry so full content survives compaction. `decay=false` = persistent (only you can unpin). |
| `context_unpin(target)` | Release a pin (main agent only). |
| `context_drop(target)` | Remove representation from context; content stays in the store. |
| `context_archive(target, summary?)` | Reduce to summary-only representation. |
| `context_read(var_id)` | Load a variable's full content into context (does NOT pin). |
| `context_query(sql)` | Read-only SQL over the store (SELECT/WITH only) — the only way to find variables (LIKE search) and to inspect them precisely. Tables: `variables`, `depends_on`, `rollups`, `decisions`. |

## How it works

- **Realtime population**: every message (user / assistant / tool result) is
  stored as a variable the moment it happens — full content, kind, size, in
  message order. This is content capture only: no summaries, no decisions.
- **Context management at compaction only**: `session_before_compact` builds a
  candidate packet (sampled messages, existing variables, pin states,
  main-agent decisions, active archive summaries); the compaction agent decides
  pin / archive / drop and returns a structured state snapshot. The extension
  deterministically renders current task, current state, constraints, decisions,
  open work, active topics, a memory index, and verbatim pins. It does not emit
  one archive bullet per message. Variables keep their realtime ids and seq.
- Completeness guarantee: every candidate ends in exactly one state
  (pin / archive / drop); unhandled candidates default to archive.
- Cache-friendly: one context rewrite per compaction; summaries are written
  once and never rewritten; mutable content sits late in the context.

## Install

Published on npm as `pi-ctx-vars`:

```bash
pi install npm:pi-ctx-vars            # install globally (user settings)
pi install -l npm:pi-ctx-vars         # install for the current project
pi -e npm:pi-ctx-vars                 # try it for one run, no install
```

Or from source:

```bash
pi -e /path/to/pi-ctx-vars/extension/index.ts
```

Dependencies: Node 22+ (uses `node:sqlite`).
## Settings (`contextVars` in `~/.pi/agent/settings.json` or `.pi/settings.json`)

| Key | Default | Meaning |
|---|---|---|
| `enabled` | `true` | Master switch |
| `realtimePopulation` | `true` | Store every message as a variable as it happens (content only); disable with `false` or `CTXV_REALTIME=0` |
| `archiveKeepIndividual` | `30` | Keep this many archive summaries individually before rolling up |
| `summaryMaxChars` | `500` | Per-entry archive summary cap |
| `summaryTokenBudget` | `3500` | Visible state-snapshot target (tokens), excluding pins |
| `snapshotMaxTopics` | `10` | Maximum synthesized active-topic sections |
| `rollupMaxChars` | `2000` | Historical rollup summary cap |
| `packetTokenBudget` | `15000` | Compaction-agent input packet budget (tokens) |
| `compactionModel` | `null` | `"provider/model"` for the compaction agent (default: session model) |
| `compactionMaxTokens` | `4000` | Compaction agent output cap |
| `pinnedMaxChars` | `40000` | Warning threshold for large pins; pins are not truncated |
| `debugLogPath` | `null` | Write a debug log (also `CTXV_DEBUG=1` + `CTXV_DEBUG_LOG`) |

Env overrides: `CTXV_*` (see `extension/config.ts`).

## Architecture

See `../ARCHITECTURE.md` and the session design notes. The extension is a port
of the "variable-based context management" design (RLM-style agent-controlled
retention) onto pi's extension API.
