pi-blackhole 0.3.1 → 0.3.3

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,15 +1,33 @@
1
1
  # pi-blackhole
2
2
 
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.
16
+ >
17
+ > See [`CONFIG.md`](CONFIG.md) for the full reference.
18
+
3
19
  **Algorithmic compaction + session-aware observational memory for [Pi](https://github.com/badlogic/pi-mono) — in one unified extension.**
4
20
 
5
21
  Blackhole merges the best ideas from [pi-vcc](https://github.com/sting8k/pi-vcc) and [pi-observational-memory](https://github.com/elpapi42/pi-observational-memory) into something that's become its own beast entirely. Deterministic compaction that costs nothing. A memory layer that survives compactions. Per-worker model fallback chains with persisted cooldowns. Manual flush mode. All configured from one JSON file.
6
22
 
7
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.
8
24
  >
9
- > The codebase has since diverged heavily from both upstreams, but tries to keep up-to-date with any fixes from them..
25
+ > The codebase has since diverged heavily from both upstreams, but tries to keep up-to-date with any fixes from them.
10
26
 
11
27
  📖 See [`CHANGELOG.md`](CHANGELOG.md) for release history.
12
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.
13
31
 
14
32
  ---
15
33
 
@@ -44,9 +62,13 @@ pi-blackhole tracks both upstream repositories via a [lockstep audit system](.pi
44
62
 
45
63
  ## Demo
46
64
 
47
- `/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
+
48
71
 
49
- https://github.com/user-attachments/assets/ab7c5787-1bbd-466f-a231-0818e68e9f39
50
72
 
51
73
 
52
74
  ---
@@ -64,28 +86,6 @@ The two upstream projects each solve one half:
64
86
 
65
87
  **pi-blackhole** puts vcc in the compaction slot and OM in the memory layer, where each does what it's designed for.
66
88
 
67
-
68
- ---
69
-
70
- ## Feature comparison
71
-
72
- | | pi-blackhole | pi-vcc | pi-obs-memory | Pi default |
73
- |---|---|---|---|---|
74
- | Algorithmic compaction (no LLM cost) | ✓ | ✓ | — | — |
75
- | Deterministic output | ✓ | ✓ | — | — |
76
- | Structured summary sections | ✓ | ✓ | — | — |
77
- | Observations + reflections | ✓ | — | ✓ | — |
78
- | Context survives across compactions | ✓ | — | ✓ | — |
79
- | Background memory workers | ✓ | — | ✓ | — |
80
- | Searchable history after compaction | ✓ | ✓ | partial | — |
81
- | Per-worker model config | ✓ | — | — | — |
82
- | Fallback model chains + persisted cooldowns | ✓ | — | — | — |
83
- | Manual flush mode (`noAutoCompact`) | ✓ | — | — | — |
84
- | Memory toggle (`/blackhole om-off`) | ✓ | — | — | — |
85
- | Unified single-file config | ✓ | — | — | — |
86
- | Per-session pending state | ✓ | — | — | — |
87
-
88
-
89
89
  ---
90
90
 
91
91
  ## How it works
@@ -99,7 +99,7 @@ The agent receives a deterministic recap of recent work *plus* durable facts fro
99
99
 
100
100
  ### The three memory workers
101
101
 
102
- 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):
103
103
 
104
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.
105
105
  - **Reflector** — distills new observations into durable reflections: stable facts, patterns, and constraints that survive future compactions. Runs less often.
@@ -181,7 +181,7 @@ When exact source context is needed for precision or traceability, use the `reca
181
181
  ----
182
182
  ```
183
183
 
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.
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.
185
185
 
186
186
  ---
187
187
 
@@ -190,11 +190,11 @@ When exact source context is needed for precision or traceability, use the `reca
190
190
  Two modes, one shared goal: keep your agent's context sharp without manual housekeeping.
191
191
 
192
192
  - **Auto mode (default):** install and forget. Workers run, observations are appended as invisible conversation markers, compaction fires automatically when tokens exceed threshold.
193
- - **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.
194
194
 
195
195
  The tradeoff is simplicity vs cleanliness:
196
196
 
197
- | | Auto (default) | Manual (`noAutoCompact: true`) |
197
+ | | Auto (default) | Manual (`compaction: "manual"`) |
198
198
  |---|---|---|
199
199
  | Workers run? | Yes | Yes |
200
200
  | Observations go to | Conversation markers (invisible in TUI) | Disk (`<sessionId>-pending.json`) |
@@ -212,15 +212,15 @@ The difference from Pi's built-in `/compact`:
212
212
  - `/compact` calls an LLM to write a free-form summary — costly, lossy, no memory layer.
213
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.
214
214
 
215
- ### Passive mode
215
+ ### Fully disabled
216
216
 
217
- 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.
218
218
 
219
219
  ### Without observational memory (vcc-only)
220
220
 
221
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`.
222
222
 
223
- 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.
224
224
 
225
225
  ---
226
226
 
@@ -228,7 +228,7 @@ This is a lighter alternative to `passive`: workers are off but auto-compaction
228
228
 
229
229
  | Command | What it does |
230
230
  |---|---|
231
- | `/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. |
232
232
  | `/blackhole-memory` (or `status`) | Pipeline status: token progress, observation/reflection counts, pending data, last errors |
233
233
  | `/blackhole-memory view` | Show visible observations and reflections (after compaction trimming), copied to clipboard |
234
234
  | `/blackhole-memory full` | Show ALL recorded memory (including dropped observations), copied to clipboard |
@@ -254,7 +254,7 @@ The agent gets a unified `recall` tool that handles three types of input:
254
254
 
255
255
  ## Configuration
256
256
 
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 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).
258
258
 
259
259
  Quick start — just set custom models (if you want):
260
260
 
@@ -266,27 +266,28 @@ Quick start — just set custom models (if you want):
266
266
  }
267
267
  ```
268
268
 
269
- That's it. Everything else has sensible defaults.
269
+ Everything else has sensible defaults.
270
270
 
271
271
  ### Settings at a glance
272
272
 
273
273
  | Setting | Default | What it controls |
274
274
  |---|---|---|
275
- | `overrideDefaultCompaction` | `false` | Route ALL Pi compactions through blackhole, not just explicit `/blackhole` |
276
- | `noAutoCompact` | `false` | Manual mode: save observations to disk, disable auto-compaction |
277
- | `memory` | `true` | `false` = vcc only, no workers, no OM injection |
278
- | `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) |
279
279
  | `model` | — | Base fallback model for all workers (last resort before session model) |
280
280
  | `observerModel` / `observerFallbackModels` | — / `[]` | Primary + fallback models for observer (extracts facts) |
281
281
  | `reflectorModel` / `reflectorFallbackModels` | — / `[]` | Primary + fallback models for reflector (synthesizes reflections) |
282
282
  | `dropperModel` / `dropperFallbackModels` | — / `[]` | Primary + fallback models for dropper (prunes observations) |
283
283
  | *(per model)* `thinking` | `"low"` | Thinking/reasoning level: `off`, `minimal`, `low`, `medium`, `high`, `xhigh` |
284
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. |
285
286
  | `observeAfterTokens` | `15000` | Min accumulated tokens before observer runs |
286
287
  | `reflectAfterTokens` | `25000` | Min accumulated tokens before reflector + dropper run |
287
- | `compactAfterTokens` | `81000` | Auto-compaction threshold (when `noAutoCompact` is `false`) |
288
+ | `compactAfterTokens` | `81000` | Auto-compaction threshold (when `compaction: "auto"`) |
288
289
  | `observerChunkMaxTokens` | `40000` | Max observer input per run (newest-first) |
289
- | `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) |
290
291
  | `observationsPoolMaxTokens` | `20000` | Max active observation pool before dropper prunes |
291
292
  | `observationsPoolTargetTokens` | `10000` | Target size dropper aims for after pruning (derived: half of pool max) |
292
293
  | `reflectorInputMaxTokens` | `80000` | Max reflector input budget |
@@ -295,7 +296,7 @@ That's it. Everything else has sensible defaults.
295
296
  | `debug` | `false` | Pre-compaction snapshot to `/tmp/pi-blackhole-debug.json` |
296
297
  | `debugLog` | `false` | Continuous JSONL debug log to `~/.pi/agent/pi-blackhole/debug.ndjson` |
297
298
 
298
- **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`.
299
300
 
300
301
  ### Configuration presets
301
302
 
@@ -480,6 +481,28 @@ Results are shown as a collapsible message and auto-fed to the agent as context.
480
481
 
481
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.
482
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
+
483
506
  ## Uninstall
484
507
 
485
508
  ```bash
@@ -500,7 +523,7 @@ What blackhole adds and reworks on top:
500
523
 
501
524
  - **Unified configuration** — one JSON file, not two
502
525
  - **Per-worker model fallback chains** with persisted cooldowns that survive Pi restarts
503
- - **Manual flush mode** — `noAutoCompact` saves observations to per-session disk buffers
526
+ - **Manual flush mode** — `compaction: "manual"` saves observations to per-session disk buffers
504
527
  - **Conflict resolution** — OM hooks into vcc's compaction, not Pi's default
505
528
  - **Memory toggle** (`/blackhole om-off` / `/blackhole om-on`) — disable the memory layer without uninstalling
506
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.1",
3
+ "version": "0.3.3",
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