README.md
  1  # grounded-compaction
  2  
  3  This extension can play two roles:
  4  * Replace Pi's compaction summarizer with configurable model presets, custom summarization prompt contracts, and deterministic files-touched tracking that covers Pi native tools, RepoPrompt, and bash-derived file operations
  5  * Augment branch summarization during `/tree` with the same files-touched grounding and optional replacement of the summarization prompt contract with a custom one
  6  
  7  > ⚠ **May conflict with other compaction extensions**: this extension hooks `session_before_compact` and returns a custom compaction result.  Any other extension that does the same (e.g. `agentic-compaction`) is incompatible.  Having both active creates a race condition where the last handler to respond wins.  Enable only one.
  8  
  9  ## Why
 10  
 11  Pi's native compaction [deterministically tracks](https://github.com/badlogic/pi-mono/blob/629341c18f3482d891b665a844975096b47b4779/packages/coding-agent/src/core/compaction/utils.ts#L74-L79) file activity from its built-in `read`, `write`, and `edit` tool calls.  Operations through bash or custom tools like RepoPrompt are invisible to it.  This extension uses a [shared collector](../../../packages/pi-files-touched/README.md) (`extensions/_shared/files-touched-core.ts`) that also covers RepoPrompt tools (`read_file`, `apply_edits`, `file_actions`, `git mv/rm`), bash patterns (`sed -i`, `mv`, `rm`, shell redirections, etc.), and normalizes all path spellings so the same file appears once regardless of how different tools referred to it.
 12  
 13  Since compaction also [serializes messages to text](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/compaction.md#message-serialization) before summarizing, which entails that there is no prefix-cache opportunity cost to routing compaction to a cheaper or faster model, you may want to be able to do that sometimes or as a default policy.  The "presets" grant that option.
 14  
 15  ## Compaction and branch summarization
 16  
 17  For background on Pi's compaction lifecycle, see the [compaction docs](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/compaction.md).  Branch summarization is the summary generated when navigating `/tree` — effectively compaction in any direction across the session tree, rather than just forward along a session's chronology.  This extension augments both.
 18  
 19  ## Files
 20  
 21  - **Config**: `config.json` (see `config.json.example` for presets)
 22  - **Compaction prompt**: `compaction-prompt.md` (falls back to default embedded in [`index.ts`](index.ts) if blank or missing)
 23  - **Branch-summary prompt**: `branch-summary-prompt.md` (falls back to Pi's stock branch summarization prompt if blank or missing)
 24  - Examples: `compaction-prompt.md.example`, `branch-summary-prompt.md.example`
 25  
 26  ## Config
 27  
 28  ```json
 29  {
 30    "includeFilesTouched": {
 31      "inCompactionSummary": true,
 32      "inBranchSummary": true
 33    },
 34    "defaultPreset": "current",
 35    "presets": {}
 36  }
 37  ```
 38  
 39  ### `includeFilesTouched`
 40  
 41  Controls files-touched grounding per feature.  Accepts `true`, `false`, or an object with both fields required:
 42  
 43  ```json
 44  { "inCompactionSummary": true, "inBranchSummary": false }
 45  ```
 46  
 47  Boolean applies to both; omitted defaults to both enabled.
 48  
 49  For compaction, the manifest is passed into the summarizer prompt and a cumulative version is appended verbatim to the persisted summary.  For branch summaries, the manifest is injected into the prompt instructions for Pi's native summarizer to reproduce.  In both cases, the manifest also serves as a recall aid for the summarizer itself — file operations buried across many tool calls in a long context are easy to miss without an authoritative inventory.
 50  
 51  ### `defaultPreset` and `presets`
 52  
 53  These are compaction-only.  `defaultPreset` controls which model runs `/compact` by default; an explicit `--preset <name>` or `-p <name>` always overrides it.
 54  
 55  ```json
 56  {
 57    "defaultPreset": "fast",
 58    "presets": {
 59      "fast": { "model": "openai-codex/gpt-5.4-mini", "thinkingLevel": "low" },
 60      "deep": { "model": "anthropic/claude-opus-4-6", "thinkingLevel": "high" }
 61    }
 62  }
 63  ```
 64  
 65  `"current"` uses the session's active model and thinking level.  Preset lookup is deterministic: exact match → case-insensitive → prefix → normalized substring.  Failed lookups fall back to the current session model with a warning.
 66  
 67  ## `/compact` usage
 68  
 69  ```text
 70  /compact
 71  /compact focus on parser regressions
 72  /compact --preset cheap
 73  /compact -p deep focus on parser regressions
 74  ```
 75  
 76  Only a leading `--preset` / `-p` is special; everything after is freeform focus text passed to the summarizer.  `--preset current` / `-p current` explicitly uses the session model even when `defaultPreset` names something else.
 77  
 78  ## Branch-summary augmentation
 79  
 80  During `/tree`, if the user chooses to summarize:
 81  
 82  - If `branch-summary-prompt.md` has content, it replaces Pi's stock branch-summary instructions
 83  - If files-touched grounding is enabled, the manifest is injected with instructions to reproduce it verbatim
 84  - If neither is active, the extension does nothing and Pi's stock flow runs unmodified
 85  - On any failure, the extension returns nothing and Pi's stock flow proceeds
 86  
 87  The user's freeform focus text from the `/tree` prompt is preserved in either mode.
 88  
 89  ### Why branch-summary control is narrower than compaction
 90  
 91  For compaction, this extension fully owns the LLM call: it can select a different model via presets, control thinking level independently, and manage token budgets.  A session running Opus with a high thinkingLevel can compact cheaply with Gemini Flash.
 92  
 93  For branch summaries, Pi's `session_before_tree` hook only exposes prompt instruction overrides.  The extension cannot control model selection, thinking level, or token budgeting for branch summaries without mutating persistent session state.  Native branch summarization always uses the current session model with a fixed `maxTokens` of 2048 and no explicit reasoning level -- the thinking overhead is minimal, but the per-token cost of the base model still applies.  At this time of writing there is no way to select a cheaper model for branch summaries from an extension.
 94  
 95  ## How compaction summaries are structured
 96  
 97  The extension mirrors Pi's stock compaction boundaries: `messagesToSummarize` for history, `turnPrefixMessages` for split-turn prefixes, and `previousSummary` for cumulative updates.  On repeated compactions, that means resuming from the previous compaction's `firstKeptEntryId`, not from the compaction entry itself, and the files-touched manifests follow that same boundary.  When files-touched is enabled, manifests are passed to the summarizer per-span and a cumulative whole-branch manifest is appended to the final persisted summary:
 98  
 99  ````md
100  ---
101  
102  ## Files touched (cumulative)
103  R=read, W=write, E=edit, M=move/rename, D=delete
104  
105  ```text
106  RE src/foo.ts
107  W  src/bar.ts
108  ```
109  ````
110  
111  `compaction.details` records the model and thinking level that actually ran:
112  
113  ```ts
114  { model: "provider/modelId", thinkingLevel?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" }
115  ```
116  
117  ## Failure policy
118  
119  **Compaction**: failed presets fall back to the session model.  If the session model also fails after an explicit preset directive, compaction is cancelled to avoid leaking raw directive text.  Aborts return cancellation quietly.
120  
121  **Branch summary**: any failure returns `undefined` with a warning, letting Pi's stock flow proceed.
122  
123  For npm installation and package-specific docs, see [`packages/pi-grounded-compaction/README.md`](../../packages/pi-grounded-compaction/README.md)