pi-blackhole 0.3.2 → 0.3.4

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.
package/README.md CHANGED
@@ -1,9 +1,18 @@
1
1
  # pi-blackhole
2
2
 
3
- > [!NOTE]
4
- > **For blackhole to handle all compaction automatically**, set `"overrideDefaultCompaction": true` in your config at
5
- > `~/.pi/agent/pi-blackhole/pi-blackhole-config.json`. Without this, blackhole stays out of Pi's compaction by default
6
- > and only activates via the `/blackhole` command.
3
+ > [!IMPORTANT]
4
+ > **Blackhole is the default compaction engine** (`compactionEngine: "blackhole"`, `compaction: "auto"`). Auto-compaction fires at the configured threshold using blackhole's pipeline — both auto-trigger and Pi's `/compact` command use it. No additional setup needed. To work automatically, blackhole needs to register its hook so it overrides /compact with the `blackhole` compaction engine. Opting out or opting for manual compaction with blackhole can be done as below:
5
+ >
6
+ > | Setting | Auto-trigger after threshold | `/compact` (Pi built-in) |
7
+ > |---|---|---|
8
+ > | `"auto"` + `"blackhole"` (default) | blackhole handles ✓ | blackhole handles |
9
+ > | `"auto"` + `"pi-default"` | Pi handles | Pi handles |
10
+ > | `"manual"` + any | skipped | Pi handles ✓ |
11
+ > | `"off"` + any | skipped (Pi handles) | Pi handles ✓ |
12
+ >
13
+ > The `/blackhole` command always uses blackhole's pipeline regardless of settings.
14
+ >
15
+ > **Upgrading from an older version?** This version replaces legacy keys (`passive`, `noAutoCompact`, `overrideDefaultCompaction`) with `compaction`, `compactionEngine`, and `tailBehavior`. Automatic migration runs at startup — old configs continue to work. Best effort was made to preserve existing behavior, but review [`MIGRATION-GUIDE.md`](MIGRATION-GUIDE.md) if something behaves differently.
7
16
  >
8
17
  > See [`CONFIG.md`](CONFIG.md) for the full reference.
9
18
 
@@ -13,25 +22,12 @@ Blackhole merges the best ideas from [pi-vcc](https://github.com/sting8k/pi-vcc)
13
22
 
14
23
  > **Why this exists:** I liked both extensions but they fought each other — OM hooked into Pi's default compaction and blocked vcc from working. So I merged them, made them share a single hook and output, and added everything both were missing: fallback chains, cooldowns, a memory toggle, and a manual mode for people who want to control when context gets compressed.
15
24
  >
16
- > The codebase has since diverged heavily from both upstreams, but tries to keep up-to-date with any fixes from them..
17
-
18
- > [!IMPORTANT]
19
- > **Auto-compaction behavior & configuration**
20
- >
21
- > Blackhole's auto-compaction **only activates when explicitly opted in**. By default (`overrideDefaultCompaction: false`), blackhole stays out of Pi's compaction — Pi handles its own automatically, and blackhole's `/blackhole` command still works manually.
22
- >
23
- > Configure via your Pi agent's `config.json`:
24
- >
25
- > | What you want | `overrideDefaultCompaction` | `noAutoCompact` |
26
- > |---|---|---|
27
- > | Blackhole auto-compacts at your threshold | `true` | `false` |
28
- > | Pi handles auto-compaction (default) | `false` | `false` |
29
- > | Manual only — use `/blackhole` | any | `true` |
30
- >
31
- > See [`CONFIG.md`](CONFIG.md) for the full reference.
25
+ > The codebase has since diverged heavily from both upstreams, but tries to keep up-to-date with any fixes from them.
32
26
 
33
27
  📖 See [`CHANGELOG.md`](CHANGELOG.md) for release history.
34
28
  ⚙️ See [`CONFIG.md`](CONFIG.md) for the full configuration reference.
29
+ 🔄 See [`MIGRATION-GUIDE.md`](MIGRATION-GUIDE.md) if upgrading from an older version.
30
+ 📜 See [`OLD_CONFIG.md`](OLD_CONFIG.md) for the legacy config documentation.
35
31
 
36
32
  ---
37
33
 
@@ -66,9 +62,13 @@ pi-blackhole tracks both upstream repositories via a [lockstep audit system](.pi
66
62
 
67
63
  ## Demo
68
64
 
69
- `/blackhole` collapses ~94k tokens of conversation into a ~7.8k structured summary (YMMV based on your settings). `/blackhole-memory` shows pipeline status. `/blackhole-recall` searches history the agent can also reach via its `recall` tool.
65
+ `/blackhole` collapses ~143k tokens of conversation into a ~6.3k structured summary (YMMV based on your settings). `/blackhole-memory` shows pipeline status. `/blackhole-recall` searches history the agent can also reach via its `recall` tool and incrementally search previous conversation history.
66
+
67
+
68
+
69
+ https://github.com/user-attachments/assets/a7dd804d-6aca-4bdb-8b6e-0dd779363a43
70
+
70
71
 
71
- https://github.com/user-attachments/assets/ab7c5787-1bbd-466f-a231-0818e68e9f39
72
72
 
73
73
 
74
74
  ---
@@ -86,28 +86,6 @@ The two upstream projects each solve one half:
86
86
 
87
87
  **pi-blackhole** puts vcc in the compaction slot and OM in the memory layer, where each does what it's designed for.
88
88
 
89
-
90
- ---
91
-
92
- ## Feature comparison
93
-
94
- | | pi-blackhole | pi-vcc | pi-obs-memory | Pi default |
95
- |---|---|---|---|---|
96
- | Algorithmic compaction (no LLM cost) | ✓ | ✓ | — | — |
97
- | Deterministic output | ✓ | ✓ | — | — |
98
- | Structured summary sections | ✓ | ✓ | — | — |
99
- | Observations + reflections | ✓ | — | ✓ | — |
100
- | Context survives across compactions | ✓ | — | ✓ | — |
101
- | Background memory workers | ✓ | — | ✓ | — |
102
- | Searchable history after compaction | ✓ | ✓ | partial | — |
103
- | Per-worker model config | ✓ | — | — | — |
104
- | Fallback model chains + persisted cooldowns | ✓ | — | — | — |
105
- | Manual flush mode (`noAutoCompact`) | ✓ | — | — | — |
106
- | Memory toggle (`/blackhole om-off`) | ✓ | — | — | — |
107
- | Unified single-file config | ✓ | — | — | — |
108
- | Per-session pending state | ✓ | — | — | — |
109
-
110
-
111
89
  ---
112
90
 
113
91
  ## How it works
@@ -121,7 +99,7 @@ The agent receives a deterministic recap of recent work *plus* durable facts fro
121
99
 
122
100
  ### The three memory workers
123
101
 
124
- Three background workers run automatically during the session (when `memory: true`, which is the default):
102
+ Three background workers (separate LLM calls) run automatically during the session (when `memory: true`, which is the default):
125
103
 
126
104
  - **Observer** — reads conversation since the last observation marker and extracts timestamped facts: events, decisions, preferences. Input is capped to `observerChunkMaxTokens` newest-first to prevent context blowup on long sessions. Runs most frequently.
127
105
  - **Reflector** — distills new observations into durable reflections: stable facts, patterns, and constraints that survive future compactions. Runs less often.
@@ -203,7 +181,7 @@ When exact source context is needed for precision or traceability, use the `reca
203
181
  ----
204
182
  ```
205
183
 
206
- > **Note:** The OM injection format uses `## Reflections` and `## Observations` Markdown headers with a preamble and footer. Each observation and reflection has a 12-char hex identifier you can use with the `recall` tool to recover source evidence.
184
+ > **Note:** The OM injection format uses `## Reflections` and `## Observations` Markdown headers with a preamble and footer. Each observation and reflection has a 12-char hex identifier you can use with the `recall` tool to recover source evidence, as well as the agent can search based on them and get relevant context back.
207
185
 
208
186
  ---
209
187
 
@@ -212,11 +190,11 @@ When exact source context is needed for precision or traceability, use the `reca
212
190
  Two modes, one shared goal: keep your agent's context sharp without manual housekeeping.
213
191
 
214
192
  - **Auto mode (default):** install and forget. Workers run, observations are appended as invisible conversation markers, compaction fires automatically when tokens exceed threshold.
215
- - **Manual mode (`noAutoCompact: true` — the maintainer's daily driver):** same workers, same pipeline. But observations go to per-session disk buffers and compaction only happens when you run `/blackhole`. Cleaner conversation, manual schedule.
193
+ - **Manual mode (`compaction: "manual"` — the maintainer's daily driver):** same workers, same pipeline. But observations go to per-session disk buffers and compaction only happens when you run `/blackhole`. Cleaner conversation, manual schedule.
216
194
 
217
195
  The tradeoff is simplicity vs cleanliness:
218
196
 
219
- | | Auto (default) | Manual (`noAutoCompact: true`) |
197
+ | | Auto (default) | Manual (`compaction: "manual"`) |
220
198
  |---|---|---|
221
199
  | Workers run? | Yes | Yes |
222
200
  | Observations go to | Conversation markers (invisible in TUI) | Disk (`<sessionId>-pending.json`) |
@@ -234,15 +212,15 @@ The difference from Pi's built-in `/compact`:
234
212
  - `/compact` calls an LLM to write a free-form summary — costly, lossy, no memory layer.
235
213
  - `/blackhole` uses algorithmic section extraction (goals, files, commits, preferences...) plus injects observations/reflections from the session ledger. No LLM involved in the compaction itself. Fast, deterministic, memory-preserving.
236
214
 
237
- ### Passive mode
215
+ ### Fully disabled
238
216
 
239
- Set `passive: true` (or the environment variable `PI_BLACKHOLE_PASSIVE=true`) to completely disable all background workers AND auto-compaction. The extension becomes a no-op until you explicitly run `/blackhole`. This is useful for debugging or if you want zero background activity.
217
+ Set `compaction: "off"` and `memory: false` (or the environment variable `PI_BLACKHOLE_PASSIVE=true` which sets both) to completely disable all background workers and blackhole's auto-compaction trigger. Pi handles auto-compaction normally. Explicit `/blackhole` still uses blackhole's pipeline. This is useful for debugging or if you want manual-only blackhole involvement.
240
218
 
241
219
  ### Without observational memory (vcc-only)
242
220
 
243
221
  Set `memory: false` or run `/blackhole om-off` for pure vcc compaction — no background workers, no memory injection. The compaction still uses the algorithmic vcc pipeline (not Pi's LLM-based compaction). Re-enable with `/blackhole om-on` or setting `memory: true`.
244
222
 
245
- This is a lighter alternative to `passive`: workers are off but auto-compaction still runs.
223
+ This is a lighter alternative to `compaction: "off"`: workers are off but blackhole's compaction engine still handles compaction.
246
224
 
247
225
  ---
248
226
 
@@ -250,7 +228,7 @@ This is a lighter alternative to `passive`: workers are off but auto-compaction
250
228
 
251
229
  | Command | What it does |
252
230
  |---|---|
253
- | `/blackhole` | Compact the conversation. Subcommands: `om-off` / `om-on` toggle observational memory. |
231
+ | `/blackhole` | Compact the conversation. Subcommands: `configure` (settings overlay), `om-off` / `om-on` toggle observational memory. |
254
232
  | `/blackhole-memory` (or `status`) | Pipeline status: token progress, observation/reflection counts, pending data, last errors |
255
233
  | `/blackhole-memory view` | Show visible observations and reflections (after compaction trimming), copied to clipboard |
256
234
  | `/blackhole-memory full` | Show ALL recorded memory (including dropped observations), copied to clipboard |
@@ -276,7 +254,7 @@ The agent gets a unified `recall` tool that handles three types of input:
276
254
 
277
255
  ## Configuration
278
256
 
279
- All settings in a single JSON file: **`~/.pi/agent/pi-blackhole/pi-blackhole-config.json`** — auto-created with defaults on first startup. See [`CONFIG.md`](CONFIG.md) for the full reference with detailed explanations for every knob. An annotated example config is at [`example-config.json`](example-config.json).
257
+ All settings in a single JSON file: **`~/.pi/agent/pi-blackhole/pi-blackhole-config.json`** — auto-created with defaults on first startup. See [`CONFIG.md`](CONFIG.md) for the full reference with detailed explanations for every knob. An annotated example config with the new config surface is at [`example-config-v2.json`](example-config-v2.json). The legacy example is at [`example-config.json`](example-config.json).
280
258
 
281
259
  Quick start — just set custom models (if you want):
282
260
 
@@ -288,27 +266,28 @@ Quick start — just set custom models (if you want):
288
266
  }
289
267
  ```
290
268
 
291
- That's it. Everything else has sensible defaults.
269
+ Everything else has sensible defaults.
292
270
 
293
271
  ### Settings at a glance
294
272
 
295
273
  | Setting | Default | What it controls |
296
274
  |---|---|---|
297
- | `overrideDefaultCompaction` | `false` | Route ALL Pi compactions through blackhole, not just explicit `/blackhole` |
298
- | `noAutoCompact` | `false` | Manual mode: save observations to disk, disable auto-compaction |
299
- | `memory` | `true` | `false` = vcc only, no workers, no OM injection |
300
- | `passive` | `false` | Disable all workers AND auto-compaction entirely |
275
+ | `compaction` | `"auto"` | When compaction triggers: `"auto"` (blackhole auto-fires), `"manual"` (only `/blackhole`), `"off"` (Pi handles auto + `/compact`, `/blackhole` still works) |
276
+ | `compactionEngine` | `"blackhole"` | Which engine handles auto-compaction: `"blackhole"` or `"pi-default"`. Only meaningful when `compaction: "auto"` — for `"manual"`/`"off"` the hook lets Pi handle everything except `/blackhole` |
277
+ | `tailBehavior` | `"minimal"` | How much of the transcript stays visible after compaction: `"minimal"` (last user message only, default) or `"pi-default"` (gentle, ~20k tokens) |
278
+ | `memory` | `true` | `false` = OM workers off + no memory injection (compaction still runs) |
301
279
  | `model` | — | Base fallback model for all workers (last resort before session model) |
302
280
  | `observerModel` / `observerFallbackModels` | — / `[]` | Primary + fallback models for observer (extracts facts) |
303
281
  | `reflectorModel` / `reflectorFallbackModels` | — / `[]` | Primary + fallback models for reflector (synthesizes reflections) |
304
282
  | `dropperModel` / `dropperFallbackModels` | — / `[]` | Primary + fallback models for dropper (prunes observations) |
305
283
  | *(per model)* `thinking` | `"low"` | Thinking/reasoning level: `off`, `minimal`, `low`, `medium`, `high`, `xhigh` |
306
284
  | *(per model)* `cooldownHours` | `1` | How long to skip this model after a retryable error |
285
+ | *(per model)* `contextWindow` | *(inherited from Pi)* | Override context window for this model. If unset, inherits from Pi's model registry. When set, the OM pipeline checks if the estimated input fits before calling the model — if not, the next fallback is tried. |
307
286
  | `observeAfterTokens` | `15000` | Min accumulated tokens before observer runs |
308
287
  | `reflectAfterTokens` | `25000` | Min accumulated tokens before reflector + dropper run |
309
- | `compactAfterTokens` | `81000` | Auto-compaction threshold (when `noAutoCompact` is `false`) |
288
+ | `compactAfterTokens` | `81000` | Auto-compaction threshold (when `compaction: "auto"`) |
310
289
  | `observerChunkMaxTokens` | `40000` | Max observer input per run (newest-first) |
311
- | `observerPreambleMaxTokens` | `0` (auto) | Preamble cap for observer in `noAutoCompact` mode (auto = 30% of chunk) |
290
+ | `observerPreambleMaxTokens` | `0` (auto) | Preamble cap for observer in `compaction: "manual"` mode (auto = 30% of chunk) |
312
291
  | `observationsPoolMaxTokens` | `20000` | Max active observation pool before dropper prunes |
313
292
  | `observationsPoolTargetTokens` | `10000` | Target size dropper aims for after pruning (derived: half of pool max) |
314
293
  | `reflectorInputMaxTokens` | `80000` | Max reflector input budget |
@@ -317,7 +296,7 @@ That's it. Everything else has sensible defaults.
317
296
  | `debug` | `false` | Pre-compaction snapshot to `/tmp/pi-blackhole-debug.json` |
318
297
  | `debugLog` | `false` | Continuous JSONL debug log to `~/.pi/agent/pi-blackhole/debug.ndjson` |
319
298
 
320
- **Environment override:** `PI_BLACKHOLE_PASSIVE=true` disables all workers without touching the config file.
299
+ **Environment override:** `PI_BLACKHOLE_PASSIVE=true` sets `compaction: "off"` + `memory: false` without touching the config file. Also accepts legacy `PI_VCC_OM_PASSIVE` / `PI_OBSERVATIONAL_MEMORY_PASSIVE`.
321
300
 
322
301
  ### Configuration presets
323
302
 
@@ -502,6 +481,28 @@ Results are shown as a collapsible message and auto-fed to the agent as context.
502
481
 
503
482
  **Touched mode** (`mode:touched`) aggregates all files written, edited, or read across the session, grouped by path. Each entry shows which tool operation touched the file and the line count. Useful for getting a lay of the land after a long session.
504
483
 
484
+ ---
485
+
486
+ ## Feature comparison
487
+
488
+ | | pi-blackhole | pi-vcc | pi-obs-memory | Pi default |
489
+ |---|---|---|---|---|
490
+ | Algorithmic compaction (no LLM cost) | ✓ | ✓ | — | — |
491
+ | Deterministic output | ✓ | ✓ | — | — |
492
+ | Structured summary sections | ✓ | ✓ | — | — |
493
+ | Observations + reflections | ✓ | — | ✓ | — |
494
+ | Context survives across compactions | ✓ | — | ✓ | — |
495
+ | Background memory workers | ✓ | — | ✓ | — |
496
+ | Searchable history after compaction | ✓ | ✓ | partial | — |
497
+ | Per-worker model config | ✓ | — | — | — |
498
+ | Fallback model chains + persisted cooldowns | ✓ | — | — | — |
499
+ | Manual flush mode (`compaction: "manual"`) | ✓ | — | — | — |
500
+ | Memory toggle (`/blackhole om-off`) | ✓ | — | — | — |
501
+ | Unified single-file config | ✓ | — | — | — |
502
+ | Per-session pending state | ✓ | — | — | — |
503
+
504
+ ---
505
+
505
506
  ## Uninstall
506
507
 
507
508
  ```bash
@@ -522,7 +523,7 @@ What blackhole adds and reworks on top:
522
523
 
523
524
  - **Unified configuration** — one JSON file, not two
524
525
  - **Per-worker model fallback chains** with persisted cooldowns that survive Pi restarts
525
- - **Manual flush mode** — `noAutoCompact` saves observations to per-session disk buffers
526
+ - **Manual flush mode** — `compaction: "manual"` saves observations to per-session disk buffers
526
527
  - **Conflict resolution** — OM hooks into vcc's compaction, not Pi's default
527
528
  - **Memory toggle** (`/blackhole om-off` / `/blackhole om-on`) — disable the memory layer without uninstalling
528
529
  - **Per-session pending state** — isolated per-session JSON files, no cross-session contamination
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-blackhole",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "packageManager": "pnpm@11.2.2",
5
5
  "description": "Unified compaction + observational memory extension for Pi — compresses conversation context while preserving durable observations and reflections",
6
6
  "license": "MIT",
@@ -1,8 +1,8 @@
1
1
  /**
2
- * /memory command — shows memory pipeline status and content.
2
+ * /blackhole-memory command — shows memory pipeline status and content.
3
3
  *
4
4
  * Created by pi-vcc-om. Replaces OM's standalone /om-status and /om-view.
5
- * Usage: /memory (status), /memory view, /memory full.
5
+ * Usage: /blackhole-memory [status|view|full]
6
6
  */
7
7
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
8
8
  import { copyTextToClipboard } from "../om/clipboard.js";
@@ -79,7 +79,7 @@ export function registerMemoryCommand(pi: ExtensionAPI, runtime: Runtime): void
79
79
  const sessionId = ctx.sessionManager.getSessionId();
80
80
  const mode = firstArg(args);
81
81
 
82
- // /memory full — show full recorded memory + copy to clipboard
82
+ // /blackhole-memory full — show full recorded memory + copy to clipboard
83
83
  if (mode === "full") {
84
84
  const projection = fullProjection(entries);
85
85
  const output = renderContentOnlyProjection(projection, "recorded");
@@ -91,7 +91,7 @@ export function registerMemoryCommand(pi: ExtensionAPI, runtime: Runtime): void
91
91
  return;
92
92
  }
93
93
 
94
- // /memory view — show visible memory + copy to clipboard
94
+ // /blackhole-memory view — show visible memory + copy to clipboard
95
95
  if (mode === "view") {
96
96
  const projection = visibleProjection(entries);
97
97
  const output = renderContentOnlyProjection(projection, "visible");
@@ -103,7 +103,7 @@ export function registerMemoryCommand(pi: ExtensionAPI, runtime: Runtime): void
103
103
  return;
104
104
  }
105
105
 
106
- // /memory (no args) — show status
106
+ // /blackhole-memory (no args) — show status
107
107
  if (mode && mode !== "status") {
108
108
  ctx.ui.notify("Usage: /blackhole-memory [status|view|full]", "info");
109
109
  return;
@@ -8,9 +8,10 @@
8
8
  */
9
9
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
10
10
  import type { Runtime } from "../om/runtime.js";
11
- import { PI_VCC_COMPACT_INSTRUCTION } from "../hooks/before-compact";
12
- import { saveUnifiedConfig } from "../core/unified-config.js";
11
+ import { PI_VCC_COMPACT_INSTRUCTION, notifyMigrationReminder } from "../hooks/before-compact";
12
+ import { saveUnifiedConfig, configPath } from "../core/unified-config.js";
13
13
  import { readPendingState, clearPendingState, hasPendingData } from "../om/pending.js";
14
+ import { createConfigureOverlay } from "../om/configure-overlay.js";
14
15
  import {
15
16
  OM_OBSERVATIONS_DROPPED,
16
17
  OM_OBSERVATIONS_RECORDED,
@@ -23,15 +24,50 @@ const formatTokens = (n: number): string => {
23
24
  };
24
25
 
25
26
  export const registerPiVccCommand = (pi: ExtensionAPI, runtime: Runtime) => {
27
+ const fuzzyMatch = (value: string, prefix: string): boolean => {
28
+ const q = prefix.toLowerCase();
29
+ let qi = 0;
30
+ for (const ch of value) {
31
+ if (qi < q.length && ch === q[qi]) qi++;
32
+ if (qi === q.length) return true;
33
+ }
34
+ return false;
35
+ };
36
+
26
37
  pi.registerCommand("blackhole", {
27
38
  description:
28
39
  "Compact conversation — structured summary (with observational memory when enabled). " +
29
- "Subcommands: /blackhole om-off (disable memory), /blackhole om-on (re-enable memory).",
40
+ "Subcommands: /blackhole configure (open settings overlay), " +
41
+ "/blackhole om-off (disable memory), /blackhole om-on (re-enable memory).",
42
+ getArgumentCompletions: (prefix: string) => {
43
+ const subcommands = [
44
+ { value: "configure", label: "Open configuration overlay to edit settings [configure]" },
45
+ { value: "om-off", label: "Disable observational memory [om-off]" },
46
+ { value: "om-on", label: "Enable observational memory [om-on]" },
47
+ ];
48
+ if (!prefix) return subcommands;
49
+ return subcommands.filter((s) => fuzzyMatch(s.value, prefix));
50
+ },
30
51
  handler: async (args, ctx) => {
31
52
  const sessionId = ctx.sessionManager.getSessionId();
32
53
 
33
- // Handle om-off / om-on subcommands
54
+ // Handle subcommands
34
55
  const trimmed = (typeof args === "string" ? args : "").trim();
56
+ if (trimmed === "configure") {
57
+ // Open the config overlay
58
+ const result = await ctx.ui.custom<{ saved: boolean; path: string } | undefined>(
59
+ (tui, theme, _kb, done) => createConfigureOverlay(configPath(), theme, tui, done),
60
+ { overlay: true },
61
+ );
62
+ if (result) {
63
+ if (result.saved) {
64
+ ctx.ui.notify("Configuration saved.", "info");
65
+ } else {
66
+ ctx.ui.notify("Failed to save configuration — the config file may be read-only (e.g., managed by Nix).", "warning");
67
+ }
68
+ }
69
+ return;
70
+ }
35
71
  if (trimmed === "om-off") {
36
72
  const saved = saveUnifiedConfig({ memory: false });
37
73
  runtime.config.memory = false;
@@ -61,9 +97,9 @@ export const registerPiVccCommand = (pi: ExtensionAPI, runtime: Runtime) => {
61
97
  return;
62
98
  }
63
99
 
64
- // If noAutoCompact: flush pending OM entries into the branch
65
- // before compacting so the summary includes accumulated memory.
66
- if (runtime.config.noAutoCompact && hasPendingData(sessionId)) {
100
+ // If compaction is manual (or legacy noAutoCompact): flush pending OM entries
101
+ // into the branch before compacting so the summary includes accumulated memory.
102
+ if (runtime.config.compaction === "manual" && hasPendingData(sessionId)) {
67
103
  const pending = readPendingState(sessionId);
68
104
  // Write all accumulated observation batches (or latest single batch
69
105
  // as fallback for legacy pending.json without batch arrays).
@@ -105,6 +141,7 @@ export const registerPiVccCommand = (pi: ExtensionAPI, runtime: Runtime) => {
105
141
  } else {
106
142
  ctx.ui.notify("Compacted with blackhole", "info");
107
143
  }
144
+ notifyMigrationReminder(sessionId, (msg, level) => ctx.ui.notify(msg, level as any));
108
145
  },
109
146
  onError: (err) => {
110
147
  if (err.message === "Compaction cancelled" || err.message === "Already compacted") {
@@ -7,17 +7,32 @@
7
7
  import { loadUnifiedConfig, scaffoldConfig } from "./unified-config.js";
8
8
 
9
9
  export interface PiVccSettings {
10
- /** When true, pi-vcc handles all compactions. */
10
+ /** @deprecated Use compactionEngine instead. */
11
11
  overrideDefaultCompaction: boolean;
12
+ /** @deprecated Use compaction instead. */
13
+ noAutoCompact: boolean;
14
+ /** @deprecated Use compaction + memory instead. */
15
+ passive: boolean;
12
16
  /** Write debug snapshots to /tmp/pi-blackhole-debug.json. */
13
17
  debug: boolean;
18
+ /** Unified compaction control: "auto" | "manual" | "off". */
19
+ compaction: "auto" | "manual" | "off";
20
+ /** Compaction engine: "blackhole" | "pi-default". */
21
+ compactionEngine: "blackhole" | "pi-default";
22
+ /** Visible tail behavior: "pi-default" | "minimal". */
23
+ tailBehavior: "pi-default" | "minimal";
14
24
  }
15
25
 
16
26
  export function loadSettings(): PiVccSettings {
17
27
  const config = loadUnifiedConfig(process.cwd());
18
28
  return {
19
- overrideDefaultCompaction: config.overrideDefaultCompaction,
29
+ overrideDefaultCompaction: config.overrideDefaultCompaction ?? false,
30
+ noAutoCompact: config.noAutoCompact ?? false,
31
+ passive: config.passive ?? false,
20
32
  debug: config.debug,
33
+ compaction: config.compaction,
34
+ compactionEngine: config.compactionEngine,
35
+ tailBehavior: config.tailBehavior,
21
36
  };
22
37
  }
23
38