pi-smart-compact 7.5.2 → 7.9.0
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/CHANGELOG.md +32 -0
- package/README.md +513 -198
- package/dist/constants.d.ts +45 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/core.d.ts +27 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3131 -0
- package/dist/phases/explore.d.ts +35 -0
- package/dist/phases/explore.d.ts.map +1 -0
- package/dist/phases/synthesize.d.ts +23 -0
- package/dist/phases/synthesize.d.ts.map +1 -0
- package/dist/phases/verify.d.ts +16 -0
- package/dist/phases/verify.d.ts.map +1 -0
- package/dist/types.d.ts +265 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/ui/overlays.d.ts +29 -0
- package/dist/ui/overlays.d.ts.map +1 -0
- package/dist/utils/cache.d.ts +27 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/damage.d.ts +28 -0
- package/dist/utils/damage.d.ts.map +1 -0
- package/dist/utils/extraction.d.ts +27 -0
- package/dist/utils/extraction.d.ts.map +1 -0
- package/dist/utils/fingerprint.d.ts +32 -0
- package/dist/utils/fingerprint.d.ts.map +1 -0
- package/dist/utils/helpers.d.ts +22 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/logger.d.ts +8 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/pruning.d.ts +19 -0
- package/dist/utils/pruning.d.ts.map +1 -0
- package/dist/utils/state.d.ts +62 -0
- package/dist/utils/state.d.ts.map +1 -0
- package/dist/utils/tokens.d.ts +8 -0
- package/dist/utils/tokens.d.ts.map +1 -0
- package/dist/utils/type-guards.d.ts +26 -0
- package/dist/utils/type-guards.d.ts.map +1 -0
- package/docs/assets/pi-smart-compact.png +0 -0
- package/package.json +13 -3
- package/src/constants.ts +0 -140
- package/src/core.ts +0 -360
- package/src/index.ts +0 -175
- package/src/phases/explore.ts +0 -371
- package/src/phases/synthesize.ts +0 -184
- package/src/phases/verify.ts +0 -191
- package/src/types.ts +0 -176
- package/src/ui/overlays.ts +0 -329
- package/src/utils/cache.ts +0 -145
- package/src/utils/damage.ts +0 -153
- package/src/utils/extraction.ts +0 -259
- package/src/utils/fingerprint.ts +0 -190
- package/src/utils/helpers.ts +0 -161
- package/src/utils/message-blocks.ts +0 -21
- package/src/utils/pruning.ts +0 -147
- package/src/utils/tokens.ts +0 -63
package/README.md
CHANGED
|
@@ -1,110 +1,457 @@
|
|
|
1
|
-
#
|
|
1
|
+
# pi-smart-compact
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/pi-smart-compact)
|
|
4
4
|
[](./LICENSE)
|
|
5
5
|
[](https://github.com/alpertarhan/pi-smart-compact)
|
|
6
6
|
|
|
7
|
-
>
|
|
7
|
+
<p align="center">
|
|
8
|
+
<img src="./docs/assets/pi-smart-compact.png" alt="pi-smart-compact" width="760" />
|
|
9
|
+
</p>
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
> Verification-oriented smart compaction for the [Pi Coding Agent](https://github.com/earendil-works/pi-coding-agent).
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
`pi-smart-compact` replaces blind conversation trimming with a structured compaction pipeline that tries to preserve the agent's working state: goal, files, errors, decisions, constraints, open loops, and cross-compaction deltas.
|
|
14
|
+
|
|
15
|
+
It is built around an **EESV** pipeline:
|
|
16
|
+
|
|
17
|
+
**Extract → Explore → Synthesize → Verify**
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Table of Contents
|
|
22
|
+
|
|
23
|
+
- [What this project is](#what-this-project-is)
|
|
24
|
+
- [Current repository snapshot](#current-repository-snapshot)
|
|
25
|
+
- [Visual identity](#visual-identity)
|
|
26
|
+
- [Why it exists](#why-it-exists)
|
|
27
|
+
- [Architecture flow](#architecture-flow)
|
|
28
|
+
- [Execution model](#execution-model)
|
|
29
|
+
- [Repository layout](#repository-layout)
|
|
30
|
+
- [Runtime artifacts](#runtime-artifacts)
|
|
31
|
+
- [Installation](#installation)
|
|
32
|
+
- [Usage](#usage)
|
|
33
|
+
- [Configuration](#configuration)
|
|
34
|
+
- [Output contract](#output-contract)
|
|
35
|
+
- [Quality controls](#quality-controls)
|
|
36
|
+
- [Current caveats](#current-caveats)
|
|
37
|
+
- [Development](#development)
|
|
38
|
+
- [License](#license)
|
|
12
39
|
|
|
13
40
|
---
|
|
14
41
|
|
|
15
|
-
##
|
|
42
|
+
## What this project is
|
|
43
|
+
|
|
44
|
+
This package is a **Pi extension** that registers three integration surfaces:
|
|
16
45
|
|
|
17
|
-
|
|
46
|
+
| Surface | Where | Purpose |
|
|
47
|
+
| --- | --- | --- |
|
|
48
|
+
| Slash command | `/smart-compact` | Manual compaction, interactive or direct |
|
|
49
|
+
| Session hook | `session_before_compact` | Auto-trigger smart compaction before Pi's default compaction |
|
|
50
|
+
| Tool | `smart_compact` | Agent-callable compaction that stages a pending summary |
|
|
18
51
|
|
|
19
|
-
|
|
20
|
-
- **Hallucination detection** — verifies the summary doesn't invent file paths or misstate error status
|
|
21
|
-
- **Decision propagation** — carries decisions across batch boundaries so the LLM never forgets what was decided
|
|
22
|
-
- **Redundancy pruning** — collapses duplicate reads, consecutive failures, and low-info messages before compaction, reducing input by 15–30%
|
|
23
|
-
- **Cross-session memory** — learns your project's language, framework, and file structure across sessions
|
|
24
|
-
- **Damage detection** — monitors post-compaction behavior for regression signals
|
|
52
|
+
The extension keeps a short-lived pending compaction in memory, then hands that summary back to Pi when compaction is applied.
|
|
25
53
|
|
|
26
54
|
---
|
|
27
55
|
|
|
28
|
-
##
|
|
56
|
+
## Current repository snapshot
|
|
29
57
|
|
|
30
|
-
|
|
31
|
-
Extract → Explore → Synthesize → Verify
|
|
32
|
-
(0 LLM) (0–8 LLM) (N+1 LLM) (0–1 LLM)
|
|
33
|
-
```
|
|
58
|
+
**Observed from the current codebase (`README`, `src/`, `test/`, `package.json`)**
|
|
34
59
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
60
|
+
- **Package version:** `7.8.0`
|
|
61
|
+
- **Runtime entrypoint:** `dist/index.js`
|
|
62
|
+
- **Source entrypoint:** `src/index.ts`
|
|
63
|
+
- **Source modules:** 16 TypeScript files under `src/`
|
|
64
|
+
- **Tests:** 9 test files, **93 passing tests**
|
|
65
|
+
- **Approx repo footprint:** ~5,053 lines across `src/` + `test/`
|
|
66
|
+
- **Documentation asset:** `docs/assets/pi-smart-compact.png`
|
|
67
|
+
- **Published package files:** `dist/`, `docs/`, `README.md`, `LICENSE`, `CHANGELOG.md`
|
|
41
68
|
|
|
42
|
-
###
|
|
69
|
+
### Current command health
|
|
43
70
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
71
|
+
| Command | Status | Notes |
|
|
72
|
+
| --- | --- | --- |
|
|
73
|
+
| `bun test` | ✅ Pass | 93/93 tests passing |
|
|
74
|
+
| `bun run build` | ✅ Pass | Bundles `src/index.ts` to `dist/index.js` |
|
|
75
|
+
| `bun run typecheck` | ⚠️ Fails | Current repo has TypeScript compatibility issues against the installed Pi typings / `.ts` import style |
|
|
76
|
+
|
|
77
|
+
So the project is currently **buildable and tested**, but **not fully typecheck-clean**.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Visual identity
|
|
82
|
+
|
|
83
|
+
The repository image used by this `README.md` now lives at:
|
|
84
|
+
|
|
85
|
+
- `docs/assets/pi-smart-compact.png`
|
|
86
|
+
|
|
87
|
+
The asset is now a cleaned transparent `PNG` instead of a checkerboard/transparent-preview render, so it displays correctly inside GitHub `README.md`.
|
|
88
|
+
|
|
89
|
+
This keeps documentation assets separate from `src/` implementation code and `test/` fixtures while still shipping the image with the package via `package.json` `files`.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Why it exists
|
|
49
94
|
|
|
50
|
-
|
|
95
|
+
Default compaction usually loses exactly the things a coding agent needs most:
|
|
51
96
|
|
|
97
|
+
- which files were actually modified
|
|
98
|
+
- which errors are still unresolved
|
|
99
|
+
- what the user explicitly asked for
|
|
100
|
+
- what decisions already won
|
|
101
|
+
- what still needs to happen next
|
|
102
|
+
|
|
103
|
+
`pi-smart-compact` tries to preserve that operational state instead of producing a generic prose summary.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Architecture flow
|
|
108
|
+
|
|
109
|
+
```mermaid
|
|
110
|
+
flowchart TD
|
|
111
|
+
A["Entry points<br/>/smart-compact<br/>session_before_compact<br/>smart_compact tool"] --> B["Load config and resolve models<br/>loadConfig()<br/>summaryModel / segmentationModel"]
|
|
112
|
+
B --> C{"Context >= 5000 tokens?"}
|
|
113
|
+
C -- No --> C1["Exit early"]
|
|
114
|
+
C -- Yes --> D["Read current branch<br/>keep recent tail by profile<br/>smartKeepBoundary()"]
|
|
115
|
+
D --> E["Pre-processing<br/>pruneRedundant()<br/>serializeConversation()<br/>backupConversation()<br/>getPreviousCompactionContext()"]
|
|
116
|
+
E --> F["Phase 1: Extract<br/>extractStructured()<br/>files, errors, decisions, constraints,<br/>heuristic topics, timeline, goal"]
|
|
117
|
+
F --> G["Cross-session helpers<br/>load or save cached extraction<br/>deriveProjectId()<br/>loadProjectFingerprint()"]
|
|
118
|
+
G --> H{"Compacted text below singlePassMaxTokens?"}
|
|
119
|
+
H -- Yes --> I["Single-pass path<br/>singlePassCompact()"]
|
|
120
|
+
H -- No --> J{"shouldExplore()?"}
|
|
121
|
+
J -- Yes --> K["Phase 2: Explore<br/>exploreConversation()<br/>tool probe -> tool loop<br/>or direct JSON fallback"]
|
|
122
|
+
J -- No --> L["Skip exploration<br/>use heuristic boundaries only"]
|
|
123
|
+
K --> M["Merge LLM boundaries<br/>with heuristic boundaries"]
|
|
124
|
+
L --> N["chunkLlmMessages()"]
|
|
125
|
+
M --> N
|
|
126
|
+
N --> O["createBatches()<br/>provider-aware concurrency"]
|
|
127
|
+
O --> P["Phase 3: Synthesize<br/>summarizeBatch() per batch<br/>assembleLLM() or assembleFallback()"]
|
|
128
|
+
I --> Q["Phase 4: Verify<br/>verifySummary()"]
|
|
129
|
+
P --> Q
|
|
130
|
+
Q --> R{"Quality score below 85?"}
|
|
131
|
+
R -- No --> S["Accept summary"]
|
|
132
|
+
R -- Yes --> T["patchDeterministic()"]
|
|
133
|
+
T --> U{"Still below 75?"}
|
|
134
|
+
U -- No --> S
|
|
135
|
+
U -- Yes --> V["patchSummary() via LLM"]
|
|
136
|
+
V --> S
|
|
137
|
+
S --> W["Post-processing<br/>extractOpenLoops()<br/>buildCompactionState()<br/>computeDelta()<br/>inject sections"]
|
|
138
|
+
W --> X["Persist artifacts<br/>project fingerprint<br/>compaction state<br/>metrics log<br/>damage report"]
|
|
139
|
+
X --> Y["Store pending compaction<br/>in memory<br/>TTL: 5 minutes"]
|
|
140
|
+
Y --> Z["ctx.compact() now<br/>or next tree compact consumes it"]
|
|
52
141
|
```
|
|
53
|
-
|
|
54
|
-
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Execution model
|
|
146
|
+
|
|
147
|
+
### 1. Entry and model resolution
|
|
148
|
+
|
|
149
|
+
`src/index.ts` is the extension boundary.
|
|
150
|
+
|
|
151
|
+
It does four jobs:
|
|
152
|
+
|
|
153
|
+
1. registers `/smart-compact`
|
|
154
|
+
2. registers `session_before_compact`
|
|
155
|
+
3. registers `smart_compact`
|
|
156
|
+
4. keeps a shared in-memory `pendingRef` and `isRunning` lock
|
|
157
|
+
|
|
158
|
+
Model resolution order is effectively:
|
|
159
|
+
|
|
160
|
+
- explicit command model argument, if provided
|
|
161
|
+
- configured `summaryModel`, if resolvable
|
|
162
|
+
- current session model
|
|
163
|
+
- first available model in the registry
|
|
164
|
+
|
|
165
|
+
`segmentationModel` falls back to the summary model unless explicitly configured.
|
|
166
|
+
|
|
167
|
+
### 2. Context gate and keep window
|
|
168
|
+
|
|
169
|
+
`src/core.ts` is the pipeline orchestrator.
|
|
170
|
+
|
|
171
|
+
Before compaction starts it:
|
|
172
|
+
|
|
173
|
+
- checks `MIN_TOKEN_THRESHOLD = 5000`
|
|
174
|
+
- reads the current session branch
|
|
175
|
+
- keeps the most recent tail according to the selected profile
|
|
176
|
+
- nudges the keep boundary with `smartKeepBoundary()` if adjacent messages appear to reference the same file
|
|
177
|
+
|
|
178
|
+
### 3. Pre-processing
|
|
179
|
+
|
|
180
|
+
Before any summarization, the pipeline performs:
|
|
181
|
+
|
|
182
|
+
- **redundancy pruning** via `src/utils/pruning.ts`
|
|
183
|
+
- **conversation backup** via `backupConversation()`
|
|
184
|
+
- **previous compaction context injection** via `getPreviousCompactionContext()`
|
|
185
|
+
- **incremental extraction cache lookup** via `src/utils/cache.ts`
|
|
186
|
+
- **project fingerprint lookup** via `src/utils/fingerprint.ts`
|
|
187
|
+
|
|
188
|
+
### 4. Phase 1 — Extract
|
|
189
|
+
|
|
190
|
+
`src/utils/extraction.ts` is the deterministic core.
|
|
191
|
+
|
|
192
|
+
It extracts, with zero LLM calls:
|
|
193
|
+
|
|
194
|
+
- modified files
|
|
195
|
+
- read files
|
|
196
|
+
- deleted files
|
|
197
|
+
- tool and bash-like errors
|
|
198
|
+
- retry / resolution signals
|
|
199
|
+
- explicit decisions from `ask_user`
|
|
200
|
+
- implicit user choices
|
|
201
|
+
- English and Turkish constraints
|
|
202
|
+
- heuristic topic segments
|
|
203
|
+
- timeline events
|
|
204
|
+
- main goal
|
|
205
|
+
- recent user messages
|
|
206
|
+
- recent error snippets
|
|
207
|
+
|
|
208
|
+
It also builds **open loops** from:
|
|
209
|
+
|
|
210
|
+
- unresolved errors
|
|
211
|
+
- follow-up language
|
|
212
|
+
- blocked/waiting language
|
|
213
|
+
- retried-but-unresolved failures
|
|
214
|
+
|
|
215
|
+
### 5. Phase 2 — Explore
|
|
216
|
+
|
|
217
|
+
`src/phases/explore.ts` adds targeted LLM exploration only when complexity justifies it.
|
|
218
|
+
|
|
219
|
+
Exploration is skipped for simple sessions when the extraction stays below these heuristics:
|
|
220
|
+
|
|
221
|
+
- `<= 3` topics
|
|
222
|
+
- `<= 1` unresolved error
|
|
223
|
+
- `<= 2` decisions
|
|
224
|
+
- `<= 2` directory groups touched
|
|
225
|
+
|
|
226
|
+
If exploration runs, it can use these tools:
|
|
227
|
+
|
|
228
|
+
- `get_message_range`
|
|
229
|
+
- `search_conversation`
|
|
230
|
+
- `get_recent_user_messages`
|
|
231
|
+
- `get_context_around`
|
|
232
|
+
- `get_file_changes`
|
|
233
|
+
- `get_error_chain`
|
|
234
|
+
|
|
235
|
+
If the provider cannot or does not use tools, exploration falls back to a direct JSON analysis prompt.
|
|
236
|
+
|
|
237
|
+
### 6. Phase 3 — Synthesize
|
|
238
|
+
|
|
239
|
+
`src/phases/synthesize.ts` supports two paths:
|
|
240
|
+
|
|
241
|
+
#### Single-pass
|
|
242
|
+
Used when the pruned conversation fits under the profile's `singlePassMaxTokens`.
|
|
243
|
+
|
|
244
|
+
#### Hierarchical
|
|
245
|
+
Used for larger sessions:
|
|
246
|
+
|
|
247
|
+
- merge heuristic and exploratory boundaries
|
|
248
|
+
- chunk messages with `chunkLlmMessages()`
|
|
249
|
+
- batch chunks with `createBatches()`
|
|
250
|
+
- summarize each batch with `summarizeBatch()`
|
|
251
|
+
- assemble a final summary with `assembleLLM()`
|
|
252
|
+
- fall back to `assembleFallback()` if assembly fails
|
|
253
|
+
|
|
254
|
+
Important synthesis behaviors already present in code:
|
|
255
|
+
|
|
256
|
+
- **decision propagation** into later batch prompts
|
|
257
|
+
- **session-type-specific prompting**
|
|
258
|
+
- **topic-level budget hints** during assembly pre-processing
|
|
259
|
+
- **provider-aware batch concurrency** from `src/utils/tokens.ts`
|
|
260
|
+
|
|
261
|
+
### 7. Phase 4 — Verify
|
|
262
|
+
|
|
263
|
+
`src/phases/verify.ts` scores the summary against deterministic extraction data.
|
|
264
|
+
|
|
265
|
+
It checks for:
|
|
266
|
+
|
|
267
|
+
- missing modified files
|
|
268
|
+
- missing unresolved errors
|
|
269
|
+
- missing high-confidence constraints
|
|
270
|
+
- missing goal coverage
|
|
271
|
+
- missing required sections
|
|
272
|
+
- suspicious fabricated file references
|
|
273
|
+
- done/unresolved inconsistency
|
|
274
|
+
- missing explicit decisions
|
|
275
|
+
- missing open-loop coverage when unresolved errors exist
|
|
276
|
+
|
|
277
|
+
Repair strategy is intentionally ordered:
|
|
278
|
+
|
|
279
|
+
1. no patch if score is acceptable
|
|
280
|
+
2. deterministic patch first
|
|
281
|
+
3. LLM patch only if deterministic patch is insufficient
|
|
282
|
+
|
|
283
|
+
### 8. Post-processing and persistence
|
|
284
|
+
|
|
285
|
+
After verification, the pipeline:
|
|
286
|
+
|
|
287
|
+
- extracts open loops
|
|
288
|
+
- injects `## Open Loops`
|
|
289
|
+
- builds a machine-readable `CompactionState`
|
|
290
|
+
- loads previous compaction state
|
|
291
|
+
- computes delta across compactions
|
|
292
|
+
- injects `## Changes Since Last Compaction`
|
|
293
|
+
- saves project fingerprint
|
|
294
|
+
- saves compaction state
|
|
295
|
+
- appends metrics log
|
|
296
|
+
- attempts post-compaction damage detection
|
|
297
|
+
|
|
298
|
+
### 9. Applying compaction
|
|
299
|
+
|
|
300
|
+
The extension stores the result in an in-memory pending object containing:
|
|
301
|
+
|
|
302
|
+
- summary
|
|
303
|
+
- first kept entry id
|
|
304
|
+
- tokens before compaction
|
|
305
|
+
- details payload
|
|
306
|
+
- structured compaction state
|
|
307
|
+
|
|
308
|
+
That pending summary is valid for **5 minutes** and is consumed by:
|
|
309
|
+
|
|
310
|
+
- immediate `ctx.compact()` in the slash-command flow, or
|
|
311
|
+
- the next `session_before_compact` hook call in tool-driven flows
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## Repository layout
|
|
316
|
+
|
|
317
|
+
### Top-level
|
|
318
|
+
|
|
319
|
+
```text
|
|
320
|
+
.
|
|
321
|
+
├── CHANGELOG.md
|
|
322
|
+
├── DEVPLAN.md
|
|
323
|
+
├── LICENSE
|
|
324
|
+
├── README.md
|
|
325
|
+
├── dist/
|
|
326
|
+
│ └── index.js
|
|
327
|
+
├── docs/
|
|
328
|
+
│ └── assets/
|
|
329
|
+
│ └── pi-smart-compact.png
|
|
330
|
+
├── package.json
|
|
331
|
+
├── src/
|
|
332
|
+
├── test/
|
|
333
|
+
└── tsconfig.json
|
|
55
334
|
```
|
|
56
335
|
|
|
336
|
+
### Source modules
|
|
337
|
+
|
|
338
|
+
| File | Role |
|
|
339
|
+
| --- | --- |
|
|
340
|
+
| `src/index.ts` | Extension registration: command, hook, tool |
|
|
341
|
+
| `src/core.ts` | End-to-end pipeline orchestration |
|
|
342
|
+
| `src/constants.ts` | Version, prompts, profiles, thresholds, config keys |
|
|
343
|
+
| `src/types.ts` | Shared types and guards |
|
|
344
|
+
| `src/phases/explore.ts` | Exploration phase, tool loop, JSON fallback |
|
|
345
|
+
| `src/phases/synthesize.ts` | Chunking, batching, single-pass and hierarchical synthesis |
|
|
346
|
+
| `src/phases/verify.ts` | Verification, deterministic patch, LLM patch |
|
|
347
|
+
| `src/ui/overlays.ts` | 2-step picker UI, progress notices, result screen |
|
|
348
|
+
| `src/utils/cache.ts` | Metrics, cache-aware LLM options, extraction cache |
|
|
349
|
+
| `src/utils/damage.ts` | Post-compaction regression signal detection |
|
|
350
|
+
| `src/utils/extraction.ts` | Deterministic extraction and open-loop detection |
|
|
351
|
+
| `src/utils/fingerprint.ts` | Cross-session project fingerprinting |
|
|
352
|
+
| `src/utils/helpers.ts` | Config loading, backups, batching, prompt helpers |
|
|
353
|
+
| `src/utils/pruning.ts` | Redundancy pruning before compaction |
|
|
354
|
+
| `src/utils/state.ts` | Compaction state persistence and delta logic |
|
|
355
|
+
| `src/utils/tokens.ts` | Provider capabilities and token estimation |
|
|
356
|
+
|
|
357
|
+
### Tests
|
|
358
|
+
|
|
359
|
+
| Test file | Coverage |
|
|
360
|
+
| --- | --- |
|
|
361
|
+
| `test/extraction.test.ts` | deterministic extraction |
|
|
362
|
+
| `test/exploration.test.ts` | exploration parsing and gating |
|
|
363
|
+
| `test/eval.test.ts` | gold scenarios, delta evaluation, fabrication safety |
|
|
364
|
+
| `test/fingerprint.test.ts` | project fingerprint helpers |
|
|
365
|
+
| `test/pruning.test.ts` | redundancy pruning |
|
|
366
|
+
| `test/semantic-compact.test.ts` | legacy-name regression coverage |
|
|
367
|
+
| `test/state.test.ts` | open loops, state, delta, persistence |
|
|
368
|
+
| `test/tokens.test.ts` | token estimation and provider caps |
|
|
369
|
+
| `test/verify.test.ts` | verification and patching |
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Runtime artifacts
|
|
374
|
+
|
|
375
|
+
The current code writes to these paths at runtime:
|
|
376
|
+
|
|
377
|
+
| Artifact | Path |
|
|
378
|
+
| --- | --- |
|
|
379
|
+
| Settings file | `~/.pi/agent/settings.json` |
|
|
380
|
+
| Conversation backups | `~/.pi/agent/compact-backups/` |
|
|
381
|
+
| Extraction cache | `~/.pi/agent/.cache/compact-extraction-<session>.json` |
|
|
382
|
+
| Metrics log | `~/.pi/agent/.cache/compact-metrics.jsonl` |
|
|
383
|
+
| Project fingerprints | `~/.pi/agent/.cache/smart-compact/projects/<projectId>.json` |
|
|
384
|
+
| Compaction states | `~/.pi/agent/.cache/smart-compact/states/<projectId>.json` |
|
|
385
|
+
| Damage reports | `~/.pi/agent/.cache/smart-compact/damage-reports.jsonl` |
|
|
386
|
+
|
|
387
|
+
### TTLs currently implemented
|
|
388
|
+
|
|
389
|
+
| Item | TTL |
|
|
390
|
+
| --- | --- |
|
|
391
|
+
| pending in-memory compaction | 5 minutes |
|
|
392
|
+
| exploration tool-support cache | 30 minutes |
|
|
393
|
+
| extraction cache | 1 hour |
|
|
394
|
+
| compaction state | 7 days |
|
|
395
|
+
| project fingerprint | 30 days |
|
|
396
|
+
|
|
57
397
|
---
|
|
58
398
|
|
|
59
399
|
## Installation
|
|
60
400
|
|
|
401
|
+
### npm / Pi package
|
|
402
|
+
|
|
61
403
|
```bash
|
|
62
|
-
|
|
63
|
-
|
|
404
|
+
pi install npm:pi-smart-compact
|
|
405
|
+
```
|
|
64
406
|
|
|
65
|
-
|
|
66
|
-
npm install pi-smart-compact
|
|
407
|
+
### GitHub
|
|
67
408
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
git clone https://github.com/alpertarhan/pi-smart-compact.git
|
|
71
|
-
cd pi-smart-compact && bun install
|
|
409
|
+
```bash
|
|
410
|
+
pi install git:github.com/alpertarhan/pi-smart-compact
|
|
72
411
|
```
|
|
73
412
|
|
|
74
|
-
|
|
413
|
+
### Local development
|
|
75
414
|
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
415
|
+
```bash
|
|
416
|
+
cd ~/.pi/agent/extensions
|
|
417
|
+
git clone https://github.com/alpertarhan/pi-smart-compact.git
|
|
418
|
+
cd pi-smart-compact
|
|
419
|
+
bun install
|
|
420
|
+
bun run build
|
|
80
421
|
```
|
|
81
422
|
|
|
82
423
|
---
|
|
83
424
|
|
|
84
425
|
## Usage
|
|
85
426
|
|
|
86
|
-
###
|
|
427
|
+
### Interactive
|
|
87
428
|
|
|
88
429
|
```bash
|
|
89
|
-
# Interactive TUI — pick model + profile
|
|
90
430
|
/smart-compact
|
|
431
|
+
```
|
|
91
432
|
|
|
92
|
-
|
|
93
|
-
/smart-compact anthropic/claude-sonnet-4 balanced
|
|
433
|
+
With no arguments, the extension opens a **2-step TUI**:
|
|
94
434
|
|
|
95
|
-
|
|
96
|
-
|
|
435
|
+
1. model selection
|
|
436
|
+
2. profile selection
|
|
97
437
|
|
|
98
|
-
|
|
99
|
-
/smart-compact debug
|
|
438
|
+
### Direct command examples
|
|
100
439
|
|
|
101
|
-
|
|
102
|
-
/smart-compact
|
|
440
|
+
```bash
|
|
441
|
+
/smart-compact anthropic/claude-sonnet-4 balanced
|
|
442
|
+
/smart-compact dry-run
|
|
443
|
+
/smart-compact debug
|
|
444
|
+
/smart-compact "focus on auth changes and unresolved follow-up work"
|
|
103
445
|
```
|
|
104
446
|
|
|
105
|
-
|
|
447
|
+
Argument parsing in the current code supports:
|
|
448
|
+
|
|
449
|
+
- model ids containing `/`
|
|
450
|
+
- profiles: `light`, `balanced`, `aggressive`
|
|
451
|
+
- flags: `verbose`, `debug`, `dry-run`
|
|
452
|
+
- remaining free text as a user steering note
|
|
106
453
|
|
|
107
|
-
|
|
454
|
+
### Tool usage
|
|
108
455
|
|
|
109
456
|
```json
|
|
110
457
|
{
|
|
@@ -117,25 +464,17 @@ The extension registers a tool the agent can call automatically:
|
|
|
117
464
|
}
|
|
118
465
|
```
|
|
119
466
|
|
|
120
|
-
|
|
467
|
+
Tool behavior is slightly different from the slash command:
|
|
121
468
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
## Profiles
|
|
127
|
-
|
|
128
|
-
| Profile | Summary Budget | Keep Recent | Best For |
|
|
129
|
-
|---------|---------------|-------------|----------|
|
|
130
|
-
| **light** | 10K tokens | 30K tokens | Debugging sessions, complex multi-file refactors where detail matters |
|
|
131
|
-
| **balanced** | 6K tokens | 20K tokens | General development (default) |
|
|
132
|
-
| **aggressive** | 3K tokens | 10K tokens | Quick exploration, prototyping, or very large contexts |
|
|
469
|
+
- it generates a pending smart summary
|
|
470
|
+
- it does **not** immediately compact when `skipCompact` is used internally
|
|
471
|
+
- it expects the next tree compaction to consume the pending result within 5 minutes
|
|
133
472
|
|
|
134
473
|
---
|
|
135
474
|
|
|
136
475
|
## Configuration
|
|
137
476
|
|
|
138
|
-
Add to `~/.pi/agent/settings.json`:
|
|
477
|
+
Add this to `~/.pi/agent/settings.json`:
|
|
139
478
|
|
|
140
479
|
```json
|
|
141
480
|
{
|
|
@@ -146,181 +485,157 @@ Add to `~/.pi/agent/settings.json`:
|
|
|
146
485
|
"autoTrigger": true,
|
|
147
486
|
"backupEnabled": true,
|
|
148
487
|
"profiles": {
|
|
149
|
-
"balanced": {
|
|
488
|
+
"balanced": {
|
|
489
|
+
"summaryBudgetTokens": 6000,
|
|
490
|
+
"keepRecentTokens": 20000
|
|
491
|
+
}
|
|
150
492
|
}
|
|
151
493
|
}
|
|
152
494
|
}
|
|
153
495
|
```
|
|
154
496
|
|
|
155
|
-
|
|
156
|
-
|--------|------|---------|-------------|
|
|
157
|
-
| `profile` | `"light"` \| `"balanced"` \| `"aggressive"` | `"balanced"` | Default compression profile |
|
|
158
|
-
| `summaryModel` | `string` \| `null` | `null` | Override model for summarization (e.g. `"anthropic/claude-sonnet-4"`) |
|
|
159
|
-
| `segmentationModel` | `string` \| `null` | `null` | Override model for exploration (e.g. `"anthropic/claude-haiku-3"`) |
|
|
160
|
-
| `autoTrigger` | `boolean` | `true` | Automatically run on Pi's `session_before_compact` hook |
|
|
161
|
-
| `backupEnabled` | `boolean` | `true` | Save conversation backup before compaction |
|
|
162
|
-
| `profiles` | `object` | — | Override per-profile token budgets |
|
|
163
|
-
|
|
164
|
-
---
|
|
165
|
-
|
|
166
|
-
## Architecture Deep Dive
|
|
167
|
-
|
|
168
|
-
### Deterministic Extraction (Phase 1)
|
|
497
|
+
### Supported keys
|
|
169
498
|
|
|
170
|
-
|
|
499
|
+
| Key | Type | Default |
|
|
500
|
+
| --- | --- | --- |
|
|
501
|
+
| `profile` | `light \| balanced \| aggressive` | `balanced` |
|
|
502
|
+
| `summaryModel` | `string \| null` | `null` |
|
|
503
|
+
| `segmentationModel` | `string \| null` | `null` |
|
|
504
|
+
| `autoTrigger` | `boolean` | `true` |
|
|
505
|
+
| `backupEnabled` | `boolean` | `true` |
|
|
506
|
+
| `backupDir` | `string` | `~/.pi/agent/compact-backups` |
|
|
507
|
+
| `profiles` | partial per-profile overrides | built-ins |
|
|
171
508
|
|
|
172
|
-
|
|
173
|
-
- **Error lifecycle** — not just "isError" but retry detection (same tool re-called within 6 messages) and resolution tracking
|
|
174
|
-
- **Decisions** — explicit (`ask_user` tool calls) and implicit (user choice patterns like "use X instead of Y")
|
|
175
|
-
- **Constraints** — regex-based mining with English + Turkish patterns, categorized as requirement/prohibition/preference
|
|
176
|
-
- **Topic segmentation** — heuristic boundaries based on file transitions, error density, user "shift" patterns, and token limits
|
|
509
|
+
### Profiles currently shipped
|
|
177
510
|
|
|
178
|
-
|
|
511
|
+
| Profile | Summary budget | Keep recent | Min chunk | Max chunk | Single-pass max | Batch max |
|
|
512
|
+
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
513
|
+
| `light` | 10000 | 30000 | 800 | 12000 | 40000 | 30000 |
|
|
514
|
+
| `balanced` | 6000 | 20000 | 500 | 8000 | 30000 | 24000 |
|
|
515
|
+
| `aggressive` | 3000 | 10000 | 300 | 6000 | 20000 | 18000 |
|
|
179
516
|
|
|
180
|
-
|
|
181
|
-
- ≤ 3 topics
|
|
182
|
-
- ≤ 1 unresolved error
|
|
183
|
-
- ≤ 2 decisions
|
|
184
|
-
- ≤ 2 directory groups
|
|
517
|
+
### Backward compatibility
|
|
185
518
|
|
|
186
|
-
|
|
519
|
+
The code still accepts the old config key:
|
|
187
520
|
|
|
188
|
-
|
|
521
|
+
- `semanticCompact`
|
|
189
522
|
|
|
190
|
-
|
|
523
|
+
but the current key is:
|
|
191
524
|
|
|
192
|
-
|
|
525
|
+
- `smartCompact`
|
|
193
526
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
> *"These are deterministically verified from the original conversation. They take priority over ANY summary content below."*
|
|
197
|
-
|
|
198
|
-
This reduces fabrication by making the LLM treat verified data as ground truth.
|
|
199
|
-
|
|
200
|
-
### Verification & Patching
|
|
201
|
-
|
|
202
|
-
1. **Verification** — checks file coverage, error coverage, constraint coverage, hallucinated file paths, error-done inconsistencies, decision coverage
|
|
203
|
-
2. **Deterministic patch** (score < 85) — injects missing items directly into the relevant markdown sections, zero LLM cost
|
|
204
|
-
3. **LLM patch** (score < 75 after deterministic) — last resort, only if deterministic patch was insufficient
|
|
205
|
-
4. **Skip** (score ≥ 85) — no patching needed
|
|
527
|
+
---
|
|
206
528
|
|
|
207
|
-
|
|
529
|
+
## Output contract
|
|
208
530
|
|
|
209
|
-
|
|
210
|
-
- **Duplicate file reads** — keeps only the last read per file
|
|
211
|
-
- **Collapsed error chains** — 3+ consecutive same-tool failures → keep first + last only
|
|
212
|
-
- **Agent acknowledgments** — "I'll fix that", "Let me check", "Sure" (zero-information messages)
|
|
213
|
-
- **Long tool outputs** — truncates to 800 chars (head 400 + tail 400)
|
|
531
|
+
The generated Markdown is expected to follow this structure:
|
|
214
532
|
|
|
215
|
-
|
|
533
|
+
```markdown
|
|
534
|
+
## Goal
|
|
535
|
+
## Constraints & Preferences
|
|
536
|
+
## Progress
|
|
537
|
+
### Done
|
|
538
|
+
### In Progress
|
|
539
|
+
### Blocked
|
|
540
|
+
## Key Decisions
|
|
541
|
+
## Files Modified
|
|
542
|
+
## Files Read
|
|
543
|
+
## Open Loops
|
|
544
|
+
## Changes Since Last Compaction
|
|
545
|
+
## Next Steps
|
|
546
|
+
## Critical Context
|
|
547
|
+
## Topics Covered
|
|
548
|
+
```
|
|
216
549
|
|
|
217
|
-
|
|
550
|
+
The extension also builds a structured `CompactionState` object containing:
|
|
218
551
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
552
|
+
- goal
|
|
553
|
+
- decisions
|
|
554
|
+
- constraints
|
|
555
|
+
- modified/read/deleted files
|
|
556
|
+
- unresolved/resolved errors
|
|
557
|
+
- open loops
|
|
558
|
+
- topics
|
|
559
|
+
- next actions
|
|
560
|
+
- critical context
|
|
561
|
+
- session type
|
|
562
|
+
- compaction version
|
|
226
563
|
|
|
227
|
-
|
|
564
|
+
This state is persisted on disk and reused for delta tracking on later compactions.
|
|
228
565
|
|
|
229
|
-
|
|
566
|
+
---
|
|
230
567
|
|
|
231
|
-
|
|
568
|
+
## Quality controls
|
|
232
569
|
|
|
233
|
-
|
|
234
|
-
|--------|----------|-----------|
|
|
235
|
-
| Agent re-reads compacted file | Medium | Tool call `read` with path from compacted section |
|
|
236
|
-
| User complaint | High | Regex: "I already told you", "you forgot", "nerede kaldı" |
|
|
237
|
-
| Re-question | Low | User mentions compacted decision topic |
|
|
570
|
+
The current codebase includes these safeguards:
|
|
238
571
|
|
|
239
|
-
|
|
572
|
+
- deterministic extraction before any summarization
|
|
573
|
+
- adaptive exploration skip for simple sessions
|
|
574
|
+
- project fingerprint reuse across sessions
|
|
575
|
+
- incremental extraction cache
|
|
576
|
+
- provider-aware token estimation and concurrency
|
|
577
|
+
- deterministic verification scoring
|
|
578
|
+
- deterministic patch before LLM patch
|
|
579
|
+
- hallucinated file-reference detection
|
|
580
|
+
- open-loop injection
|
|
581
|
+
- cross-compaction delta injection
|
|
582
|
+
- post-compaction damage detection
|
|
583
|
+
- backup creation before compaction
|
|
584
|
+
- metrics logging for LLM cost/latency/cache usage
|
|
240
585
|
|
|
241
|
-
|
|
586
|
+
---
|
|
242
587
|
|
|
243
|
-
|
|
244
|
-
- **JSON penalty** (0.85x) — JSON.stringify'd content has denser tokenization
|
|
245
|
-
- **Language penalty** (0.9x) — Turkish/CE characters tokenize differently
|
|
246
|
-
- **Per-provider EMA calibration** — learns from actual API responses, scoped per provider
|
|
588
|
+
## Current caveats
|
|
247
589
|
|
|
248
|
-
|
|
590
|
+
To keep this README aligned with the repository's **actual** current state:
|
|
249
591
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
| MiniMax | 2 | anthropic caching |
|
|
255
|
-
| Xiaomi | 2 | openai caching |
|
|
256
|
-
| Default | 2 | none |
|
|
592
|
+
1. **`bun run typecheck` is currently failing.** The repo builds with Bun and passes tests, but strict TypeScript compatibility is not clean right now.
|
|
593
|
+
2. **One legacy test filename remains:** `test/semantic-compact.test.ts`.
|
|
594
|
+
3. **The package is published from `dist/`, not directly from `src/`.** Source and tests are not included in the package tarball.
|
|
595
|
+
4. **The extension depends on Pi runtime APIs and peer packages** (`@earendil-works/pi-ai`, `@earendil-works/pi-coding-agent`, `@earendil-works/pi-tui`, `typebox`).
|
|
257
596
|
|
|
258
597
|
---
|
|
259
598
|
|
|
260
|
-
##
|
|
261
|
-
|
|
262
|
-
Smart Compact produces structured markdown:
|
|
263
|
-
|
|
264
|
-
```markdown
|
|
265
|
-
## Goal
|
|
266
|
-
[What the user is trying to accomplish]
|
|
599
|
+
## Development
|
|
267
600
|
|
|
268
|
-
|
|
269
|
-
- [requirement] Must use TypeScript strict mode
|
|
270
|
-
- [preference] Prefer functional components
|
|
601
|
+
### Install
|
|
271
602
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
### In Progress
|
|
276
|
-
- [ ] Database migration
|
|
277
|
-
### Blocked
|
|
278
|
-
- Waiting for API credentials
|
|
603
|
+
```bash
|
|
604
|
+
bun install
|
|
605
|
+
```
|
|
279
606
|
|
|
280
|
-
|
|
281
|
-
- **Use JWT for auth**: User confirmed over session cookies
|
|
607
|
+
### Test
|
|
282
608
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
609
|
+
```bash
|
|
610
|
+
bun test
|
|
611
|
+
bun test test/eval.test.ts
|
|
612
|
+
```
|
|
286
613
|
|
|
287
|
-
|
|
288
|
-
- src/config.ts
|
|
289
|
-
- package.json
|
|
614
|
+
### Build
|
|
290
615
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
616
|
+
```bash
|
|
617
|
+
bun run build
|
|
618
|
+
```
|
|
294
619
|
|
|
295
|
-
|
|
296
|
-
- Unresolved error: test failed in auth.ts line 42
|
|
297
|
-
- API base URL: https://api.example.com/v2
|
|
620
|
+
Current build command:
|
|
298
621
|
|
|
299
|
-
|
|
300
|
-
-
|
|
301
|
-
- **DB schema design** [normal]
|
|
302
|
-
- **Config review** [low]
|
|
622
|
+
```bash
|
|
623
|
+
rm -rf dist && mkdir dist && bun build ./src/index.ts --outdir ./dist --target bun --external '@earendil-works/*' --external 'typebox'
|
|
303
624
|
```
|
|
304
625
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
## Development
|
|
626
|
+
### Typecheck
|
|
308
627
|
|
|
309
628
|
```bash
|
|
310
|
-
bun
|
|
311
|
-
bun test # 56 tests across 7 files
|
|
312
|
-
bun run typecheck # TypeScript check
|
|
629
|
+
bun run typecheck
|
|
313
630
|
```
|
|
314
631
|
|
|
315
|
-
|
|
632
|
+
At the moment, this command is expected to report errors.
|
|
316
633
|
|
|
317
|
-
|
|
634
|
+
### Typical local path inside Pi
|
|
318
635
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
4. Push (`git push origin feat/amazing-feature`)
|
|
323
|
-
5. Open a Pull Request
|
|
636
|
+
```text
|
|
637
|
+
~/.pi/agent/extensions/pi-smart-compact
|
|
638
|
+
```
|
|
324
639
|
|
|
325
640
|
---
|
|
326
641
|
|