pi-smart-compact 7.15.1 → 7.18.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/README.md +166 -285
  3. package/SECURITY.md +14 -5
  4. package/SUPPORT.md +18 -5
  5. package/dist/app/run-smart-compact.d.ts.map +1 -1
  6. package/dist/app/steps/extract.d.ts.map +1 -1
  7. package/dist/app/steps/persist.d.ts.map +1 -1
  8. package/dist/app/steps/recover.d.ts.map +1 -1
  9. package/dist/app/steps/state.d.ts.map +1 -1
  10. package/dist/app/steps/synthesize.d.ts.map +1 -1
  11. package/dist/constants.d.ts +60 -4
  12. package/dist/constants.d.ts.map +1 -1
  13. package/dist/domain/keywords.d.ts +20 -0
  14. package/dist/domain/keywords.d.ts.map +1 -0
  15. package/dist/domain/tool-semantics.d.ts +45 -0
  16. package/dist/domain/tool-semantics.d.ts.map +1 -0
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +1624 -1226
  19. package/dist/infra/ai-messages.d.ts +40 -0
  20. package/dist/infra/ai-messages.d.ts.map +1 -0
  21. package/dist/infra/paths.d.ts +2 -0
  22. package/dist/infra/paths.d.ts.map +1 -1
  23. package/dist/infra/services.d.ts +1 -0
  24. package/dist/infra/services.d.ts.map +1 -1
  25. package/dist/phases/explore.d.ts +1 -1
  26. package/dist/phases/explore.d.ts.map +1 -1
  27. package/dist/phases/synthesize.d.ts +7 -0
  28. package/dist/phases/synthesize.d.ts.map +1 -1
  29. package/dist/phases/verify.d.ts.map +1 -1
  30. package/dist/types.d.ts +3 -0
  31. package/dist/types.d.ts.map +1 -1
  32. package/dist/ui/overlays.d.ts +7 -0
  33. package/dist/ui/overlays.d.ts.map +1 -1
  34. package/dist/utils/cache.d.ts.map +1 -1
  35. package/dist/utils/damage.d.ts +14 -0
  36. package/dist/utils/damage.d.ts.map +1 -1
  37. package/dist/utils/extraction.d.ts.map +1 -1
  38. package/dist/utils/fingerprint.d.ts.map +1 -1
  39. package/dist/utils/helpers.d.ts +33 -0
  40. package/dist/utils/helpers.d.ts.map +1 -1
  41. package/dist/utils/pruning.d.ts.map +1 -1
  42. package/dist/utils/session-log.d.ts.map +1 -1
  43. package/dist/utils/state.d.ts +7 -0
  44. package/dist/utils/state.d.ts.map +1 -1
  45. package/dist/utils/tokens.d.ts.map +1 -1
  46. package/docs/RELEASE.md +1 -1
  47. package/docs/assets/banner.svg +71 -0
  48. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,80 @@
1
1
  # Changelog
2
2
 
3
+ ## [7.18.0] - 2026-06-26
4
+
5
+ ### Fixed
6
+ - **`mergeExtractions` mainGoal corruption** — incremental extraction replaced the original goal with a delta-suffix message; now prefers `base.mainGoal`.
7
+ - **`mergeExtractions` boundary gap** — `lastUserMessages`/`lastErrors` now span the cache boundary instead of dropping base's tail.
8
+ - **`catalogErrors` id-less retry** — retry resolution falls back to tool-name match when the retry call lacks an id.
9
+ - **Pruning hides errors** — short error-containing tool outputs preserved from 800-char truncation (shared `LIKELY_ERROR_RE`).
10
+ - **`computeDelta` collision** — prefix-slice keys collided different items sharing an opening; now full-normalized text.
11
+ - **`smartKeepBoundary` dead regex** — `path="..."` never matched agent output; replaced with toolCall-arg file extraction.
12
+ - **`buildCompactionState` basename** — raw basename → `buildPathNeedles` (generic-basename gate, consistent with `extractOpenLoops`).
13
+ - **`extractNextActions`/`Critical`** — case-sensitive regex → canonical `findSection`.
14
+ - **`CONSTRAINT_PATTERNS`** — `\b` → lookarounds so Turkish-leading chars (`önemli`, `şart`) match.
15
+ - **`verifySummary` fuzzy** — salient-token keyword extraction; error snippet whitespace-normalized.
16
+ - **`estimateTokens` JSON** — density fallback for non-brace-first JSON (capped at 8KB).
17
+
18
+ ### Added
19
+ - **`domain/keywords.ts`** — `extractCheckKeywords` (shared by verify + damage).
20
+ - **Centralized constants** — `TRUNC` (truncation budgets), `ID_PREFIX`, `TUNING` (EMA/clamp/confidence), shared durations, `EXTRACTION_CACHE_PREFIX`, `LIKELY_ERROR_RE`.
21
+
22
+ ### Changed
23
+ - **Zero inline magic values** — ~70 truncation literals, ID prefixes, confidence scores, TTL duplications (7d×3, 1h×2), and tuning factors centralized into named constants.
24
+ - **`makeCompactSessionId`** — single source (services.ts); cache.ts fallback deduped.
25
+ - **`damage.ts` re-question** — shared `extractCheckKeywords` (threshold relaxed for high-precision salient tokens).
26
+
27
+ ## [7.17.0] - 2026-06-26
28
+
29
+ ### Added
30
+ - **Name-agnostic tool classification** (`src/domain/tool-semantics.ts`) — a pure `classifyTool(args)` that classifies a tool call by its argument shape (`mutates` / `accesses` / `executes` / `other`) plus `extractToolPath(args)`. A tool is a write because its arguments carry a content payload, not because its name contains "write" — so this auto-adapts to tools the code has never seen (`hypa_*`, MCP servers, custom extensions) with no name list to maintain.
31
+
32
+ ### Changed
33
+ - **Extraction is now name-agnostic.** `trackFileOps`, `catalogErrors`, `segmentTopicsHeuristic` (`utils/extraction.ts`), `get_file_changes` (`phases/explore.ts`), and re-read detection (`utils/damage.ts`) all classify via `classifyTool` instead of substring name matching. Removes the `WRITE/DELETE/READ_TOOL_HINTS` lists, `hasToolHint`, and the hardcoded `=== "bash"` gate. Shell-like tools (`hypa_shell`, …) and path-bearing readers (`hypa_grep`/`find`/`ls`) are now detected correctly by argument shape.
34
+ - **Model resolution deduplicated** (`index.ts`) — the `provider/id` split + `modelRegistry.find` pattern (duplicated three times) is now a single `findModelById` helper; `resolveModelArg` removed.
35
+ - **`SHIFT_RE` Turkish coverage** — the topic-shift cue regex was ASCII-only and silently missed natural Turkish spellings (`şimdi`, `geçelim`, `bakalım`, `yapalım`, `başka`); both spellings now match, consistent with `FOLLOWUP_RE`'s dual-spelling convention.
36
+ - **`CONSTRAINT_PATTERNS` readability** — the Turkish regexes use raw UTF-8 characters instead of `\u00f6`/`\u015f` escapes (the source is UTF-8; the escapes added no value and hurt readability).
37
+
38
+ ### Fixed
39
+ - **`trackFileOps` duplicated branch** — the `isTruncated` and `!NO_OP_RE` arms had identical bodies; collapsed into one condition (`isTruncated(resultText) || !NO_OP_RE.test(resultText)`).
40
+ - **Dead locals in `segmentTopicsHeuristic`** — `type` and `primaryFile` were assigned every iteration but never read (the topic push uses `currentType`/`currentPrimaryFile`); removed. Path lookup now uses `extractToolPath`, matching the other consumers.
41
+
42
+ ### Tests
43
+ - New `test/tool-semantics.test.ts` covering all four tool classes, the path-only delete/read ambiguity, and `extractToolPath` across key variants. Extraction fixtures updated to realistic content payloads; a regression case proves an unknown tool name (`totally_unknown_mcp_tool`) is still classified correctly. Suite: 501 tests across 43 files.
44
+
45
+ ## [7.16.0] - 2026-06-18
46
+
47
+ ### Added
48
+ - **Pinned never-compact context** (`smartCompact.pinPaths`) — file paths that must always survive compaction regardless of what the LLM summary includes. Surfaced in the summary's Files Read via a deterministic, LLM-free `ensurePinnedPaths` step in `buildState`.
49
+ - **Damage auto-remediation** — `detectDamage` now collects the files the agent re-reads after a compaction (`reReadFiles`), persists them as remediation hints, and the *next* compaction re-preserves them (merged with `pinPaths`) so lost context stops being lost twice. Closes the detect → remediate loop.
50
+ - **`/smart-compact restore`** — list, view, and restore backups. `listBackups`/`readBackupContent` make the previously write-only backups browsable; `showRestorePicker` + `showRestoreAction` + `showBackupViewer` provide a TUI; and a true restore forks from the current leaf and re-injects the pre-compaction content as context via `sendMessage` (graceful fallback to view on any failure).
51
+ - `asBranchMessage` / `asSerializableMessages` boundary adapters in `src/infra/ai-messages.ts`, documenting why each cross-package upcast is sound.
52
+
53
+ ### Fixed
54
+ - **session-log timestamp** — `normalizeLogMessage` stamped `Date.now()` (the recovery wall-clock) gated on a nonsensical content-shape condition, and dropped `toolName`. Now parses the log entry's real timestamp and preserves `toolName`.
55
+ - **`synthesize` empty-batch guard** — `batches[0]` could be dereferenced when the chunk list was empty; now guarded with a deterministic fallback.
56
+ - **`backupDir` config validation** — the one config key without type validation now rejects non-string values.
57
+ - **result-screen timer** — the `setTimeout` used in the result-screen `Promise.race` is now cleared in a `finally` instead of lingering up to 5s.
58
+ - **negative exploration boundary clamp** — `normalizeBoundaries` now lower-clamps `afterIndex` to 0 (LLMs occasionally emit negative values) and guards `confidence` against non-numeric values.
59
+ - **`computeToolCharPercentage` dead branch** — removed the unreachable `block.content` path (text blocks carry `.text`).
60
+ - **`ctx.ui.notify` invalid type** — restore used `"success"`, which `ctx.ui.notify` does not accept; corrected to `"info"`.
61
+ - **state.ts basename recompute** — the per-error file-attribution basename is now precomputed once instead of recomputed for every (error × file) pair.
62
+
63
+ ### Changed
64
+ - **Message cast normalization** — the explore feedback loop now builds native `Message[]` (assistant turns are the real `AssistantMessage` from `trackedComplete`, no longer downcast to `LlmMessage`); `recover`/`persist`/`extract` route through the documented `asBranchMessage`/`asSerializableMessages` adapters. Removes the lossy `as unknown as Message[]` casts and the silent dropping of `usage`/`api`/`provider`/`model`/`stopReason`.
65
+ - **Tools cast normalization** — `EXPLORATION_TOOLS` is now declared as native `Tool[]` using typebox schemas, removing both `as unknown as Parameters<...>["tools"]` casts. Behavior-preserving: every pi-ai provider only serializes the schema, so real typebox schemas are wire-identical to the previous plain JSON-schema objects.
66
+ - `failedChunkSummary` co-located with `assembleFallback` in `phases/synthesize.ts` and exported (was an untested module-private in the step module).
67
+ - `buildExplorationReportFromParsed` parameter narrowed `any` → `unknown` with proper field validation.
68
+
69
+ ### Build
70
+ - **pi runtime peers resolved 0.79.4 → 0.79.6** and **typebox 1.2.11 → 1.2.16** in the lockfile. `peerDependencies`/`devDependencies` keep their `*` wildcard ranges per the forward-compatibility policy from 7.15.0.
71
+
72
+ ### Tests
73
+ - **+79 tests (414 → 493):** type-guards validators (`isValidSmartCompactDetails`/`sanitizeSmartCompactDetails`), synthesize fallback contracts (`assembleFallback`/`failedChunkSummary`), `ai-messages` adapters, pinned-paths injection, remediation-hints round-trip, backup restore (list/read/build-restore-message), and exploration boundary normalization (negative clamp, confidence guard, non-string mainGoal).
74
+
75
+ ### Docs
76
+ - README, ARCHITECTURE, CONTRIBUTING, SECURITY, SUPPORT, RELEASE, and CODE_OF_CONDUCT redesigned; new `docs/assets/banner.svg` hero. CONTRIBUTING drift fixed (`core.ts`/`DEVPLAN.md`/`ROADMAP.md` references removed; repo map updated to the layered architecture).
77
+
3
78
  ## [7.15.1] - 2026-06-15
4
79
 
5
80
  ### Fixed
package/README.md CHANGED
@@ -1,396 +1,277 @@
1
- # pi-smart-compact
1
+ <div align="center">
2
2
 
3
- [CI](https://github.com/alpertarhan/pi-smart-compact/actions/workflows/ci.yml) · [npm](https://www.npmjs.com/package/pi-smart-compact) · [MIT License](./LICENSE) · [Pi extension](https://github.com/earendil-works/pi)
3
+ <img src="./docs/assets/banner.svg" alt="pi-smart-compact" width="860" />
4
4
 
5
- <p align="center">
6
- <img src="./docs/assets/pi-smart-compact.png" alt="pi-smart-compact" width="420" />
7
- </p>
5
+ [![CI](https://github.com/alpertarhan/pi-smart-compact/actions/workflows/ci.yml/badge.svg)](https://github.com/alpertarhan/pi-smart-compact/actions/workflows/ci.yml)
6
+ [![npm version](https://img.shields.io/npm/v/pi-smart-compact?color=60a5fa)](https://www.npmjs.com/package/pi-smart-compact)
7
+ [![license](https://img.shields.io/npm/l/pi-smart-compact?color=22c55e)](./LICENSE)
8
+ [![Pi extension](https://img.shields.io/badge/Pi-extension-fbbf24)](https://github.com/earendil-works/pi)
8
9
 
9
- > Verification-oriented smart compaction for the [Pi Coding Agent](https://github.com/earendil-works/pi-coding-agent).
10
+ **Verification-oriented smart compaction for the [Pi Coding Agent](https://github.com/earendil-works/pi-coding-agent).**
10
11
 
11
- `pi-smart-compact` replaces blind conversation trimming with a structured compaction pipeline that tries to preserve what an agent actually needs to continue working: the goal, modified files, unresolved errors, decisions, constraints, and open follow-up loops.
12
+ </div>
12
13
 
13
- It uses an **EESV** pipeline:
14
+ Default compaction trims your conversation blind. `pi-smart-compact` keeps what
15
+ the agent actually needs to continue — the **goal, changed files, unresolved
16
+ errors, decisions, constraints, and open loops** — through a verified
17
+ **Extract → Explore → Synthesize → Verify** pipeline.
14
18
 
15
- **Extract Explore Synthesize Verify**
16
-
17
- ## Highlights
18
-
19
- - **Pi-native integration** — `/smart-compact`, `smart_compact`, and `session_before_compact` support.
20
- - **Verification-oriented output** — deterministic extraction and repair before trusting LLM synthesis.
21
- - **Adaptive cost profile** — skips unnecessary work on small sessions and uses chunking only when useful.
22
- - **Operational safety** — pending summaries expire, backups are available, and metrics make regressions visible.
23
- - **Companion-friendly** — designed to coexist with context hygiene tools such as `pi-toolkit`.
24
-
25
- Under the hood, the design is grounded in two core ideas:
26
-
27
- - **agentic compaction**: let the system inspect and reason about the session instead of collapsing everything into generic prose
28
- - **Kamradt-style chunking**: break large conversations into more coherent segments before synthesis
19
+ > Facts first, synthesis second, verification last.
29
20
 
30
21
  ---
31
22
 
32
- ## What this project is
23
+ ## Why
33
24
 
34
- This package is a **Pi extension** with three integration surfaces:
25
+ Default compaction produces a vague recap and quietly drops the operational
26
+ context that matters most during coding. The result is the classic
27
+ *"didn't we already fix this?"* loop.
35
28
 
36
- | Surface | Purpose |
29
+ | Default compaction | `pi-smart-compact` |
37
30
  | --- | --- |
38
- | `/smart-compact` | manual compaction from the chat UI |
39
- | `session_before_compact` | auto-run before Pi's default compaction |
40
- | `smart_compact` tool | agent-callable compaction for long sessions |
41
-
42
- The extension stages a short-lived pending summary in memory, then hands it back to Pi when compaction is applied.
43
-
44
- ---
45
-
46
- ## Project status
31
+ | Trims by token count | Extracts facts deterministically (zero LLM) |
32
+ | Generic prose recap | Structured working-state summary |
33
+ | Loses files / errors / decisions | Preserves them, then **verifies** they survived |
34
+ | No regression signal | Damage detection + metrics dashboard |
47
35
 
48
- This is an actively maintained Pi extension. The public API is intentionally small, but the internals are still evolving as Pi's compaction lifecycle and extension APIs mature. Pin versions in production workflows if compaction behavior is mission-critical.
36
+ ## Install
49
37
 
50
- ## Compatibility note
51
-
52
- `pi-smart-compact` sits close to Pi's compaction path: it registers `session_before_compact`, reads the active branch and session log, stages a pending summary, and may call Pi's native compaction flow from `/smart-compact`.
53
-
54
- Because of that, use extra care with extensions that also manipulate:
55
-
56
- - **compaction hooks** — especially extensions that return a custom result from `session_before_compact`
57
- - **session / branch history** — rewriting, pruning, reordering, or replacing entries before compaction
58
- - **message identity** — removing entry IDs, tool-call IDs, or tool-result metadata used to align log entries
59
- - **tool output content** — truncating or rewriting `toolResult` messages before extraction
60
- - **compaction boundaries** — moving the keep/discard split or splitting `toolCall` / `toolResult` pairs
61
- - **session log storage** — replacing or deleting Pi's `.jsonl` logs under `~/.pi/agent/sessions`
62
-
63
- It is intentionally compatible with, and recommended alongside, [`pi-toolkit`](https://github.com/ersintarhan/pi-toolkit): pi-toolkit handles everyday context hygiene such as anchors, pivots, status lines, and old tool-output trimming; `pi-smart-compact` handles high-pressure verified compaction. The integration protects recent pi-toolkit anchors and can recover original tool outputs from the session log when older tool results were trimmed.
38
+ ```bash
39
+ pi install npm:pi-smart-compact
40
+ ```
64
41
 
65
- If you use another automatic compaction or context-rewriting extension, prefer enabling only one `session_before_compact` owner unless the hook order and returned values are explicitly coordinated.
42
+ From GitHub:
66
43
 
67
- ---
44
+ ```bash
45
+ pi install git:github.com/alpertarhan/pi-smart-compact
46
+ ```
68
47
 
69
- ## Why it exists
48
+ ## Quick start
70
49
 
71
- Default compaction often loses the parts that matter most during coding work:
50
+ ```bash
51
+ /smart-compact # interactive — pick model + profile
52
+ /smart-compact anthropic/claude-sonnet-4 balanced
53
+ /smart-compact "focus on auth + unresolved follow-ups"
54
+ /smart-compact metrics # profile / provider comparison
55
+ /smart-compact dashboard # interactive TUI dashboard
56
+ /smart-compact restore # list + view + restore backups
57
+ ```
72
58
 
73
- - which files were actually changed
74
- - which errors are still unresolved
75
- - what the user explicitly asked for
76
- - what decisions already won
77
- - what should happen next
59
+ Or let the agent call it as a tool on long sessions:
78
60
 
79
- `pi-smart-compact` is built to preserve that operational context instead of producing a vague recap.
61
+ ```jsonc
62
+ {
63
+ "name": "smart_compact",
64
+ "parameters": { "profile": "balanced", "dashboard": false }
65
+ }
66
+ ```
80
67
 
81
- ---
68
+ Auto-compaction also runs before Pi's native compact once context pressure
69
+ crosses your threshold (default 60% **actual** context usage).
82
70
 
83
71
  ## How it works
84
72
 
85
73
  ```mermaid
86
74
  flowchart LR
87
- A[Extract<br/>deterministic facts] --> B[Explore<br/>optional targeted analysis]
88
- B --> C[Synthesize<br/>single-pass or chunked summary]
89
- C --> D[Verify<br/>score gaps and repair]
90
- D --> E[Return smart compaction to Pi]
75
+ A["Extract<br/>deterministic facts<br/><i>0 LLM calls</i>"] --> B["Explore<br/>optional deep<br/>analysis"]
76
+ B --> C["Synthesize<br/>single-pass or<br/>chunked summary"]
77
+ C --> D["Verify<br/>score gaps,<br/>repair"]
78
+ D --> E["Return verified<br/>summary to Pi"]
91
79
  ```
92
80
 
93
- ### Pipeline summary
94
-
95
- 1. **Extract**
96
- - deterministically pulls files, errors, decisions, constraints, topics, and open loops from the session
97
- 2. **Explore**
98
- - optionally inspects the conversation more deeply when the session is complex
99
- 3. **Synthesize**
100
- - creates either a single-pass summary or a chunked hierarchical summary
101
- 4. **Verify**
102
- - checks the result against extracted facts and patches missing critical details
103
-
104
- In short: **facts first, synthesis second, verification last**.
105
-
106
- ---
107
-
108
- ## What it tries to preserve
109
-
110
- - user goal
111
- - constraints and preferences
112
- - modified / read / deleted files
113
- - unresolved and resolved errors
114
- - key decisions
115
- - open follow-up work
116
- - critical context needed for the next turn
117
- - delta from the previous compaction
118
-
119
- ---
81
+ | Stage | What it does |
82
+ | --- | --- |
83
+ | **Extract** | Deterministically pulls files, errors, decisions, constraints, topics, and open loops — no LLM, the ground truth. |
84
+ | **Explore** | Optionally inspects the conversation more deeply when the session is complex. |
85
+ | **Synthesize** | Single-pass for short sessions, Kamradt-style chunked + assembled for long ones. |
86
+ | **Verify** | Scores the result against extracted facts and patches missing critical details. |
120
87
 
121
- ## Installation
88
+ **What it preserves:** user goal · constraints & preferences · modified / read /
89
+ deleted files · unresolved & resolved errors · key decisions · open follow-up
90
+ work · critical next-turn context · the delta since the previous compaction.
122
91
 
123
- ### npm / Pi package
92
+ ## Integration surfaces
124
93
 
125
- ```bash
126
- pi install npm:pi-smart-compact
127
- ```
94
+ | Surface | When | Detail |
95
+ | --- | --- | --- |
96
+ | `/smart-compact` | Manual | Interactive picker or direct args; bypasses the adaptive gate. |
97
+ | `session_before_compact` | Auto | Runs before Pi's native compaction when context pressure is high. |
98
+ | `smart_compact` tool | Agent | Prepares a pending summary; Pi applies it on the next natural compact. |
128
99
 
129
- ### GitHub
100
+ A short-lived pending summary is staged in memory (5-minute TTL) and handed to
101
+ Pi when compaction is applied.
130
102
 
131
- ```bash
132
- pi install git:github.com/alpertarhan/pi-smart-compact
133
- ```
103
+ ## Example output
134
104
 
135
- ### Local development
105
+ A generated summary follows a stable, structured contract:
136
106
 
137
- ```bash
138
- cd ~/.pi/agent/extensions
139
- git clone https://github.com/alpertarhan/pi-smart-compact.git
140
- cd pi-smart-compact
141
- bun install
142
- bun run build
143
- ```
107
+ ```markdown
108
+ ## Goal
109
+ Add retry/backoff to the LLM client so transient 429/5xx don't abort compaction.
144
110
 
145
- ---
111
+ ## Constraints & Preferences
112
+ - [requirement] never compact mid-turn from the tool path
146
113
 
147
- ## Quick start
114
+ ## Progress
115
+ ### Done
116
+ - [x] Added `withRetry` wrapper in src/infra/llm-retry.ts
117
+ ### In Progress
118
+ - [ ] Wire retry client into the services container
119
+ ### Blocked
120
+ - None
148
121
 
149
- ### Interactive
122
+ ## Key Decisions
123
+ - **Honor Retry-After verbatim**: providers that set it know their limits best.
150
124
 
151
- ```bash
152
- /smart-compact
153
- ```
125
+ ## Files Modified
126
+ - src/infra/llm-retry.ts
127
+ - src/infra/llm-client.ts
154
128
 
155
- With no arguments, the extension opens a small picker for:
129
+ ## Files Read
130
+ - src/app/run-smart-compact.ts
156
131
 
157
- 1. model
158
- 2. profile
132
+ ## Open Loops
133
+ - [high] Retried but unresolved: AbortSignal ignored by some providers
159
134
 
160
- ### Direct command examples
135
+ ## Changes Since Last Compaction
136
+ - New files touched: src/infra/llm-retry.ts
137
+ - New loops: AbortSignal ignored by some providers
161
138
 
162
- ```bash
163
- /smart-compact anthropic/claude-sonnet-4 balanced
164
- /smart-compact dry-run
165
- /smart-compact debug
166
- /smart-compact metrics
167
- /smart-compact dashboard
168
- /smart-compact "focus on auth changes and unresolved follow-up work"
169
- ```
139
+ ## Next Steps
140
+ 1. Add an outer hard-timeout as a second line of defense
170
141
 
171
- ### Tool usage
142
+ ## Critical Context
143
+ - 408/425/429/5xx are retriable; 4xx (other) fails fast
172
144
 
173
- ```json
174
- {
175
- "name": "smart_compact",
176
- "parameters": {
177
- "profile": "balanced",
178
- "verbose": false,
179
- "dry_run": false,
180
- "report": false,
181
- "dashboard": false
182
- }
183
- }
145
+ ## Topics Covered
146
+ - LLM retry wrapper (high)
184
147
  ```
185
148
 
186
- The tool prepares a pending smart summary and lets Pi consume it on the next natural compaction.
187
-
188
- ---
189
-
190
- ## Usage notes
191
-
192
- - auto/tool compaction is skipped when the context is still small enough (default: below 60% actual context usage)
193
- - explicit manual `/smart-compact` commands bypass the 60% adaptive gate because the user intentionally requested compaction
194
- - pi-toolkit `tool=XX%` status means tool-output ratio, **not** context fullness; smart-compact uses actual `context=XX%`
195
- - the tool path does **not** compact the conversation mid-turn
196
- - pending summaries are kept in memory for **5 minutes**
197
- - exploration is adaptive and may be skipped for simple sessions
198
- - use `/smart-compact metrics` for profile/provider comparisons
199
- - use `/smart-compact dashboard` to open the interactive TUI dashboard (overview, latest run, current session, recent runs, or write HTML)
200
-
201
- This keeps the extension helpful without forcing extra work when it is not needed.
202
-
203
- ---
149
+ A machine-readable `CompactionState` is built alongside it for reuse across
150
+ later compactions (delta tracking, damage detection).
204
151
 
205
152
  ## Configuration
206
153
 
207
- Add this to `~/.pi/agent/settings.json`:
154
+ Add to `~/.pi/agent/settings.json`:
208
155
 
209
156
  ```json
210
157
  {
211
158
  "smartCompact": {
212
159
  "profile": "balanced",
213
160
  "summaryModel": "anthropic/claude-sonnet-4",
214
- "segmentationModel": "anthropic/claude-haiku-3",
215
161
  "autoTrigger": true,
216
- "autoTriggerTimeoutMs": 120000,
217
162
  "minContextPercent": 60,
218
- "backupEnabled": true,
219
- "profiles": {
220
- "balanced": {
221
- "summaryBudgetTokens": 6000,
222
- "keepRecentTokens": 20000
223
- }
224
- }
163
+ "backupEnabled": true
225
164
  }
226
165
  }
227
166
  ```
228
167
 
229
- ### Supported keys
230
-
231
168
  | Key | Type | Default |
232
169
  | --- | --- | --- |
233
170
  | `profile` | `light \| balanced \| aggressive` | `balanced` |
234
- | `summaryModel` | `string \| null` | `null` |
171
+ | `summaryModel` | `string \| null` | `null` (uses session model) |
235
172
  | `segmentationModel` | `string \| null` | `null` |
236
173
  | `autoTrigger` | `boolean` | `true` |
237
174
  | `autoTriggerTimeoutMs` | `number` | `120000` |
238
175
  | `minContextPercent` | `number` | `60` |
239
176
  | `backupEnabled` | `boolean` | `true` |
240
177
  | `backupDir` | `string` | `~/.pi/agent/compact-backups` |
241
- | `profiles` | partial per-profile overrides | built-ins |
178
+ | `profiles` | per-profile overrides | built-ins |
179
+ | `pinPaths` | `string[]` | `[]` (paths always preserved) |
242
180
 
243
181
  ### Profiles
244
182
 
245
- | Profile | Summary budget | Keep recent | Typical use |
183
+ | Profile | Summary budget | Keep recent | Use when |
246
184
  | --- | ---: | ---: | --- |
247
185
  | `light` | 10000 | 30000 | preserve more detail |
248
- | `balanced` | 6000 | 20000 | default general use |
186
+ | `balanced` | 6000 | 20000 | default, general use |
249
187
  | `aggressive` | 3000 | 10000 | tighter summaries |
250
188
 
251
- ### Backward compatibility
189
+ The legacy config key `semanticCompact` is still accepted.
252
190
 
253
- The extension still accepts the old config key `semanticCompact`, but `smartCompact` is the current key.
191
+ ## Safeguards
254
192
 
255
- ---
193
+ **Correctness**
256
194
 
257
- ## Output contract
195
+ - Deterministic extraction before any synthesis
196
+ - Verification scoring with deterministic patching **before** LLM patching
197
+ - Hallucinated file-reference detection (SemVer-aware)
198
+ - Open-loop injection + cross-compaction delta tracking
199
+ - Pinned-path preservation (`pinPaths`) — a deterministic, LLM-free guarantee
200
+ - Damage auto-remediation — re-read files feed forward and get re-preserved next compaction
258
201
 
259
- Generated summaries are expected to use this structure:
202
+ **Safety**
260
203
 
261
- ```markdown
262
- ## Goal
263
- ## Constraints & Preferences
264
- ## Progress
265
- ### Done
266
- ### In Progress
267
- ### Blocked
268
- ## Key Decisions
269
- ## Files Modified
270
- ## Files Read
271
- ## Open Loops
272
- ## Changes Since Last Compaction
273
- ## Next Steps
274
- ## Critical Context
275
- ## Topics Covered
276
- ```
204
+ - Conversation backups before compaction (retention-pruned), browsable + restorable via `/smart-compact restore`
205
+ - `toolCall` / `toolResult` pair integrity at the compaction boundary
206
+ - Cross-session leak guard on the pending summary
207
+ - Session-log recovery that bypasses truncation of older tool results
277
208
 
278
- The extension also builds a structured `CompactionState` for reuse across later compactions.
209
+ **Observability**
279
210
 
280
- ---
211
+ - Metrics logging with profile / provider comparison
212
+ - Post-compaction damage (regression) detection
213
+ - Interactive TUI + HTML dashboards
281
214
 
282
- ## Safeguards
283
-
284
- The current design includes:
285
-
286
- - deterministic extraction before summarization
287
- - adaptive exploration
288
- - chunked synthesis for larger sessions
289
- - deterministic verification scoring
290
- - deterministic patching before LLM patching
291
- - hallucinated file-reference detection
292
- - open-loop injection
293
- - project fingerprinting and delta tracking
294
- - provider-specific timeout and single-pass strategies
295
- - multimodal attachment metadata preservation
296
- - backup creation before compaction
297
- - metrics logging, profile/provider comparison, and damage detection
215
+ ## Usage notes
298
216
 
299
- ---
217
+ - Auto / tool compaction is skipped while context is small (below 60% actual usage).
218
+ - Manual `/smart-compact` bypasses that gate — you asked for it.
219
+ - `pi-toolkit`'s `tool=XX%` means tool-output ratio, **not** context fullness;
220
+ smart-compact uses actual `context=XX%`.
221
+ - The tool path does **not** compact mid-turn (it stages a pending summary).
222
+ - Exploration is adaptive and may be skipped for simple sessions.
300
223
 
301
- ## Runtime artifacts
224
+ ## Companions & compatibility
302
225
 
303
- At runtime, the extension writes to paths under `~/.pi/agent/`, including:
226
+ `pi-smart-compact` is designed to coexist with and recommended alongside —
227
+ [`pi-toolkit`](https://github.com/ersintarhan/pi-toolkit). pi-toolkit handles
228
+ everyday context hygiene (anchors, pivots, status lines, old tool-output
229
+ trimming); smart-compact handles high-pressure verified compaction. The
230
+ integration protects recent pi-toolkit anchors and recovers original tool
231
+ outputs from the session log.
304
232
 
305
- - `settings.json`
306
- - `compact-backups/`
307
- - `.cache/compact-extraction-<session>.json`
308
- - `.cache/compact-metrics.jsonl`
309
- - `.cache/smart-compact-report.html`
310
- - `.cache/smart-compact/projects/<projectId>.json`
311
- - `.cache/smart-compact/states/<projectId>.json`
312
- - `.cache/smart-compact/damage-reports.jsonl`
233
+ Because smart-compact sits close to Pi's compaction path, take extra care with
234
+ extensions that also rewrite compaction hooks, branch history, entry IDs, tool
235
+ output, or the compaction boundary. If you run another automatic compaction /
236
+ context-rewriting extension, prefer a single `session_before_compact` owner
237
+ unless hook order is explicitly coordinated.
313
238
 
314
- ---
315
-
316
- ## Repository layout
317
-
318
- ```text
319
- .
320
- ├── src/
321
- │ ├── index.ts # extension registration + command routing
322
- │ ├── constants.ts # version, thresholds, prompts
323
- │ ├── types.ts # shared types
324
- │ ├── app/ # orchestration layer
325
- │ │ ├── run-smart-compact.ts # pipeline orchestrator (was core.ts)
326
- │ │ ├── run-context.ts # typed stage chain
327
- │ │ ├── pending-slot.ts # encapsulated pending-compaction state cell
328
- │ │ ├── explore-wrap.ts # explore re-export shim
329
- │ │ └── steps/ # 10 stage modules
330
- │ │ ├── prepare.ts → resolves config + auth
331
- │ │ ├── window.ts → picks compaction window
332
- │ │ ├── recover.ts → recovers truncated messages
333
- │ │ ├── tier.ts → chooses compaction tier
334
- │ │ ├── extract.ts → pruning + extraction + cache
335
- │ │ ├── synthesize.ts→ single-pass / EESV summarization
336
- │ │ ├── verify.ts → structural verify + repair
337
- │ │ ├── state.ts → state machine + open loops
338
- │ │ ├── persist.ts → apply compaction
339
- │ │ └── metrics.ts → success / failure metrics
340
- │ ├── domain/ # pure semantics (no I/O)
341
- │ │ ├── summary-schema.ts
342
- │ │ └── summary-parse.ts
343
- │ ├── phases/ # algorithms
344
- │ │ ├── explore.ts
345
- │ │ ├── synthesize.ts
346
- │ │ └── verify.ts
347
- │ ├── infra/ # external-world interaction
348
- │ │ ├── fs.ts # atomic writes, advisory locks
349
- │ │ ├── paths.ts # canonical paths
350
- │ │ ├── git.ts # git-root discovery (cached)
351
- │ │ ├── clock.ts # injectable clock
352
- │ │ ├── llm-client.ts # LLM client seam
353
- │ │ ├── llm-retry.ts # 429/5xx backoff
354
- │ │ ├── services.ts # per-run services container
355
- │ │ └── session-identity.ts # robust session-id resolution
356
- │ ├── ui/ # TUI overlays + dashboard
357
- │ │ ├── overlays.ts
358
- │ │ └── dashboard-format.ts
359
- │ └── utils/ # 15 focused utility modules
360
- ├── test/ # 414 tests across 36 files
361
- ├── docs/
362
- ├── dist/
363
- └── package.json
364
- ```
239
+ ## Runtime artifacts
365
240
 
366
- See `ARCHITECTURE.md` for the full responsibility breakdown of each layer.
241
+ The extension writes under `~/.pi/agent/`:
367
242
 
368
- ---
243
+ | Path | Purpose |
244
+ | --- | --- |
245
+ | `settings.json` | configuration (read) |
246
+ | `compact-backups/` | conversation backups (retention-pruned) |
247
+ | `.cache/compact-extraction-<session>.json` | incremental extraction cache |
248
+ | `.cache/compact-metrics.jsonl` | metrics log |
249
+ | `.cache/smart-compact-report.html` | HTML dashboard |
250
+ | `.cache/smart-compact/projects/<projectId>.json` | project fingerprint |
251
+ | `.cache/smart-compact/states/<projectId>.json` | reusable compaction state |
252
+ | `.cache/smart-compact/damage-reports.jsonl` | regression signals |
253
+ | `.cache/smart-compact/remediation-<projectId>.json` | files to re-preserve after damage |
369
254
 
370
255
  ## Development
371
256
 
372
257
  ```bash
373
258
  bun install
374
- bun test
375
- bun run build
376
- bun run typecheck
259
+ bun run typecheck # tsc --noEmit
260
+ bun test # full test suite
261
+ bun run build # dist/ output for publishing
377
262
  ```
378
263
 
379
- Build output is published from `dist/`. Pull requests are expected to pass the same verification in GitHub Actions before merge.
264
+ Pull requests run the same verification in GitHub Actions before merge.
380
265
 
381
- ---
382
-
383
- ## Project docs
266
+ ## Documentation
384
267
 
268
+ - [`ARCHITECTURE.md`](./ARCHITECTURE.md) — system design, execution model, layer responsibilities
385
269
  - [`CHANGELOG.md`](./CHANGELOG.md) — release history
386
- - [`ARCHITECTURE.md`](./ARCHITECTURE.md) — system design and execution model
387
270
  - [`CONTRIBUTING.md`](./CONTRIBUTING.md) — contributor workflow and expectations
388
271
  - [`SECURITY.md`](./SECURITY.md) — vulnerability reporting and data-handling notes
389
272
  - [`SUPPORT.md`](./SUPPORT.md) — where to ask for help
390
273
  - [`docs/RELEASE.md`](./docs/RELEASE.md) — release checklist
391
274
 
392
- ---
393
-
394
275
  ## License
395
276
 
396
277
  MIT © [Alper Tarhan](https://github.com/alpertarhan)